]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_routemap.c
*: use an ifindex_t type, defined in lib/if.h, for ifindex values
[mirror_frr.git] / zebra / zebra_routemap.c
1 /* zebra routemap.
2 * Copyright (C) 2006 IBM Corporation
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 "rib.h"
27 #include "routemap.h"
28 #include "command.h"
29 #include "filter.h"
30 #include "plist.h"
31 #include "nexthop.h"
32 #include "vrf.h"
33
34 #include "zebra/zserv.h"
35 #include "zebra/redistribute.h"
36 #include "zebra/debug.h"
37 #include "zebra/zebra_rnh.h"
38 #include "zebra/zebra_routemap.h"
39
40 static u_int32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER;
41 static struct thread *zebra_t_rmap_update = NULL;
42 char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1]; /* "any" == ZEBRA_ROUTE_MAX */
43 /* NH Tracking route map */
44 char *nht_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1]; /* "any" == ZEBRA_ROUTE_MAX */
45 char *zebra_import_table_routemap[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX];
46
47 struct nh_rmap_obj
48 {
49 struct nexthop *nexthop;
50 vrf_id_t vrf_id;
51 u_int32_t source_protocol;
52 int metric;
53 u_short tag;
54 };
55
56 static void zebra_route_map_set_delay_timer(u_int32_t value);
57
58 /* Add zebra route map rule */
59 static int
60 zebra_route_match_add(struct vty *vty, struct route_map_index *index,
61 const char *command, const char *arg,
62 route_map_event_t type)
63 {
64 int ret;
65
66 ret = route_map_add_match (index, command, arg);
67 if (ret)
68 {
69 switch (ret)
70 {
71 case RMAP_RULE_MISSING:
72 vty_out (vty, "%% Zebra Can't find rule.%s", VTY_NEWLINE);
73 return CMD_WARNING;
74 case RMAP_COMPILE_ERROR:
75 vty_out (vty, "%% Zebra Argument is malformed.%s", VTY_NEWLINE);
76 return CMD_WARNING;
77 }
78 }
79
80 if (type != RMAP_EVENT_MATCH_ADDED)
81 {
82 route_map_upd8_dependency (type, arg, index->map->name);
83 }
84 return CMD_SUCCESS;
85 }
86
87 /* Delete zebra route map rule. */
88 static int
89 zebra_route_match_delete (struct vty *vty, struct route_map_index *index,
90 const char *command, const char *arg,
91 route_map_event_t type)
92 {
93 int ret;
94 char *dep_name = NULL;
95 const char *tmpstr;
96 char *rmap_name = NULL;
97
98 if (type != RMAP_EVENT_MATCH_DELETED)
99 {
100 /* ignore the mundane, the types without any dependency */
101 if (arg == NULL)
102 {
103 if ((tmpstr = route_map_get_match_arg(index, command)) != NULL)
104 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
105 }
106 else
107 {
108 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg);
109 }
110 rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
111 }
112
113 ret = route_map_delete_match (index, command, arg);
114 if (ret)
115 {
116 switch (ret)
117 {
118 case RMAP_RULE_MISSING:
119 vty_out (vty, "%% Zebra Can't find rule.%s", VTY_NEWLINE);
120 return CMD_WARNING;
121 case RMAP_COMPILE_ERROR:
122 vty_out (vty, "%% Zebra Argument is malformed.%s", VTY_NEWLINE);
123 return CMD_WARNING;
124 }
125 }
126
127 if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
128 route_map_upd8_dependency(type, dep_name, rmap_name);
129
130 if (dep_name)
131 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
132 if (rmap_name)
133 XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
134
135 return CMD_SUCCESS;
136 }
137
138 /* Add zebra route map rule. */
139 static int
140 zebra_route_set_add (struct vty *vty, struct route_map_index *index,
141 const char *command, const char *arg)
142 {
143 int ret;
144
145 ret = route_map_add_set (index, command, arg);
146 if (ret)
147 {
148 switch (ret)
149 {
150 case RMAP_RULE_MISSING:
151 vty_out (vty, "%% Zebra Can't find rule.%s", VTY_NEWLINE);
152 return CMD_WARNING;
153 case RMAP_COMPILE_ERROR:
154 vty_out (vty, "%% Zebra Argument is malformed.%s", VTY_NEWLINE);
155 return CMD_WARNING;
156 }
157 }
158 return CMD_SUCCESS;
159 }
160
161 /* Delete zebra route map rule. */
162 static int
163 zebra_route_set_delete (struct vty *vty, struct route_map_index *index,
164 const char *command, const char *arg)
165 {
166 int ret;
167
168 ret = route_map_delete_set (index, command, arg);
169 if (ret)
170 {
171 switch (ret)
172 {
173 case RMAP_RULE_MISSING:
174 vty_out (vty, "%% Zebra Can't find rule.%s", VTY_NEWLINE);
175 return CMD_WARNING;
176 case RMAP_COMPILE_ERROR:
177 vty_out (vty, "%% Zebra Argument is malformed.%s", VTY_NEWLINE);
178 return CMD_WARNING;
179 }
180 }
181 return CMD_SUCCESS;
182 }
183
184 /* 'match tag TAG'
185 * Match function return 1 if match is success else return 0
186 */
187 static route_map_result_t
188 route_match_tag (void *rule, struct prefix *prefix,
189 route_map_object_t type, void *object)
190 {
191 u_short *tag;
192 struct nh_rmap_obj *nh_data;
193
194 if (type == RMAP_ZEBRA)
195 {
196 tag = rule;
197 nh_data = object;
198
199 if (nh_data->tag == *tag)
200 return RMAP_MATCH;
201 }
202 return RMAP_NOMATCH;
203 }
204
205 /* Route map 'match tag' match statement. 'arg' is TAG value */
206 static void *
207 route_match_tag_compile (const char *arg)
208 {
209 u_short *tag;
210 u_short tmp;
211
212 /* tag value shoud be integer. */
213 if (! all_digit (arg))
214 return NULL;
215
216 tmp = atoi(arg);
217 if (tmp < 1)
218 return NULL;
219
220 tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
221
222 if (!tag)
223 return tag;
224
225 *tag = tmp;
226
227 return tag;
228 }
229
230 /* Free route map's compiled 'match tag' value. */
231 static void
232 route_match_tag_free (void *rule)
233 {
234 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
235 }
236
237 /* Route map commands for tag matching */
238 struct route_map_rule_cmd route_match_tag_cmd =
239 {
240 "tag",
241 route_match_tag,
242 route_match_tag_compile,
243 route_match_tag_free
244 };
245
246
247 /* `match interface IFNAME' */
248 /* Match function return 1 if match is success else return zero. */
249 static route_map_result_t
250 route_match_interface (void *rule, struct prefix *prefix,
251 route_map_object_t type, void *object)
252 {
253 struct nh_rmap_obj *nh_data;
254 char *ifname = rule;
255 ifindex_t ifindex;
256
257 if (type == RMAP_ZEBRA)
258 {
259 if (strcasecmp(ifname, "any") == 0)
260 return RMAP_MATCH;
261 nh_data = object;
262 if (!nh_data || !nh_data->nexthop)
263 return RMAP_NOMATCH;
264 ifindex = ifname2ifindex_vrf (ifname, nh_data->vrf_id);
265 if (ifindex == 0)
266 return RMAP_NOMATCH;
267 if (nh_data->nexthop->ifindex == ifindex)
268 return RMAP_MATCH;
269 }
270 return RMAP_NOMATCH;
271 }
272
273 /* Route map `match interface' match statement. `arg' is IFNAME value */
274 static void *
275 route_match_interface_compile (const char *arg)
276 {
277 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
278 }
279
280 /* Free route map's compiled `match interface' value. */
281 static void
282 route_match_interface_free (void *rule)
283 {
284 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
285 }
286
287 /* Route map commands for interface matching */
288 struct route_map_rule_cmd route_match_interface_cmd =
289 {
290 "interface",
291 route_match_interface,
292 route_match_interface_compile,
293 route_match_interface_free
294 };
295
296 DEFUN (match_interface,
297 match_interface_cmd,
298 "match interface WORD",
299 MATCH_STR
300 "match first hop interface of route\n"
301 "Interface name\n")
302 {
303 return zebra_route_match_add (vty, vty->index, "interface", argv[0],
304 RMAP_EVENT_MATCH_ADDED);
305 }
306
307 DEFUN (no_match_interface,
308 no_match_interface_cmd,
309 "no match interface",
310 NO_STR
311 MATCH_STR
312 "Match first hop interface of route\n")
313 {
314 if (argc == 0)
315 return zebra_route_match_delete (vty, vty->index, "interface", NULL, RMAP_EVENT_MATCH_DELETED);
316
317 return zebra_route_match_delete (vty, vty->index, "interface", argv[0], RMAP_EVENT_MATCH_DELETED);
318 }
319
320 ALIAS (no_match_interface,
321 no_match_interface_val_cmd,
322 "no match interface WORD",
323 NO_STR
324 MATCH_STR
325 "Match first hop interface of route\n"
326 "Interface name\n")
327
328 DEFUN (match_tag,
329 match_tag_cmd,
330 "match tag <1-65535>",
331 MATCH_STR
332 "Match tag of route\n"
333 "Tag value\n")
334 {
335 return zebra_route_match_add (vty, vty->index, "tag", argv[0],
336 RMAP_EVENT_MATCH_ADDED);
337 }
338
339 DEFUN (no_match_tag,
340 no_match_tag_cmd,
341 "no match tag",
342 NO_STR
343 MATCH_STR
344 "Match tag of route\n")
345 {
346 if (argc == 0)
347 return zebra_route_match_delete (vty, vty->index, "tag", NULL,
348 RMAP_EVENT_MATCH_DELETED);
349
350 return zebra_route_match_delete (vty, vty->index, "tag", argv[0],
351 RMAP_EVENT_MATCH_DELETED);
352 }
353
354 ALIAS (no_match_tag,
355 no_match_tag_val_cmd,
356 "no match tag <1-65535>",
357 NO_STR
358 MATCH_STR
359 "Match tag of route\n")
360
361 DEFUN (match_ip_next_hop,
362 match_ip_next_hop_cmd,
363 "match ip next-hop (<1-199>|<1300-2699>|WORD)",
364 MATCH_STR
365 IP_STR
366 "Match next-hop address of route\n"
367 "IP access-list number\n"
368 "IP access-list number (expanded range)\n"
369 "IP Access-list name\n")
370 {
371 return zebra_route_match_add (vty, vty->index, "ip next-hop", argv[0], RMAP_EVENT_FILTER_ADDED);
372 }
373
374 DEFUN (no_match_ip_next_hop,
375 no_match_ip_next_hop_cmd,
376 "no match ip next-hop",
377 NO_STR
378 MATCH_STR
379 IP_STR
380 "Match next-hop address of route\n")
381 {
382 if (argc == 0)
383 return zebra_route_match_delete (vty, vty->index, "ip next-hop", NULL,
384 RMAP_EVENT_FILTER_DELETED);
385
386 return zebra_route_match_delete (vty, vty->index, "ip next-hop", argv[0],
387 RMAP_EVENT_FILTER_DELETED);
388 }
389
390 ALIAS (no_match_ip_next_hop,
391 no_match_ip_next_hop_val_cmd,
392 "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
393 NO_STR
394 MATCH_STR
395 IP_STR
396 "Match next-hop address of route\n"
397 "IP access-list number\n"
398 "IP access-list number (expanded range)\n"
399 "IP Access-list name\n")
400
401 DEFUN (match_ip_next_hop_prefix_list,
402 match_ip_next_hop_prefix_list_cmd,
403 "match ip next-hop prefix-list WORD",
404 MATCH_STR
405 IP_STR
406 "Match next-hop address of route\n"
407 "Match entries of prefix-lists\n"
408 "IP prefix-list name\n")
409 {
410 return zebra_route_match_add (vty, vty->index, "ip next-hop prefix-list",
411 argv[0], RMAP_EVENT_PLIST_ADDED);
412 }
413
414 DEFUN (no_match_ip_next_hop_prefix_list,
415 no_match_ip_next_hop_prefix_list_cmd,
416 "no match ip next-hop prefix-list",
417 NO_STR
418 MATCH_STR
419 IP_STR
420 "Match next-hop address of route\n"
421 "Match entries of prefix-lists\n")
422 {
423 if (argc == 0)
424 return zebra_route_match_delete (vty, vty->index,
425 "ip next-hop prefix-list", NULL,
426 RMAP_EVENT_PLIST_DELETED);
427
428 return zebra_route_match_delete (vty, vty->index,
429 "ip next-hop prefix-list", argv[0],
430 RMAP_EVENT_PLIST_DELETED);
431 }
432
433 ALIAS (no_match_ip_next_hop_prefix_list,
434 no_match_ip_next_hop_prefix_list_val_cmd,
435 "no match ip next-hop prefix-list WORD",
436 NO_STR
437 MATCH_STR
438 IP_STR
439 "Match next-hop address of route\n"
440 "Match entries of prefix-lists\n"
441 "IP prefix-list name\n")
442
443 DEFUN (match_ip_address,
444 match_ip_address_cmd,
445 "match ip address (<1-199>|<1300-2699>|WORD)",
446 MATCH_STR
447 IP_STR
448 "Match address of route\n"
449 "IP access-list number\n"
450 "IP access-list number (expanded range)\n"
451 "IP Access-list name\n")
452
453 {
454 return zebra_route_match_add (vty, vty->index, "ip address", argv[0],
455 RMAP_EVENT_FILTER_ADDED);
456 }
457
458 DEFUN (no_match_ip_address,
459 no_match_ip_address_cmd,
460 "no match ip address",
461 NO_STR
462 MATCH_STR
463 IP_STR
464 "Match address of route\n")
465 {
466 if (argc == 0)
467 return zebra_route_match_delete (vty, vty->index, "ip address", NULL,
468 RMAP_EVENT_FILTER_DELETED);
469
470 return zebra_route_match_delete (vty, vty->index, "ip address", argv[0],
471 RMAP_EVENT_FILTER_DELETED);
472 }
473
474 ALIAS (no_match_ip_address,
475 no_match_ip_address_val_cmd,
476 "no match ip address (<1-199>|<1300-2699>|WORD)",
477 NO_STR
478 MATCH_STR
479 IP_STR
480 "Match address of route\n"
481 "IP access-list number\n"
482 "IP access-list number (expanded range)\n"
483 "IP Access-list name\n")
484
485 DEFUN (match_ip_address_prefix_list,
486 match_ip_address_prefix_list_cmd,
487 "match ip address prefix-list WORD",
488 MATCH_STR
489 IP_STR
490 "Match address of route\n"
491 "Match entries of prefix-lists\n"
492 "IP prefix-list name\n")
493 {
494 return zebra_route_match_add (vty, vty->index, "ip address prefix-list",
495 argv[0], RMAP_EVENT_PLIST_ADDED);
496 }
497
498 DEFUN (no_match_ip_address_prefix_list,
499 no_match_ip_address_prefix_list_cmd,
500 "no match ip address prefix-list",
501 NO_STR
502 MATCH_STR
503 IP_STR
504 "Match address of route\n"
505 "Match entries of prefix-lists\n")
506 {
507 if (argc == 0)
508 return zebra_route_match_delete (vty, vty->index,
509 "ip address prefix-list", NULL,
510 RMAP_EVENT_PLIST_DELETED);
511
512 return zebra_route_match_delete (vty, vty->index,
513 "ip address prefix-list", argv[0],
514 RMAP_EVENT_PLIST_DELETED);
515 }
516
517 ALIAS (no_match_ip_address_prefix_list,
518 no_match_ip_address_prefix_list_val_cmd,
519 "no match ip address prefix-list WORD",
520 NO_STR
521 MATCH_STR
522 IP_STR
523 "Match address of route\n"
524 "Match entries of prefix-lists\n"
525 "IP prefix-list name\n")
526
527 DEFUN (match_ip_address_prefix_len,
528 match_ip_address_prefix_len_cmd,
529 "match ip address prefix-len NUMBER",
530 MATCH_STR
531 IP_STR
532 "Match prefix length of ip address\n"
533 "Match prefix length of ip address\n"
534 "Prefix length\n")
535 {
536 return zebra_route_match_add (vty, vty->index, "ip address prefix-len",
537 argv[0], RMAP_EVENT_MATCH_ADDED);
538 }
539
540 DEFUN (no_match_ip_address_prefix_len,
541 no_match_ip_address_prefix_len_cmd,
542 "no match ip address prefix-len",
543 NO_STR
544 MATCH_STR
545 IP_STR
546 "Match prefixlen of ip address of route\n"
547 "prefix length of ip address\n")
548 {
549 if (argc == 0)
550 return zebra_route_match_delete (vty, vty->index,
551 "ip address prefix-len", NULL,
552 RMAP_EVENT_MATCH_DELETED);
553
554 return zebra_route_match_delete (vty, vty->index,
555 "ip address prefix-len", argv[0],
556 RMAP_EVENT_MATCH_DELETED);
557 }
558
559 ALIAS (no_match_ip_address_prefix_len,
560 no_match_ip_address_prefix_len_val_cmd,
561 "no match ip address prefix-len NUMBER",
562 NO_STR
563 MATCH_STR
564 IP_STR
565 "Match prefixlen of ip address of route\n"
566 "prefix length of ip address\n")
567
568 DEFUN (match_ip_nexthop_prefix_len,
569 match_ip_nexthop_prefix_len_cmd,
570 "match ip next-hop prefix-len NUMBER",
571 MATCH_STR
572 IP_STR
573 "Match prefixlen of nexthop ip address\n"
574 "Match prefixlen of given nexthop\n"
575 "Prefix length\n")
576 {
577 return zebra_route_match_add (vty, vty->index, "ip next-hop prefix-len",
578 argv[0], RMAP_EVENT_MATCH_ADDED);
579 }
580
581 DEFUN (no_match_ip_nexthop_prefix_len,
582 no_match_ip_nexthop_prefix_len_cmd,
583 "no match ip next-hop prefix-len",
584 NO_STR
585 MATCH_STR
586 IP_STR
587 "Match prefixlen of nexthop ip address\n"
588 "Match prefix length of nexthop\n")
589 {
590 if (argc == 0)
591 return zebra_route_match_delete (vty, vty->index,
592 "ip next-hop prefix-len", NULL,
593 RMAP_EVENT_MATCH_DELETED);
594
595 return zebra_route_match_delete (vty, vty->index,
596 "ip next-hop prefix-len", argv[0],
597 RMAP_EVENT_MATCH_DELETED);
598 }
599
600 ALIAS (no_match_ip_nexthop_prefix_len,
601 no_match_ip_nexthop_prefix_len_val_cmd,
602 "no match ip next-hop prefix-len NUMBER",
603 MATCH_STR
604 "Match prefixlen of ip address of route\n"
605 "prefix length of ip address\n")
606
607 DEFUN (match_source_protocol,
608 match_source_protocol_cmd,
609 "match source-protocol (bgp|ospf|rip|ripng|isis|ospf6|connected|system|kernel|static)",
610 MATCH_STR
611 "Match protocol via which the route was learnt\n")
612 {
613 int i;
614
615 i = proto_name2num(argv[0]);
616 if (i < 0)
617 {
618 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
619 VTY_NEWLINE);
620 return CMD_WARNING;
621 }
622 return zebra_route_match_add (vty, vty->index, "source-protocol",
623 argv[0], RMAP_EVENT_MATCH_ADDED);
624 }
625
626 DEFUN (no_match_source_protocol,
627 no_match_source_protocol_cmd,
628 "no match source-protocol (bgp|ospf|rip|ripng|isis|ospf6|connected|system|kernel|static)",
629 NO_STR
630 MATCH_STR
631 "No match protocol via which the route was learnt\n")
632 {
633 int i;
634
635 if (argc >= 1)
636 {
637 i = proto_name2num(argv[0]);
638 if (i < 0)
639 {
640 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
641 VTY_NEWLINE);
642 return CMD_WARNING;
643 }
644 }
645 return zebra_route_match_delete (vty, vty->index,
646 "source-protocol", argv[0] ? argv[0] : NULL,
647 RMAP_EVENT_MATCH_DELETED);
648 }
649
650 /* set functions */
651
652 DEFUN (set_src,
653 set_src_cmd,
654 "set src (A.B.C.D|X:X::X:X)",
655 SET_STR
656 "src address for route\n"
657 "src address\n")
658 {
659 union g_addr src;
660 struct interface *pif = NULL;
661 int family;
662 struct prefix p;
663 vrf_iter_t iter;
664
665 if (inet_pton(AF_INET, argv[0], &src.ipv4) != 1)
666 {
667 if (inet_pton(AF_INET6, argv[0], &src.ipv6) != 1)
668 {
669 vty_out (vty, "%% not a valid IPv4/v6 address%s", VTY_NEWLINE);
670 return CMD_WARNING;
671 }
672
673 p.family = family = AF_INET6;
674 p.u.prefix6 = src.ipv6;
675 p.prefixlen = IPV6_MAX_BITLEN;
676 }
677 else
678 {
679 p.family = family = AF_INET;
680 p.u.prefix4 = src.ipv4;
681 p.prefixlen = IPV4_MAX_BITLEN;
682 }
683
684 if (!zebra_check_addr(&p))
685 {
686 vty_out (vty, "%% not a valid source IPv4/v6 address%s", VTY_NEWLINE);
687 return CMD_WARNING;
688 }
689
690 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
691 {
692 if (family == AF_INET)
693 pif = if_lookup_exact_address_vrf ((void *)&src.ipv4, AF_INET,
694 vrf_iter2id (iter));
695 else if (family == AF_INET6)
696 pif = if_lookup_exact_address_vrf ((void *)&src.ipv6, AF_INET6,
697 vrf_iter2id (iter));
698
699 if (pif != NULL)
700 break;
701 }
702
703 if (!pif)
704 {
705 vty_out (vty, "%% not a local address%s", VTY_NEWLINE);
706 return CMD_WARNING;
707 }
708 return zebra_route_set_add (vty, vty->index, "src", argv[0]);
709 }
710
711 DEFUN (no_set_src,
712 no_set_src_cmd,
713 "no set src {A.B.C.D|X:X::X:X}",
714 NO_STR
715 SET_STR
716 "Source address for route\n")
717 {
718 if (argc == 0)
719 return zebra_route_set_delete (vty, vty->index, "src", NULL);
720
721 return zebra_route_set_delete (vty, vty->index, "src", argv[0]);
722 }
723
724 DEFUN (zebra_route_map_timer,
725 zebra_route_map_timer_cmd,
726 "zebra route-map delay-timer <0-600>",
727 "Time to wait before route-map updates are processed\n"
728 "0 means event-driven updates are disabled\n")
729 {
730 u_int32_t rmap_delay_timer;
731
732 VTY_GET_INTEGER_RANGE ("delay-timer", rmap_delay_timer, argv[0], 0, 600);
733 zebra_route_map_set_delay_timer(rmap_delay_timer);
734
735 return (CMD_SUCCESS);
736 }
737
738 DEFUN (no_zebra_route_map_timer,
739 no_zebra_route_map_timer_cmd,
740 "no zebra route-map delay-timer",
741 NO_STR
742 "Time to wait before route-map updates are processed\n"
743 "Reset delay-timer to default value, 30 secs\n")
744 {
745 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER);
746
747 return (CMD_SUCCESS);
748 }
749
750 ALIAS (no_zebra_route_map_timer,
751 no_zebra_route_map_timer_val_cmd,
752 "no zebra route-map delay-timer <0-600>",
753 NO_STR
754 "Time to wait before route-map updates are processed\n"
755 "Reset delay-timer to default value, 30 secs\n"
756 "0 means event-driven updates are disabled\n")
757
758 DEFUN (ip_protocol,
759 ip_protocol_cmd,
760 "ip protocol " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
761 IP_STR
762 "Filter routing info exchanged between zebra and protocol\n"
763 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
764 "Route map name\n")
765 {
766 int i;
767
768 if (strcasecmp(argv[0], "any") == 0)
769 i = ZEBRA_ROUTE_MAX;
770 else
771 i = proto_name2num(argv[0]);
772 if (i < 0)
773 {
774 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
775 VTY_NEWLINE);
776 return CMD_WARNING;
777 }
778 if (proto_rm[AFI_IP][i])
779 {
780 if (strcmp(proto_rm[AFI_IP][i], argv[1]) == 0)
781 return CMD_SUCCESS;
782
783 XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
784 }
785 proto_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
786
787 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
788 zlog_debug ("%u: IPv4 Routemap config for protocol %s, scheduling RIB processing",
789 VRF_DEFAULT, argv[0]);
790
791 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
792 return CMD_SUCCESS;
793 }
794
795 DEFUN (no_ip_protocol,
796 no_ip_protocol_cmd,
797 "no ip protocol " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA,
798 NO_STR
799 IP_STR
800 "Stop filtering routing info between zebra and protocol\n"
801 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
802 "Protocol from which to stop filtering routes\n")
803 {
804 int i;
805
806 if (strcasecmp(argv[0], "any") == 0)
807 i = ZEBRA_ROUTE_MAX;
808 else
809 i = proto_name2num(argv[0]);
810 if (i < 0)
811 {
812 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
813 VTY_NEWLINE);
814 return CMD_WARNING;
815 }
816 if (!proto_rm[AFI_IP][i])
817 return CMD_SUCCESS;
818
819 if ((argc == 2 && strcmp(argv[1], proto_rm[AFI_IP][i]) == 0) ||
820 (argc < 2))
821 {
822 XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
823 proto_rm[AFI_IP][i] = NULL;
824
825 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
826 zlog_debug ("%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing",
827 VRF_DEFAULT, argv[0]);
828 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
829 }
830 return CMD_SUCCESS;
831 }
832
833 ALIAS (no_ip_protocol,
834 no_ip_protocol_val_cmd,
835 "no ip protocol " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
836 NO_STR
837 IP_STR
838 "Stop filtering routing info between zebra and protocol\n"
839 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
840 "route map name")
841
842 DEFUN (show_ip_protocol,
843 show_ip_protocol_cmd,
844 "show ip protocol",
845 SHOW_STR
846 IP_STR
847 "IP protocol filtering status\n")
848 {
849 int i;
850
851 vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
852 vty_out(vty, "------------------------%s", VTY_NEWLINE);
853 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
854 {
855 if (proto_rm[AFI_IP][i])
856 vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
857 proto_rm[AFI_IP][i],
858 VTY_NEWLINE);
859 else
860 vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
861 }
862 if (proto_rm[AFI_IP][i])
863 vty_out (vty, "%-10s : %-10s%s", "any", proto_rm[AFI_IP][i],
864 VTY_NEWLINE);
865 else
866 vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
867
868 return CMD_SUCCESS;
869 }
870
871 DEFUN (ipv6_protocol,
872 ipv6_protocol_cmd,
873 "ipv6 protocol " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
874 IP6_STR
875 "Filter IPv6 routing info exchanged between zebra and protocol\n"
876 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
877 "Route map name\n")
878 {
879 int i;
880
881 if (strcasecmp(argv[0], "any") == 0)
882 i = ZEBRA_ROUTE_MAX;
883 else
884 i = proto_name2num(argv[0]);
885 if (i < 0)
886 {
887 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
888 VTY_NEWLINE);
889 return CMD_WARNING;
890 }
891 if (proto_rm[AFI_IP6][i])
892 {
893 if (strcmp(proto_rm[AFI_IP6][i], argv[1]) == 0)
894 return CMD_SUCCESS;
895
896 XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
897 }
898 proto_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
899
900 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
901 zlog_debug ("%u: IPv6 Routemap config for protocol %s, scheduling RIB processing",
902 VRF_DEFAULT, argv[0]);
903
904 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
905 return CMD_SUCCESS;
906 }
907
908 DEFUN (no_ipv6_protocol,
909 no_ipv6_protocol_cmd,
910 "no ipv6 protocol " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA,
911 NO_STR
912 IP6_STR
913 "Stop filtering IPv6 routing info between zebra and protocol\n"
914 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
915 "Protocol from which to stop filtering routes\n")
916 {
917 int i;
918
919 if (strcasecmp(argv[0], "any") == 0)
920 i = ZEBRA_ROUTE_MAX;
921 else
922 i = proto_name2num(argv[0]);
923 if (i < 0)
924 {
925 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
926 VTY_NEWLINE);
927 return CMD_WARNING;
928 }
929 if (!proto_rm[AFI_IP6][i])
930 return CMD_SUCCESS;
931
932 if ((argc == 2 && strcmp(argv[1], proto_rm[AFI_IP6][i]) == 0) ||
933 (argc < 2))
934 {
935 XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
936 proto_rm[AFI_IP6][i] = NULL;
937
938 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
939 zlog_debug ("%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing",
940 VRF_DEFAULT, argv[0]);
941
942 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
943 }
944 return CMD_SUCCESS;
945 }
946
947 ALIAS (no_ipv6_protocol,
948 no_ipv6_protocol_val_cmd,
949 "no ipv6 protocol " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
950 NO_STR
951 IP6_STR
952 "Stop filtering IPv6 routing info between zebra and protocol\n"
953 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
954 "route map name")
955
956 DEFUN (show_ipv6_protocol,
957 show_ipv6_protocol_cmd,
958 "show ipv6 protocol",
959 SHOW_STR
960 IP6_STR
961 "IPv6 protocol filtering status\n")
962 {
963 int i;
964
965 vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
966 vty_out(vty, "------------------------%s", VTY_NEWLINE);
967 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
968 {
969 if (proto_rm[AFI_IP6][i])
970 vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
971 proto_rm[AFI_IP6][i],
972 VTY_NEWLINE);
973 else
974 vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
975 }
976 if (proto_rm[AFI_IP6][i])
977 vty_out (vty, "%-10s : %-10s%s", "any", proto_rm[AFI_IP6][i],
978 VTY_NEWLINE);
979 else
980 vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
981
982 return CMD_SUCCESS;
983 }
984
985 DEFUN (ip_protocol_nht_rmap,
986 ip_protocol_nht_rmap_cmd,
987 "ip nht " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
988 IP_STR
989 "Filter Next Hop tracking route resolution\n"
990 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
991 "Route map name\n")
992 {
993 int i;
994
995 if (strcasecmp(argv[0], "any") == 0)
996 i = ZEBRA_ROUTE_MAX;
997 else
998 i = proto_name2num(argv[0]);
999 if (i < 0)
1000 {
1001 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
1002 VTY_NEWLINE);
1003 return CMD_WARNING;
1004 }
1005 if (nht_rm[AFI_IP][i])
1006 {
1007 if (strcmp(nht_rm[AFI_IP][i], argv[1]) == 0)
1008 return CMD_SUCCESS;
1009
1010 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]);
1011 }
1012
1013 nht_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
1014 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1015
1016 return CMD_SUCCESS;
1017 }
1018
1019 DEFUN (no_ip_protocol_nht_rmap,
1020 no_ip_protocol_nht_rmap_cmd,
1021 "no ip nht " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA,
1022 NO_STR
1023 IP_STR
1024 "Filter Next Hop tracking route resolution\n"
1025 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA)
1026 {
1027 int i;
1028
1029 if (strcasecmp(argv[0], "any") == 0)
1030 i = ZEBRA_ROUTE_MAX;
1031 else
1032 i = proto_name2num(argv[0]);
1033 if (i < 0)
1034 {
1035 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
1036 VTY_NEWLINE);
1037 return CMD_WARNING;
1038 }
1039 if (!nht_rm[AFI_IP][i])
1040 return CMD_SUCCESS;
1041
1042 if ((argc == 2 && strcmp(argv[1], nht_rm[AFI_IP][i]) == 0) ||
1043 (argc < 2))
1044 {
1045 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]);
1046 nht_rm[AFI_IP][i] = NULL;
1047 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1048 }
1049 return CMD_SUCCESS;
1050 }
1051
1052 ALIAS (no_ip_protocol_nht_rmap,
1053 no_ip_protocol_nht_rmap_val_cmd,
1054 "no ip nht " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
1055 IP_STR
1056 "Filter Next Hop tracking route resolution\n"
1057 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
1058 "Route map name\n")
1059
1060 DEFUN (show_ip_protocol_nht,
1061 show_ip_protocol_nht_cmd,
1062 "show ip nht route-map",
1063 SHOW_STR
1064 IP_STR
1065 "IP Next Hop tracking filtering status\n")
1066 {
1067 int i;
1068
1069 vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
1070 vty_out(vty, "------------------------%s", VTY_NEWLINE);
1071 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
1072 {
1073 if (nht_rm[AFI_IP][i])
1074 vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
1075 nht_rm[AFI_IP][i],
1076 VTY_NEWLINE);
1077 else
1078 vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
1079 }
1080 if (nht_rm[AFI_IP][i])
1081 vty_out (vty, "%-10s : %-10s%s", "any", nht_rm[AFI_IP][i],
1082 VTY_NEWLINE);
1083 else
1084 vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
1085
1086 return CMD_SUCCESS;
1087 }
1088
1089 DEFUN (ipv6_protocol_nht_rmap,
1090 ipv6_protocol_nht_rmap_cmd,
1091 "ipv6 nht " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
1092 IP6_STR
1093 "Filter Next Hop tracking route resolution\n"
1094 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
1095 "Route map name\n")
1096 {
1097 int i;
1098
1099 if (strcasecmp(argv[0], "any") == 0)
1100 i = ZEBRA_ROUTE_MAX;
1101 else
1102 i = proto_name2num(argv[0]);
1103 if (i < 0)
1104 {
1105 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
1106 VTY_NEWLINE);
1107 return CMD_WARNING;
1108 }
1109 if (nht_rm[AFI_IP6][i])
1110 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]);
1111 nht_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
1112 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1113
1114 return CMD_SUCCESS;
1115 }
1116
1117 DEFUN (no_ipv6_protocol_nht_rmap,
1118 no_ipv6_protocol_nht_rmap_cmd,
1119 "no ipv6 nht " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA,
1120 NO_STR
1121 IP6_STR
1122 "Filter Next Hop tracking route resolution\n"
1123 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA)
1124 {
1125 int i;
1126
1127 if (strcasecmp(argv[0], "any") == 0)
1128 i = ZEBRA_ROUTE_MAX;
1129 else
1130 i = proto_name2num(argv[0]);
1131 if (i < 0)
1132 {
1133 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
1134 VTY_NEWLINE);
1135 return CMD_WARNING;
1136 }
1137
1138 if (nht_rm[AFI_IP6][i] && argc == 2 && strcmp(argv[1], nht_rm[AFI_IP6][i]))
1139 {
1140 vty_out (vty, "invalid route-map \"%s\"%s", argv[1], VTY_NEWLINE);
1141 return CMD_WARNING;
1142 }
1143
1144 if (nht_rm[AFI_IP6][i])
1145 {
1146 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]);
1147 nht_rm[AFI_IP6][i] = NULL;
1148 }
1149
1150 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1151
1152 return CMD_SUCCESS;
1153 }
1154
1155 ALIAS (no_ipv6_protocol_nht_rmap,
1156 no_ipv6_protocol_nht_rmap_val_cmd,
1157 "no ipv6 nht " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
1158 NO_STR
1159 IP6_STR
1160 "Filter Next Hop tracking route resolution\n"
1161 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
1162 "Route map name\n")
1163
1164 DEFUN (show_ipv6_protocol_nht,
1165 show_ipv6_protocol_nht_cmd,
1166 "show ipv6 nht route-map",
1167 SHOW_STR
1168 IP6_STR
1169 "IPv6 protocol Next Hop filtering status\n")
1170 {
1171 int i;
1172
1173 vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
1174 vty_out(vty, "------------------------%s", VTY_NEWLINE);
1175 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
1176 {
1177 if (nht_rm[AFI_IP6][i])
1178 vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
1179 nht_rm[AFI_IP6][i],
1180 VTY_NEWLINE);
1181 else
1182 vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
1183 }
1184 if (nht_rm[AFI_IP][i])
1185 vty_out (vty, "%-10s : %-10s%s", "any", nht_rm[AFI_IP6][i],
1186 VTY_NEWLINE);
1187 else
1188 vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
1189
1190 return CMD_SUCCESS;
1191 }
1192
1193 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1194
1195 /* `match ip next-hop IP_ACCESS_LIST' */
1196
1197 /* Match function return 1 if match is success else return zero. */
1198 static route_map_result_t
1199 route_match_ip_next_hop (void *rule, struct prefix *prefix,
1200 route_map_object_t type, void *object)
1201 {
1202 struct access_list *alist;
1203 struct nh_rmap_obj *nh_data;
1204 struct prefix_ipv4 p;
1205
1206 if (type == RMAP_ZEBRA)
1207 {
1208 nh_data = object;
1209 if (!nh_data)
1210 return RMAP_DENYMATCH;
1211
1212 switch (nh_data->nexthop->type) {
1213 case NEXTHOP_TYPE_IFINDEX:
1214 /* Interface routes can't match ip next-hop */
1215 return RMAP_NOMATCH;
1216 case NEXTHOP_TYPE_IPV4_IFINDEX:
1217 case NEXTHOP_TYPE_IPV4:
1218 p.family = AF_INET;
1219 p.prefix = nh_data->nexthop->gate.ipv4;
1220 p.prefixlen = IPV4_MAX_BITLEN;
1221 break;
1222 default:
1223 return RMAP_NOMATCH;
1224 }
1225 alist = access_list_lookup (AFI_IP, (char *) rule);
1226 if (alist == NULL)
1227 return RMAP_NOMATCH;
1228
1229 return (access_list_apply (alist, &p) == FILTER_DENY ?
1230 RMAP_NOMATCH : RMAP_MATCH);
1231 }
1232 return RMAP_NOMATCH;
1233 }
1234
1235 /* Route map `ip next-hop' match statement. `arg' should be
1236 access-list name. */
1237 static void *
1238 route_match_ip_next_hop_compile (const char *arg)
1239 {
1240 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1241 }
1242
1243 /* Free route map's compiled `. */
1244 static void
1245 route_match_ip_next_hop_free (void *rule)
1246 {
1247 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1248 }
1249
1250 /* Route map commands for ip next-hop matching. */
1251 static struct route_map_rule_cmd route_match_ip_next_hop_cmd =
1252 {
1253 "ip next-hop",
1254 route_match_ip_next_hop,
1255 route_match_ip_next_hop_compile,
1256 route_match_ip_next_hop_free
1257 };
1258
1259 /* `match ip next-hop prefix-list PREFIX_LIST' */
1260
1261 static route_map_result_t
1262 route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
1263 route_map_object_t type, void *object)
1264 {
1265 struct prefix_list *plist;
1266 struct nh_rmap_obj *nh_data;
1267 struct prefix_ipv4 p;
1268
1269 if (type == RMAP_ZEBRA)
1270 {
1271 nh_data = (struct nh_rmap_obj *)object;
1272 if (!nh_data)
1273 return RMAP_DENYMATCH;
1274
1275 switch (nh_data->nexthop->type) {
1276 case NEXTHOP_TYPE_IFINDEX:
1277 /* Interface routes can't match ip next-hop */
1278 return RMAP_NOMATCH;
1279 case NEXTHOP_TYPE_IPV4_IFINDEX:
1280 case NEXTHOP_TYPE_IPV4:
1281 p.family = AF_INET;
1282 p.prefix = nh_data->nexthop->gate.ipv4;
1283 p.prefixlen = IPV4_MAX_BITLEN;
1284 break;
1285 default:
1286 return RMAP_NOMATCH;
1287 }
1288 plist = prefix_list_lookup (AFI_IP, (char *) rule);
1289 if (plist == NULL)
1290 return RMAP_NOMATCH;
1291
1292 return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
1293 RMAP_NOMATCH : RMAP_MATCH);
1294 }
1295 return RMAP_NOMATCH;
1296 }
1297
1298 static void *
1299 route_match_ip_next_hop_prefix_list_compile (const char *arg)
1300 {
1301 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1302 }
1303
1304 static void
1305 route_match_ip_next_hop_prefix_list_free (void *rule)
1306 {
1307 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1308 }
1309
1310 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
1311 {
1312 "ip next-hop prefix-list",
1313 route_match_ip_next_hop_prefix_list,
1314 route_match_ip_next_hop_prefix_list_compile,
1315 route_match_ip_next_hop_prefix_list_free
1316 };
1317
1318 /* `match ip address IP_ACCESS_LIST' */
1319
1320 /* Match function should return 1 if match is success else return
1321 zero. */
1322 static route_map_result_t
1323 route_match_ip_address (void *rule, struct prefix *prefix,
1324 route_map_object_t type, void *object)
1325 {
1326 struct access_list *alist;
1327
1328 if (type == RMAP_ZEBRA)
1329 {
1330 alist = access_list_lookup (AFI_IP, (char *) rule);
1331 if (alist == NULL)
1332 return RMAP_NOMATCH;
1333
1334 return (access_list_apply (alist, prefix) == FILTER_DENY ?
1335 RMAP_NOMATCH : RMAP_MATCH);
1336 }
1337 return RMAP_NOMATCH;
1338 }
1339
1340 /* Route map `ip address' match statement. `arg' should be
1341 access-list name. */
1342 static void *
1343 route_match_ip_address_compile (const char *arg)
1344 {
1345 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1346 }
1347
1348 /* Free route map's compiled `ip address' value. */
1349 static void
1350 route_match_ip_address_free (void *rule)
1351 {
1352 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1353 }
1354
1355 /* Route map commands for ip address matching. */
1356 static struct route_map_rule_cmd route_match_ip_address_cmd =
1357 {
1358 "ip address",
1359 route_match_ip_address,
1360 route_match_ip_address_compile,
1361 route_match_ip_address_free
1362 };
1363
1364 /* `match ip address prefix-list PREFIX_LIST' */
1365
1366 static route_map_result_t
1367 route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
1368 route_map_object_t type, void *object)
1369 {
1370 struct prefix_list *plist;
1371
1372 if (type == RMAP_ZEBRA)
1373 {
1374 plist = prefix_list_lookup (AFI_IP, (char *) rule);
1375 if (plist == NULL)
1376 return RMAP_NOMATCH;
1377
1378 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
1379 RMAP_NOMATCH : RMAP_MATCH);
1380 }
1381 return RMAP_NOMATCH;
1382 }
1383
1384 static void *
1385 route_match_ip_address_prefix_list_compile (const char *arg)
1386 {
1387 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1388 }
1389
1390 static void
1391 route_match_ip_address_prefix_list_free (void *rule)
1392 {
1393 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1394 }
1395
1396 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
1397 {
1398 "ip address prefix-list",
1399 route_match_ip_address_prefix_list,
1400 route_match_ip_address_prefix_list_compile,
1401 route_match_ip_address_prefix_list_free
1402 };
1403
1404
1405 /* `match ip address prefix-len PREFIXLEN' */
1406
1407 static route_map_result_t
1408 route_match_ip_address_prefix_len (void *rule, struct prefix *prefix,
1409 route_map_object_t type, void *object)
1410 {
1411 u_int32_t *prefixlen = (u_int32_t *)rule;
1412
1413 if (type == RMAP_ZEBRA)
1414 {
1415 return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
1416 }
1417 return RMAP_NOMATCH;
1418 }
1419
1420 static void *
1421 route_match_ip_address_prefix_len_compile (const char *arg)
1422 {
1423 u_int32_t *prefix_len;
1424 char *endptr = NULL;
1425 unsigned long tmpval;
1426
1427 /* prefix len value shoud be integer. */
1428 if (! all_digit (arg))
1429 return NULL;
1430
1431 errno = 0;
1432 tmpval = strtoul (arg, &endptr, 10);
1433 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1434 return NULL;
1435
1436 prefix_len = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
1437
1438 if (!prefix_len)
1439 return prefix_len;
1440
1441 *prefix_len = tmpval;
1442 return prefix_len;
1443 }
1444
1445 static void
1446 route_match_ip_address_prefix_len_free (void *rule)
1447 {
1448 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1449 }
1450
1451 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd =
1452 {
1453 "ip address prefix-len",
1454 route_match_ip_address_prefix_len,
1455 route_match_ip_address_prefix_len_compile,
1456 route_match_ip_address_prefix_len_free
1457 };
1458
1459
1460 /* `match ip nexthop prefix-len PREFIXLEN' */
1461
1462 static route_map_result_t
1463 route_match_ip_nexthop_prefix_len (void *rule, struct prefix *prefix,
1464 route_map_object_t type, void *object)
1465 {
1466 u_int32_t *prefixlen = (u_int32_t *)rule;
1467 struct nh_rmap_obj *nh_data;
1468 struct prefix_ipv4 p;
1469
1470 if (type == RMAP_ZEBRA)
1471 {
1472 nh_data = (struct nh_rmap_obj *)object;
1473 if (!nh_data || !nh_data->nexthop)
1474 return RMAP_DENYMATCH;
1475
1476 switch (nh_data->nexthop->type) {
1477 case NEXTHOP_TYPE_IFINDEX:
1478 /* Interface routes can't match ip next-hop */
1479 return RMAP_NOMATCH;
1480 case NEXTHOP_TYPE_IPV4_IFINDEX:
1481 case NEXTHOP_TYPE_IPV4:
1482 p.family = AF_INET;
1483 p.prefix = nh_data->nexthop->gate.ipv4;
1484 p.prefixlen = IPV4_MAX_BITLEN;
1485 break;
1486 default:
1487 return RMAP_NOMATCH;
1488 }
1489 return ((p.prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
1490 }
1491 return RMAP_NOMATCH;
1492 }
1493
1494 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd =
1495 {
1496 "ip next-hop prefix-len",
1497 route_match_ip_nexthop_prefix_len,
1498 route_match_ip_address_prefix_len_compile, /* reuse */
1499 route_match_ip_address_prefix_len_free /* reuse */
1500 };
1501
1502 /* `match source-protocol PROTOCOL' */
1503
1504 static route_map_result_t
1505 route_match_source_protocol (void *rule, struct prefix *prefix,
1506 route_map_object_t type, void *object)
1507 {
1508 u_int32_t *rib_type = (u_int32_t *)rule;
1509 struct nh_rmap_obj *nh_data;
1510
1511 if (type == RMAP_ZEBRA)
1512 {
1513 nh_data = (struct nh_rmap_obj *)object;
1514 if (!nh_data)
1515 return RMAP_DENYMATCH;
1516
1517 return ((nh_data->source_protocol == *rib_type)
1518 ? RMAP_MATCH : RMAP_NOMATCH);
1519 }
1520 return RMAP_NOMATCH;
1521 }
1522
1523 static void *
1524 route_match_source_protocol_compile (const char *arg)
1525 {
1526 u_int32_t *rib_type;
1527 int i;
1528
1529 i = proto_name2num(arg);
1530 rib_type = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
1531
1532 *rib_type = i;
1533
1534 return rib_type;
1535 }
1536
1537 static void
1538 route_match_source_protocol_free (void *rule)
1539 {
1540 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1541 }
1542
1543 static struct route_map_rule_cmd route_match_source_protocol_cmd =
1544 {
1545 "source-protocol",
1546 route_match_source_protocol,
1547 route_match_source_protocol_compile,
1548 route_match_source_protocol_free
1549 };
1550
1551 /* `set src A.B.C.D' */
1552
1553 /* Set src. */
1554 static route_map_result_t
1555 route_set_src (void *rule, struct prefix *prefix,
1556 route_map_object_t type, void *object)
1557 {
1558 struct nh_rmap_obj *nh_data;
1559
1560 if (type == RMAP_ZEBRA)
1561 {
1562 nh_data = (struct nh_rmap_obj *)object;
1563 nh_data->nexthop->rmap_src = *(union g_addr *)rule;
1564 }
1565 return RMAP_OKAY;
1566 }
1567
1568 /* set src compilation. */
1569 static void *
1570 route_set_src_compile (const char *arg)
1571 {
1572 union g_addr src, *psrc;
1573
1574 if (
1575 #ifdef HAVE_IPV6
1576 (inet_pton(AF_INET6, arg, &src.ipv6) == 1) ||
1577 #endif /* HAVE_IPV6 */
1578 (src.ipv4.s_addr && (inet_pton(AF_INET, arg, &src.ipv4) == 1)))
1579 {
1580 psrc = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union g_addr));
1581 *psrc = src;
1582 return psrc;
1583 }
1584 return NULL;
1585 }
1586
1587 /* Free route map's compiled `set src' value. */
1588 static void
1589 route_set_src_free (void *rule)
1590 {
1591 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1592 }
1593
1594 /* Set src rule structure. */
1595 static struct route_map_rule_cmd route_set_src_cmd =
1596 {
1597 "src",
1598 route_set_src,
1599 route_set_src_compile,
1600 route_set_src_free,
1601 };
1602
1603 static int
1604 zebra_route_map_update_timer (struct thread *thread)
1605 {
1606 zebra_t_rmap_update = NULL;
1607
1608 if (IS_ZEBRA_DEBUG_EVENT)
1609 zlog_debug("Event driven route-map update triggered");
1610
1611 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1612 zlog_debug ("%u: Routemap update-timer fired, scheduling RIB processing",
1613 VRF_DEFAULT);
1614
1615 zebra_import_table_rm_update ();
1616 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
1617 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1618 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1619
1620 return (0);
1621 }
1622
1623 static void
1624 zebra_route_map_set_delay_timer(u_int32_t value)
1625 {
1626 zebra_rmap_update_timer = value;
1627 if (!value && zebra_t_rmap_update)
1628 {
1629 /* Event driven route map updates is being disabled */
1630 /* But there's a pending timer. Fire it off now */
1631 thread_cancel(zebra_t_rmap_update);
1632 zebra_route_map_update_timer(zebra_t_rmap_update);
1633 }
1634 }
1635
1636 void
1637 zebra_route_map_write_delay_timer (struct vty *vty)
1638 {
1639 if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER))
1640 vty_out (vty, "zebra route-map delay-timer %d%s", zebra_rmap_update_timer,
1641 VTY_NEWLINE);
1642 return;
1643 }
1644
1645 route_map_result_t
1646 zebra_route_map_check (int family, int rib_type, struct prefix *p,
1647 struct nexthop *nexthop, vrf_id_t vrf_id, u_short tag)
1648 {
1649 struct route_map *rmap = NULL;
1650 route_map_result_t ret = RMAP_MATCH;
1651 struct nh_rmap_obj nh_obj;
1652
1653 nh_obj.nexthop = nexthop;
1654 nh_obj.vrf_id = vrf_id;
1655 nh_obj.source_protocol = rib_type;
1656 nh_obj.metric = 0;
1657 nh_obj.tag = tag;
1658
1659 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
1660 rmap = route_map_lookup_by_name (proto_rm[family][rib_type]);
1661 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1662 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1663 if (rmap) {
1664 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1665 }
1666
1667 return (ret);
1668 }
1669
1670 char *
1671 zebra_get_import_table_route_map (afi_t afi, uint32_t table)
1672 {
1673 return zebra_import_table_routemap[afi][table];
1674 }
1675
1676 void
1677 zebra_add_import_table_route_map (afi_t afi, const char *rmap_name, uint32_t table)
1678 {
1679 zebra_import_table_routemap[afi][table] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap_name);
1680 }
1681
1682 void
1683 zebra_del_import_table_route_map (afi_t afi, uint32_t table)
1684 {
1685 XFREE (MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
1686 }
1687
1688 route_map_result_t
1689 zebra_import_table_route_map_check (int family, int rib_type, struct prefix *p,
1690 struct nexthop *nexthop, vrf_id_t vrf_id, u_short tag, const char *rmap_name)
1691 {
1692 struct route_map *rmap = NULL;
1693 route_map_result_t ret = RMAP_DENYMATCH;
1694 struct nh_rmap_obj nh_obj;
1695
1696 nh_obj.nexthop = nexthop;
1697 nh_obj.vrf_id = vrf_id;
1698 nh_obj.source_protocol = rib_type;
1699 nh_obj.metric = 0;
1700 nh_obj.tag = tag;
1701
1702 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
1703 rmap = route_map_lookup_by_name (rmap_name);
1704 if (rmap) {
1705 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1706 }
1707
1708 return (ret);
1709 }
1710
1711 route_map_result_t
1712 zebra_nht_route_map_check (int family, int client_proto, struct prefix *p,
1713 struct rib * rib, struct nexthop *nexthop)
1714 {
1715 struct route_map *rmap = NULL;
1716 route_map_result_t ret = RMAP_MATCH;
1717 struct nh_rmap_obj nh_obj;
1718
1719 nh_obj.nexthop = nexthop;
1720 nh_obj.vrf_id = rib->vrf_id;
1721 nh_obj.source_protocol = rib->type;
1722 nh_obj.metric = rib->metric;
1723 nh_obj.tag = rib->tag;
1724
1725 if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
1726 rmap = route_map_lookup_by_name (nht_rm[family][client_proto]);
1727 if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX])
1728 rmap = route_map_lookup_by_name (nht_rm[family][ZEBRA_ROUTE_MAX]);
1729 if (rmap) {
1730 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1731 }
1732
1733 return (ret);
1734 }
1735
1736 static void
1737 zebra_route_map_mark_update (const char *rmap_name)
1738 {
1739 /* rmap_update_timer of 0 means don't do route updates */
1740 if (zebra_rmap_update_timer && !zebra_t_rmap_update)
1741 zebra_t_rmap_update =
1742 thread_add_timer(zebrad.master, zebra_route_map_update_timer, NULL,
1743 zebra_rmap_update_timer);
1744 }
1745
1746 static void
1747 zebra_route_map_add (const char *rmap_name)
1748 {
1749 zebra_route_map_mark_update(rmap_name);
1750 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1751 }
1752
1753 static void
1754 zebra_route_map_delete (const char *rmap_name)
1755 {
1756 zebra_route_map_mark_update(rmap_name);
1757 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
1758 }
1759
1760 static void
1761 zebra_route_map_event (route_map_event_t event, const char *rmap_name)
1762 {
1763 zebra_route_map_mark_update(rmap_name);
1764 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1765 }
1766
1767 /* ip protocol configuration write function */
1768 void
1769 zebra_routemap_config_write_protocol (struct vty *vty)
1770 {
1771 int i;
1772
1773 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
1774 {
1775 if (proto_rm[AFI_IP][i])
1776 vty_out (vty, "ip protocol %s route-map %s%s", zebra_route_string(i),
1777 proto_rm[AFI_IP][i], VTY_NEWLINE);
1778
1779 if (proto_rm[AFI_IP6][i])
1780 vty_out (vty, "ipv6 protocol %s route-map %s%s", zebra_route_string(i),
1781 proto_rm[AFI_IP6][i], VTY_NEWLINE);
1782
1783 if (nht_rm[AFI_IP][i])
1784 vty_out (vty, "ip nht %s route-map %s%s", zebra_route_string(i),
1785 nht_rm[AFI_IP][i], VTY_NEWLINE);
1786
1787 if (nht_rm[AFI_IP6][i])
1788 vty_out (vty, "ipv6 nht %s route-map %s%s", zebra_route_string(i),
1789 nht_rm[AFI_IP6][i], VTY_NEWLINE);
1790 }
1791
1792 if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1793 vty_out (vty, "ip protocol %s route-map %s%s", "any",
1794 proto_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
1795
1796 if (proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1797 vty_out (vty, "ipv6 protocol %s route-map %s%s", "any",
1798 proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
1799
1800 if (nht_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1801 vty_out (vty, "ip nht %s route-map %s%s", "any",
1802 nht_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
1803
1804 if (nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1805 vty_out (vty, "ipv6 nht %s route-map %s%s", "any",
1806 nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
1807
1808 if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
1809 vty_out (vty, "zebra route-map delay-timer %d%s", zebra_rmap_update_timer,
1810 VTY_NEWLINE);
1811 }
1812
1813 void
1814 zebra_route_map_init ()
1815 {
1816 install_element (CONFIG_NODE, &ip_protocol_cmd);
1817 install_element (CONFIG_NODE, &no_ip_protocol_cmd);
1818 install_element (CONFIG_NODE, &no_ip_protocol_val_cmd);
1819 install_element (VIEW_NODE, &show_ip_protocol_cmd);
1820 install_element (ENABLE_NODE, &show_ip_protocol_cmd);
1821 install_element (CONFIG_NODE, &ipv6_protocol_cmd);
1822 install_element (CONFIG_NODE, &no_ipv6_protocol_cmd);
1823 install_element (CONFIG_NODE, &no_ipv6_protocol_val_cmd);
1824 install_element (VIEW_NODE, &show_ipv6_protocol_cmd);
1825 install_element (ENABLE_NODE, &show_ipv6_protocol_cmd);
1826 install_element (CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
1827 install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
1828 install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_val_cmd);
1829 install_element (VIEW_NODE, &show_ip_protocol_nht_cmd);
1830 install_element (ENABLE_NODE, &show_ip_protocol_nht_cmd);
1831 install_element (CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
1832 install_element (CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1833 install_element (CONFIG_NODE, &no_ipv6_protocol_nht_rmap_val_cmd);
1834 install_element (VIEW_NODE, &show_ipv6_protocol_nht_cmd);
1835 install_element (ENABLE_NODE, &show_ipv6_protocol_nht_cmd);
1836 install_element (CONFIG_NODE, &zebra_route_map_timer_cmd);
1837 install_element (CONFIG_NODE, &no_zebra_route_map_timer_cmd);
1838 install_element (CONFIG_NODE, &no_zebra_route_map_timer_val_cmd);
1839
1840 route_map_init ();
1841 route_map_init_vty ();
1842
1843 route_map_add_hook (zebra_route_map_add);
1844 route_map_delete_hook (zebra_route_map_delete);
1845 route_map_event_hook (zebra_route_map_event);
1846
1847 route_map_install_match (&route_match_tag_cmd);
1848 route_map_install_match (&route_match_interface_cmd);
1849 route_map_install_match (&route_match_ip_next_hop_cmd);
1850 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
1851 route_map_install_match (&route_match_ip_address_cmd);
1852 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
1853 route_map_install_match (&route_match_ip_address_prefix_len_cmd);
1854 route_map_install_match (&route_match_ip_nexthop_prefix_len_cmd);
1855 route_map_install_match (&route_match_source_protocol_cmd);
1856 /* */
1857 route_map_install_set (&route_set_src_cmd);
1858 /* */
1859 install_element (RMAP_NODE, &match_tag_cmd);
1860 install_element (RMAP_NODE, &no_match_tag_cmd);
1861 install_element (RMAP_NODE, &no_match_tag_val_cmd);
1862 install_element (RMAP_NODE, &match_interface_cmd);
1863 install_element (RMAP_NODE, &no_match_interface_cmd);
1864 install_element (RMAP_NODE, &no_match_interface_val_cmd);
1865 install_element (RMAP_NODE, &match_ip_next_hop_cmd);
1866 install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
1867 install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd);
1868 install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
1869 install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
1870 install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
1871 install_element (RMAP_NODE, &match_ip_address_cmd);
1872 install_element (RMAP_NODE, &no_match_ip_address_cmd);
1873 install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
1874 install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
1875 install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
1876 install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
1877 install_element (RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
1878 install_element (RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
1879 install_element (RMAP_NODE, &no_match_ip_nexthop_prefix_len_val_cmd);
1880 install_element (RMAP_NODE, &match_ip_address_prefix_len_cmd);
1881 install_element (RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
1882 install_element (RMAP_NODE, &no_match_ip_address_prefix_len_val_cmd);
1883 install_element (RMAP_NODE, &match_source_protocol_cmd);
1884 install_element (RMAP_NODE, &no_match_source_protocol_cmd);
1885 /* */
1886 install_element (RMAP_NODE, &set_src_cmd);
1887 install_element (RMAP_NODE, &no_set_src_cmd);
1888 }