]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* RIPv2 routemap. |
2 | * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org> | |
3 | * | |
4 | * This file is part of GNU Zebra. | |
5 | * | |
6 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2, or (at your option) any | |
9 | * later version. | |
10 | * | |
11 | * GNU Zebra is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with GNU Zebra; see the file COPYING. If not, write to the Free | |
18 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
19 | * 02111-1307, USA. | |
20 | */ | |
21 | ||
22 | #include <zebra.h> | |
23 | ||
24 | #include "memory.h" | |
25 | #include "prefix.h" | |
26 | #include "routemap.h" | |
27 | #include "command.h" | |
28 | #include "filter.h" | |
29 | #include "log.h" | |
30 | #include "sockunion.h" /* for inet_aton () */ | |
31 | #include "plist.h" | |
32 | ||
33 | #include "ripd/ripd.h" | |
16705130 | 34 | \f |
35 | struct rip_metric_modifier | |
36 | { | |
37 | enum | |
38 | { | |
39 | metric_increment, | |
40 | metric_decrement, | |
41 | metric_absolute | |
42 | } type; | |
43 | ||
44 | u_char metric; | |
45 | }; | |
718e3744 | 46 | |
47 | /* Add rip route map rule. */ | |
48 | int | |
49 | rip_route_match_add (struct vty *vty, struct route_map_index *index, | |
8a676be3 | 50 | const char *command, char *arg) |
718e3744 | 51 | { |
52 | int ret; | |
53 | ||
54 | ret = route_map_add_match (index, command, arg); | |
55 | if (ret) | |
56 | { | |
57 | switch (ret) | |
58 | { | |
59 | case RMAP_RULE_MISSING: | |
60 | vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); | |
61 | return CMD_WARNING; | |
718e3744 | 62 | case RMAP_COMPILE_ERROR: |
63 | vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); | |
64 | return CMD_WARNING; | |
718e3744 | 65 | } |
66 | } | |
67 | return CMD_SUCCESS; | |
68 | } | |
69 | ||
70 | /* Delete rip route map rule. */ | |
71 | int | |
72 | rip_route_match_delete (struct vty *vty, struct route_map_index *index, | |
8a676be3 | 73 | const char *command, char *arg) |
718e3744 | 74 | { |
75 | int ret; | |
76 | ||
77 | ret = route_map_delete_match (index, command, arg); | |
78 | if (ret) | |
79 | { | |
80 | switch (ret) | |
81 | { | |
82 | case RMAP_RULE_MISSING: | |
83 | vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); | |
84 | return CMD_WARNING; | |
718e3744 | 85 | case RMAP_COMPILE_ERROR: |
86 | vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); | |
87 | return CMD_WARNING; | |
718e3744 | 88 | } |
89 | } | |
90 | return CMD_SUCCESS; | |
91 | } | |
92 | ||
93 | /* Add rip route map rule. */ | |
94 | int | |
95 | rip_route_set_add (struct vty *vty, struct route_map_index *index, | |
8a676be3 | 96 | const char *command, char *arg) |
718e3744 | 97 | { |
98 | int ret; | |
99 | ||
100 | ret = route_map_add_set (index, command, arg); | |
101 | if (ret) | |
102 | { | |
103 | switch (ret) | |
104 | { | |
105 | case RMAP_RULE_MISSING: | |
106 | vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); | |
107 | return CMD_WARNING; | |
718e3744 | 108 | case RMAP_COMPILE_ERROR: |
109 | vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); | |
110 | return CMD_WARNING; | |
718e3744 | 111 | } |
112 | } | |
113 | return CMD_SUCCESS; | |
114 | } | |
115 | ||
116 | /* Delete rip route map rule. */ | |
117 | int | |
118 | rip_route_set_delete (struct vty *vty, struct route_map_index *index, | |
8a676be3 | 119 | const char *command, char *arg) |
718e3744 | 120 | { |
121 | int ret; | |
122 | ||
123 | ret = route_map_delete_set (index, command, arg); | |
124 | if (ret) | |
125 | { | |
126 | switch (ret) | |
127 | { | |
128 | case RMAP_RULE_MISSING: | |
129 | vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); | |
130 | return CMD_WARNING; | |
718e3744 | 131 | case RMAP_COMPILE_ERROR: |
132 | vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); | |
133 | return CMD_WARNING; | |
718e3744 | 134 | } |
135 | } | |
136 | return CMD_SUCCESS; | |
137 | } | |
138 | ||
139 | /* Hook function for updating route_map assignment. */ | |
11dde9c2 | 140 | /* ARGSUSED */ |
718e3744 | 141 | void |
11dde9c2 | 142 | rip_route_map_update (char *notused) |
718e3744 | 143 | { |
144 | int i; | |
145 | ||
146 | if (rip) | |
147 | { | |
148 | for (i = 0; i < ZEBRA_ROUTE_MAX; i++) | |
149 | { | |
150 | if (rip->route_map[i].name) | |
151 | rip->route_map[i].map = | |
152 | route_map_lookup_by_name (rip->route_map[i].name); | |
153 | } | |
154 | } | |
155 | } | |
156 | \f | |
157 | /* `match metric METRIC' */ | |
158 | /* Match function return 1 if match is success else return zero. */ | |
159 | route_map_result_t | |
160 | route_match_metric (void *rule, struct prefix *prefix, | |
161 | route_map_object_t type, void *object) | |
162 | { | |
163 | u_int32_t *metric; | |
164 | struct rip_info *rinfo; | |
165 | ||
166 | if (type == RMAP_RIP) | |
167 | { | |
168 | metric = rule; | |
169 | rinfo = object; | |
170 | ||
171 | if (rinfo->metric == *metric) | |
172 | return RMAP_MATCH; | |
173 | else | |
174 | return RMAP_NOMATCH; | |
175 | } | |
176 | return RMAP_NOMATCH; | |
177 | } | |
178 | ||
179 | /* Route map `match metric' match statement. `arg' is METRIC value */ | |
180 | void * | |
181 | route_match_metric_compile (char *arg) | |
182 | { | |
183 | u_int32_t *metric; | |
184 | ||
185 | metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); | |
186 | *metric = atoi (arg); | |
187 | ||
188 | if(*metric > 0) | |
189 | return metric; | |
190 | ||
191 | XFREE (MTYPE_ROUTE_MAP_COMPILED, metric); | |
192 | return NULL; | |
193 | } | |
194 | ||
195 | /* Free route map's compiled `match metric' value. */ | |
196 | void | |
197 | route_match_metric_free (void *rule) | |
198 | { | |
199 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
200 | } | |
201 | ||
202 | /* Route map commands for metric matching. */ | |
203 | struct route_map_rule_cmd route_match_metric_cmd = | |
204 | { | |
205 | "metric", | |
206 | route_match_metric, | |
207 | route_match_metric_compile, | |
208 | route_match_metric_free | |
209 | }; | |
210 | ||
211 | /* `match interface IFNAME' */ | |
212 | /* Match function return 1 if match is success else return zero. */ | |
213 | route_map_result_t | |
214 | route_match_interface (void *rule, struct prefix *prefix, | |
215 | route_map_object_t type, void *object) | |
216 | { | |
217 | struct rip_info *rinfo; | |
218 | struct interface *ifp; | |
219 | char *ifname; | |
220 | ||
221 | if (type == RMAP_RIP) | |
222 | { | |
223 | ifname = rule; | |
224 | ifp = if_lookup_by_name(ifname); | |
225 | ||
226 | if (!ifp) | |
227 | return RMAP_NOMATCH; | |
228 | ||
229 | rinfo = object; | |
230 | ||
231 | if (rinfo->ifindex_out == ifp->ifindex) | |
232 | return RMAP_MATCH; | |
233 | else | |
234 | return RMAP_NOMATCH; | |
235 | } | |
236 | return RMAP_NOMATCH; | |
237 | } | |
238 | ||
239 | /* Route map `match interface' match statement. `arg' is IFNAME value */ | |
240 | /* XXX I don`t know if I need to check does interface exist? */ | |
241 | void * | |
242 | route_match_interface_compile (char *arg) | |
243 | { | |
244 | return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); | |
245 | } | |
246 | ||
247 | /* Free route map's compiled `match interface' value. */ | |
248 | void | |
249 | route_match_interface_free (void *rule) | |
250 | { | |
251 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
252 | } | |
253 | ||
254 | /* Route map commands for interface matching. */ | |
255 | struct route_map_rule_cmd route_match_interface_cmd = | |
256 | { | |
257 | "interface", | |
258 | route_match_interface, | |
259 | route_match_interface_compile, | |
260 | route_match_interface_free | |
261 | }; | |
262 | ||
263 | /* `match ip next-hop IP_ACCESS_LIST' */ | |
264 | ||
265 | /* Match function return 1 if match is success else return zero. */ | |
266 | route_map_result_t | |
267 | route_match_ip_next_hop (void *rule, struct prefix *prefix, | |
268 | route_map_object_t type, void *object) | |
269 | { | |
270 | struct access_list *alist; | |
271 | struct rip_info *rinfo; | |
272 | struct prefix_ipv4 p; | |
273 | ||
274 | if (type == RMAP_RIP) | |
275 | { | |
276 | rinfo = object; | |
277 | p.family = AF_INET; | |
278 | p.prefix = rinfo->nexthop; | |
279 | p.prefixlen = IPV4_MAX_BITLEN; | |
280 | ||
281 | alist = access_list_lookup (AFI_IP, (char *) rule); | |
282 | if (alist == NULL) | |
283 | return RMAP_NOMATCH; | |
284 | ||
285 | return (access_list_apply (alist, &p) == FILTER_DENY ? | |
286 | RMAP_NOMATCH : RMAP_MATCH); | |
287 | } | |
288 | return RMAP_NOMATCH; | |
289 | } | |
290 | ||
291 | /* Route map `ip next-hop' match statement. `arg' should be | |
292 | access-list name. */ | |
293 | void * | |
294 | route_match_ip_next_hop_compile (char *arg) | |
295 | { | |
296 | return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); | |
297 | } | |
298 | ||
299 | /* Free route map's compiled `. */ | |
300 | void | |
301 | route_match_ip_next_hop_free (void *rule) | |
302 | { | |
303 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
304 | } | |
305 | ||
306 | /* Route map commands for ip next-hop matching. */ | |
307 | struct route_map_rule_cmd route_match_ip_next_hop_cmd = | |
308 | { | |
309 | "ip next-hop", | |
310 | route_match_ip_next_hop, | |
311 | route_match_ip_next_hop_compile, | |
312 | route_match_ip_next_hop_free | |
313 | }; | |
314 | \f | |
315 | /* `match ip next-hop prefix-list PREFIX_LIST' */ | |
316 | ||
317 | route_map_result_t | |
318 | route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix, | |
319 | route_map_object_t type, void *object) | |
320 | { | |
321 | struct prefix_list *plist; | |
322 | struct rip_info *rinfo; | |
323 | struct prefix_ipv4 p; | |
324 | ||
325 | if (type == RMAP_RIP) | |
326 | { | |
327 | rinfo = object; | |
328 | p.family = AF_INET; | |
329 | p.prefix = rinfo->nexthop; | |
330 | p.prefixlen = IPV4_MAX_BITLEN; | |
331 | ||
332 | plist = prefix_list_lookup (AFI_IP, (char *) rule); | |
333 | if (plist == NULL) | |
334 | return RMAP_NOMATCH; | |
335 | ||
336 | return (prefix_list_apply (plist, &p) == PREFIX_DENY ? | |
337 | RMAP_NOMATCH : RMAP_MATCH); | |
338 | } | |
339 | return RMAP_NOMATCH; | |
340 | } | |
341 | ||
342 | void * | |
343 | route_match_ip_next_hop_prefix_list_compile (char *arg) | |
344 | { | |
345 | return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); | |
346 | } | |
347 | ||
348 | void | |
349 | route_match_ip_next_hop_prefix_list_free (void *rule) | |
350 | { | |
351 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
352 | } | |
353 | ||
354 | struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = | |
355 | { | |
356 | "ip next-hop prefix-list", | |
357 | route_match_ip_next_hop_prefix_list, | |
358 | route_match_ip_next_hop_prefix_list_compile, | |
359 | route_match_ip_next_hop_prefix_list_free | |
360 | }; | |
361 | \f | |
362 | /* `match ip address IP_ACCESS_LIST' */ | |
363 | ||
364 | /* Match function should return 1 if match is success else return | |
365 | zero. */ | |
366 | route_map_result_t | |
367 | route_match_ip_address (void *rule, struct prefix *prefix, | |
368 | route_map_object_t type, void *object) | |
369 | { | |
370 | struct access_list *alist; | |
371 | ||
372 | if (type == RMAP_RIP) | |
373 | { | |
374 | alist = access_list_lookup (AFI_IP, (char *) rule); | |
375 | if (alist == NULL) | |
376 | return RMAP_NOMATCH; | |
377 | ||
378 | return (access_list_apply (alist, prefix) == FILTER_DENY ? | |
379 | RMAP_NOMATCH : RMAP_MATCH); | |
380 | } | |
381 | return RMAP_NOMATCH; | |
382 | } | |
383 | ||
384 | /* Route map `ip address' match statement. `arg' should be | |
385 | access-list name. */ | |
386 | void * | |
387 | route_match_ip_address_compile (char *arg) | |
388 | { | |
389 | return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); | |
390 | } | |
391 | ||
392 | /* Free route map's compiled `ip address' value. */ | |
393 | void | |
394 | route_match_ip_address_free (void *rule) | |
395 | { | |
396 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
397 | } | |
398 | ||
399 | /* Route map commands for ip address matching. */ | |
400 | struct route_map_rule_cmd route_match_ip_address_cmd = | |
401 | { | |
402 | "ip address", | |
403 | route_match_ip_address, | |
404 | route_match_ip_address_compile, | |
405 | route_match_ip_address_free | |
406 | }; | |
407 | \f | |
408 | /* `match ip address prefix-list PREFIX_LIST' */ | |
409 | ||
410 | route_map_result_t | |
411 | route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, | |
412 | route_map_object_t type, void *object) | |
413 | { | |
414 | struct prefix_list *plist; | |
415 | ||
416 | if (type == RMAP_RIP) | |
417 | { | |
418 | plist = prefix_list_lookup (AFI_IP, (char *) rule); | |
419 | if (plist == NULL) | |
420 | return RMAP_NOMATCH; | |
421 | ||
422 | return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? | |
423 | RMAP_NOMATCH : RMAP_MATCH); | |
424 | } | |
425 | return RMAP_NOMATCH; | |
426 | } | |
427 | ||
428 | void * | |
429 | route_match_ip_address_prefix_list_compile (char *arg) | |
430 | { | |
431 | return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); | |
432 | } | |
433 | ||
434 | void | |
435 | route_match_ip_address_prefix_list_free (void *rule) | |
436 | { | |
437 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
438 | } | |
439 | ||
440 | struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = | |
441 | { | |
442 | "ip address prefix-list", | |
443 | route_match_ip_address_prefix_list, | |
444 | route_match_ip_address_prefix_list_compile, | |
445 | route_match_ip_address_prefix_list_free | |
446 | }; | |
16705130 | 447 | |
448 | /* `match tag TAG' */ | |
449 | /* Match function return 1 if match is success else return zero. */ | |
450 | route_map_result_t | |
451 | route_match_tag (void *rule, struct prefix *prefix, | |
452 | route_map_object_t type, void *object) | |
453 | { | |
454 | u_short *tag; | |
455 | struct rip_info *rinfo; | |
456 | ||
457 | if (type == RMAP_RIP) | |
458 | { | |
459 | tag = rule; | |
460 | rinfo = object; | |
461 | ||
462 | /* The information stored by rinfo is host ordered. */ | |
463 | if (rinfo->tag == *tag) | |
464 | return RMAP_MATCH; | |
465 | else | |
466 | return RMAP_NOMATCH; | |
467 | } | |
468 | return RMAP_NOMATCH; | |
469 | } | |
470 | ||
471 | /* Route map `match tag' match statement. `arg' is TAG value */ | |
472 | void * | |
473 | route_match_tag_compile (char *arg) | |
474 | { | |
475 | u_short *tag; | |
476 | ||
477 | tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); | |
478 | *tag = atoi (arg); | |
479 | ||
480 | return tag; | |
481 | } | |
482 | ||
483 | /* Free route map's compiled `match tag' value. */ | |
484 | void | |
485 | route_match_tag_free (void *rule) | |
486 | { | |
487 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
488 | } | |
489 | ||
490 | /* Route map commands for tag matching. */ | |
491 | struct route_map_rule_cmd route_match_tag_cmd = | |
492 | { | |
493 | "tag", | |
494 | route_match_tag, | |
495 | route_match_tag_compile, | |
496 | route_match_tag_free | |
497 | }; | |
718e3744 | 498 | \f |
499 | /* `set metric METRIC' */ | |
500 | ||
501 | /* Set metric to attribute. */ | |
502 | route_map_result_t | |
503 | route_set_metric (void *rule, struct prefix *prefix, | |
504 | route_map_object_t type, void *object) | |
505 | { | |
718e3744 | 506 | if (type == RMAP_RIP) |
507 | { | |
16705130 | 508 | struct rip_metric_modifier *mod; |
509 | struct rip_info *rinfo; | |
510 | ||
511 | mod = rule; | |
718e3744 | 512 | rinfo = object; |
16705130 | 513 | |
514 | if (mod->type == metric_increment) | |
515 | rinfo->metric_out += mod->metric; | |
516 | else if (mod->type == metric_decrement) | |
517 | rinfo->metric_out -= mod->metric; | |
518 | else if (mod->type == metric_absolute) | |
519 | rinfo->metric_out = mod->metric; | |
520 | ||
521 | if (rinfo->metric_out < 1) | |
522 | rinfo->metric_out = 1; | |
523 | if (rinfo->metric_out > RIP_METRIC_INFINITY) | |
524 | rinfo->metric_out = RIP_METRIC_INFINITY; | |
525 | ||
718e3744 | 526 | rinfo->metric_set = 1; |
527 | } | |
528 | return RMAP_OKAY; | |
529 | } | |
530 | ||
531 | /* set metric compilation. */ | |
532 | void * | |
533 | route_set_metric_compile (char *arg) | |
534 | { | |
16705130 | 535 | int len; |
536 | char *pnt; | |
537 | int type; | |
538 | long metric; | |
539 | char *endptr = NULL; | |
540 | struct rip_metric_modifier *mod; | |
718e3744 | 541 | |
16705130 | 542 | len = strlen (arg); |
543 | pnt = arg; | |
718e3744 | 544 | |
16705130 | 545 | if (len == 0) |
546 | return NULL; | |
718e3744 | 547 | |
16705130 | 548 | /* Examine first character. */ |
549 | if (arg[0] == '+') | |
550 | { | |
551 | type = metric_increment; | |
552 | pnt++; | |
553 | } | |
554 | else if (arg[0] == '-') | |
555 | { | |
556 | type = metric_decrement; | |
557 | pnt++; | |
558 | } | |
559 | else | |
560 | type = metric_absolute; | |
718e3744 | 561 | |
16705130 | 562 | /* Check beginning with digit string. */ |
563 | if (*pnt < '0' || *pnt > '9') | |
564 | return NULL; | |
565 | ||
566 | /* Convert string to integer. */ | |
567 | metric = strtol (pnt, &endptr, 10); | |
568 | ||
569 | if (metric == LONG_MAX || *endptr != '\0') | |
570 | return NULL; | |
571 | if (metric < 0 || metric > RIP_METRIC_INFINITY) | |
572 | return NULL; | |
573 | ||
574 | mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, | |
575 | sizeof (struct rip_metric_modifier)); | |
576 | mod->type = type; | |
577 | mod->metric = metric; | |
578 | ||
579 | return mod; | |
718e3744 | 580 | } |
581 | ||
582 | /* Free route map's compiled `set metric' value. */ | |
583 | void | |
584 | route_set_metric_free (void *rule) | |
585 | { | |
586 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
587 | } | |
588 | ||
589 | /* Set metric rule structure. */ | |
590 | struct route_map_rule_cmd route_set_metric_cmd = | |
591 | { | |
592 | "metric", | |
593 | route_set_metric, | |
594 | route_set_metric_compile, | |
595 | route_set_metric_free, | |
596 | }; | |
597 | ||
598 | /* `set ip next-hop IP_ADDRESS' */ | |
599 | ||
600 | /* Set nexthop to object. ojbect must be pointer to struct attr. */ | |
601 | route_map_result_t | |
602 | route_set_ip_nexthop (void *rule, struct prefix *prefix, | |
603 | route_map_object_t type, void *object) | |
604 | { | |
605 | struct in_addr *address; | |
606 | struct rip_info *rinfo; | |
607 | ||
608 | if(type == RMAP_RIP) | |
609 | { | |
610 | /* Fetch routemap's rule information. */ | |
611 | address = rule; | |
612 | rinfo = object; | |
613 | ||
614 | /* Set next hop value. */ | |
615 | rinfo->nexthop_out = *address; | |
616 | } | |
617 | ||
618 | return RMAP_OKAY; | |
619 | } | |
620 | ||
621 | /* Route map `ip nexthop' compile function. Given string is converted | |
622 | to struct in_addr structure. */ | |
623 | void * | |
624 | route_set_ip_nexthop_compile (char *arg) | |
625 | { | |
626 | int ret; | |
627 | struct in_addr *address; | |
628 | ||
629 | address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr)); | |
630 | ||
631 | ret = inet_aton (arg, address); | |
632 | ||
633 | if (ret == 0) | |
634 | { | |
635 | XFREE (MTYPE_ROUTE_MAP_COMPILED, address); | |
636 | return NULL; | |
637 | } | |
638 | ||
639 | return address; | |
640 | } | |
641 | ||
642 | /* Free route map's compiled `ip nexthop' value. */ | |
643 | void | |
644 | route_set_ip_nexthop_free (void *rule) | |
645 | { | |
646 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
647 | } | |
648 | ||
649 | /* Route map commands for ip nexthop set. */ | |
650 | struct route_map_rule_cmd route_set_ip_nexthop_cmd = | |
651 | { | |
652 | "ip next-hop", | |
653 | route_set_ip_nexthop, | |
654 | route_set_ip_nexthop_compile, | |
655 | route_set_ip_nexthop_free | |
656 | }; | |
16705130 | 657 | |
658 | /* `set tag TAG' */ | |
659 | ||
660 | /* Set tag to object. ojbect must be pointer to struct attr. */ | |
661 | route_map_result_t | |
662 | route_set_tag (void *rule, struct prefix *prefix, | |
663 | route_map_object_t type, void *object) | |
664 | { | |
665 | u_short *tag; | |
666 | struct rip_info *rinfo; | |
667 | ||
668 | if(type == RMAP_RIP) | |
669 | { | |
670 | /* Fetch routemap's rule information. */ | |
671 | tag = rule; | |
672 | rinfo = object; | |
673 | ||
674 | /* Set next hop value. */ | |
675 | rinfo->tag_out = *tag; | |
676 | } | |
677 | ||
678 | return RMAP_OKAY; | |
679 | } | |
680 | ||
681 | /* Route map `tag' compile function. Given string is converted | |
682 | to u_short. */ | |
683 | void * | |
684 | route_set_tag_compile (char *arg) | |
685 | { | |
686 | u_short *tag; | |
687 | ||
688 | tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); | |
689 | *tag = atoi (arg); | |
690 | ||
691 | return tag; | |
692 | } | |
693 | ||
694 | /* Free route map's compiled `ip nexthop' value. */ | |
695 | void | |
696 | route_set_tag_free (void *rule) | |
697 | { | |
698 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
699 | } | |
700 | ||
701 | /* Route map commands for tag set. */ | |
702 | struct route_map_rule_cmd route_set_tag_cmd = | |
703 | { | |
704 | "tag", | |
705 | route_set_tag, | |
706 | route_set_tag_compile, | |
707 | route_set_tag_free | |
708 | }; | |
718e3744 | 709 | \f |
710 | #define MATCH_STR "Match values from routing table\n" | |
711 | #define SET_STR "Set values in destination routing protocol\n" | |
712 | ||
713 | DEFUN (match_metric, | |
714 | match_metric_cmd, | |
715 | "match metric <0-4294967295>", | |
716 | MATCH_STR | |
717 | "Match metric of route\n" | |
718 | "Metric value\n") | |
719 | { | |
720 | return rip_route_match_add (vty, vty->index, "metric", argv[0]); | |
721 | } | |
722 | ||
723 | DEFUN (no_match_metric, | |
724 | no_match_metric_cmd, | |
725 | "no match metric", | |
726 | NO_STR | |
727 | MATCH_STR | |
728 | "Match metric of route\n") | |
729 | { | |
730 | if (argc == 0) | |
731 | return rip_route_match_delete (vty, vty->index, "metric", NULL); | |
732 | ||
733 | return rip_route_match_delete (vty, vty->index, "metric", argv[0]); | |
734 | } | |
735 | ||
736 | ALIAS (no_match_metric, | |
737 | no_match_metric_val_cmd, | |
738 | "no match metric <0-4294967295>", | |
739 | NO_STR | |
740 | MATCH_STR | |
741 | "Match metric of route\n" | |
742 | "Metric value\n") | |
743 | ||
744 | DEFUN (match_interface, | |
745 | match_interface_cmd, | |
746 | "match interface WORD", | |
747 | MATCH_STR | |
748 | "Match first hop interface of route\n" | |
749 | "Interface name\n") | |
750 | { | |
751 | return rip_route_match_add (vty, vty->index, "interface", argv[0]); | |
752 | } | |
753 | ||
754 | DEFUN (no_match_interface, | |
755 | no_match_interface_cmd, | |
756 | "no match interface", | |
757 | NO_STR | |
758 | MATCH_STR | |
759 | "Match first hop interface of route\n") | |
760 | { | |
761 | if (argc == 0) | |
762 | return rip_route_match_delete (vty, vty->index, "interface", NULL); | |
763 | ||
764 | return rip_route_match_delete (vty, vty->index, "interface", argv[0]); | |
765 | } | |
766 | ||
767 | ALIAS (no_match_interface, | |
768 | no_match_interface_val_cmd, | |
769 | "no match interface WORD", | |
770 | NO_STR | |
771 | MATCH_STR | |
772 | "Match first hop interface of route\n" | |
773 | "Interface name\n") | |
774 | ||
775 | DEFUN (match_ip_next_hop, | |
776 | match_ip_next_hop_cmd, | |
73ffb25b | 777 | "match ip next-hop (<1-199>|<1300-2699>|WORD)", |
718e3744 | 778 | MATCH_STR |
779 | IP_STR | |
780 | "Match next-hop address of route\n" | |
73ffb25b | 781 | "IP access-list number\n" |
782 | "IP access-list number (expanded range)\n" | |
783 | "IP Access-list name\n") | |
718e3744 | 784 | { |
785 | return rip_route_match_add (vty, vty->index, "ip next-hop", argv[0]); | |
786 | } | |
787 | ||
788 | DEFUN (no_match_ip_next_hop, | |
789 | no_match_ip_next_hop_cmd, | |
790 | "no match ip next-hop", | |
791 | NO_STR | |
792 | MATCH_STR | |
793 | IP_STR | |
794 | "Match next-hop address of route\n") | |
795 | { | |
796 | if (argc == 0) | |
797 | return rip_route_match_delete (vty, vty->index, "ip next-hop", NULL); | |
798 | ||
799 | return rip_route_match_delete (vty, vty->index, "ip next-hop", argv[0]); | |
800 | } | |
801 | ||
802 | ALIAS (no_match_ip_next_hop, | |
803 | no_match_ip_next_hop_val_cmd, | |
73ffb25b | 804 | "no match ip next-hop (<1-199>|<1300-2699>|WORD)", |
718e3744 | 805 | NO_STR |
806 | MATCH_STR | |
807 | IP_STR | |
808 | "Match next-hop address of route\n" | |
73ffb25b | 809 | "IP access-list number\n" |
810 | "IP access-list number (expanded range)\n" | |
811 | "IP Access-list name\n") | |
718e3744 | 812 | |
813 | DEFUN (match_ip_next_hop_prefix_list, | |
814 | match_ip_next_hop_prefix_list_cmd, | |
815 | "match ip next-hop prefix-list WORD", | |
816 | MATCH_STR | |
817 | IP_STR | |
818 | "Match next-hop address of route\n" | |
819 | "Match entries of prefix-lists\n" | |
820 | "IP prefix-list name\n") | |
821 | { | |
822 | return rip_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]); | |
823 | } | |
824 | ||
825 | DEFUN (no_match_ip_next_hop_prefix_list, | |
826 | no_match_ip_next_hop_prefix_list_cmd, | |
827 | "no match ip next-hop prefix-list", | |
828 | NO_STR | |
829 | MATCH_STR | |
830 | IP_STR | |
831 | "Match next-hop address of route\n" | |
832 | "Match entries of prefix-lists\n") | |
833 | { | |
834 | if (argc == 0) | |
835 | return rip_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL); | |
836 | ||
837 | return rip_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]); | |
838 | } | |
839 | ||
840 | ALIAS (no_match_ip_next_hop_prefix_list, | |
841 | no_match_ip_next_hop_prefix_list_val_cmd, | |
842 | "no match ip next-hop prefix-list WORD", | |
843 | NO_STR | |
844 | MATCH_STR | |
845 | IP_STR | |
846 | "Match next-hop address of route\n" | |
847 | "Match entries of prefix-lists\n" | |
848 | "IP prefix-list name\n") | |
849 | ||
73ffb25b | 850 | DEFUN (match_ip_address, |
718e3744 | 851 | match_ip_address_cmd, |
73ffb25b | 852 | "match ip address (<1-199>|<1300-2699>|WORD)", |
718e3744 | 853 | MATCH_STR |
854 | IP_STR | |
855 | "Match address of route\n" | |
73ffb25b | 856 | "IP access-list number\n" |
857 | "IP access-list number (expanded range)\n" | |
858 | "IP Access-list name\n") | |
859 | ||
718e3744 | 860 | { |
861 | return rip_route_match_add (vty, vty->index, "ip address", argv[0]); | |
862 | } | |
863 | ||
864 | DEFUN (no_match_ip_address, | |
865 | no_match_ip_address_cmd, | |
866 | "no match ip address", | |
867 | NO_STR | |
868 | MATCH_STR | |
869 | IP_STR | |
870 | "Match address of route\n") | |
871 | { | |
872 | if (argc == 0) | |
873 | return rip_route_match_delete (vty, vty->index, "ip address", NULL); | |
874 | ||
875 | return rip_route_match_delete (vty, vty->index, "ip address", argv[0]); | |
876 | } | |
877 | ||
73ffb25b | 878 | ALIAS (no_match_ip_address, |
718e3744 | 879 | no_match_ip_address_val_cmd, |
73ffb25b | 880 | "no match ip address (<1-199>|<1300-2699>|WORD)", |
718e3744 | 881 | NO_STR |
882 | MATCH_STR | |
883 | IP_STR | |
884 | "Match address of route\n" | |
73ffb25b | 885 | "IP access-list number\n" |
886 | "IP access-list number (expanded range)\n" | |
887 | "IP Access-list name\n") | |
718e3744 | 888 | |
889 | DEFUN (match_ip_address_prefix_list, | |
890 | match_ip_address_prefix_list_cmd, | |
891 | "match ip address prefix-list WORD", | |
892 | MATCH_STR | |
893 | IP_STR | |
894 | "Match address of route\n" | |
895 | "Match entries of prefix-lists\n" | |
896 | "IP prefix-list name\n") | |
897 | { | |
898 | return rip_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]); | |
899 | } | |
900 | ||
901 | DEFUN (no_match_ip_address_prefix_list, | |
902 | no_match_ip_address_prefix_list_cmd, | |
903 | "no match ip address prefix-list", | |
904 | NO_STR | |
905 | MATCH_STR | |
906 | IP_STR | |
907 | "Match address of route\n" | |
908 | "Match entries of prefix-lists\n") | |
909 | { | |
910 | if (argc == 0) | |
911 | return rip_route_match_delete (vty, vty->index, "ip address prefix-list", NULL); | |
912 | ||
913 | return rip_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]); | |
914 | } | |
915 | ||
916 | ALIAS (no_match_ip_address_prefix_list, | |
917 | no_match_ip_address_prefix_list_val_cmd, | |
918 | "no match ip address prefix-list WORD", | |
919 | NO_STR | |
920 | MATCH_STR | |
921 | IP_STR | |
922 | "Match address of route\n" | |
923 | "Match entries of prefix-lists\n" | |
924 | "IP prefix-list name\n") | |
925 | ||
16705130 | 926 | DEFUN (match_tag, |
927 | match_tag_cmd, | |
928 | "match tag <0-65535>", | |
929 | MATCH_STR | |
930 | "Match tag of route\n" | |
931 | "Metric value\n") | |
932 | { | |
933 | return rip_route_match_add (vty, vty->index, "tag", argv[0]); | |
934 | } | |
935 | ||
936 | DEFUN (no_match_tag, | |
937 | no_match_tag_cmd, | |
938 | "no match tag", | |
939 | NO_STR | |
940 | MATCH_STR | |
941 | "Match tag of route\n") | |
942 | { | |
943 | if (argc == 0) | |
944 | return rip_route_match_delete (vty, vty->index, "tag", NULL); | |
945 | ||
946 | return rip_route_match_delete (vty, vty->index, "tag", argv[0]); | |
947 | } | |
948 | ||
949 | ALIAS (no_match_tag, | |
950 | no_match_tag_val_cmd, | |
951 | "no match tag <0-65535>", | |
952 | NO_STR | |
953 | MATCH_STR | |
954 | "Match tag of route\n" | |
955 | "Metric value\n") | |
956 | ||
718e3744 | 957 | /* set functions */ |
958 | ||
959 | DEFUN (set_metric, | |
960 | set_metric_cmd, | |
dd55f9eb | 961 | "set metric <0-4294967295>", |
718e3744 | 962 | SET_STR |
963 | "Metric value for destination routing protocol\n" | |
dd55f9eb | 964 | "Metric value\n") |
718e3744 | 965 | { |
966 | return rip_route_set_add (vty, vty->index, "metric", argv[0]); | |
967 | } | |
968 | ||
dd55f9eb | 969 | ALIAS (set_metric, |
970 | set_metric_addsub_cmd, | |
971 | "set metric <+/-metric>", | |
972 | SET_STR | |
973 | "Metric value for destination routing protocol\n" | |
974 | "Add or subtract BGP metric\n") | |
975 | ||
718e3744 | 976 | DEFUN (no_set_metric, |
977 | no_set_metric_cmd, | |
978 | "no set metric", | |
979 | NO_STR | |
980 | SET_STR | |
981 | "Metric value for destination routing protocol\n") | |
982 | { | |
983 | if (argc == 0) | |
984 | return rip_route_set_delete (vty, vty->index, "metric", NULL); | |
985 | ||
986 | return rip_route_set_delete (vty, vty->index, "metric", argv[0]); | |
987 | } | |
988 | ||
989 | ALIAS (no_set_metric, | |
990 | no_set_metric_val_cmd, | |
16705130 | 991 | "no set metric (<0-4294967295>|<+/-metric>)", |
718e3744 | 992 | NO_STR |
993 | SET_STR | |
994 | "Metric value for destination routing protocol\n" | |
16705130 | 995 | "Metric value\n" |
996 | "Add or subtract metric\n") | |
718e3744 | 997 | |
998 | DEFUN (set_ip_nexthop, | |
999 | set_ip_nexthop_cmd, | |
1000 | "set ip next-hop A.B.C.D", | |
1001 | SET_STR | |
1002 | IP_STR | |
1003 | "Next hop address\n" | |
1004 | "IP address of next hop\n") | |
1005 | { | |
1006 | union sockunion su; | |
1007 | int ret; | |
1008 | ||
1009 | ret = str2sockunion (argv[0], &su); | |
1010 | if (ret < 0) | |
1011 | { | |
1012 | vty_out (vty, "%% Malformed next-hop address%s", VTY_NEWLINE); | |
1013 | return CMD_WARNING; | |
1014 | } | |
1015 | ||
1016 | return rip_route_set_add (vty, vty->index, "ip next-hop", argv[0]); | |
1017 | } | |
1018 | ||
1019 | DEFUN (no_set_ip_nexthop, | |
1020 | no_set_ip_nexthop_cmd, | |
1021 | "no set ip next-hop", | |
1022 | NO_STR | |
1023 | SET_STR | |
1024 | IP_STR | |
1025 | "Next hop address\n") | |
1026 | { | |
1027 | if (argc == 0) | |
1028 | return rip_route_set_delete (vty, vty->index, "ip next-hop", NULL); | |
1029 | ||
1030 | return rip_route_set_delete (vty, vty->index, "ip next-hop", argv[0]); | |
1031 | } | |
1032 | ||
1033 | ALIAS (no_set_ip_nexthop, | |
1034 | no_set_ip_nexthop_val_cmd, | |
1035 | "no set ip next-hop A.B.C.D", | |
1036 | NO_STR | |
1037 | SET_STR | |
1038 | IP_STR | |
1039 | "Next hop address\n" | |
1040 | "IP address of next hop\n") | |
1041 | ||
16705130 | 1042 | DEFUN (set_tag, |
1043 | set_tag_cmd, | |
1044 | "set tag <0-65535>", | |
1045 | SET_STR | |
1046 | "Tag value for routing protocol\n" | |
1047 | "Tag value\n") | |
1048 | { | |
1049 | return rip_route_set_add (vty, vty->index, "tag", argv[0]); | |
1050 | } | |
1051 | ||
1052 | DEFUN (no_set_tag, | |
1053 | no_set_tag_cmd, | |
1054 | "no set tag", | |
1055 | NO_STR | |
1056 | SET_STR | |
1057 | "Tag value for routing protocol\n") | |
1058 | { | |
1059 | if (argc == 0) | |
1060 | return rip_route_set_delete (vty, vty->index, "tag", NULL); | |
1061 | ||
1062 | return rip_route_set_delete (vty, vty->index, "tag", argv[0]); | |
1063 | } | |
1064 | ||
1065 | ALIAS (no_set_tag, | |
1066 | no_set_tag_val_cmd, | |
1067 | "no set tag <0-65535>", | |
1068 | NO_STR | |
1069 | SET_STR | |
1070 | "Tag value for routing protocol\n" | |
1071 | "Tag value\n") | |
1072 | ||
718e3744 | 1073 | void |
1074 | rip_route_map_reset () | |
1075 | { | |
1076 | ; | |
1077 | } | |
1078 | ||
1079 | /* Route-map init */ | |
1080 | void | |
1081 | rip_route_map_init () | |
1082 | { | |
1083 | route_map_init (); | |
1084 | route_map_init_vty (); | |
1085 | route_map_add_hook (rip_route_map_update); | |
1086 | route_map_delete_hook (rip_route_map_update); | |
1087 | ||
1088 | route_map_install_match (&route_match_metric_cmd); | |
1089 | route_map_install_match (&route_match_interface_cmd); | |
1090 | route_map_install_match (&route_match_ip_next_hop_cmd); | |
1091 | route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd); | |
1092 | route_map_install_match (&route_match_ip_address_cmd); | |
1093 | route_map_install_match (&route_match_ip_address_prefix_list_cmd); | |
16705130 | 1094 | route_map_install_match (&route_match_tag_cmd); |
718e3744 | 1095 | |
1096 | route_map_install_set (&route_set_metric_cmd); | |
1097 | route_map_install_set (&route_set_ip_nexthop_cmd); | |
16705130 | 1098 | route_map_install_set (&route_set_tag_cmd); |
718e3744 | 1099 | |
1100 | install_element (RMAP_NODE, &match_metric_cmd); | |
1101 | install_element (RMAP_NODE, &no_match_metric_cmd); | |
1102 | install_element (RMAP_NODE, &no_match_metric_val_cmd); | |
1103 | install_element (RMAP_NODE, &match_interface_cmd); | |
1104 | install_element (RMAP_NODE, &no_match_interface_cmd); | |
1105 | install_element (RMAP_NODE, &no_match_interface_val_cmd); | |
1106 | install_element (RMAP_NODE, &match_ip_next_hop_cmd); | |
1107 | install_element (RMAP_NODE, &no_match_ip_next_hop_cmd); | |
1108 | install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd); | |
1109 | install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd); | |
1110 | install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd); | |
1111 | install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd); | |
1112 | install_element (RMAP_NODE, &match_ip_address_cmd); | |
1113 | install_element (RMAP_NODE, &no_match_ip_address_cmd); | |
1114 | install_element (RMAP_NODE, &no_match_ip_address_val_cmd); | |
1115 | install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd); | |
1116 | install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd); | |
1117 | install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd); | |
16705130 | 1118 | install_element (RMAP_NODE, &match_tag_cmd); |
1119 | install_element (RMAP_NODE, &no_match_tag_cmd); | |
1120 | install_element (RMAP_NODE, &no_match_tag_val_cmd); | |
718e3744 | 1121 | |
1122 | install_element (RMAP_NODE, &set_metric_cmd); | |
dd55f9eb | 1123 | install_element (RMAP_NODE, &set_metric_addsub_cmd); |
718e3744 | 1124 | install_element (RMAP_NODE, &no_set_metric_cmd); |
1125 | install_element (RMAP_NODE, &no_set_metric_val_cmd); | |
1126 | install_element (RMAP_NODE, &set_ip_nexthop_cmd); | |
1127 | install_element (RMAP_NODE, &no_set_ip_nexthop_cmd); | |
1128 | install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd); | |
16705130 | 1129 | install_element (RMAP_NODE, &set_tag_cmd); |
1130 | install_element (RMAP_NODE, &no_set_tag_cmd); | |
1131 | install_element (RMAP_NODE, &no_set_tag_val_cmd); | |
718e3744 | 1132 | } |