2 * Copyright (C) 2006 IBM Corporation
4 * This file is part of GNU Zebra.
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
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.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "zebra_memory.h"
35 #include "zebra/zserv.h"
36 #include "zebra/redistribute.h"
37 #include "zebra/debug.h"
38 #include "zebra/zebra_rnh.h"
39 #include "zebra/zebra_routemap.h"
41 static u_int32_t zebra_rmap_update_timer
= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
;
42 static struct thread
*zebra_t_rmap_update
= NULL
;
43 char *proto_rm
[AFI_MAX
][ZEBRA_ROUTE_MAX
+1]; /* "any" == ZEBRA_ROUTE_MAX */
44 /* NH Tracking route map */
45 char *nht_rm
[AFI_MAX
][ZEBRA_ROUTE_MAX
+1]; /* "any" == ZEBRA_ROUTE_MAX */
46 char *zebra_import_table_routemap
[AFI_MAX
][ZEBRA_KERNEL_TABLE_MAX
];
50 struct nexthop
*nexthop
;
52 u_int32_t source_protocol
;
57 static void zebra_route_map_set_delay_timer(u_int32_t value
);
61 /* Add zebra route map rule */
63 zebra_route_match_add(struct vty
*vty
,
64 const char *command
, const char *arg
,
65 route_map_event_t type
)
67 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
70 ret
= route_map_add_match (index
, command
, arg
);
75 case RMAP_RULE_MISSING
:
76 vty_out (vty
, "%% Zebra Can't find rule.\n");
78 case RMAP_COMPILE_ERROR
:
79 vty_out (vty
, "%% Zebra Argument is malformed.\n");
84 if (type
!= RMAP_EVENT_MATCH_ADDED
)
86 route_map_upd8_dependency (type
, arg
, index
->map
->name
);
91 /* Delete zebra route map rule. */
93 zebra_route_match_delete (struct vty
*vty
,
94 const char *command
, const char *arg
,
95 route_map_event_t type
)
97 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
99 char *dep_name
= NULL
;
101 char *rmap_name
= NULL
;
103 if (type
!= RMAP_EVENT_MATCH_DELETED
)
105 /* ignore the mundane, the types without any dependency */
108 if ((tmpstr
= route_map_get_match_arg(index
, command
)) != NULL
)
109 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, tmpstr
);
113 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, arg
);
115 rmap_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, index
->map
->name
);
118 ret
= route_map_delete_match (index
, command
, arg
);
123 case RMAP_RULE_MISSING
:
124 vty_out (vty
, "%% Zebra Can't find rule.\n");
126 case RMAP_COMPILE_ERROR
:
127 vty_out (vty
, "%% Zebra Argument is malformed.\n");
132 if (type
!= RMAP_EVENT_MATCH_DELETED
&& dep_name
)
133 route_map_upd8_dependency(type
, dep_name
, rmap_name
);
136 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
138 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
144 * Match function return 1 if match is success else return 0
146 static route_map_result_t
147 route_match_tag (void *rule
, struct prefix
*prefix
,
148 route_map_object_t type
, void *object
)
151 struct nh_rmap_obj
*nh_data
;
153 if (type
== RMAP_ZEBRA
)
158 if (nh_data
->tag
== *tag
)
164 /* Route map commands for tag matching */
165 static struct route_map_rule_cmd route_match_tag_cmd
=
169 route_map_rule_tag_compile
,
170 route_map_rule_tag_free
,
174 /* `match interface IFNAME' */
175 /* Match function return 1 if match is success else return zero. */
176 static route_map_result_t
177 route_match_interface (void *rule
, struct prefix
*prefix
,
178 route_map_object_t type
, void *object
)
180 struct nh_rmap_obj
*nh_data
;
184 if (type
== RMAP_ZEBRA
)
186 if (strcasecmp(ifname
, "any") == 0)
189 if (!nh_data
|| !nh_data
->nexthop
)
191 ifindex
= ifname2ifindex (ifname
, nh_data
->vrf_id
);
194 if (nh_data
->nexthop
->ifindex
== ifindex
)
200 /* Route map `match interface' match statement. `arg' is IFNAME value */
202 route_match_interface_compile (const char *arg
)
204 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
207 /* Free route map's compiled `match interface' value. */
209 route_match_interface_free (void *rule
)
211 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
214 /* Route map commands for interface matching */
215 struct route_map_rule_cmd route_match_interface_cmd
=
218 route_match_interface
,
219 route_match_interface_compile
,
220 route_match_interface_free
223 DEFUN (match_ip_address_prefix_len
,
224 match_ip_address_prefix_len_cmd
,
225 "match ip address prefix-len (0-32)",
228 "Match prefix length of ip address\n"
229 "Match prefix length of ip address\n"
232 return zebra_route_match_add (vty
, "ip address prefix-len",
233 argv
[4]->arg
, RMAP_EVENT_MATCH_ADDED
);
236 DEFUN (no_match_ip_address_prefix_len
,
237 no_match_ip_address_prefix_len_cmd
,
238 "no match ip address prefix-len [(0-32)]",
242 "Match prefix length of ip address\n"
243 "Match prefix length of ip address\n"
246 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
247 return zebra_route_match_delete (vty
,
248 "ip address prefix-len", plen
,
249 RMAP_EVENT_MATCH_DELETED
);
253 DEFUN (match_ip_nexthop_prefix_len
,
254 match_ip_nexthop_prefix_len_cmd
,
255 "match ip next-hop prefix-len (0-32)",
258 "Match prefixlen of nexthop ip address\n"
259 "Match prefixlen of given nexthop\n"
262 return zebra_route_match_add (vty
, "ip next-hop prefix-len",
263 argv
[4]->arg
, RMAP_EVENT_MATCH_ADDED
);
266 DEFUN (no_match_ip_nexthop_prefix_len
,
267 no_match_ip_nexthop_prefix_len_cmd
,
268 "no match ip next-hop prefix-len [(0-32)]",
272 "Match prefixlen of nexthop ip address\n"
273 "Match prefix length of nexthop\n"
276 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
277 return zebra_route_match_delete (vty
,
278 "ip next-hop prefix-len", plen
,
279 RMAP_EVENT_MATCH_DELETED
);
283 DEFUN (match_source_protocol
,
284 match_source_protocol_cmd
,
285 "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|connected|system|kernel|static>",
287 "Match protocol via which the route was learnt\n"
294 "Routes from directly connected peer\n"
295 "Routes from system configuration\n"
296 "Routes from kernel\n"
297 "Statically configured routes\n")
299 char *proto
= argv
[2]->text
;
302 i
= proto_name2num(proto
);
305 vty_outln (vty
, "invalid protocol name \"%s\"", proto
);
308 return zebra_route_match_add (vty
, "source-protocol", proto
, RMAP_EVENT_MATCH_ADDED
);
311 DEFUN (no_match_source_protocol
,
312 no_match_source_protocol_cmd
,
313 "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|connected|system|kernel|static>]",
316 "No match protocol via which the route was learnt\n"
323 "Routes from directly connected peer\n"
324 "Routes from system configuration\n"
325 "Routes from kernel\n"
326 "Statically configured routes\n")
328 char *proto
= (argc
== 4) ? argv
[3]->text
: NULL
;
329 return zebra_route_match_delete (vty
, "source-protocol", proto
, RMAP_EVENT_MATCH_DELETED
);
336 "set src <A.B.C.D|X:X::X:X>",
338 "src address for route\n"
340 "IPv6 src address\n")
344 struct interface
*pif
= NULL
;
349 if (inet_pton(AF_INET
, argv
[idx_ip
]->arg
, &src
.ipv4
) != 1)
351 if (inet_pton(AF_INET6
, argv
[idx_ip
]->arg
, &src
.ipv6
) != 1)
353 vty_out (vty
, "%% not a valid IPv4/v6 address\n");
357 p
.family
= family
= AF_INET6
;
358 p
.u
.prefix6
= src
.ipv6
;
359 p
.prefixlen
= IPV6_MAX_BITLEN
;
363 p
.family
= family
= AF_INET
;
364 p
.u
.prefix4
= src
.ipv4
;
365 p
.prefixlen
= IPV4_MAX_BITLEN
;
368 if (!zebra_check_addr(&p
))
370 vty_out (vty
, "%% not a valid source IPv4/v6 address\n");
374 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
376 if (family
== AF_INET
)
377 pif
= if_lookup_exact_address ((void *)&src
.ipv4
, AF_INET
,
379 else if (family
== AF_INET6
)
380 pif
= if_lookup_exact_address ((void *)&src
.ipv6
, AF_INET6
,
389 vty_out (vty
, "%% not a local address\n");
393 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
394 return generic_set_add (vty
, index
, "src", argv
[idx_ip
]->arg
);
399 "no set src [<A.B.C.D|X:X::X:X>]",
402 "Source address for route\n"
406 char *ip
= (argc
== 4) ? argv
[3]->arg
: NULL
;
407 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
408 return generic_set_delete (vty
, index
, "src", ip
);
411 DEFUN (zebra_route_map_timer
,
412 zebra_route_map_timer_cmd
,
413 "zebra route-map delay-timer (0-600)",
414 "Zebra information\n"
415 "Set route-map parameters\n"
416 "Time to wait before route-map updates are processed\n"
417 "0 means event-driven updates are disabled\n")
420 u_int32_t rmap_delay_timer
;
422 rmap_delay_timer
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
423 zebra_route_map_set_delay_timer(rmap_delay_timer
);
425 return (CMD_SUCCESS
);
428 DEFUN (no_zebra_route_map_timer
,
429 no_zebra_route_map_timer_cmd
,
430 "no zebra route-map delay-timer [(0-600)]",
432 "Zebra information\n"
433 "Set route-map parameters\n"
434 "Reset delay-timer to default value, 30 secs\n"
435 "0 means event-driven updates are disabled\n")
437 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
);
439 return (CMD_SUCCESS
);
445 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
" route-map ROUTE-MAP",
447 "Filter routing info exchanged between zebra and protocol\n"
448 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
449 "Specify route-map\n"
452 char *proto
= argv
[2]->text
;
453 char *rmap
= argv
[4]->arg
;
456 if (strcasecmp(proto
, "any") == 0)
459 i
= proto_name2num(proto
);
462 vty_outln (vty
, "invalid protocol name \"%s\"", proto
);
465 if (proto_rm
[AFI_IP
][i
])
467 if (strcmp(proto_rm
[AFI_IP
][i
], rmap
) == 0)
470 XFREE (MTYPE_ROUTE_MAP_NAME
, proto_rm
[AFI_IP
][i
]);
472 proto_rm
[AFI_IP
][i
] = XSTRDUP (MTYPE_ROUTE_MAP_NAME
, rmap
);
474 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
475 zlog_debug ("%u: IPv4 Routemap config for protocol %s, scheduling RIB processing",
478 rib_update(VRF_DEFAULT
, RIB_UPDATE_RMAP_CHANGE
);
482 DEFUN (no_ip_protocol
,
484 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
" [route-map ROUTE-MAP]",
487 "Stop filtering routing info between zebra and protocol\n"
488 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
489 "Specify route map\n"
492 char *proto
= argv
[3]->text
;
493 char *rmap
= (argc
== 6) ? argv
[5]->arg
: NULL
;
496 if (strcasecmp(proto
, "any") == 0)
499 i
= proto_name2num(proto
);
503 vty_outln (vty
, "invalid protocol name \"%s\"", proto
);
507 if (!proto_rm
[AFI_IP
][i
])
510 if (!rmap
|| strcmp (rmap
, proto_rm
[AFI_IP
][i
]) == 0)
512 XFREE (MTYPE_ROUTE_MAP_NAME
, proto_rm
[AFI_IP
][i
]);
513 proto_rm
[AFI_IP
][i
] = NULL
;
515 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
516 zlog_debug ("%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing",
518 rib_update(VRF_DEFAULT
, RIB_UPDATE_RMAP_CHANGE
);
523 DEFUN (show_ip_protocol
,
524 show_ip_protocol_cmd
,
528 "IP protocol filtering status\n")
532 vty_out (vty
, "Protocol : route-map \n");
533 vty_out (vty
, "------------------------\n");
534 for (i
=0;i
<ZEBRA_ROUTE_MAX
;i
++)
536 if (proto_rm
[AFI_IP
][i
])
537 vty_out (vty
, "%-10s : %-10s\n", zebra_route_string(i
),
538 proto_rm
[AFI_IP
][i
]);
540 vty_out (vty
, "%-10s : none\n", zebra_route_string(i
));
542 if (proto_rm
[AFI_IP
][i
])
543 vty_out (vty
, "%-10s : %-10s\n", "any",proto_rm
[AFI_IP
][i
]);
545 vty_out (vty
, "%-10s : none\n", "any");
550 DEFUN (ipv6_protocol
,
552 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
" route-map ROUTE-MAP",
554 "Filter IPv6 routing info exchanged between zebra and protocol\n"
555 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
556 "Specify route map\n"
559 char *proto
= argv
[2]->text
;
560 char *rmap
= argv
[4]->arg
;
563 if (strcasecmp(proto
, "any") == 0)
566 i
= proto_name2num(proto
);
569 vty_outln (vty
, "invalid protocol name \"%s\"", proto
);
572 if (proto_rm
[AFI_IP6
][i
])
574 if (strcmp(proto_rm
[AFI_IP6
][i
], rmap
) == 0)
577 XFREE (MTYPE_ROUTE_MAP_NAME
, proto_rm
[AFI_IP6
][i
]);
579 proto_rm
[AFI_IP6
][i
] = XSTRDUP (MTYPE_ROUTE_MAP_NAME
, rmap
);
581 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
582 zlog_debug ("%u: IPv6 Routemap config for protocol %s, scheduling RIB processing",
585 rib_update(VRF_DEFAULT
, RIB_UPDATE_RMAP_CHANGE
);
589 DEFUN (no_ipv6_protocol
,
590 no_ipv6_protocol_cmd
,
591 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
" [route-map ROUTE-MAP]",
594 "Stop filtering IPv6 routing info between zebra and protocol\n"
595 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
596 "Specify route map\n"
599 const char *proto
= argv
[3]->text
;
600 const char *rmap
= (argc
== 6) ? argv
[5]->arg
: NULL
;
603 if (strcasecmp(proto
, "any") == 0)
606 i
= proto_name2num(proto
);
609 vty_outln (vty
, "invalid protocol name \"%s\"", proto
);
612 if (!proto_rm
[AFI_IP6
][i
])
615 if (!rmap
|| strcmp(rmap
, proto_rm
[AFI_IP6
][i
]) == 0)
617 XFREE (MTYPE_ROUTE_MAP_NAME
, proto_rm
[AFI_IP6
][i
]);
618 proto_rm
[AFI_IP6
][i
] = NULL
;
620 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
621 zlog_debug ("%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing",
624 rib_update(VRF_DEFAULT
, RIB_UPDATE_RMAP_CHANGE
);
629 DEFUN (show_ipv6_protocol
,
630 show_ipv6_protocol_cmd
,
631 "show ipv6 protocol",
634 "IPv6 protocol filtering status\n")
638 vty_out (vty
, "Protocol : route-map \n");
639 vty_out (vty
, "------------------------\n");
640 for (i
=0;i
<ZEBRA_ROUTE_MAX
;i
++)
642 if (proto_rm
[AFI_IP6
][i
])
643 vty_out (vty
, "%-10s : %-10s\n", zebra_route_string(i
),
644 proto_rm
[AFI_IP6
][i
]);
646 vty_out (vty
, "%-10s : none\n", zebra_route_string(i
));
648 if (proto_rm
[AFI_IP6
][i
])
649 vty_out (vty
, "%-10s : %-10s\n", "any",proto_rm
[AFI_IP6
][i
]);
651 vty_out (vty
, "%-10s : none\n", "any");
656 DEFUN (ip_protocol_nht_rmap
,
657 ip_protocol_nht_rmap_cmd
,
658 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
" route-map ROUTE-MAP",
660 "Filter Next Hop tracking route resolution\n"
661 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
662 "Specify route map\n"
665 char *proto
= argv
[2]->text
;
666 char *rmap
= argv
[4]->arg
;
669 if (strcasecmp(proto
, "any") == 0)
672 i
= proto_name2num(proto
);
675 vty_outln (vty
, "invalid protocol name \"%s\"", proto
);
678 if (nht_rm
[AFI_IP
][i
])
680 if (strcmp(nht_rm
[AFI_IP
][i
], rmap
) == 0)
683 XFREE (MTYPE_ROUTE_MAP_NAME
, nht_rm
[AFI_IP
][i
]);
686 nht_rm
[AFI_IP
][i
] = XSTRDUP (MTYPE_ROUTE_MAP_NAME
, rmap
);
687 zebra_evaluate_rnh(0, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
692 DEFUN (no_ip_protocol_nht_rmap
,
693 no_ip_protocol_nht_rmap_cmd
,
694 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
" [route-map ROUTE-MAP]",
697 "Filter Next Hop tracking route resolution\n"
698 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
699 "Specify route map\n"
703 char *proto
= argv
[3]->text
;
704 char *rmap
= argv_find (argv
, argc
, "ROUTE-MAP", &idx
) ? argv
[idx
]->arg
: NULL
;
706 int i
= strmatch(proto
, "any") ? ZEBRA_ROUTE_MAX
: proto_name2num(proto
);
710 vty_outln (vty
, "invalid protocol name \"%s\"", proto
);
714 if (!nht_rm
[AFI_IP
][i
])
717 if (!rmap
|| strcmp(rmap
, nht_rm
[AFI_IP
][i
]) == 0)
719 XFREE (MTYPE_ROUTE_MAP_NAME
, nht_rm
[AFI_IP
][i
]);
720 nht_rm
[AFI_IP
][i
] = NULL
;
721 zebra_evaluate_rnh(0, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
726 DEFUN (show_ip_protocol_nht
,
727 show_ip_protocol_nht_cmd
,
728 "show ip nht route-map",
731 "IP nexthop tracking table\n"
732 "IP Next Hop tracking filtering status\n")
736 vty_out (vty
, "Protocol : route-map \n");
737 vty_out (vty
, "------------------------\n");
738 for (i
=0;i
<ZEBRA_ROUTE_MAX
;i
++)
740 if (nht_rm
[AFI_IP
][i
])
741 vty_out (vty
, "%-10s : %-10s\n", zebra_route_string(i
),
744 vty_out (vty
, "%-10s : none\n", zebra_route_string(i
));
746 if (nht_rm
[AFI_IP
][i
])
747 vty_out (vty
, "%-10s : %-10s\n", "any",nht_rm
[AFI_IP
][i
]);
749 vty_out (vty
, "%-10s : none\n", "any");
754 DEFUN (ipv6_protocol_nht_rmap
,
755 ipv6_protocol_nht_rmap_cmd
,
756 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
" route-map ROUTE-MAP",
758 "Filter Next Hop tracking route resolution\n"
759 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
760 "Specify route map\n"
763 char *proto
= argv
[2]->text
;
764 char *rmap
= argv
[4]->arg
;
767 if (strcasecmp(proto
, "any") == 0)
770 i
= proto_name2num(proto
);
773 vty_outln (vty
, "invalid protocol name \"%s\"", proto
);
776 if (nht_rm
[AFI_IP6
][i
])
777 XFREE (MTYPE_ROUTE_MAP_NAME
, nht_rm
[AFI_IP6
][i
]);
778 nht_rm
[AFI_IP6
][i
] = XSTRDUP (MTYPE_ROUTE_MAP_NAME
, rmap
);
779 zebra_evaluate_rnh(0, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
784 DEFUN (no_ipv6_protocol_nht_rmap
,
785 no_ipv6_protocol_nht_rmap_cmd
,
786 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
" [route-map ROUTE-MAP]",
789 "Filter Next Hop tracking route resolution\n"
790 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
791 "Specify route map\n"
794 char *proto
= argv
[3]->text
;
795 char *rmap
= (argc
== 6) ? argv
[5]->arg
: NULL
;
798 if (strcasecmp(proto
, "any") == 0)
801 i
= proto_name2num(proto
);
804 vty_outln (vty
, "invalid protocol name \"%s\"", proto
);
808 if (nht_rm
[AFI_IP6
][i
] && rmap
&& strcmp(rmap
, nht_rm
[AFI_IP6
][i
]))
810 vty_outln (vty
, "invalid route-map \"%s\"", rmap
);
814 if (nht_rm
[AFI_IP6
][i
])
816 XFREE (MTYPE_ROUTE_MAP_NAME
, nht_rm
[AFI_IP6
][i
]);
817 nht_rm
[AFI_IP6
][i
] = NULL
;
820 zebra_evaluate_rnh(0, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
825 DEFUN (show_ipv6_protocol_nht
,
826 show_ipv6_protocol_nht_cmd
,
827 "show ipv6 nht route-map",
830 "Next Hop filtering status\n"
835 vty_out (vty
, "Protocol : route-map \n");
836 vty_out (vty
, "------------------------\n");
837 for (i
=0;i
<ZEBRA_ROUTE_MAX
;i
++)
839 if (nht_rm
[AFI_IP6
][i
])
840 vty_out (vty
, "%-10s : %-10s\n", zebra_route_string(i
),
843 vty_out (vty
, "%-10s : none\n", zebra_route_string(i
));
845 if (nht_rm
[AFI_IP
][i
])
846 vty_out (vty
, "%-10s : %-10s\n", "any",nht_rm
[AFI_IP6
][i
]);
848 vty_out (vty
, "%-10s : none\n", "any");
853 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
855 /* `match ip next-hop IP_ACCESS_LIST' */
857 /* Match function return 1 if match is success else return zero. */
858 static route_map_result_t
859 route_match_ip_next_hop (void *rule
, struct prefix
*prefix
,
860 route_map_object_t type
, void *object
)
862 struct access_list
*alist
;
863 struct nh_rmap_obj
*nh_data
;
864 struct prefix_ipv4 p
;
866 if (type
== RMAP_ZEBRA
)
870 return RMAP_DENYMATCH
;
872 switch (nh_data
->nexthop
->type
) {
873 case NEXTHOP_TYPE_IFINDEX
:
874 /* Interface routes can't match ip next-hop */
876 case NEXTHOP_TYPE_IPV4_IFINDEX
:
877 case NEXTHOP_TYPE_IPV4
:
879 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
880 p
.prefixlen
= IPV4_MAX_BITLEN
;
885 alist
= access_list_lookup (AFI_IP
, (char *) rule
);
889 return (access_list_apply (alist
, &p
) == FILTER_DENY
?
890 RMAP_NOMATCH
: RMAP_MATCH
);
895 /* Route map `ip next-hop' match statement. `arg' should be
898 route_match_ip_next_hop_compile (const char *arg
)
900 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
903 /* Free route map's compiled `. */
905 route_match_ip_next_hop_free (void *rule
)
907 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
910 /* Route map commands for ip next-hop matching. */
911 static struct route_map_rule_cmd route_match_ip_next_hop_cmd
=
914 route_match_ip_next_hop
,
915 route_match_ip_next_hop_compile
,
916 route_match_ip_next_hop_free
919 /* `match ip next-hop prefix-list PREFIX_LIST' */
921 static route_map_result_t
922 route_match_ip_next_hop_prefix_list (void *rule
, struct prefix
*prefix
,
923 route_map_object_t type
, void *object
)
925 struct prefix_list
*plist
;
926 struct nh_rmap_obj
*nh_data
;
927 struct prefix_ipv4 p
;
929 if (type
== RMAP_ZEBRA
)
931 nh_data
= (struct nh_rmap_obj
*)object
;
933 return RMAP_DENYMATCH
;
935 switch (nh_data
->nexthop
->type
) {
936 case NEXTHOP_TYPE_IFINDEX
:
937 /* Interface routes can't match ip next-hop */
939 case NEXTHOP_TYPE_IPV4_IFINDEX
:
940 case NEXTHOP_TYPE_IPV4
:
942 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
943 p
.prefixlen
= IPV4_MAX_BITLEN
;
948 plist
= prefix_list_lookup (AFI_IP
, (char *) rule
);
952 return (prefix_list_apply (plist
, &p
) == PREFIX_DENY
?
953 RMAP_NOMATCH
: RMAP_MATCH
);
959 route_match_ip_next_hop_prefix_list_compile (const char *arg
)
961 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
965 route_match_ip_next_hop_prefix_list_free (void *rule
)
967 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
970 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd
=
972 "ip next-hop prefix-list",
973 route_match_ip_next_hop_prefix_list
,
974 route_match_ip_next_hop_prefix_list_compile
,
975 route_match_ip_next_hop_prefix_list_free
978 /* `match ip address IP_ACCESS_LIST' */
980 /* Match function should return 1 if match is success else return
982 static route_map_result_t
983 route_match_ip_address (void *rule
, struct prefix
*prefix
,
984 route_map_object_t type
, void *object
)
986 struct access_list
*alist
;
988 if (type
== RMAP_ZEBRA
)
990 alist
= access_list_lookup (AFI_IP
, (char *) rule
);
994 return (access_list_apply (alist
, prefix
) == FILTER_DENY
?
995 RMAP_NOMATCH
: RMAP_MATCH
);
1000 /* Route map `ip address' match statement. `arg' should be
1001 access-list name. */
1003 route_match_ip_address_compile (const char *arg
)
1005 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
1008 /* Free route map's compiled `ip address' value. */
1010 route_match_ip_address_free (void *rule
)
1012 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
1015 /* Route map commands for ip address matching. */
1016 static struct route_map_rule_cmd route_match_ip_address_cmd
=
1019 route_match_ip_address
,
1020 route_match_ip_address_compile
,
1021 route_match_ip_address_free
1024 /* `match ip address prefix-list PREFIX_LIST' */
1026 static route_map_result_t
1027 route_match_ip_address_prefix_list (void *rule
, struct prefix
*prefix
,
1028 route_map_object_t type
, void *object
)
1030 struct prefix_list
*plist
;
1032 if (type
== RMAP_ZEBRA
)
1034 plist
= prefix_list_lookup (AFI_IP
, (char *) rule
);
1036 return RMAP_NOMATCH
;
1038 return (prefix_list_apply (plist
, prefix
) == PREFIX_DENY
?
1039 RMAP_NOMATCH
: RMAP_MATCH
);
1041 return RMAP_NOMATCH
;
1045 route_match_ip_address_prefix_list_compile (const char *arg
)
1047 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
1051 route_match_ip_address_prefix_list_free (void *rule
)
1053 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
1056 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd
=
1058 "ip address prefix-list",
1059 route_match_ip_address_prefix_list
,
1060 route_match_ip_address_prefix_list_compile
,
1061 route_match_ip_address_prefix_list_free
1065 /* `match ip address prefix-len PREFIXLEN' */
1067 static route_map_result_t
1068 route_match_ip_address_prefix_len (void *rule
, struct prefix
*prefix
,
1069 route_map_object_t type
, void *object
)
1071 u_int32_t
*prefixlen
= (u_int32_t
*)rule
;
1073 if (type
== RMAP_ZEBRA
)
1075 return ((prefix
->prefixlen
== *prefixlen
) ? RMAP_MATCH
: RMAP_NOMATCH
);
1077 return RMAP_NOMATCH
;
1081 route_match_ip_address_prefix_len_compile (const char *arg
)
1083 u_int32_t
*prefix_len
;
1084 char *endptr
= NULL
;
1085 unsigned long tmpval
;
1087 /* prefix len value shoud be integer. */
1088 if (! all_digit (arg
))
1092 tmpval
= strtoul (arg
, &endptr
, 10);
1093 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
1096 prefix_len
= XMALLOC (MTYPE_ROUTE_MAP_COMPILED
, sizeof (u_int32_t
));
1101 *prefix_len
= tmpval
;
1106 route_match_ip_address_prefix_len_free (void *rule
)
1108 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
1111 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd
=
1113 "ip address prefix-len",
1114 route_match_ip_address_prefix_len
,
1115 route_match_ip_address_prefix_len_compile
,
1116 route_match_ip_address_prefix_len_free
1120 /* `match ip nexthop prefix-len PREFIXLEN' */
1122 static route_map_result_t
1123 route_match_ip_nexthop_prefix_len (void *rule
, struct prefix
*prefix
,
1124 route_map_object_t type
, void *object
)
1126 u_int32_t
*prefixlen
= (u_int32_t
*)rule
;
1127 struct nh_rmap_obj
*nh_data
;
1128 struct prefix_ipv4 p
;
1130 if (type
== RMAP_ZEBRA
)
1132 nh_data
= (struct nh_rmap_obj
*)object
;
1133 if (!nh_data
|| !nh_data
->nexthop
)
1134 return RMAP_DENYMATCH
;
1136 switch (nh_data
->nexthop
->type
) {
1137 case NEXTHOP_TYPE_IFINDEX
:
1138 /* Interface routes can't match ip next-hop */
1139 return RMAP_NOMATCH
;
1140 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1141 case NEXTHOP_TYPE_IPV4
:
1143 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1144 p
.prefixlen
= IPV4_MAX_BITLEN
;
1147 return RMAP_NOMATCH
;
1149 return ((p
.prefixlen
== *prefixlen
) ? RMAP_MATCH
: RMAP_NOMATCH
);
1151 return RMAP_NOMATCH
;
1154 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd
=
1156 "ip next-hop prefix-len",
1157 route_match_ip_nexthop_prefix_len
,
1158 route_match_ip_address_prefix_len_compile
, /* reuse */
1159 route_match_ip_address_prefix_len_free
/* reuse */
1162 /* `match source-protocol PROTOCOL' */
1164 static route_map_result_t
1165 route_match_source_protocol (void *rule
, struct prefix
*prefix
,
1166 route_map_object_t type
, void *object
)
1168 u_int32_t
*rib_type
= (u_int32_t
*)rule
;
1169 struct nh_rmap_obj
*nh_data
;
1171 if (type
== RMAP_ZEBRA
)
1173 nh_data
= (struct nh_rmap_obj
*)object
;
1175 return RMAP_DENYMATCH
;
1177 return ((nh_data
->source_protocol
== *rib_type
)
1178 ? RMAP_MATCH
: RMAP_NOMATCH
);
1180 return RMAP_NOMATCH
;
1184 route_match_source_protocol_compile (const char *arg
)
1186 u_int32_t
*rib_type
;
1189 i
= proto_name2num(arg
);
1190 rib_type
= XMALLOC (MTYPE_ROUTE_MAP_COMPILED
, sizeof (u_int32_t
));
1198 route_match_source_protocol_free (void *rule
)
1200 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
1203 static struct route_map_rule_cmd route_match_source_protocol_cmd
=
1206 route_match_source_protocol
,
1207 route_match_source_protocol_compile
,
1208 route_match_source_protocol_free
1211 /* `set src A.B.C.D' */
1214 static route_map_result_t
1215 route_set_src (void *rule
, struct prefix
*prefix
,
1216 route_map_object_t type
, void *object
)
1218 struct nh_rmap_obj
*nh_data
;
1220 if (type
== RMAP_ZEBRA
)
1222 nh_data
= (struct nh_rmap_obj
*)object
;
1223 nh_data
->nexthop
->rmap_src
= *(union g_addr
*)rule
;
1228 /* set src compilation. */
1230 route_set_src_compile (const char *arg
)
1232 union g_addr src
, *psrc
;
1234 if ((inet_pton(AF_INET6
, arg
, &src
.ipv6
) == 1) ||
1235 (src
.ipv4
.s_addr
&& (inet_pton(AF_INET
, arg
, &src
.ipv4
) == 1)))
1237 psrc
= XMALLOC (MTYPE_ROUTE_MAP_COMPILED
, sizeof (union g_addr
));
1244 /* Free route map's compiled `set src' value. */
1246 route_set_src_free (void *rule
)
1248 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
1251 /* Set src rule structure. */
1252 static struct route_map_rule_cmd route_set_src_cmd
=
1256 route_set_src_compile
,
1261 zebra_route_map_update_timer (struct thread
*thread
)
1263 zebra_t_rmap_update
= NULL
;
1265 if (IS_ZEBRA_DEBUG_EVENT
)
1266 zlog_debug("Event driven route-map update triggered");
1268 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
1269 zlog_debug ("%u: Routemap update-timer fired, scheduling RIB processing",
1272 zebra_import_table_rm_update ();
1273 rib_update(VRF_DEFAULT
, RIB_UPDATE_RMAP_CHANGE
);
1274 zebra_evaluate_rnh(0, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1275 zebra_evaluate_rnh(0, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1281 zebra_route_map_set_delay_timer(u_int32_t value
)
1283 zebra_rmap_update_timer
= value
;
1284 if (!value
&& zebra_t_rmap_update
)
1286 /* Event driven route map updates is being disabled */
1287 /* But there's a pending timer. Fire it off now */
1288 thread_cancel(zebra_t_rmap_update
);
1289 zebra_route_map_update_timer(zebra_t_rmap_update
);
1294 zebra_route_map_write_delay_timer (struct vty
*vty
)
1296 if (vty
&& (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
))
1297 vty_out (vty
, "zebra route-map delay-timer %d\n",
1298 zebra_rmap_update_timer
);
1303 zebra_route_map_check (int family
, int rib_type
, struct prefix
*p
,
1304 struct nexthop
*nexthop
, vrf_id_t vrf_id
, route_tag_t tag
)
1306 struct route_map
*rmap
= NULL
;
1307 route_map_result_t ret
= RMAP_MATCH
;
1308 struct nh_rmap_obj nh_obj
;
1310 nh_obj
.nexthop
= nexthop
;
1311 nh_obj
.vrf_id
= vrf_id
;
1312 nh_obj
.source_protocol
= rib_type
;
1316 if (rib_type
>= 0 && rib_type
< ZEBRA_ROUTE_MAX
)
1317 rmap
= route_map_lookup_by_name (proto_rm
[family
][rib_type
]);
1318 if (!rmap
&& proto_rm
[family
][ZEBRA_ROUTE_MAX
])
1319 rmap
= route_map_lookup_by_name (proto_rm
[family
][ZEBRA_ROUTE_MAX
]);
1321 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1328 zebra_get_import_table_route_map (afi_t afi
, uint32_t table
)
1330 return zebra_import_table_routemap
[afi
][table
];
1334 zebra_add_import_table_route_map (afi_t afi
, const char *rmap_name
, uint32_t table
)
1336 zebra_import_table_routemap
[afi
][table
] = XSTRDUP (MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1340 zebra_del_import_table_route_map (afi_t afi
, uint32_t table
)
1342 XFREE (MTYPE_ROUTE_MAP_NAME
, zebra_import_table_routemap
[afi
][table
]);
1346 zebra_import_table_route_map_check (int family
, int re_type
, struct prefix
*p
,
1347 struct nexthop
*nexthop
, vrf_id_t vrf_id
, route_tag_t tag
, const char *rmap_name
)
1349 struct route_map
*rmap
= NULL
;
1350 route_map_result_t ret
= RMAP_DENYMATCH
;
1351 struct nh_rmap_obj nh_obj
;
1353 nh_obj
.nexthop
= nexthop
;
1354 nh_obj
.vrf_id
= vrf_id
;
1355 nh_obj
.source_protocol
= re_type
;
1359 if (re_type
>= 0 && re_type
< ZEBRA_ROUTE_MAX
)
1360 rmap
= route_map_lookup_by_name (rmap_name
);
1362 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1369 zebra_nht_route_map_check (int family
, int client_proto
, struct prefix
*p
,
1370 struct route_entry
* re
, struct nexthop
*nexthop
)
1372 struct route_map
*rmap
= NULL
;
1373 route_map_result_t ret
= RMAP_MATCH
;
1374 struct nh_rmap_obj nh_obj
;
1376 nh_obj
.nexthop
= nexthop
;
1377 nh_obj
.vrf_id
= re
->vrf_id
;
1378 nh_obj
.source_protocol
= re
->type
;
1379 nh_obj
.metric
= re
->metric
;
1380 nh_obj
.tag
= re
->tag
;
1382 if (client_proto
>= 0 && client_proto
< ZEBRA_ROUTE_MAX
)
1383 rmap
= route_map_lookup_by_name (nht_rm
[family
][client_proto
]);
1384 if (!rmap
&& nht_rm
[family
][ZEBRA_ROUTE_MAX
])
1385 rmap
= route_map_lookup_by_name (nht_rm
[family
][ZEBRA_ROUTE_MAX
]);
1387 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1394 zebra_route_map_mark_update (const char *rmap_name
)
1396 /* rmap_update_timer of 0 means don't do route updates */
1397 if (zebra_rmap_update_timer
&& !zebra_t_rmap_update
) {
1398 zebra_t_rmap_update
= NULL
;
1399 thread_add_timer(zebrad
.master
, zebra_route_map_update_timer
, NULL
, zebra_rmap_update_timer
,
1400 &zebra_t_rmap_update
);
1405 zebra_route_map_add (const char *rmap_name
)
1407 zebra_route_map_mark_update(rmap_name
);
1408 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1412 zebra_route_map_delete (const char *rmap_name
)
1414 zebra_route_map_mark_update(rmap_name
);
1415 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
1419 zebra_route_map_event (route_map_event_t event
, const char *rmap_name
)
1421 zebra_route_map_mark_update(rmap_name
);
1422 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1425 /* ip protocol configuration write function */
1427 zebra_routemap_config_write_protocol (struct vty
*vty
)
1431 for (i
=0;i
<ZEBRA_ROUTE_MAX
;i
++)
1433 if (proto_rm
[AFI_IP
][i
])
1434 vty_out (vty
, "ip protocol %s route-map %s\n", zebra_route_string(i
),
1435 proto_rm
[AFI_IP
][i
]);
1437 if (proto_rm
[AFI_IP6
][i
])
1438 vty_out (vty
, "ipv6 protocol %s route-map %s\n", zebra_route_string(i
),
1439 proto_rm
[AFI_IP6
][i
]);
1441 if (nht_rm
[AFI_IP
][i
])
1442 vty_out (vty
, "ip nht %s route-map %s\n", zebra_route_string(i
),
1445 if (nht_rm
[AFI_IP6
][i
])
1446 vty_out (vty
, "ipv6 nht %s route-map %s\n", zebra_route_string(i
),
1447 nht_rm
[AFI_IP6
][i
]);
1450 if (proto_rm
[AFI_IP
][ZEBRA_ROUTE_MAX
])
1451 vty_out (vty
, "ip protocol %s route-map %s\n", "any",
1452 proto_rm
[AFI_IP
][ZEBRA_ROUTE_MAX
]);
1454 if (proto_rm
[AFI_IP6
][ZEBRA_ROUTE_MAX
])
1455 vty_out (vty
, "ipv6 protocol %s route-map %s\n", "any",
1456 proto_rm
[AFI_IP6
][ZEBRA_ROUTE_MAX
]);
1458 if (nht_rm
[AFI_IP
][ZEBRA_ROUTE_MAX
])
1459 vty_out (vty
, "ip nht %s route-map %s\n", "any",
1460 nht_rm
[AFI_IP
][ZEBRA_ROUTE_MAX
]);
1462 if (nht_rm
[AFI_IP6
][ZEBRA_ROUTE_MAX
])
1463 vty_out (vty
, "ipv6 nht %s route-map %s\n", "any",
1464 nht_rm
[AFI_IP6
][ZEBRA_ROUTE_MAX
]);
1466 if (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
)
1467 vty_out (vty
, "zebra route-map delay-timer %d\n",
1468 zebra_rmap_update_timer
);
1472 zebra_route_map_init ()
1474 install_element (CONFIG_NODE
, &ip_protocol_cmd
);
1475 install_element (CONFIG_NODE
, &no_ip_protocol_cmd
);
1476 install_element (VIEW_NODE
, &show_ip_protocol_cmd
);
1477 install_element (CONFIG_NODE
, &ipv6_protocol_cmd
);
1478 install_element (CONFIG_NODE
, &no_ipv6_protocol_cmd
);
1479 install_element (VIEW_NODE
, &show_ipv6_protocol_cmd
);
1480 install_element (CONFIG_NODE
, &ip_protocol_nht_rmap_cmd
);
1481 install_element (CONFIG_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1482 install_element (VIEW_NODE
, &show_ip_protocol_nht_cmd
);
1483 install_element (CONFIG_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1484 install_element (CONFIG_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1485 install_element (VIEW_NODE
, &show_ipv6_protocol_nht_cmd
);
1486 install_element (CONFIG_NODE
, &zebra_route_map_timer_cmd
);
1487 install_element (CONFIG_NODE
, &no_zebra_route_map_timer_cmd
);
1491 route_map_add_hook (zebra_route_map_add
);
1492 route_map_delete_hook (zebra_route_map_delete
);
1493 route_map_event_hook (zebra_route_map_event
);
1495 route_map_match_interface_hook (generic_match_add
);
1496 route_map_no_match_interface_hook (generic_match_delete
);
1498 route_map_match_ip_address_hook (generic_match_add
);
1499 route_map_no_match_ip_address_hook (generic_match_delete
);
1501 route_map_match_ip_address_prefix_list_hook (generic_match_add
);
1502 route_map_no_match_ip_address_prefix_list_hook (generic_match_delete
);
1504 route_map_match_ip_next_hop_hook (generic_match_add
);
1505 route_map_no_match_ip_next_hop_hook (generic_match_delete
);
1507 route_map_match_ip_next_hop_prefix_list_hook (generic_match_add
);
1508 route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete
);
1510 route_map_match_tag_hook (generic_match_add
);
1511 route_map_no_match_tag_hook (generic_match_delete
);
1513 route_map_install_match (&route_match_tag_cmd
);
1514 route_map_install_match (&route_match_interface_cmd
);
1515 route_map_install_match (&route_match_ip_next_hop_cmd
);
1516 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd
);
1517 route_map_install_match (&route_match_ip_address_cmd
);
1518 route_map_install_match (&route_match_ip_address_prefix_list_cmd
);
1519 route_map_install_match (&route_match_ip_address_prefix_len_cmd
);
1520 route_map_install_match (&route_match_ip_nexthop_prefix_len_cmd
);
1521 route_map_install_match (&route_match_source_protocol_cmd
);
1523 route_map_install_set (&route_set_src_cmd
);
1525 install_element (RMAP_NODE
, &match_ip_nexthop_prefix_len_cmd
);
1526 install_element (RMAP_NODE
, &no_match_ip_nexthop_prefix_len_cmd
);
1527 install_element (RMAP_NODE
, &match_ip_address_prefix_len_cmd
);
1528 install_element (RMAP_NODE
, &no_match_ip_address_prefix_len_cmd
);
1529 install_element (RMAP_NODE
, &match_source_protocol_cmd
);
1530 install_element (RMAP_NODE
, &no_match_source_protocol_cmd
);
1532 install_element (RMAP_NODE
, &set_src_cmd
);
1533 install_element (RMAP_NODE
, &no_set_src_cmd
);