diff options
Diffstat (limited to 'lib/routemap.c')
-rw-r--r-- | lib/routemap.c | 4017 |
1 files changed, 1905 insertions, 2112 deletions
diff --git a/lib/routemap.c b/lib/routemap.c index 9ceaa1115..3d1add25d 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -31,13 +31,13 @@ #include "hash.h" #include "libfrr.h" -DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP, "Route map") -DEFINE_MTYPE( LIB, ROUTE_MAP_NAME, "Route map name") -DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_INDEX, "Route map index") -DEFINE_MTYPE( LIB, ROUTE_MAP_RULE, "Route map rule") +DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP, "Route map") +DEFINE_MTYPE(LIB, ROUTE_MAP_NAME, "Route map name") +DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_INDEX, "Route map index") +DEFINE_MTYPE(LIB, ROUTE_MAP_RULE, "Route map rule") DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_RULE_STR, "Route map rule str") -DEFINE_MTYPE( LIB, ROUTE_MAP_COMPILED, "Route map compiled") -DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_DEP, "Route map dependency") +DEFINE_MTYPE(LIB, ROUTE_MAP_COMPILED, "Route map compiled") +DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_DEP, "Route map dependency") DEFINE_QOBJ_TYPE(route_map_index) DEFINE_QOBJ_TYPE(route_map) @@ -48,1477 +48,1293 @@ static vector route_match_vec; /* Vector for route set rules. */ static vector route_set_vec; -struct route_map_match_set_hooks -{ - /* match interface */ - int (*match_interface) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match interface */ - int (*no_match_interface) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match ip address */ - int (*match_ip_address) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match ip address */ - int (*no_match_ip_address) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match ip address prefix list */ - int (*match_ip_address_prefix_list) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match ip address prefix list */ - int (*no_match_ip_address_prefix_list) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match ip next hop */ - int (*match_ip_next_hop) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match ip next hop */ - int (*no_match_ip_next_hop) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match ip next hop prefix list */ - int (*match_ip_next_hop_prefix_list) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match ip next hop prefix list */ - int (*no_match_ip_next_hop_prefix_list) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match ipv6 address */ - int (*match_ipv6_address) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match ipv6 address */ - int (*no_match_ipv6_address) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - - /* match ipv6 address prefix list */ - int (*match_ipv6_address_prefix_list) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match ipv6 address prefix list */ - int (*no_match_ipv6_address_prefix_list) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match metric */ - int (*match_metric) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match metric */ - int (*no_match_metric) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match tag */ - int (*match_tag) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match tag */ - int (*no_match_tag) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* set ip nexthop */ - int (*set_ip_nexthop) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* no set ip nexthop */ - int (*no_set_ip_nexthop) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* set ipv6 nexthop local */ - int (*set_ipv6_nexthop_local) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* no set ipv6 nexthop local */ - int (*no_set_ipv6_nexthop_local) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* set metric */ - int (*set_metric) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* no set metric */ - int (*no_set_metric) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* set tag */ - int (*set_tag) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* no set tag */ - int (*no_set_tag) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - +struct route_map_match_set_hooks { + /* match interface */ + int (*match_interface)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* no match interface */ + int (*no_match_interface)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* match ip address */ + int (*match_ip_address)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* no match ip address */ + int (*no_match_ip_address)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* match ip address prefix list */ + int (*match_ip_address_prefix_list)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg, + route_map_event_t type); + + /* no match ip address prefix list */ + int (*no_match_ip_address_prefix_list)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg, + route_map_event_t type); + + /* match ip next hop */ + int (*match_ip_next_hop)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* no match ip next hop */ + int (*no_match_ip_next_hop)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* match ip next hop prefix list */ + int (*match_ip_next_hop_prefix_list)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg, + route_map_event_t type); + + /* no match ip next hop prefix list */ + int (*no_match_ip_next_hop_prefix_list)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg, + route_map_event_t type); + + /* match ipv6 address */ + int (*match_ipv6_address)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* no match ipv6 address */ + int (*no_match_ipv6_address)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + + /* match ipv6 address prefix list */ + int (*match_ipv6_address_prefix_list)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg, + route_map_event_t type); + + /* no match ipv6 address prefix list */ + int (*no_match_ipv6_address_prefix_list)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg, + route_map_event_t type); + + /* match metric */ + int (*match_metric)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* no match metric */ + int (*no_match_metric)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* match tag */ + int (*match_tag)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* no match tag */ + int (*no_match_tag)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* set ip nexthop */ + int (*set_ip_nexthop)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); + + /* no set ip nexthop */ + int (*no_set_ip_nexthop)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); + + /* set ipv6 nexthop local */ + int (*set_ipv6_nexthop_local)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg); + + /* no set ipv6 nexthop local */ + int (*no_set_ipv6_nexthop_local)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg); + + /* set metric */ + int (*set_metric)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); + + /* no set metric */ + int (*no_set_metric)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); + + /* set tag */ + int (*set_tag)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); + + /* no set tag */ + int (*no_set_tag)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); }; struct route_map_match_set_hooks rmap_match_set_hook; /* match interface */ -void -route_map_match_interface_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_interface_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_interface = func; + rmap_match_set_hook.match_interface = func; } /* no match interface */ -void -route_map_no_match_interface_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_interface_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_interface = func; + rmap_match_set_hook.no_match_interface = func; } /* match ip address */ -void -route_map_match_ip_address_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_ip_address_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_ip_address = func; + rmap_match_set_hook.match_ip_address = func; } /* no match ip address */ -void -route_map_no_match_ip_address_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_ip_address_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_ip_address = func; + rmap_match_set_hook.no_match_ip_address = func; } /* match ip address prefix list */ -void -route_map_match_ip_address_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_ip_address_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_ip_address_prefix_list = func; + rmap_match_set_hook.match_ip_address_prefix_list = func; } /* no match ip address prefix list */ -void -route_map_no_match_ip_address_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_ip_address_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_ip_address_prefix_list = func; + rmap_match_set_hook.no_match_ip_address_prefix_list = func; } /* match ip next hop */ -void -route_map_match_ip_next_hop_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_ip_next_hop_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_ip_next_hop = func; + rmap_match_set_hook.match_ip_next_hop = func; } /* no match ip next hop */ -void -route_map_no_match_ip_next_hop_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_ip_next_hop_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_ip_next_hop = func; + rmap_match_set_hook.no_match_ip_next_hop = func; } /* match ip next hop prefix list */ -void -route_map_match_ip_next_hop_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_ip_next_hop_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_ip_next_hop_prefix_list = func; + rmap_match_set_hook.match_ip_next_hop_prefix_list = func; } /* no match ip next hop prefix list */ -void -route_map_no_match_ip_next_hop_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_ip_next_hop_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_ip_next_hop_prefix_list = func; + rmap_match_set_hook.no_match_ip_next_hop_prefix_list = func; } /* match ipv6 address */ -void -route_map_match_ipv6_address_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_ipv6_address_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_ipv6_address = func; + rmap_match_set_hook.match_ipv6_address = func; } /* no match ipv6 address */ -void -route_map_no_match_ipv6_address_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_ipv6_address_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_ipv6_address = func; + rmap_match_set_hook.no_match_ipv6_address = func; } /* match ipv6 address prefix list */ -void -route_map_match_ipv6_address_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_ipv6_address_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_ipv6_address_prefix_list = func; + rmap_match_set_hook.match_ipv6_address_prefix_list = func; } /* no match ipv6 address prefix list */ -void -route_map_no_match_ipv6_address_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_ipv6_address_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_ipv6_address_prefix_list = func; + rmap_match_set_hook.no_match_ipv6_address_prefix_list = func; } /* match metric */ -void -route_map_match_metric_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_metric_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_metric = func; + rmap_match_set_hook.match_metric = func; } /* no match metric */ -void -route_map_no_match_metric_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_metric_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_metric = func; + rmap_match_set_hook.no_match_metric = func; } /* match tag */ -void -route_map_match_tag_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_tag_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type)) { - rmap_match_set_hook.match_tag = func; + rmap_match_set_hook.match_tag = func; } /* no match tag */ -void -route_map_no_match_tag_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_tag_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_tag = func; + rmap_match_set_hook.no_match_tag = func; } /* set ip nexthop */ -void -route_map_set_ip_nexthop_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_set_ip_nexthop_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg)) { - rmap_match_set_hook.set_ip_nexthop = func; + rmap_match_set_hook.set_ip_nexthop = func; } /* no set ip nexthop */ -void -route_map_no_set_ip_nexthop_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_no_set_ip_nexthop_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg)) { - rmap_match_set_hook.no_set_ip_nexthop = func; + rmap_match_set_hook.no_set_ip_nexthop = func; } /* set ipv6 nexthop local */ -void -route_map_set_ipv6_nexthop_local_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_set_ipv6_nexthop_local_hook( + int (*func)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg)) { - rmap_match_set_hook.set_ipv6_nexthop_local = func; + rmap_match_set_hook.set_ipv6_nexthop_local = func; } /* no set ipv6 nexthop local */ -void -route_map_no_set_ipv6_nexthop_local_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_no_set_ipv6_nexthop_local_hook( + int (*func)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg)) { - rmap_match_set_hook.no_set_ipv6_nexthop_local = func; + rmap_match_set_hook.no_set_ipv6_nexthop_local = func; } /* set metric */ -void -route_map_set_metric_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_set_metric_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg)) { - rmap_match_set_hook.set_metric = func; + rmap_match_set_hook.set_metric = func; } /* no set metric */ -void -route_map_no_set_metric_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_no_set_metric_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg)) { - rmap_match_set_hook.no_set_metric = func; + rmap_match_set_hook.no_set_metric = func; } /* set tag */ -void -route_map_set_tag_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_set_tag_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg)) { - rmap_match_set_hook.set_tag = func; + rmap_match_set_hook.set_tag = func; } /* no set tag */ -void -route_map_no_set_tag_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) -{ - rmap_match_set_hook.no_set_tag = func; -} - -int -generic_match_add (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg, - route_map_event_t type) -{ - int ret; - - ret = route_map_add_match (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% [%s] Can't find rule.\n", frr_protonameinst); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% [%s] Argument form is unsupported or malformed.\n", - frr_protonameinst); - return CMD_WARNING_CONFIG_FAILED; - } - } - - if (type != RMAP_EVENT_MATCH_ADDED) - { - route_map_upd8_dependency (type, arg, index->map->name); - } - return CMD_SUCCESS; -} - -int -generic_match_delete (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg, - route_map_event_t type) -{ - int ret; - char *dep_name = NULL; - const char *tmpstr; - char *rmap_name = NULL; - - if (type != RMAP_EVENT_MATCH_DELETED) - { - /* ignore the mundane, the types without any dependency */ - if (arg == NULL) - { - if ((tmpstr = route_map_get_match_arg(index, command)) != NULL) - dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); - } - else - { - dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg); - } - rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); - } - - ret = route_map_delete_match (index, command, dep_name); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% [%s] Can't find rule.\n", frr_protonameinst); - break; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% [%s] Argument form is unsupported or malformed.\n", - frr_protonameinst); - break; - } - if (dep_name) - XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); - if (rmap_name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); - return CMD_WARNING_CONFIG_FAILED; - } - - if (type != RMAP_EVENT_MATCH_DELETED && dep_name) - route_map_upd8_dependency(type, dep_name, rmap_name); - - if (dep_name) - XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); - if (rmap_name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); - - return CMD_SUCCESS; -} - -int -generic_set_add (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg) -{ - int ret; - - ret = route_map_add_set (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% [%s] Can't find rule.\n", frr_protonameinst); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% [%s] Argument form is unsupported or malformed.\n", - frr_protonameinst); - return CMD_WARNING_CONFIG_FAILED; - } - } - return CMD_SUCCESS; -} - -int -generic_set_delete (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg) -{ - int ret; - - ret = route_map_delete_set (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% [%s] Can't find rule.\n", frr_protonameinst); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% [%s] Argument form is unsupported or malformed.\n", - frr_protonameinst); - return CMD_WARNING_CONFIG_FAILED; - } - } - return CMD_SUCCESS; +void route_map_no_set_tag_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg)) +{ + rmap_match_set_hook.no_set_tag = func; } +int generic_match_add(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type) +{ + int ret; + + ret = route_map_add_match(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% [%s] Can't find rule.\n", + frr_protonameinst); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, + "%% [%s] Argument form is unsupported or malformed.\n", + frr_protonameinst); + return CMD_WARNING_CONFIG_FAILED; + } + } -/* Route map rule. This rule has both `match' rule and `set' rule. */ -struct route_map_rule + if (type != RMAP_EVENT_MATCH_ADDED) { + route_map_upd8_dependency(type, arg, index->map->name); + } + return CMD_SUCCESS; +} + +int generic_match_delete(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type) +{ + int ret; + char *dep_name = NULL; + const char *tmpstr; + char *rmap_name = NULL; + + if (type != RMAP_EVENT_MATCH_DELETED) { + /* ignore the mundane, the types without any dependency */ + if (arg == NULL) { + if ((tmpstr = route_map_get_match_arg(index, command)) + != NULL) + dep_name = + XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); + } else { + dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg); + } + rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); + } + + ret = route_map_delete_match(index, command, dep_name); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% [%s] Can't find rule.\n", + frr_protonameinst); + break; + case RMAP_COMPILE_ERROR: + vty_out(vty, + "%% [%s] Argument form is unsupported or malformed.\n", + frr_protonameinst); + break; + } + if (dep_name) + XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); + if (rmap_name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + return CMD_WARNING_CONFIG_FAILED; + } + + if (type != RMAP_EVENT_MATCH_DELETED && dep_name) + route_map_upd8_dependency(type, dep_name, rmap_name); + + if (dep_name) + XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); + if (rmap_name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + + return CMD_SUCCESS; +} + +int generic_set_add(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg) { - /* Rule type. */ - struct route_map_rule_cmd *cmd; + int ret; + + ret = route_map_add_set(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% [%s] Can't find rule.\n", + frr_protonameinst); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, + "%% [%s] Argument form is unsupported or malformed.\n", + frr_protonameinst); + return CMD_WARNING_CONFIG_FAILED; + } + } + return CMD_SUCCESS; +} + +int generic_set_delete(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg) +{ + int ret; + + ret = route_map_delete_set(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% [%s] Can't find rule.\n", + frr_protonameinst); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, + "%% [%s] Argument form is unsupported or malformed.\n", + frr_protonameinst); + return CMD_WARNING_CONFIG_FAILED; + } + } + return CMD_SUCCESS; +} + + +/* Route map rule. This rule has both `match' rule and `set' rule. */ +struct route_map_rule { + /* Rule type. */ + struct route_map_rule_cmd *cmd; - /* For pretty printing. */ - char *rule_str; + /* For pretty printing. */ + char *rule_str; - /* Pre-compiled match rule. */ - void *value; + /* Pre-compiled match rule. */ + void *value; - /* Linked list. */ - struct route_map_rule *next; - struct route_map_rule *prev; + /* Linked list. */ + struct route_map_rule *next; + struct route_map_rule *prev; }; /* Making route map list. */ -struct route_map_list -{ - struct route_map *head; - struct route_map *tail; +struct route_map_list { + struct route_map *head; + struct route_map *tail; - void (*add_hook) (const char *); - void (*delete_hook) (const char *); - void (*event_hook) (route_map_event_t, const char *); + void (*add_hook)(const char *); + void (*delete_hook)(const char *); + void (*event_hook)(route_map_event_t, const char *); }; /* Master list of route map. */ -static struct route_map_list route_map_master = { NULL, NULL, NULL, NULL, NULL }; +static struct route_map_list route_map_master = {NULL, NULL, NULL, NULL, NULL}; struct hash *route_map_master_hash = NULL; -static unsigned int -route_map_hash_key_make (void *p) +static unsigned int route_map_hash_key_make(void *p) { - const struct route_map *map = p; - return string_hash_make (map->name); + const struct route_map *map = p; + return string_hash_make(map->name); } -static int -route_map_hash_cmp(const void *p1, const void *p2) +static int route_map_hash_cmp(const void *p1, const void *p2) { - const struct route_map *map1 = p1; - const struct route_map *map2 = p2; + const struct route_map *map1 = p1; + const struct route_map *map2 = p2; - if (map1->deleted == map2->deleted) - { - if (map1->name && map2->name) - { - if (!strcmp (map1->name, map2->name)) - { - return 1; - } - } - else if (!map1->name && !map2->name) - { - return 1; - } - } + if (map1->deleted == map2->deleted) { + if (map1->name && map2->name) { + if (!strcmp(map1->name, map2->name)) { + return 1; + } + } else if (!map1->name && !map2->name) { + return 1; + } + } - return 0; + return 0; } -enum route_map_upd8_type - { - ROUTE_MAP_ADD = 1, - ROUTE_MAP_DEL, - }; +enum route_map_upd8_type { + ROUTE_MAP_ADD = 1, + ROUTE_MAP_DEL, +}; /* all possible route-map dependency types */ -enum route_map_dep_type - { - ROUTE_MAP_DEP_RMAP = 1, - ROUTE_MAP_DEP_CLIST, - ROUTE_MAP_DEP_ECLIST, - ROUTE_MAP_DEP_LCLIST, - ROUTE_MAP_DEP_PLIST, - ROUTE_MAP_DEP_ASPATH, - ROUTE_MAP_DEP_FILTER, - ROUTE_MAP_DEP_MAX, - }; - -struct route_map_dep -{ - char *dep_name; - struct hash *dep_rmap_hash; - struct hash *this_hash; /* ptr to the hash structure this is part of */ +enum route_map_dep_type { + ROUTE_MAP_DEP_RMAP = 1, + ROUTE_MAP_DEP_CLIST, + ROUTE_MAP_DEP_ECLIST, + ROUTE_MAP_DEP_LCLIST, + ROUTE_MAP_DEP_PLIST, + ROUTE_MAP_DEP_ASPATH, + ROUTE_MAP_DEP_FILTER, + ROUTE_MAP_DEP_MAX, +}; + +struct route_map_dep { + char *dep_name; + struct hash *dep_rmap_hash; + struct hash *this_hash; /* ptr to the hash structure this is part of */ }; /* Hashes maintaining dependency between various sublists used by route maps */ struct hash *route_map_dep_hash[ROUTE_MAP_DEP_MAX]; -static unsigned int route_map_dep_hash_make_key (void *p); -static int route_map_dep_hash_cmp (const void *p1, const void *p2); -static void route_map_clear_all_references (char *rmap_name); -static void route_map_rule_delete (struct route_map_rule_list *, - struct route_map_rule *); +static unsigned int route_map_dep_hash_make_key(void *p); +static int route_map_dep_hash_cmp(const void *p1, const void *p2); +static void route_map_clear_all_references(char *rmap_name); +static void route_map_rule_delete(struct route_map_rule_list *, + struct route_map_rule *); static int rmap_debug = 0; -static void -route_map_index_delete (struct route_map_index *, int); +static void route_map_index_delete(struct route_map_index *, int); /* New route map allocation. Please note route map's name must be specified. */ -static struct route_map * -route_map_new (const char *name) +static struct route_map *route_map_new(const char *name) { - struct route_map *new; + struct route_map *new; - new = XCALLOC (MTYPE_ROUTE_MAP, sizeof (struct route_map)); - new->name = XSTRDUP (MTYPE_ROUTE_MAP_NAME, name); - QOBJ_REG (new, route_map); - return new; + new = XCALLOC(MTYPE_ROUTE_MAP, sizeof(struct route_map)); + new->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); + QOBJ_REG(new, route_map); + return new; } /* Add new name to route_map. */ -static struct route_map * -route_map_add (const char *name) -{ - struct route_map *map; - struct route_map_list *list; - - map = route_map_new (name); - list = &route_map_master; - - /* Add map to the hash */ - hash_get(route_map_master_hash, map, hash_alloc_intern); - - /* Add new entry to the head of the list to match how it is added in the - * hash table. This is to ensure that if the same route-map has been - * created more than once and then marked for deletion (which can happen - * if prior deletions haven't completed as BGP hasn't yet done the - * route-map processing), the order of the entities is the same in both - * the list and the hash table. Otherwise, since there is nothing to - * distinguish between the two entries, the wrong entry could get freed. - * TODO: This needs to be re-examined to handle it better - e.g., revive - * a deleted entry if the route-map is created again. - */ - map->prev = NULL; - map->next = list->head; - if (list->head) - list->head->prev = map; - list->head = map; - if (!list->tail) - list->tail = map; - - /* Execute hook. */ - if (route_map_master.add_hook) - { - (*route_map_master.add_hook) (name); - route_map_notify_dependencies(name, RMAP_EVENT_CALL_ADDED); - } - return map; +static struct route_map *route_map_add(const char *name) +{ + struct route_map *map; + struct route_map_list *list; + + map = route_map_new(name); + list = &route_map_master; + + /* Add map to the hash */ + hash_get(route_map_master_hash, map, hash_alloc_intern); + + /* Add new entry to the head of the list to match how it is added in the + * hash table. This is to ensure that if the same route-map has been + * created more than once and then marked for deletion (which can happen + * if prior deletions haven't completed as BGP hasn't yet done the + * route-map processing), the order of the entities is the same in both + * the list and the hash table. Otherwise, since there is nothing to + * distinguish between the two entries, the wrong entry could get freed. + * TODO: This needs to be re-examined to handle it better - e.g., revive + * a deleted entry if the route-map is created again. + */ + map->prev = NULL; + map->next = list->head; + if (list->head) + list->head->prev = map; + list->head = map; + if (!list->tail) + list->tail = map; + + /* Execute hook. */ + if (route_map_master.add_hook) { + (*route_map_master.add_hook)(name); + route_map_notify_dependencies(name, RMAP_EVENT_CALL_ADDED); + } + return map; } /* this is supposed to be called post processing by * the delete hook function. Don't invoke delete_hook * again in this routine. */ -static void -route_map_free_map (struct route_map *map) +static void route_map_free_map(struct route_map *map) { - struct route_map_list *list; - struct route_map_index *index; + struct route_map_list *list; + struct route_map_index *index; - if (map == NULL) - return; + if (map == NULL) + return; - while ((index = map->head) != NULL) - route_map_index_delete (index, 0); + while ((index = map->head) != NULL) + route_map_index_delete(index, 0); - list = &route_map_master; + list = &route_map_master; - QOBJ_UNREG (map); + QOBJ_UNREG(map); - if (map->next) - map->next->prev = map->prev; - else - list->tail = map->prev; + if (map->next) + map->next->prev = map->prev; + else + list->tail = map->prev; - if (map->prev) - map->prev->next = map->next; - else - list->head = map->next; + if (map->prev) + map->prev->next = map->next; + else + list->head = map->next; - hash_release(route_map_master_hash, map); - XFREE (MTYPE_ROUTE_MAP_NAME, map->name); - XFREE (MTYPE_ROUTE_MAP, map); + hash_release(route_map_master_hash, map); + XFREE(MTYPE_ROUTE_MAP_NAME, map->name); + XFREE(MTYPE_ROUTE_MAP, map); } /* Route map delete from list. */ -static void -route_map_delete (struct route_map *map) +static void route_map_delete(struct route_map *map) { - struct route_map_index *index; - char *name; + struct route_map_index *index; + char *name; - while ((index = map->head) != NULL) - route_map_index_delete (index, 0); + while ((index = map->head) != NULL) + route_map_index_delete(index, 0); - name = map->name; - map->head = NULL; + name = map->name; + map->head = NULL; - /* Clear all dependencies */ - route_map_clear_all_references(name); - map->deleted = 1; - /* Execute deletion hook. */ - if (route_map_master.delete_hook) - { - (*route_map_master.delete_hook) (name); - route_map_notify_dependencies(name, RMAP_EVENT_CALL_DELETED); - } + /* Clear all dependencies */ + route_map_clear_all_references(name); + map->deleted = 1; + /* Execute deletion hook. */ + if (route_map_master.delete_hook) { + (*route_map_master.delete_hook)(name); + route_map_notify_dependencies(name, RMAP_EVENT_CALL_DELETED); + } - if (!map->to_be_processed) - { - route_map_free_map (map); - } + if (!map->to_be_processed) { + route_map_free_map(map); + } } /* Lookup route map by route map name string. */ -struct route_map * -route_map_lookup_by_name (const char *name) +struct route_map *route_map_lookup_by_name(const char *name) { - struct route_map *map; - struct route_map tmp_map; + struct route_map *map; + struct route_map tmp_map; - if (!name) - return NULL; + if (!name) + return NULL; - // map.deleted is 0 via memset - memset(&tmp_map, 0, sizeof(struct route_map)); - tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); - map = hash_lookup(route_map_master_hash, &tmp_map); - XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name); - return map; + // map.deleted is 0 via memset + memset(&tmp_map, 0, sizeof(struct route_map)); + tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); + map = hash_lookup(route_map_master_hash, &tmp_map); + XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name); + return map; } -int -route_map_mark_updated (const char *name, int del_later) +int route_map_mark_updated(const char *name, int del_later) { - struct route_map *map; - int ret = -1; - struct route_map tmp_map; + struct route_map *map; + int ret = -1; + struct route_map tmp_map; - if (!name) - return (ret); + if (!name) + return (ret); - map = route_map_lookup_by_name(name); + map = route_map_lookup_by_name(name); - /* If we did not find the routemap with deleted=0 try again - * with deleted=1 - */ - if (!map) - { - memset(&tmp_map, 0, sizeof(struct route_map)); - tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); - tmp_map.deleted = 1; - map = hash_lookup(route_map_master_hash, &tmp_map); - XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name); - } + /* If we did not find the routemap with deleted=0 try again + * with deleted=1 + */ + if (!map) { + memset(&tmp_map, 0, sizeof(struct route_map)); + tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); + tmp_map.deleted = 1; + map = hash_lookup(route_map_master_hash, &tmp_map); + XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name); + } - if (map) - { - map->to_be_processed = 1; - ret = 0; - } + if (map) { + map->to_be_processed = 1; + ret = 0; + } - return(ret); + return (ret); } -int -route_map_clear_updated (struct route_map *map) +int route_map_clear_updated(struct route_map *map) { - int ret = -1; + int ret = -1; - if (map) - { - map->to_be_processed = 0; - if (map->deleted) - route_map_free_map(map); - } + if (map) { + map->to_be_processed = 0; + if (map->deleted) + route_map_free_map(map); + } - return (ret); + return (ret); } /* Lookup route map. If there isn't route map create one and return it. */ -static struct route_map * -route_map_get (const char *name) +static struct route_map *route_map_get(const char *name) { - struct route_map *map; + struct route_map *map; - map = route_map_lookup_by_name (name); - if (map == NULL) - map = route_map_add (name); + map = route_map_lookup_by_name(name); + if (map == NULL) + map = route_map_add(name); - return map; + return map; } -void -route_map_walk_update_list (int (*route_map_update_fn) (char *name)) +void route_map_walk_update_list(int (*route_map_update_fn)(char *name)) { - struct route_map *node; - struct route_map *nnode = NULL; + struct route_map *node; + struct route_map *nnode = NULL; - for (node = route_map_master.head; node; node = nnode) - { - if (node->to_be_processed) - { - /* DD: Should we add any thread yield code here */ - route_map_update_fn(node->name); - nnode = node->next; - route_map_clear_updated(node); + for (node = route_map_master.head; node; node = nnode) { + if (node->to_be_processed) { + /* DD: Should we add any thread yield code here */ + route_map_update_fn(node->name); + nnode = node->next; + route_map_clear_updated(node); + } else + nnode = node->next; } - else - nnode = node->next; - } } /* Return route map's type string. */ -static const char * -route_map_type_str (enum route_map_type type) -{ - switch (type) - { - case RMAP_PERMIT: - return "permit"; - break; - case RMAP_DENY: - return "deny"; - break; - default: - return ""; - break; - } +static const char *route_map_type_str(enum route_map_type type) +{ + switch (type) { + case RMAP_PERMIT: + return "permit"; + break; + case RMAP_DENY: + return "deny"; + break; + default: + return ""; + break; + } } -static int -route_map_empty (struct route_map *map) +static int route_map_empty(struct route_map *map) { - if (map->head == NULL && map->tail == NULL) - return 1; - else - return 0; + if (map->head == NULL && map->tail == NULL) + return 1; + else + return 0; } /* show route-map */ -static void -vty_show_route_map_entry (struct vty *vty, struct route_map *map) -{ - struct route_map_index *index; - struct route_map_rule *rule; - - vty_out (vty, "%s:\n", frr_protonameinst); - - for (index = map->head; index; index = index->next) - { - vty_out (vty, "route-map %s, %s, sequence %d\n", - map->name, route_map_type_str (index->type), - index->pref); - - /* Description */ - if (index->description) - vty_out (vty, " Description:\n %s\n", - index->description); - - /* Match clauses */ - vty_out (vty, " Match clauses:\n"); - for (rule = index->match_list.head; rule; rule = rule->next) - vty_out (vty, " %s %s\n", - rule->cmd->str, rule->rule_str); - - vty_out (vty, " Set clauses:\n"); - for (rule = index->set_list.head; rule; rule = rule->next) - vty_out (vty, " %s %s\n", - rule->cmd->str, rule->rule_str); - - /* Call clause */ - vty_out (vty, " Call clause:\n"); - if (index->nextrm) - vty_out (vty, " Call %s\n", index->nextrm); - - /* Exit Policy */ - vty_out (vty, " Action:\n"); - if (index->exitpolicy == RMAP_GOTO) - vty_out (vty, " Goto %d\n", index->nextpref); - else if (index->exitpolicy == RMAP_NEXT) - vty_out (vty, " Continue to next entry\n"); - else if (index->exitpolicy == RMAP_EXIT) - vty_out (vty, " Exit routemap\n"); - } -} - -static int -vty_show_route_map (struct vty *vty, const char *name) -{ - struct route_map *map; - - if (name) - { - map = route_map_lookup_by_name (name); - - if (map) - { - vty_show_route_map_entry (vty, map); - return CMD_SUCCESS; - } - else - { - vty_out (vty, "%s: 'route-map %s' not found\n", frr_protonameinst, - name); - return CMD_SUCCESS; - } - } - else - { - for (map = route_map_master.head; map; map = map->next) - if (!map->deleted) - vty_show_route_map_entry (vty, map); - } - return CMD_SUCCESS; +static void vty_show_route_map_entry(struct vty *vty, struct route_map *map) +{ + struct route_map_index *index; + struct route_map_rule *rule; + + vty_out(vty, "%s:\n", frr_protonameinst); + + for (index = map->head; index; index = index->next) { + vty_out(vty, "route-map %s, %s, sequence %d\n", map->name, + route_map_type_str(index->type), index->pref); + + /* Description */ + if (index->description) + vty_out(vty, " Description:\n %s\n", + index->description); + + /* Match clauses */ + vty_out(vty, " Match clauses:\n"); + for (rule = index->match_list.head; rule; rule = rule->next) + vty_out(vty, " %s %s\n", rule->cmd->str, + rule->rule_str); + + vty_out(vty, " Set clauses:\n"); + for (rule = index->set_list.head; rule; rule = rule->next) + vty_out(vty, " %s %s\n", rule->cmd->str, + rule->rule_str); + + /* Call clause */ + vty_out(vty, " Call clause:\n"); + if (index->nextrm) + vty_out(vty, " Call %s\n", index->nextrm); + + /* Exit Policy */ + vty_out(vty, " Action:\n"); + if (index->exitpolicy == RMAP_GOTO) + vty_out(vty, " Goto %d\n", index->nextpref); + else if (index->exitpolicy == RMAP_NEXT) + vty_out(vty, " Continue to next entry\n"); + else if (index->exitpolicy == RMAP_EXIT) + vty_out(vty, " Exit routemap\n"); + } +} + +static int vty_show_route_map(struct vty *vty, const char *name) +{ + struct route_map *map; + + if (name) { + map = route_map_lookup_by_name(name); + + if (map) { + vty_show_route_map_entry(vty, map); + return CMD_SUCCESS; + } else { + vty_out(vty, "%s: 'route-map %s' not found\n", + frr_protonameinst, name); + return CMD_SUCCESS; + } + } else { + for (map = route_map_master.head; map; map = map->next) + if (!map->deleted) + vty_show_route_map_entry(vty, map); + } + return CMD_SUCCESS; } /* New route map allocation. Please note route map's name must be specified. */ -static struct route_map_index * -route_map_index_new (void) +static struct route_map_index *route_map_index_new(void) { - struct route_map_index *new; + struct route_map_index *new; - new = XCALLOC (MTYPE_ROUTE_MAP_INDEX, sizeof (struct route_map_index)); - new->exitpolicy = RMAP_EXIT; /* Default to Cisco-style */ - QOBJ_REG (new, route_map_index); - return new; + new = XCALLOC(MTYPE_ROUTE_MAP_INDEX, sizeof(struct route_map_index)); + new->exitpolicy = RMAP_EXIT; /* Default to Cisco-style */ + QOBJ_REG(new, route_map_index); + return new; } /* Free route map index. */ -static void -route_map_index_delete (struct route_map_index *index, int notify) +static void route_map_index_delete(struct route_map_index *index, int notify) { - struct route_map_rule *rule; + struct route_map_rule *rule; - QOBJ_UNREG (index); + QOBJ_UNREG(index); - /* Free route match. */ - while ((rule = index->match_list.head) != NULL) - route_map_rule_delete (&index->match_list, rule); + /* Free route match. */ + while ((rule = index->match_list.head) != NULL) + route_map_rule_delete(&index->match_list, rule); - /* Free route set. */ - while ((rule = index->set_list.head) != NULL) - route_map_rule_delete (&index->set_list, rule); + /* Free route set. */ + while ((rule = index->set_list.head) != NULL) + route_map_rule_delete(&index->set_list, rule); - /* Remove index from route map list. */ - if (index->next) - index->next->prev = index->prev; - else - index->map->tail = index->prev; + /* Remove index from route map list. */ + if (index->next) + index->next->prev = index->prev; + else + index->map->tail = index->prev; - if (index->prev) - index->prev->next = index->next; - else - index->map->head = index->next; + if (index->prev) + index->prev->next = index->next; + else + index->map->head = index->next; - /* Free 'char *nextrm' if not NULL */ - if (index->nextrm) - XFREE (MTYPE_ROUTE_MAP_NAME, index->nextrm); + /* Free 'char *nextrm' if not NULL */ + if (index->nextrm) + XFREE(MTYPE_ROUTE_MAP_NAME, index->nextrm); - /* Execute event hook. */ - if (route_map_master.event_hook && notify) - { - (*route_map_master.event_hook) (RMAP_EVENT_INDEX_DELETED, - index->map->name); - route_map_notify_dependencies(index->map->name, RMAP_EVENT_CALL_ADDED); - } - XFREE (MTYPE_ROUTE_MAP_INDEX, index); + /* Execute event hook. */ + if (route_map_master.event_hook && notify) { + (*route_map_master.event_hook)(RMAP_EVENT_INDEX_DELETED, + index->map->name); + route_map_notify_dependencies(index->map->name, + RMAP_EVENT_CALL_ADDED); + } + XFREE(MTYPE_ROUTE_MAP_INDEX, index); } /* Lookup index from route map. */ -static struct route_map_index * -route_map_index_lookup (struct route_map *map, enum route_map_type type, - int pref) +static struct route_map_index *route_map_index_lookup(struct route_map *map, + enum route_map_type type, + int pref) { - struct route_map_index *index; + struct route_map_index *index; - for (index = map->head; index; index = index->next) - if ((index->type == type || type == RMAP_ANY) - && index->pref == pref) - return index; - return NULL; + for (index = map->head; index; index = index->next) + if ((index->type == type || type == RMAP_ANY) + && index->pref == pref) + return index; + return NULL; } /* Add new index to route map. */ static struct route_map_index * -route_map_index_add (struct route_map *map, enum route_map_type type, - int pref) -{ - struct route_map_index *index; - struct route_map_index *point; - - /* Allocate new route map inex. */ - index = route_map_index_new (); - index->map = map; - index->type = type; - index->pref = pref; - - /* Compare preference. */ - for (point = map->head; point; point = point->next) - if (point->pref >= pref) - break; - - if (map->head == NULL) - { - map->head = map->tail = index; - } - else if (point == NULL) - { - index->prev = map->tail; - map->tail->next = index; - map->tail = index; - } - else if (point == map->head) - { - index->next = map->head; - map->head->prev = index; - map->head = index; - } - else - { - index->next = point; - index->prev = point->prev; - if (point->prev) - point->prev->next = index; - point->prev = index; - } - - /* Execute event hook. */ - if (route_map_master.event_hook) - { - (*route_map_master.event_hook) (RMAP_EVENT_INDEX_ADDED, - map->name); - route_map_notify_dependencies (map->name, RMAP_EVENT_CALL_ADDED); - } - return index; +route_map_index_add(struct route_map *map, enum route_map_type type, int pref) +{ + struct route_map_index *index; + struct route_map_index *point; + + /* Allocate new route map inex. */ + index = route_map_index_new(); + index->map = map; + index->type = type; + index->pref = pref; + + /* Compare preference. */ + for (point = map->head; point; point = point->next) + if (point->pref >= pref) + break; + + if (map->head == NULL) { + map->head = map->tail = index; + } else if (point == NULL) { + index->prev = map->tail; + map->tail->next = index; + map->tail = index; + } else if (point == map->head) { + index->next = map->head; + map->head->prev = index; + map->head = index; + } else { + index->next = point; + index->prev = point->prev; + if (point->prev) + point->prev->next = index; + point->prev = index; + } + + /* Execute event hook. */ + if (route_map_master.event_hook) { + (*route_map_master.event_hook)(RMAP_EVENT_INDEX_ADDED, + map->name); + route_map_notify_dependencies(map->name, RMAP_EVENT_CALL_ADDED); + } + return index; } /* Get route map index. */ static struct route_map_index * -route_map_index_get (struct route_map *map, enum route_map_type type, - int pref) +route_map_index_get(struct route_map *map, enum route_map_type type, int pref) { - struct route_map_index *index; + struct route_map_index *index; - index = route_map_index_lookup (map, RMAP_ANY, pref); - if (index && index->type != type) - { - /* Delete index from route map. */ - route_map_index_delete (index, 1); - index = NULL; - } - if (index == NULL) - index = route_map_index_add (map, type, pref); - return index; + index = route_map_index_lookup(map, RMAP_ANY, pref); + if (index && index->type != type) { + /* Delete index from route map. */ + route_map_index_delete(index, 1); + index = NULL; + } + if (index == NULL) + index = route_map_index_add(map, type, pref); + return index; } /* New route map rule */ -static struct route_map_rule * -route_map_rule_new (void) +static struct route_map_rule *route_map_rule_new(void) { - struct route_map_rule *new; + struct route_map_rule *new; - new = XCALLOC (MTYPE_ROUTE_MAP_RULE, sizeof (struct route_map_rule)); - return new; + new = XCALLOC(MTYPE_ROUTE_MAP_RULE, sizeof(struct route_map_rule)); + return new; } /* Install rule command to the match list. */ -void -route_map_install_match (struct route_map_rule_cmd *cmd) +void route_map_install_match(struct route_map_rule_cmd *cmd) { - vector_set (route_match_vec, cmd); + vector_set(route_match_vec, cmd); } /* Install rule command to the set list. */ -void -route_map_install_set (struct route_map_rule_cmd *cmd) +void route_map_install_set(struct route_map_rule_cmd *cmd) { - vector_set (route_set_vec, cmd); + vector_set(route_set_vec, cmd); } /* Lookup rule command from match list. */ -static struct route_map_rule_cmd * -route_map_lookup_match (const char *name) +static struct route_map_rule_cmd *route_map_lookup_match(const char *name) { - unsigned int i; - struct route_map_rule_cmd *rule; + unsigned int i; + struct route_map_rule_cmd *rule; - for (i = 0; i < vector_active (route_match_vec); i++) - if ((rule = vector_slot (route_match_vec, i)) != NULL) - if (strcmp (rule->str, name) == 0) - return rule; - return NULL; + for (i = 0; i < vector_active(route_match_vec); i++) + if ((rule = vector_slot(route_match_vec, i)) != NULL) + if (strcmp(rule->str, name) == 0) + return rule; + return NULL; } /* Lookup rule command from set list. */ -static struct route_map_rule_cmd * -route_map_lookup_set (const char *name) +static struct route_map_rule_cmd *route_map_lookup_set(const char *name) { - unsigned int i; - struct route_map_rule_cmd *rule; + unsigned int i; + struct route_map_rule_cmd *rule; - for (i = 0; i < vector_active (route_set_vec); i++) - if ((rule = vector_slot (route_set_vec, i)) != NULL) - if (strcmp (rule->str, name) == 0) - return rule; - return NULL; + for (i = 0; i < vector_active(route_set_vec); i++) + if ((rule = vector_slot(route_set_vec, i)) != NULL) + if (strcmp(rule->str, name) == 0) + return rule; + return NULL; } /* Add match and set rule to rule list. */ -static void -route_map_rule_add (struct route_map_rule_list *list, - struct route_map_rule *rule) +static void route_map_rule_add(struct route_map_rule_list *list, + struct route_map_rule *rule) { - rule->next = NULL; - rule->prev = list->tail; - if (list->tail) - list->tail->next = rule; - else - list->head = rule; - list->tail = rule; + rule->next = NULL; + rule->prev = list->tail; + if (list->tail) + list->tail->next = rule; + else + list->head = rule; + list->tail = rule; } /* Delete rule from rule list. */ -static void -route_map_rule_delete (struct route_map_rule_list *list, - struct route_map_rule *rule) +static void route_map_rule_delete(struct route_map_rule_list *list, + struct route_map_rule *rule) { - if (rule->cmd->func_free) - (*rule->cmd->func_free) (rule->value); + if (rule->cmd->func_free) + (*rule->cmd->func_free)(rule->value); - if (rule->rule_str) - XFREE (MTYPE_ROUTE_MAP_RULE_STR, rule->rule_str); + if (rule->rule_str) + XFREE(MTYPE_ROUTE_MAP_RULE_STR, rule->rule_str); - if (rule->next) - rule->next->prev = rule->prev; - else - list->tail = rule->prev; - if (rule->prev) - rule->prev->next = rule->next; - else - list->head = rule->next; + if (rule->next) + rule->next->prev = rule->prev; + else + list->tail = rule->prev; + if (rule->prev) + rule->prev->next = rule->next; + else + list->head = rule->next; - XFREE (MTYPE_ROUTE_MAP_RULE, rule); + XFREE(MTYPE_ROUTE_MAP_RULE, rule); } /* strcmp wrapper function which don't crush even argument is NULL. */ -static int -rulecmp (const char *dst, const char *src) -{ - if (dst == NULL) - { - if (src == NULL) - return 0; - else - return 1; - } - else - { - if (src == NULL) +static int rulecmp(const char *dst, const char *src) +{ + if (dst == NULL) { + if (src == NULL) + return 0; + else + return 1; + } else { + if (src == NULL) + return 1; + else + return strcmp(dst, src); + } return 1; - else - return strcmp (dst, src); - } - return 1; } /* Use this to return the already specified argument for this match. This is * useful to get the specified argument with a route map match rule when the * rule is being deleted and the argument is not provided. */ -const char * -route_map_get_match_arg(struct route_map_index *index, const char *match_name) +const char *route_map_get_match_arg(struct route_map_index *index, + const char *match_name) { - struct route_map_rule *rule; - struct route_map_rule_cmd *cmd; + struct route_map_rule *rule; + struct route_map_rule_cmd *cmd; - /* First lookup rule for add match statement. */ - cmd = route_map_lookup_match (match_name); - if (cmd == NULL) - return NULL; + /* First lookup rule for add match statement. */ + cmd = route_map_lookup_match(match_name); + if (cmd == NULL) + return NULL; - for (rule = index->match_list.head; rule; rule = rule->next) - if (rule->cmd == cmd && rule->rule_str != NULL) - return (rule->rule_str); + for (rule = index->match_list.head; rule; rule = rule->next) + if (rule->cmd == cmd && rule->rule_str != NULL) + return (rule->rule_str); - return (NULL); + return (NULL); } /* Add match statement to route map. */ -int -route_map_add_match (struct route_map_index *index, const char *match_name, - const char *match_arg) -{ - struct route_map_rule *rule; - struct route_map_rule *next; - struct route_map_rule_cmd *cmd; - void *compile; - int replaced = 0; - - /* First lookup rule for add match statement. */ - cmd = route_map_lookup_match (match_name); - if (cmd == NULL) - return RMAP_RULE_MISSING; - - /* Next call compile function for this match statement. */ - if (cmd->func_compile) - { - compile= (*cmd->func_compile)(match_arg); - if (compile == NULL) - return RMAP_COMPILE_ERROR; - } - else - compile = NULL; - - /* If argument is completely same ignore it. */ - for (rule = index->match_list.head; rule; rule = next) - { - next = rule->next; - if (rule->cmd == cmd) - { - route_map_rule_delete (&index->match_list, rule); - replaced = 1; +int route_map_add_match(struct route_map_index *index, const char *match_name, + const char *match_arg) +{ + struct route_map_rule *rule; + struct route_map_rule *next; + struct route_map_rule_cmd *cmd; + void *compile; + int replaced = 0; + + /* First lookup rule for add match statement. */ + cmd = route_map_lookup_match(match_name); + if (cmd == NULL) + return RMAP_RULE_MISSING; + + /* Next call compile function for this match statement. */ + if (cmd->func_compile) { + compile = (*cmd->func_compile)(match_arg); + if (compile == NULL) + return RMAP_COMPILE_ERROR; + } else + compile = NULL; + + /* If argument is completely same ignore it. */ + for (rule = index->match_list.head; rule; rule = next) { + next = rule->next; + if (rule->cmd == cmd) { + route_map_rule_delete(&index->match_list, rule); + replaced = 1; + } } - } - /* Add new route map match rule. */ - rule = route_map_rule_new (); - rule->cmd = cmd; - rule->value = compile; - if (match_arg) - rule->rule_str = XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR, match_arg); - else - rule->rule_str = NULL; + /* Add new route map match rule. */ + rule = route_map_rule_new(); + rule->cmd = cmd; + rule->value = compile; + if (match_arg) + rule->rule_str = XSTRDUP(MTYPE_ROUTE_MAP_RULE_STR, match_arg); + else + rule->rule_str = NULL; - /* Add new route match rule to linked list. */ - route_map_rule_add (&index->match_list, rule); + /* Add new route match rule to linked list. */ + route_map_rule_add(&index->match_list, rule); - /* Execute event hook. */ - if (route_map_master.event_hook) - { - (*route_map_master.event_hook) (replaced ? - RMAP_EVENT_MATCH_REPLACED: - RMAP_EVENT_MATCH_ADDED, - index->map->name); - route_map_notify_dependencies(index->map->name, RMAP_EVENT_CALL_ADDED); - } + /* Execute event hook. */ + if (route_map_master.event_hook) { + (*route_map_master.event_hook)( + replaced ? RMAP_EVENT_MATCH_REPLACED + : RMAP_EVENT_MATCH_ADDED, + index->map->name); + route_map_notify_dependencies(index->map->name, + RMAP_EVENT_CALL_ADDED); + } - return 0; + return 0; } /* Delete specified route match rule. */ -int -route_map_delete_match (struct route_map_index *index, const char *match_name, - const char *match_arg) -{ - struct route_map_rule *rule; - struct route_map_rule_cmd *cmd; - - cmd = route_map_lookup_match (match_name); - if (cmd == NULL) - return 1; - - for (rule = index->match_list.head; rule; rule = rule->next) - if (rule->cmd == cmd && - (rulecmp (rule->rule_str, match_arg) == 0 || match_arg == NULL)) - { - route_map_rule_delete (&index->match_list, rule); - /* Execute event hook. */ - if (route_map_master.event_hook) - { - (*route_map_master.event_hook) (RMAP_EVENT_MATCH_DELETED, - index->map->name); - route_map_notify_dependencies(index->map->name, RMAP_EVENT_CALL_ADDED); - } - return 0; - } - /* Can't find matched rule. */ - return 1; +int route_map_delete_match(struct route_map_index *index, + const char *match_name, const char *match_arg) +{ + struct route_map_rule *rule; + struct route_map_rule_cmd *cmd; + + cmd = route_map_lookup_match(match_name); + if (cmd == NULL) + return 1; + + for (rule = index->match_list.head; rule; rule = rule->next) + if (rule->cmd == cmd && (rulecmp(rule->rule_str, match_arg) == 0 + || match_arg == NULL)) { + route_map_rule_delete(&index->match_list, rule); + /* Execute event hook. */ + if (route_map_master.event_hook) { + (*route_map_master.event_hook)( + RMAP_EVENT_MATCH_DELETED, + index->map->name); + route_map_notify_dependencies( + index->map->name, + RMAP_EVENT_CALL_ADDED); + } + return 0; + } + /* Can't find matched rule. */ + return 1; } /* Add route-map set statement to the route map. */ -int -route_map_add_set (struct route_map_index *index, const char *set_name, - const char *set_arg) -{ - struct route_map_rule *rule; - struct route_map_rule *next; - struct route_map_rule_cmd *cmd; - void *compile; - int replaced = 0; - - cmd = route_map_lookup_set (set_name); - if (cmd == NULL) - return RMAP_RULE_MISSING; - - /* Next call compile function for this match statement. */ - if (cmd->func_compile) - { - compile= (*cmd->func_compile)(set_arg); - if (compile == NULL) - return RMAP_COMPILE_ERROR; - } - else - compile = NULL; - - /* Add by WJL. if old set command of same kind exist, delete it first - to ensure only one set command of same kind exist under a - route_map_index. */ - for (rule = index->set_list.head; rule; rule = next) - { - next = rule->next; - if (rule->cmd == cmd) - { - route_map_rule_delete (&index->set_list, rule); - replaced = 1; +int route_map_add_set(struct route_map_index *index, const char *set_name, + const char *set_arg) +{ + struct route_map_rule *rule; + struct route_map_rule *next; + struct route_map_rule_cmd *cmd; + void *compile; + int replaced = 0; + + cmd = route_map_lookup_set(set_name); + if (cmd == NULL) + return RMAP_RULE_MISSING; + + /* Next call compile function for this match statement. */ + if (cmd->func_compile) { + compile = (*cmd->func_compile)(set_arg); + if (compile == NULL) + return RMAP_COMPILE_ERROR; + } else + compile = NULL; + + /* Add by WJL. if old set command of same kind exist, delete it first + to ensure only one set command of same kind exist under a + route_map_index. */ + for (rule = index->set_list.head; rule; rule = next) { + next = rule->next; + if (rule->cmd == cmd) { + route_map_rule_delete(&index->set_list, rule); + replaced = 1; + } + } + + /* Add new route map match rule. */ + rule = route_map_rule_new(); + rule->cmd = cmd; + rule->value = compile; + if (set_arg) + rule->rule_str = XSTRDUP(MTYPE_ROUTE_MAP_RULE_STR, set_arg); + else + rule->rule_str = NULL; + + /* Add new route match rule to linked list. */ + route_map_rule_add(&index->set_list, rule); + + /* Execute event hook. */ + if (route_map_master.event_hook) { + (*route_map_master.event_hook)(replaced + ? RMAP_EVENT_SET_REPLACED + : RMAP_EVENT_SET_ADDED, + index->map->name); + route_map_notify_dependencies(index->map->name, + RMAP_EVENT_CALL_ADDED); } - } - - /* Add new route map match rule. */ - rule = route_map_rule_new (); - rule->cmd = cmd; - rule->value = compile; - if (set_arg) - rule->rule_str = XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR, set_arg); - else - rule->rule_str = NULL; - - /* Add new route match rule to linked list. */ - route_map_rule_add (&index->set_list, rule); - - /* Execute event hook. */ - if (route_map_master.event_hook) - { - (*route_map_master.event_hook) (replaced ? - RMAP_EVENT_SET_REPLACED: - RMAP_EVENT_SET_ADDED, - index->map->name); - route_map_notify_dependencies(index->map->name, RMAP_EVENT_CALL_ADDED); - } - return 0; + return 0; } /* Delete route map set rule. */ -int -route_map_delete_set (struct route_map_index *index, const char *set_name, - const char *set_arg) -{ - struct route_map_rule *rule; - struct route_map_rule_cmd *cmd; - - cmd = route_map_lookup_set (set_name); - if (cmd == NULL) - return 1; - - for (rule = index->set_list.head; rule; rule = rule->next) - if ((rule->cmd == cmd) && - (rulecmp (rule->rule_str, set_arg) == 0 || set_arg == NULL)) - { - route_map_rule_delete (&index->set_list, rule); - /* Execute event hook. */ - if (route_map_master.event_hook) - { - (*route_map_master.event_hook) (RMAP_EVENT_SET_DELETED, - index->map->name); - route_map_notify_dependencies(index->map->name, RMAP_EVENT_CALL_ADDED); - } - return 0; - } - /* Can't find matched rule. */ - return 1; +int route_map_delete_set(struct route_map_index *index, const char *set_name, + const char *set_arg) +{ + struct route_map_rule *rule; + struct route_map_rule_cmd *cmd; + + cmd = route_map_lookup_set(set_name); + if (cmd == NULL) + return 1; + + for (rule = index->set_list.head; rule; rule = rule->next) + if ((rule->cmd == cmd) && (rulecmp(rule->rule_str, set_arg) == 0 + || set_arg == NULL)) { + route_map_rule_delete(&index->set_list, rule); + /* Execute event hook. */ + if (route_map_master.event_hook) { + (*route_map_master.event_hook)( + RMAP_EVENT_SET_DELETED, + index->map->name); + route_map_notify_dependencies( + index->map->name, + RMAP_EVENT_CALL_ADDED); + } + return 0; + } + /* Can't find matched rule. */ + return 1; } /* Apply route map's each index to the object. @@ -1526,20 +1342,20 @@ route_map_delete_set (struct route_map_index *index, const char *set_name, The matrix for a route-map looks like this: (note, this includes the description for the "NEXT" and "GOTO" frobs now - - Match | No Match - | + + Match | No Match + | permit action | cont - | + | ------------------+--------------- - | + | deny deny | cont - | - + | + action) -Apply Set statements, accept route -If Call statement is present jump to the specified route-map, if it - denies the route we finish. + denies the route we finish. -If NEXT is specified, goto NEXT statement -If GOTO is specified, goto the first clause where pref > nextpref -If nothing is specified, do as Cisco and finish @@ -1547,434 +1363,415 @@ route_map_delete_set (struct route_map_index *index, const char *set_name, -Route is denied by route-map. cont) -Goto Next index - + If we get no matches after we've processed all updates, then the route is dropped too. - + Some notes on the new "CALL", "NEXT" and "GOTO" call WORD - If this clause is matched, then the set statements - are executed and then we jump to route-map 'WORD'. If - this route-map denies the route, we finish, in other case we - do whatever the exit policy (EXIT, NEXT or GOTO) tells. + are executed and then we jump to route-map 'WORD'. If + this route-map denies the route, we finish, in other + case we + do whatever the exit policy (EXIT, NEXT or GOTO) tells. on-match next - If this clause is matched, then the set statements - are executed and then we drop through to the next clause + are executed and then we drop through to the next clause on-match goto n - If this clause is matched, then the set statments - are executed and then we goto the nth clause, or the - first clause greater than this. In order to ensure - route-maps *always* exit, you cannot jump backwards. - Sorry ;) - + are executed and then we goto the nth clause, or the + first clause greater than this. In order to ensure + route-maps *always* exit, you cannot jump backwards. + Sorry ;) + We need to make sure our route-map processing matches the above */ static route_map_result_t -route_map_apply_match (struct route_map_rule_list *match_list, - struct prefix *prefix, route_map_object_t type, - void *object) -{ - route_map_result_t ret = RMAP_NOMATCH; - struct route_map_rule *match; - - - /* Check all match rule and if there is no match rule, go to the - set statement. */ - if (!match_list->head) - ret = RMAP_MATCH; - else - { - for (match = match_list->head; match; match = match->next) - { - /* Try each match statement in turn, If any do not return - RMAP_MATCH, return, otherwise continue on to next match - statement. All match statements must match for end-result - to be a match. */ - ret = (*match->cmd->func_apply) (match->value, prefix, - type, object); - if (ret != RMAP_MATCH) - return ret; - } - } - return ret; +route_map_apply_match(struct route_map_rule_list *match_list, + struct prefix *prefix, route_map_object_t type, + void *object) +{ + route_map_result_t ret = RMAP_NOMATCH; + struct route_map_rule *match; + + + /* Check all match rule and if there is no match rule, go to the + set statement. */ + if (!match_list->head) + ret = RMAP_MATCH; + else { + for (match = match_list->head; match; match = match->next) { + /* Try each match statement in turn, If any do not + return + RMAP_MATCH, return, otherwise continue on to next + match + statement. All match statements must match for + end-result + to be a match. */ + ret = (*match->cmd->func_apply)(match->value, prefix, + type, object); + if (ret != RMAP_MATCH) + return ret; + } + } + return ret; } /* Apply route map to the object. */ -route_map_result_t -route_map_apply (struct route_map *map, struct prefix *prefix, - route_map_object_t type, void *object) -{ - static int recursion = 0; - int ret = 0; - struct route_map_index *index; - struct route_map_rule *set; - - if (recursion > RMAP_RECURSION_LIMIT) - { - zlog_warn("route-map recursion limit (%d) reached, discarding route", - RMAP_RECURSION_LIMIT); - recursion = 0; - return RMAP_DENYMATCH; - } - - if (map == NULL) - return RMAP_DENYMATCH; - - for (index = map->head; index; index = index->next) - { - /* Apply this index. */ - ret = route_map_apply_match (&index->match_list, prefix, type, object); - - /* Now we apply the matrix from above */ - if (ret == RMAP_NOMATCH) - /* 'cont' from matrix - continue to next route-map sequence */ - continue; - else if (ret == RMAP_MATCH) - { - if (index->type == RMAP_PERMIT) - /* 'action' */ - { - /* permit+match must execute sets */ - for (set = index->set_list.head; set; set = set->next) - ret = (*set->cmd->func_apply) (set->value, prefix, - type, object); - - /* Call another route-map if available */ - if (index->nextrm) - { - struct route_map *nextrm = - route_map_lookup_by_name (index->nextrm); - - if (nextrm) /* Target route-map found, jump to it */ - { - recursion++; - ret = route_map_apply (nextrm, prefix, type, object); - recursion--; - } - - /* If nextrm returned 'deny', finish. */ - if (ret == RMAP_DENYMATCH) - return ret; - } - - switch (index->exitpolicy) - { - case RMAP_EXIT: - return ret; - case RMAP_NEXT: - continue; - case RMAP_GOTO: - { - /* Find the next clause to jump to */ - struct route_map_index *next = index->next; - int nextpref = index->nextpref; - - while (next && next->pref < nextpref) - { - index = next; - next = next->next; - } - if (next == NULL) - { - /* No clauses match! */ - return ret; - } - } - } - } - else if (index->type == RMAP_DENY) - /* 'deny' */ - { - return RMAP_DENYMATCH; - } - } - } - /* Finally route-map does not match at all. */ - return RMAP_DENYMATCH; -} - -void -route_map_add_hook (void (*func) (const char *)) -{ - route_map_master.add_hook = func; -} - -void -route_map_delete_hook (void (*func) (const char *)) -{ - route_map_master.delete_hook = func; -} - -void -route_map_event_hook (void (*func) (route_map_event_t, const char *)) -{ - route_map_master.event_hook = func; +route_map_result_t route_map_apply(struct route_map *map, struct prefix *prefix, + route_map_object_t type, void *object) +{ + static int recursion = 0; + int ret = 0; + struct route_map_index *index; + struct route_map_rule *set; + + if (recursion > RMAP_RECURSION_LIMIT) { + zlog_warn( + "route-map recursion limit (%d) reached, discarding route", + RMAP_RECURSION_LIMIT); + recursion = 0; + return RMAP_DENYMATCH; + } + + if (map == NULL) + return RMAP_DENYMATCH; + + for (index = map->head; index; index = index->next) { + /* Apply this index. */ + ret = route_map_apply_match(&index->match_list, prefix, type, + object); + + /* Now we apply the matrix from above */ + if (ret == RMAP_NOMATCH) + /* 'cont' from matrix - continue to next route-map + * sequence */ + continue; + else if (ret == RMAP_MATCH) { + if (index->type == RMAP_PERMIT) + /* 'action' */ + { + /* permit+match must execute sets */ + for (set = index->set_list.head; set; + set = set->next) + ret = (*set->cmd->func_apply)( + set->value, prefix, type, + object); + + /* Call another route-map if available */ + if (index->nextrm) { + struct route_map *nextrm = + route_map_lookup_by_name( + index->nextrm); + + if (nextrm) /* Target route-map found, + jump to it */ + { + recursion++; + ret = route_map_apply( + nextrm, prefix, type, + object); + recursion--; + } + + /* If nextrm returned 'deny', finish. */ + if (ret == RMAP_DENYMATCH) + return ret; + } + + switch (index->exitpolicy) { + case RMAP_EXIT: + return ret; + case RMAP_NEXT: + continue; + case RMAP_GOTO: { + /* Find the next clause to jump to */ + struct route_map_index *next = + index->next; + int nextpref = index->nextpref; + + while (next && next->pref < nextpref) { + index = next; + next = next->next; + } + if (next == NULL) { + /* No clauses match! */ + return ret; + } + } + } + } else if (index->type == RMAP_DENY) + /* 'deny' */ + { + return RMAP_DENYMATCH; + } + } + } + /* Finally route-map does not match at all. */ + return RMAP_DENYMATCH; +} + +void route_map_add_hook(void (*func)(const char *)) +{ + route_map_master.add_hook = func; +} + +void route_map_delete_hook(void (*func)(const char *)) +{ + route_map_master.delete_hook = func; +} + +void route_map_event_hook(void (*func)(route_map_event_t, const char *)) +{ + route_map_master.event_hook = func; } /* Routines for route map dependency lists and dependency processing */ -static int -route_map_rmap_hash_cmp (const void *p1, const void *p2) +static int route_map_rmap_hash_cmp(const void *p1, const void *p2) { - return (strcmp((const char *)p1, (const char *)p2) == 0); + return (strcmp((const char *)p1, (const char *)p2) == 0); } -static int -route_map_dep_hash_cmp (const void *p1, const void *p2) +static int route_map_dep_hash_cmp(const void *p1, const void *p2) { - return (strcmp (((const struct route_map_dep *)p1)->dep_name, (const char *)p2) == 0); + return (strcmp(((const struct route_map_dep *)p1)->dep_name, + (const char *)p2) + == 0); } -static void -route_map_clear_reference(struct hash_backet *backet, void *arg) +static void route_map_clear_reference(struct hash_backet *backet, void *arg) { - struct route_map_dep *dep = (struct route_map_dep *)backet->data; - char *rmap_name; + struct route_map_dep *dep = (struct route_map_dep *)backet->data; + char *rmap_name; - if (dep && arg) - { - rmap_name = (char *)hash_release(dep->dep_rmap_hash, (void *)arg); - if (rmap_name) - { - XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + if (dep && arg) { + rmap_name = + (char *)hash_release(dep->dep_rmap_hash, (void *)arg); + if (rmap_name) { + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + } + if (!dep->dep_rmap_hash->count) { + dep = hash_release(dep->this_hash, + (void *)dep->dep_name); + hash_free(dep->dep_rmap_hash); + XFREE(MTYPE_ROUTE_MAP_NAME, dep->dep_name); + XFREE(MTYPE_ROUTE_MAP_DEP, dep); + } } - if (!dep->dep_rmap_hash->count) - { - dep = hash_release(dep->this_hash, (void *)dep->dep_name); - hash_free(dep->dep_rmap_hash); - XFREE(MTYPE_ROUTE_MAP_NAME, dep->dep_name); - XFREE(MTYPE_ROUTE_MAP_DEP, dep); +} + +static void route_map_clear_all_references(char *rmap_name) +{ + int i; + + for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) { + hash_iterate(route_map_dep_hash[i], route_map_clear_reference, + (void *)rmap_name); } - } } -static void -route_map_clear_all_references (char *rmap_name) +static void *route_map_dep_hash_alloc(void *p) { - int i; + char *dep_name = (char *)p; + struct route_map_dep *dep_entry; + + dep_entry = XCALLOC(MTYPE_ROUTE_MAP_DEP, sizeof(struct route_map_dep)); + dep_entry->dep_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, dep_name); + dep_entry->dep_rmap_hash = hash_create(route_map_dep_hash_make_key, + route_map_rmap_hash_cmp, NULL); + dep_entry->this_hash = NULL; + + return ((void *)dep_entry); +} - for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) - { - hash_iterate(route_map_dep_hash[i], route_map_clear_reference, - (void *)rmap_name); - } +static void *route_map_name_hash_alloc(void *p) +{ + return ((void *)XSTRDUP(MTYPE_ROUTE_MAP_NAME, (const char *)p)); } -static void * -route_map_dep_hash_alloc(void *p) +static unsigned int route_map_dep_hash_make_key(void *p) { - char *dep_name = (char *)p; - struct route_map_dep *dep_entry; + return (string_hash_make((char *)p)); +} - dep_entry = XCALLOC(MTYPE_ROUTE_MAP_DEP, sizeof(struct route_map_dep)); - dep_entry->dep_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, dep_name); - dep_entry->dep_rmap_hash = hash_create(route_map_dep_hash_make_key, - route_map_rmap_hash_cmp, NULL); - dep_entry->this_hash = NULL; +static void route_map_print_dependency(struct hash_backet *backet, void *data) +{ + char *rmap_name = (char *)backet->data; + char *dep_name = (char *)data; - return((void *)dep_entry); + if (rmap_name) + zlog_debug("%s: Dependency for %s: %s", __FUNCTION__, dep_name, + rmap_name); } -static void * -route_map_name_hash_alloc(void *p) +static int route_map_dep_update(struct hash *dephash, const char *dep_name, + const char *rmap_name, route_map_event_t type) { - return((void *)XSTRDUP(MTYPE_ROUTE_MAP_NAME, (const char *)p)); + struct route_map_dep *dep = NULL; + char *ret_map_name; + char *dname, *rname; + int ret = 0; + + dname = XSTRDUP(MTYPE_ROUTE_MAP_NAME, dep_name); + rname = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name); + + switch (type) { + case RMAP_EVENT_PLIST_ADDED: + case RMAP_EVENT_CLIST_ADDED: + case RMAP_EVENT_ECLIST_ADDED: + case RMAP_EVENT_ASLIST_ADDED: + case RMAP_EVENT_LLIST_ADDED: + case RMAP_EVENT_CALL_ADDED: + case RMAP_EVENT_FILTER_ADDED: + if (rmap_debug) + zlog_debug("%s: Adding dependency for %s in %s", + __FUNCTION__, dep_name, rmap_name); + dep = (struct route_map_dep *)hash_get( + dephash, dname, route_map_dep_hash_alloc); + if (!dep) { + ret = -1; + goto out; + } + + if (!dep->this_hash) + dep->this_hash = dephash; + + hash_get(dep->dep_rmap_hash, rname, route_map_name_hash_alloc); + break; + case RMAP_EVENT_PLIST_DELETED: + case RMAP_EVENT_CLIST_DELETED: + case RMAP_EVENT_ECLIST_DELETED: + case RMAP_EVENT_ASLIST_DELETED: + case RMAP_EVENT_LLIST_DELETED: + case RMAP_EVENT_CALL_DELETED: + case RMAP_EVENT_FILTER_DELETED: + if (rmap_debug) + zlog_debug("%s: Deleting dependency for %s in %s", + __FUNCTION__, dep_name, rmap_name); + dep = (struct route_map_dep *)hash_get(dephash, dname, NULL); + if (!dep) { + goto out; + } + + ret_map_name = (char *)hash_release(dep->dep_rmap_hash, rname); + if (ret_map_name) + XFREE(MTYPE_ROUTE_MAP_NAME, ret_map_name); + + if (!dep->dep_rmap_hash->count) { + dep = hash_release(dephash, dname); + hash_free(dep->dep_rmap_hash); + XFREE(MTYPE_ROUTE_MAP_NAME, dep->dep_name); + XFREE(MTYPE_ROUTE_MAP_DEP, dep); + dep = NULL; + } + break; + default: + break; + } + + if (dep) { + if (rmap_debug) + hash_iterate(dep->dep_rmap_hash, + route_map_print_dependency, dname); + } + +out: + XFREE(MTYPE_ROUTE_MAP_NAME, rname); + XFREE(MTYPE_ROUTE_MAP_NAME, dname); + return ret; +} + +static struct hash *route_map_get_dep_hash(route_map_event_t event) +{ + struct hash *upd8_hash = NULL; + + switch (event) { + case RMAP_EVENT_PLIST_ADDED: + case RMAP_EVENT_PLIST_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_PLIST]; + break; + case RMAP_EVENT_CLIST_ADDED: + case RMAP_EVENT_CLIST_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_CLIST]; + break; + case RMAP_EVENT_ECLIST_ADDED: + case RMAP_EVENT_ECLIST_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_ECLIST]; + break; + case RMAP_EVENT_ASLIST_ADDED: + case RMAP_EVENT_ASLIST_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_ASPATH]; + break; + case RMAP_EVENT_LLIST_ADDED: + case RMAP_EVENT_LLIST_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_LCLIST]; + break; + case RMAP_EVENT_CALL_ADDED: + case RMAP_EVENT_CALL_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_RMAP]; + break; + case RMAP_EVENT_FILTER_ADDED: + case RMAP_EVENT_FILTER_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_FILTER]; + break; + default: + upd8_hash = NULL; + break; + } + return (upd8_hash); } -static unsigned int -route_map_dep_hash_make_key (void *p) +static void route_map_process_dependency(struct hash_backet *backet, void *data) { - return (string_hash_make((char *)p)); + char *rmap_name; + route_map_event_t type = (route_map_event_t)(ptrdiff_t)data; + + rmap_name = (char *)backet->data; + + if (rmap_name) { + if (rmap_debug) + zlog_debug("%s: Notifying %s of dependency", + __FUNCTION__, rmap_name); + if (route_map_master.event_hook) + (*route_map_master.event_hook)(type, rmap_name); + } } -static void -route_map_print_dependency (struct hash_backet *backet, void *data) +void route_map_upd8_dependency(route_map_event_t type, const char *arg, + const char *rmap_name) { - char *rmap_name = (char *)backet->data; - char *dep_name = (char *)data; + struct hash *upd8_hash = NULL; - if (rmap_name) - zlog_debug("%s: Dependency for %s: %s", __FUNCTION__, dep_name, rmap_name); + if ((upd8_hash = route_map_get_dep_hash(type))) + route_map_dep_update(upd8_hash, arg, rmap_name, type); } -static int -route_map_dep_update (struct hash *dephash, const char *dep_name, - const char *rmap_name, - route_map_event_t type) +void route_map_notify_dependencies(const char *affected_name, + route_map_event_t event) { - struct route_map_dep *dep = NULL; - char *ret_map_name; - char *dname, *rname; - int ret = 0; - - dname = XSTRDUP(MTYPE_ROUTE_MAP_NAME, dep_name); - rname = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name); - - switch (type) - { - case RMAP_EVENT_PLIST_ADDED: - case RMAP_EVENT_CLIST_ADDED: - case RMAP_EVENT_ECLIST_ADDED: - case RMAP_EVENT_ASLIST_ADDED: - case RMAP_EVENT_LLIST_ADDED: - case RMAP_EVENT_CALL_ADDED: - case RMAP_EVENT_FILTER_ADDED: - if (rmap_debug) - zlog_debug("%s: Adding dependency for %s in %s", __FUNCTION__, - dep_name, rmap_name); - dep = (struct route_map_dep *) hash_get (dephash, dname, - route_map_dep_hash_alloc); - if (!dep) { - ret = -1; - goto out; - } - - if (!dep->this_hash) - dep->this_hash = dephash; - - hash_get(dep->dep_rmap_hash, rname, route_map_name_hash_alloc); - break; - case RMAP_EVENT_PLIST_DELETED: - case RMAP_EVENT_CLIST_DELETED: - case RMAP_EVENT_ECLIST_DELETED: - case RMAP_EVENT_ASLIST_DELETED: - case RMAP_EVENT_LLIST_DELETED: - case RMAP_EVENT_CALL_DELETED: - case RMAP_EVENT_FILTER_DELETED: - if (rmap_debug) - zlog_debug("%s: Deleting dependency for %s in %s", __FUNCTION__, - dep_name, rmap_name); - dep = (struct route_map_dep *) hash_get (dephash, dname, NULL); - if (!dep) { - goto out; - } - - ret_map_name = (char *)hash_release(dep->dep_rmap_hash, rname); - if (ret_map_name) - XFREE(MTYPE_ROUTE_MAP_NAME, ret_map_name); - - if (!dep->dep_rmap_hash->count) - { - dep = hash_release(dephash, dname); - hash_free(dep->dep_rmap_hash); - XFREE(MTYPE_ROUTE_MAP_NAME, dep->dep_name); - XFREE(MTYPE_ROUTE_MAP_DEP, dep); - dep = NULL; + struct route_map_dep *dep; + struct hash *upd8_hash; + char *name; + + if (!affected_name) + return; + + name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, affected_name); + + if ((upd8_hash = route_map_get_dep_hash(event)) == NULL) { + XFREE(MTYPE_ROUTE_MAP_NAME, name); + return; } - break; - default: - break; - } - - if (dep) - { - if (rmap_debug) - hash_iterate (dep->dep_rmap_hash, route_map_print_dependency, dname); - } - - out: - XFREE(MTYPE_ROUTE_MAP_NAME, rname); - XFREE(MTYPE_ROUTE_MAP_NAME, dname); - return ret; -} - -static struct hash * -route_map_get_dep_hash (route_map_event_t event) -{ - struct hash *upd8_hash = NULL; - - switch (event) - { - case RMAP_EVENT_PLIST_ADDED: - case RMAP_EVENT_PLIST_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_PLIST]; - break; - case RMAP_EVENT_CLIST_ADDED: - case RMAP_EVENT_CLIST_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_CLIST]; - break; - case RMAP_EVENT_ECLIST_ADDED: - case RMAP_EVENT_ECLIST_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_ECLIST]; - break; - case RMAP_EVENT_ASLIST_ADDED: - case RMAP_EVENT_ASLIST_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_ASPATH]; - break; - case RMAP_EVENT_LLIST_ADDED: - case RMAP_EVENT_LLIST_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_LCLIST]; - break; - case RMAP_EVENT_CALL_ADDED: - case RMAP_EVENT_CALL_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_RMAP]; - break; - case RMAP_EVENT_FILTER_ADDED: - case RMAP_EVENT_FILTER_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_FILTER]; - break; - default: - upd8_hash = NULL; - break; - } - return (upd8_hash); -} - -static void -route_map_process_dependency (struct hash_backet *backet, void *data) -{ - char *rmap_name; - route_map_event_t type = (route_map_event_t)(ptrdiff_t)data; - - rmap_name = (char *)backet->data; - - if (rmap_name) - { - if (rmap_debug) - zlog_debug("%s: Notifying %s of dependency", __FUNCTION__, - rmap_name); - if (route_map_master.event_hook) - (*route_map_master.event_hook) (type, rmap_name); - } -} - -void -route_map_upd8_dependency (route_map_event_t type, const char *arg, - const char *rmap_name) -{ - struct hash *upd8_hash = NULL; - - if ((upd8_hash = route_map_get_dep_hash(type))) - route_map_dep_update (upd8_hash, arg, rmap_name, type); -} - -void -route_map_notify_dependencies (const char *affected_name, route_map_event_t event) -{ - struct route_map_dep *dep; - struct hash *upd8_hash; - char *name; - - if (!affected_name) - return; - - name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, affected_name); - - if ((upd8_hash = route_map_get_dep_hash(event)) == NULL) - { - XFREE (MTYPE_ROUTE_MAP_NAME, name); - return; - } - - dep = (struct route_map_dep *)hash_get (upd8_hash, name, - NULL); - if (dep) - { - if (!dep->this_hash) - dep->this_hash = upd8_hash; - - hash_iterate (dep->dep_rmap_hash, route_map_process_dependency, (void *)event); - } - - XFREE (MTYPE_ROUTE_MAP_NAME, name); + + dep = (struct route_map_dep *)hash_get(upd8_hash, name, NULL); + if (dep) { + if (!dep->this_hash) + dep->this_hash = upd8_hash; + + hash_iterate(dep->dep_rmap_hash, route_map_process_dependency, + (void *)event); + } + + XFREE(MTYPE_ROUTE_MAP_NAME, name); } @@ -1986,12 +1783,14 @@ DEFUN (match_interface, "match first hop interface of route\n" "Interface name\n") { - int idx_word = 2; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 2; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_interface) - return rmap_match_set_hook.match_interface (vty, index, "interface", argv[idx_word]->arg, RMAP_EVENT_MATCH_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_interface) + return rmap_match_set_hook.match_interface( + vty, index, "interface", argv[idx_word]->arg, + RMAP_EVENT_MATCH_ADDED); + return CMD_SUCCESS; } DEFUN (no_match_interface, @@ -2002,12 +1801,14 @@ DEFUN (no_match_interface, "Match first hop interface of route\n" "Interface name\n") { - char *iface = (argc == 4) ? argv[3]->arg : NULL; - VTY_DECLVAR_CONTEXT (route_map_index, index); + char *iface = (argc == 4) ? argv[3]->arg : NULL; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.no_match_interface) - return rmap_match_set_hook.no_match_interface (vty, index, "interface", iface, RMAP_EVENT_MATCH_DELETED); - return CMD_SUCCESS; + if (rmap_match_set_hook.no_match_interface) + return rmap_match_set_hook.no_match_interface( + vty, index, "interface", iface, + RMAP_EVENT_MATCH_DELETED); + return CMD_SUCCESS; } @@ -2021,13 +1822,14 @@ DEFUN (match_ip_address, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - int idx_acl = 3; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_acl = 3; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_ip_address) - return rmap_match_set_hook.match_ip_address (vty, index, "ip address", argv[idx_acl]->arg, - RMAP_EVENT_FILTER_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_ip_address) + return rmap_match_set_hook.match_ip_address( + vty, index, "ip address", argv[idx_acl]->arg, + RMAP_EVENT_FILTER_ADDED); + return CMD_SUCCESS; } @@ -2042,18 +1844,19 @@ DEFUN (no_match_ip_address, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - int idx_word = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); - - if (rmap_match_set_hook.no_match_ip_address) - { - if (argc <= idx_word) - return rmap_match_set_hook.no_match_ip_address (vty, index, "ip address", NULL, - RMAP_EVENT_FILTER_DELETED); - return rmap_match_set_hook.no_match_ip_address (vty, index, "ip address", argv[idx_word]->arg, - RMAP_EVENT_FILTER_DELETED); - } - return CMD_SUCCESS; + int idx_word = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); + + if (rmap_match_set_hook.no_match_ip_address) { + if (argc <= idx_word) + return rmap_match_set_hook.no_match_ip_address( + vty, index, "ip address", NULL, + RMAP_EVENT_FILTER_DELETED); + return rmap_match_set_hook.no_match_ip_address( + vty, index, "ip address", argv[idx_word]->arg, + RMAP_EVENT_FILTER_DELETED); + } + return CMD_SUCCESS; } @@ -2066,13 +1869,14 @@ DEFUN (match_ip_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_ip_address_prefix_list) - return rmap_match_set_hook.match_ip_address_prefix_list (vty, index, "ip address prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_ip_address_prefix_list) + return rmap_match_set_hook.match_ip_address_prefix_list( + vty, index, "ip address prefix-list", + argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); + return CMD_SUCCESS; } @@ -2086,18 +1890,20 @@ DEFUN (no_match_ip_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 5; - VTY_DECLVAR_CONTEXT (route_map_index, index); - - if (rmap_match_set_hook.no_match_ip_address_prefix_list) - { - if (argc <= idx_word) - return rmap_match_set_hook.no_match_ip_address_prefix_list (vty, index, "ip address prefix-list", - NULL, RMAP_EVENT_PLIST_DELETED); - return rmap_match_set_hook.no_match_ip_address_prefix_list(vty, index, "ip address prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED); - } - return CMD_SUCCESS; + int idx_word = 5; + VTY_DECLVAR_CONTEXT(route_map_index, index); + + if (rmap_match_set_hook.no_match_ip_address_prefix_list) { + if (argc <= idx_word) + return rmap_match_set_hook + .no_match_ip_address_prefix_list( + vty, index, "ip address prefix-list", + NULL, RMAP_EVENT_PLIST_DELETED); + return rmap_match_set_hook.no_match_ip_address_prefix_list( + vty, index, "ip address prefix-list", + argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED); + } + return CMD_SUCCESS; } @@ -2111,13 +1917,14 @@ DEFUN (match_ip_next_hop, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - int idx_acl = 3; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_acl = 3; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_ip_next_hop) - return rmap_match_set_hook.match_ip_next_hop (vty, index, "ip next-hop", argv[idx_acl]->arg, - RMAP_EVENT_FILTER_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_ip_next_hop) + return rmap_match_set_hook.match_ip_next_hop( + vty, index, "ip next-hop", argv[idx_acl]->arg, + RMAP_EVENT_FILTER_ADDED); + return CMD_SUCCESS; } @@ -2132,18 +1939,19 @@ DEFUN (no_match_ip_next_hop, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - int idx_word = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); - - if (rmap_match_set_hook.no_match_ip_next_hop) - { - if (argc <= idx_word) - return rmap_match_set_hook.no_match_ip_next_hop (vty, index, "ip next-hop", NULL, - RMAP_EVENT_FILTER_DELETED); - return rmap_match_set_hook.no_match_ip_next_hop (vty, index, "ip next-hop", argv[idx_word]->arg, - RMAP_EVENT_FILTER_DELETED); - } - return CMD_SUCCESS; + int idx_word = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); + + if (rmap_match_set_hook.no_match_ip_next_hop) { + if (argc <= idx_word) + return rmap_match_set_hook.no_match_ip_next_hop( + vty, index, "ip next-hop", NULL, + RMAP_EVENT_FILTER_DELETED); + return rmap_match_set_hook.no_match_ip_next_hop( + vty, index, "ip next-hop", argv[idx_word]->arg, + RMAP_EVENT_FILTER_DELETED); + } + return CMD_SUCCESS; } @@ -2156,13 +1964,14 @@ DEFUN (match_ip_next_hop_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_ip_next_hop_prefix_list) - return rmap_match_set_hook.match_ip_next_hop_prefix_list (vty, index, "ip next-hop prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_ip_next_hop_prefix_list) + return rmap_match_set_hook.match_ip_next_hop_prefix_list( + vty, index, "ip next-hop prefix-list", + argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); + return CMD_SUCCESS; } DEFUN (no_match_ip_next_hop_prefix_list, @@ -2175,18 +1984,19 @@ DEFUN (no_match_ip_next_hop_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 5; - VTY_DECLVAR_CONTEXT (route_map_index, index); - - if (rmap_match_set_hook.no_match_ip_next_hop) - { - if (argc <= idx_word) - return rmap_match_set_hook.no_match_ip_next_hop (vty, index, "ip next-hop prefix-list", - NULL, RMAP_EVENT_PLIST_DELETED); - return rmap_match_set_hook.no_match_ip_next_hop (vty, index, "ip next-hop prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED); - } - return CMD_SUCCESS; + int idx_word = 5; + VTY_DECLVAR_CONTEXT(route_map_index, index); + + if (rmap_match_set_hook.no_match_ip_next_hop) { + if (argc <= idx_word) + return rmap_match_set_hook.no_match_ip_next_hop( + vty, index, "ip next-hop prefix-list", NULL, + RMAP_EVENT_PLIST_DELETED); + return rmap_match_set_hook.no_match_ip_next_hop( + vty, index, "ip next-hop prefix-list", + argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED); + } + return CMD_SUCCESS; } @@ -2198,13 +2008,14 @@ DEFUN (match_ipv6_address, "Match IPv6 address of route\n" "IPv6 access-list name\n") { - int idx_word = 3; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 3; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_ipv6_address) - return rmap_match_set_hook.match_ipv6_address (vty, index, "ipv6 address", argv[idx_word]->arg, - RMAP_EVENT_FILTER_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_ipv6_address) + return rmap_match_set_hook.match_ipv6_address( + vty, index, "ipv6 address", argv[idx_word]->arg, + RMAP_EVENT_FILTER_ADDED); + return CMD_SUCCESS; } DEFUN (no_match_ipv6_address, @@ -2216,13 +2027,14 @@ DEFUN (no_match_ipv6_address, "Match IPv6 address of route\n" "IPv6 access-list name\n") { - int idx_word = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.no_match_ipv6_address) - return rmap_match_set_hook.no_match_ipv6_address (vty, index, "ipv6 address", argv[idx_word]->arg, - RMAP_EVENT_FILTER_DELETED); - return CMD_SUCCESS; + if (rmap_match_set_hook.no_match_ipv6_address) + return rmap_match_set_hook.no_match_ipv6_address( + vty, index, "ipv6 address", argv[idx_word]->arg, + RMAP_EVENT_FILTER_DELETED); + return CMD_SUCCESS; } @@ -2235,13 +2047,14 @@ DEFUN (match_ipv6_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_ipv6_address_prefix_list) - return rmap_match_set_hook.match_ipv6_address_prefix_list (vty, index, "ipv6 address prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_ipv6_address_prefix_list) + return rmap_match_set_hook.match_ipv6_address_prefix_list( + vty, index, "ipv6 address prefix-list", + argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); + return CMD_SUCCESS; } DEFUN (no_match_ipv6_address_prefix_list, @@ -2254,13 +2067,14 @@ DEFUN (no_match_ipv6_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 5; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 5; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.no_match_ipv6_address_prefix_list) - return rmap_match_set_hook.no_match_ipv6_address_prefix_list(vty, index, "ipv6 address prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED); - return CMD_SUCCESS; + if (rmap_match_set_hook.no_match_ipv6_address_prefix_list) + return rmap_match_set_hook.no_match_ipv6_address_prefix_list( + vty, index, "ipv6 address prefix-list", + argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED); + return CMD_SUCCESS; } @@ -2271,13 +2085,14 @@ DEFUN (match_metric, "Match metric of route\n" "Metric value\n") { - int idx_number = 2; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_number = 2; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_metric) - return rmap_match_set_hook.match_metric(vty, index, "metric", argv[idx_number]->arg, - RMAP_EVENT_MATCH_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_metric) + return rmap_match_set_hook.match_metric(vty, index, "metric", + argv[idx_number]->arg, + RMAP_EVENT_MATCH_ADDED); + return CMD_SUCCESS; } @@ -2289,19 +2104,19 @@ DEFUN (no_match_metric, "Match metric of route\n" "Metric value\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (route_map_index, index); - - if (rmap_match_set_hook.no_match_metric) - { - if (argc <= idx_number) - return rmap_match_set_hook.no_match_metric (vty, index, "metric", - NULL, RMAP_EVENT_MATCH_DELETED); - return rmap_match_set_hook.no_match_metric(vty, index, "metric", - argv[idx_number]->arg, - RMAP_EVENT_MATCH_DELETED); - } - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(route_map_index, index); + + if (rmap_match_set_hook.no_match_metric) { + if (argc <= idx_number) + return rmap_match_set_hook.no_match_metric( + vty, index, "metric", NULL, + RMAP_EVENT_MATCH_DELETED); + return rmap_match_set_hook.no_match_metric( + vty, index, "metric", argv[idx_number]->arg, + RMAP_EVENT_MATCH_DELETED); + } + return CMD_SUCCESS; } @@ -2312,13 +2127,14 @@ DEFUN (match_tag, "Match tag of route\n" "Tag value\n") { - int idx_number = 2; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_number = 2; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_tag) - return rmap_match_set_hook.match_tag(vty, index, "tag", argv[idx_number]->arg, - RMAP_EVENT_MATCH_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_tag) + return rmap_match_set_hook.match_tag(vty, index, "tag", + argv[idx_number]->arg, + RMAP_EVENT_MATCH_ADDED); + return CMD_SUCCESS; } @@ -2330,16 +2146,17 @@ DEFUN (no_match_tag, "Match tag of route\n" "Tag value\n") { - VTY_DECLVAR_CONTEXT (route_map_index, index); + VTY_DECLVAR_CONTEXT(route_map_index, index); - int idx = 0; - char *arg = argv_find (argv, argc, "(1-4294967295)", &idx) ? - argv[idx]->arg : NULL; + int idx = 0; + char *arg = argv_find(argv, argc, "(1-4294967295)", &idx) + ? argv[idx]->arg + : NULL; - if (rmap_match_set_hook.no_match_tag) - return rmap_match_set_hook.no_match_tag (vty, index, "tag", arg, - RMAP_EVENT_MATCH_DELETED); - return CMD_SUCCESS; + if (rmap_match_set_hook.no_match_tag) + return rmap_match_set_hook.no_match_tag( + vty, index, "tag", arg, RMAP_EVENT_MATCH_DELETED); + return CMD_SUCCESS; } @@ -2351,28 +2168,27 @@ DEFUN (set_ip_nexthop, "Next hop address\n" "IP address of next hop\n") { - int idx_ipv4 = 3; - union sockunion su; - int ret; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_ipv4 = 3; + union sockunion su; + int ret; + VTY_DECLVAR_CONTEXT(route_map_index, index); - ret = str2sockunion (argv[idx_ipv4]->arg, &su); - if (ret < 0) - { - vty_out (vty, "%% Malformed nexthop address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (su.sin.sin_addr.s_addr == 0 || - IPV4_CLASS_DE(su.sin.sin_addr.s_addr)) - { - vty_out (vty, - "%% nexthop address cannot be 0.0.0.0, multicast or reserved\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = str2sockunion(argv[idx_ipv4]->arg, &su); + if (ret < 0) { + vty_out(vty, "%% Malformed nexthop address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (su.sin.sin_addr.s_addr == 0 + || IPV4_CLASS_DE(su.sin.sin_addr.s_addr)) { + vty_out(vty, + "%% nexthop address cannot be 0.0.0.0, multicast or reserved\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (rmap_match_set_hook.set_ip_nexthop) - return rmap_match_set_hook.set_ip_nexthop(vty, index, "ip next-hop", argv[idx_ipv4]->arg); - return CMD_SUCCESS; + if (rmap_match_set_hook.set_ip_nexthop) + return rmap_match_set_hook.set_ip_nexthop( + vty, index, "ip next-hop", argv[idx_ipv4]->arg); + return CMD_SUCCESS; } @@ -2386,16 +2202,17 @@ DEFUN (no_set_ip_nexthop, "Use peer address (for BGP only)\n" "IP address of next hop\n") { - int idx_peer = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_peer = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.no_set_ip_nexthop) - { - if (argc <= idx_peer) - return rmap_match_set_hook.no_set_ip_nexthop (vty, index, "ip next-hop", NULL); - return rmap_match_set_hook.no_set_ip_nexthop (vty, index, "ip next-hop", argv[idx_peer]->arg); - } - return CMD_SUCCESS; + if (rmap_match_set_hook.no_set_ip_nexthop) { + if (argc <= idx_peer) + return rmap_match_set_hook.no_set_ip_nexthop( + vty, index, "ip next-hop", NULL); + return rmap_match_set_hook.no_set_ip_nexthop( + vty, index, "ip next-hop", argv[idx_peer]->arg); + } + return CMD_SUCCESS; } @@ -2408,26 +2225,25 @@ DEFUN (set_ipv6_nexthop_local, "IPv6 local address\n" "IPv6 address of next hop\n") { - int idx_ipv6 = 4; - struct in6_addr addr; - int ret; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_ipv6 = 4; + struct in6_addr addr; + int ret; + VTY_DECLVAR_CONTEXT(route_map_index, index); - ret = inet_pton (AF_INET6, argv[idx_ipv6]->arg, &addr); - if (!ret) - { - vty_out (vty, "%% Malformed nexthop address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (!IN6_IS_ADDR_LINKLOCAL(&addr)) - { - vty_out (vty, "%% Invalid link-local nexthop address\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = inet_pton(AF_INET6, argv[idx_ipv6]->arg, &addr); + if (!ret) { + vty_out(vty, "%% Malformed nexthop address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (!IN6_IS_ADDR_LINKLOCAL(&addr)) { + vty_out(vty, "%% Invalid link-local nexthop address\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (rmap_match_set_hook.set_ipv6_nexthop_local) - return rmap_match_set_hook.set_ipv6_nexthop_local (vty, index, "ipv6 next-hop local", argv[idx_ipv6]->arg); - return CMD_SUCCESS; + if (rmap_match_set_hook.set_ipv6_nexthop_local) + return rmap_match_set_hook.set_ipv6_nexthop_local( + vty, index, "ipv6 next-hop local", argv[idx_ipv6]->arg); + return CMD_SUCCESS; } @@ -2441,16 +2257,17 @@ DEFUN (no_set_ipv6_nexthop_local, "IPv6 local address\n" "IPv6 address of next hop\n") { - int idx_ipv6 = 5; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_ipv6 = 5; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.no_set_ipv6_nexthop_local) - { - if (argc <= idx_ipv6) - return rmap_match_set_hook.no_set_ipv6_nexthop_local (vty, index, "ipv6 next-hop local", NULL); - return rmap_match_set_hook.no_set_ipv6_nexthop_local (vty, index, "ipv6 next-hop local", argv[5]->arg); - } - return CMD_SUCCESS; + if (rmap_match_set_hook.no_set_ipv6_nexthop_local) { + if (argc <= idx_ipv6) + return rmap_match_set_hook.no_set_ipv6_nexthop_local( + vty, index, "ipv6 next-hop local", NULL); + return rmap_match_set_hook.no_set_ipv6_nexthop_local( + vty, index, "ipv6 next-hop local", argv[5]->arg); + } + return CMD_SUCCESS; } DEFUN (set_metric, @@ -2465,15 +2282,17 @@ DEFUN (set_metric, "Add metric\n" "Subtract metric\n") { - int idx_number = 2; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_number = 2; + VTY_DECLVAR_CONTEXT(route_map_index, index); - const char *pass = (argv[idx_number]->type == RANGE_TKN) ? - argv[idx_number]->arg : argv[idx_number]->text; + const char *pass = (argv[idx_number]->type == RANGE_TKN) + ? argv[idx_number]->arg + : argv[idx_number]->text; - if (rmap_match_set_hook.set_metric) - return rmap_match_set_hook.set_metric (vty, index, "metric", pass); - return CMD_SUCCESS; + if (rmap_match_set_hook.set_metric) + return rmap_match_set_hook.set_metric(vty, index, "metric", + pass); + return CMD_SUCCESS; } @@ -2485,16 +2304,17 @@ DEFUN (no_set_metric, "Metric value for destination routing protocol\n" "Metric value\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_number = 3; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.no_set_metric) - { - if (argc <= idx_number) - return rmap_match_set_hook.no_set_metric (vty, index, "metric", NULL); - return rmap_match_set_hook.no_set_metric (vty, index, "metric", argv[idx_number]->arg); - } - return CMD_SUCCESS; + if (rmap_match_set_hook.no_set_metric) { + if (argc <= idx_number) + return rmap_match_set_hook.no_set_metric( + vty, index, "metric", NULL); + return rmap_match_set_hook.no_set_metric(vty, index, "metric", + argv[idx_number]->arg); + } + return CMD_SUCCESS; } @@ -2505,12 +2325,13 @@ DEFUN (set_tag, "Tag value for routing protocol\n" "Tag value\n") { - VTY_DECLVAR_CONTEXT (route_map_index, index); + VTY_DECLVAR_CONTEXT(route_map_index, index); - int idx_number = 2; - if (rmap_match_set_hook.set_tag) - return rmap_match_set_hook.set_tag (vty, index, "tag", argv[idx_number]->arg); - return CMD_SUCCESS; + int idx_number = 2; + if (rmap_match_set_hook.set_tag) + return rmap_match_set_hook.set_tag(vty, index, "tag", + argv[idx_number]->arg); + return CMD_SUCCESS; } @@ -2522,20 +2343,20 @@ DEFUN (no_set_tag, "Tag value for routing protocol\n" "Tag value\n") { - VTY_DECLVAR_CONTEXT (route_map_index, index); + VTY_DECLVAR_CONTEXT(route_map_index, index); - int idx_number = 3; - if (rmap_match_set_hook.no_set_tag) - { - if (argc <= idx_number) - return rmap_match_set_hook.no_set_tag (vty, index, "tag", NULL); - return rmap_match_set_hook.no_set_tag (vty, index, "tag", argv[idx_number]->arg); - } - return CMD_SUCCESS; + int idx_number = 3; + if (rmap_match_set_hook.no_set_tag) { + if (argc <= idx_number) + return rmap_match_set_hook.no_set_tag(vty, index, "tag", + NULL); + return rmap_match_set_hook.no_set_tag(vty, index, "tag", + argv[idx_number]->arg); + } + return CMD_SUCCESS; } - DEFUN_NOSH (route_map, route_map_cmd, "route-map WORD <deny|permit> (1-65535)", @@ -2545,22 +2366,23 @@ DEFUN_NOSH (route_map, "Route map permits set operations\n" "Sequence to insert to/delete from existing route-map entry\n") { - int idx_word = 1; - int idx_permit_deny = 2; - int idx_number = 3; - struct route_map *map; - struct route_map_index *index; - char *endptr = NULL; - int permit = argv[idx_permit_deny]->arg[0] == 'p' ? RMAP_PERMIT : RMAP_DENY; - unsigned long pref = strtoul (argv[idx_number]->arg, &endptr, 10); - const char *mapname = argv[idx_word]->arg; + int idx_word = 1; + int idx_permit_deny = 2; + int idx_number = 3; + struct route_map *map; + struct route_map_index *index; + char *endptr = NULL; + int permit = + argv[idx_permit_deny]->arg[0] == 'p' ? RMAP_PERMIT : RMAP_DENY; + unsigned long pref = strtoul(argv[idx_number]->arg, &endptr, 10); + const char *mapname = argv[idx_word]->arg; - /* Get route map. */ - map = route_map_get (mapname); - index = route_map_index_get (map, permit, pref); + /* Get route map. */ + map = route_map_get(mapname); + index = route_map_index_get(map, permit, pref); - VTY_PUSH_CONTEXT (RMAP_NODE, index); - return CMD_SUCCESS; + VTY_PUSH_CONTEXT(RMAP_NODE, index); + return CMD_SUCCESS; } DEFUN (no_route_map_all, @@ -2570,20 +2392,19 @@ DEFUN (no_route_map_all, "Create route-map or enter route-map command mode\n" "Route map tag\n") { - int idx_word = 2; - const char *mapname = argv[idx_word]->arg; - struct route_map *map; + int idx_word = 2; + const char *mapname = argv[idx_word]->arg; + struct route_map *map; - map = route_map_lookup_by_name (mapname); - if (map == NULL) - { - vty_out (vty, "%% Could not find route-map %s\n", mapname); - return CMD_WARNING_CONFIG_FAILED; - } + map = route_map_lookup_by_name(mapname); + if (map == NULL) { + vty_out(vty, "%% Could not find route-map %s\n", mapname); + return CMD_WARNING_CONFIG_FAILED; + } - route_map_delete (map); + route_map_delete(map); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_route_map, @@ -2596,43 +2417,42 @@ DEFUN (no_route_map, "Route map permits set operations\n" "Sequence to insert to/delete from existing route-map entry\n") { - int idx_word = 2; - int idx_permit_deny = 3; - int idx_number = 4; - struct route_map *map; - struct route_map_index *index; - char *endptr = NULL; - int permit = strmatch (argv[idx_permit_deny]->text, "permit") ? - RMAP_PERMIT : RMAP_DENY; - const char *prefstr = argv[idx_number]->arg; - const char *mapname = argv[idx_word]->arg; - unsigned long pref = strtoul (prefstr, &endptr, 10); - - /* Existence check. */ - map = route_map_lookup_by_name (mapname); - if (map == NULL) - { - vty_out (vty, "%% Could not find route-map %s\n", mapname); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Lookup route map index. */ - index = route_map_index_lookup (map, permit, pref); - if (index == NULL) - { - vty_out (vty, "%% Could not find route-map entry %s %s\n", - mapname, prefstr); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Delete index from route map. */ - route_map_index_delete (index, 1); - - /* If this route rule is the last one, delete route map itself. */ - if (route_map_empty (map)) - route_map_delete (map); - - return CMD_SUCCESS; + int idx_word = 2; + int idx_permit_deny = 3; + int idx_number = 4; + struct route_map *map; + struct route_map_index *index; + char *endptr = NULL; + int permit = strmatch(argv[idx_permit_deny]->text, "permit") + ? RMAP_PERMIT + : RMAP_DENY; + const char *prefstr = argv[idx_number]->arg; + const char *mapname = argv[idx_word]->arg; + unsigned long pref = strtoul(prefstr, &endptr, 10); + + /* Existence check. */ + map = route_map_lookup_by_name(mapname); + if (map == NULL) { + vty_out(vty, "%% Could not find route-map %s\n", mapname); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Lookup route map index. */ + index = route_map_index_lookup(map, permit, pref); + if (index == NULL) { + vty_out(vty, "%% Could not find route-map entry %s %s\n", + mapname, prefstr); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Delete index from route map. */ + route_map_index_delete(index, 1); + + /* If this route rule is the last one, delete route map itself. */ + if (route_map_empty(map)) + route_map_delete(map); + + return CMD_SUCCESS; } DEFUN (rmap_onmatch_next, @@ -2641,19 +2461,19 @@ DEFUN (rmap_onmatch_next, "Exit policy on matches\n" "Next clause\n") { - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); - - if (index) - { - if (index->type == RMAP_DENY) - { - /* Under a deny clause, match means it's finished. No need to set next */ - vty_out (vty,"on-match next not supported under route-map deny\n"); - return CMD_WARNING_CONFIG_FAILED; - } - index->exitpolicy = RMAP_NEXT; - } - return CMD_SUCCESS; + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); + + if (index) { + if (index->type == RMAP_DENY) { + /* Under a deny clause, match means it's finished. No + * need to set next */ + vty_out(vty, + "on-match next not supported under route-map deny\n"); + return CMD_WARNING_CONFIG_FAILED; + } + index->exitpolicy = RMAP_NEXT; + } + return CMD_SUCCESS; } DEFUN (no_rmap_onmatch_next, @@ -2663,12 +2483,12 @@ DEFUN (no_rmap_onmatch_next, "Exit policy on matches\n" "Next clause\n") { - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); - - if (index) - index->exitpolicy = RMAP_EXIT; + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); + + if (index) + index->exitpolicy = RMAP_EXIT; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (rmap_onmatch_goto, @@ -2678,39 +2498,37 @@ DEFUN (rmap_onmatch_goto, "Goto Clause number\n" "Number\n") { - int idx = 0; - char *num = argv_find (argv, argc, "(1-65535)", &idx) ? argv[idx]->arg : NULL; - - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); - int d = 0; - - if (index) - { - if (index->type == RMAP_DENY) - { - /* Under a deny clause, match means it's finished. No need to go anywhere */ - vty_out (vty,"on-match goto not supported under route-map deny\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (num) - d = strtoul(num, NULL, 10); - else - d = index->pref + 1; - - if (d <= index->pref) - { - /* Can't allow you to do that, Dave */ - vty_out (vty, "can't jump backwards in route-maps\n"); - return CMD_WARNING_CONFIG_FAILED; - } - else - { - index->exitpolicy = RMAP_GOTO; - index->nextpref = d; + int idx = 0; + char *num = argv_find(argv, argc, "(1-65535)", &idx) ? argv[idx]->arg + : NULL; + + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); + int d = 0; + + if (index) { + if (index->type == RMAP_DENY) { + /* Under a deny clause, match means it's finished. No + * need to go anywhere */ + vty_out(vty, + "on-match goto not supported under route-map deny\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (num) + d = strtoul(num, NULL, 10); + else + d = index->pref + 1; + + if (d <= index->pref) { + /* Can't allow you to do that, Dave */ + vty_out(vty, "can't jump backwards in route-maps\n"); + return CMD_WARNING_CONFIG_FAILED; + } else { + index->exitpolicy = RMAP_GOTO; + index->nextpref = d; + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_rmap_onmatch_goto, @@ -2720,12 +2538,12 @@ DEFUN (no_rmap_onmatch_goto, "Exit policy on matches\n" "Goto Clause number\n") { - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); - if (index) - index->exitpolicy = RMAP_EXIT; - - return CMD_SUCCESS; + if (index) + index->exitpolicy = RMAP_EXIT; + + return CMD_SUCCESS; } /* Cisco/GNU Zebra compatibility aliases */ @@ -2736,7 +2554,7 @@ DEFUN (rmap_continue, "Continue on a different entry within the route-map\n" "Route-map entry sequence number\n") { - return rmap_onmatch_goto (self, vty, argc, argv); + return rmap_onmatch_goto(self, vty, argc, argv); } /* ALIAS_FIXME */ @@ -2747,7 +2565,7 @@ DEFUN (no_rmap_continue, "Continue on a different entry within the route-map\n" "Route-map entry sequence number\n") { - return no_rmap_onmatch_goto (self, vty, argc, argv); + return no_rmap_onmatch_goto(self, vty, argc, argv); } @@ -2758,9 +2576,9 @@ DEFUN (rmap_show_name, "route-map information\n" "route-map name\n") { - int idx_word = 2; - const char *name = (argc == 3) ? argv[idx_word]->arg : NULL; - return vty_show_route_map (vty, name); + int idx_word = 2; + const char *name = (argc == 3) ? argv[idx_word]->arg : NULL; + return vty_show_route_map(vty, name); } DEFUN (rmap_call, @@ -2769,26 +2587,23 @@ DEFUN (rmap_call, "Jump to another Route-Map after match+set\n" "Target route-map name\n") { - int idx_word = 1; - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); - const char *rmap = argv[idx_word]->arg; + int idx_word = 1; + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); + const char *rmap = argv[idx_word]->arg; - assert(index); + assert(index); - if (index->nextrm) - { - route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED, - index->nextrm, - index->map->name); - XFREE (MTYPE_ROUTE_MAP_NAME, index->nextrm); - } - index->nextrm = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap); + if (index->nextrm) { + route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED, + index->nextrm, index->map->name); + XFREE(MTYPE_ROUTE_MAP_NAME, index->nextrm); + } + index->nextrm = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - /* Execute event hook. */ - route_map_upd8_dependency (RMAP_EVENT_CALL_ADDED, - index->nextrm, - index->map->name); - return CMD_SUCCESS; + /* Execute event hook. */ + route_map_upd8_dependency(RMAP_EVENT_CALL_ADDED, index->nextrm, + index->map->name); + return CMD_SUCCESS; } DEFUN (no_rmap_call, @@ -2797,18 +2612,16 @@ DEFUN (no_rmap_call, NO_STR "Jump to another Route-Map after match+set\n") { - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); - if (index->nextrm) - { - route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED, - index->nextrm, - index->map->name); - XFREE (MTYPE_ROUTE_MAP_NAME, index->nextrm); - index->nextrm = NULL; - } + if (index->nextrm) { + route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED, + index->nextrm, index->map->name); + XFREE(MTYPE_ROUTE_MAP_NAME, index->nextrm); + index->nextrm = NULL; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (rmap_description, @@ -2817,16 +2630,15 @@ DEFUN (rmap_description, "Route-map comment\n" "Comment describing this route-map rule\n") { - int idx_line = 1; - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); + int idx_line = 1; + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); - if (index) - { - if (index->description) - XFREE (MTYPE_TMP, index->description); - index->description = argv_concat (argv, argc, idx_line); - } - return CMD_SUCCESS; + if (index) { + if (index->description) + XFREE(MTYPE_TMP, index->description); + index->description = argv_concat(argv, argc, idx_line); + } + return CMD_SUCCESS; } DEFUN (no_rmap_description, @@ -2835,233 +2647,214 @@ DEFUN (no_rmap_description, NO_STR "Route-map comment\n") { - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); - if (index) - { - if (index->description) - XFREE (MTYPE_TMP, index->description); - index->description = NULL; - } - return CMD_SUCCESS; + if (index) { + if (index->description) + XFREE(MTYPE_TMP, index->description); + index->description = NULL; + } + return CMD_SUCCESS; } /* Configuration write function. */ -static int -route_map_config_write (struct vty *vty) -{ - struct route_map *map; - struct route_map_index *index; - struct route_map_rule *rule; - int first = 1; - int write = 0; - - for (map = route_map_master.head; map; map = map->next) - for (index = map->head; index; index = index->next) - { - if (!first) - vty_out (vty, "!\n"); - else - first = 0; - - vty_out (vty, "route-map %s %s %d\n", - map->name, - route_map_type_str (index->type), - index->pref); - - if (index->description) - vty_out (vty, " description %s\n", index->description); - - for (rule = index->match_list.head; rule; rule = rule->next) - vty_out (vty, " match %s %s\n", rule->cmd->str, - rule->rule_str ? rule->rule_str : ""); - - for (rule = index->set_list.head; rule; rule = rule->next) - vty_out (vty, " set %s %s\n", rule->cmd->str, - rule->rule_str ? rule->rule_str : ""); - if (index->nextrm) - vty_out (vty, " call %s\n", index->nextrm); - if (index->exitpolicy == RMAP_GOTO) - vty_out (vty, " on-match goto %d\n", index->nextpref); - if (index->exitpolicy == RMAP_NEXT) - vty_out (vty," on-match next\n"); - - write++; - } - return write; +static int route_map_config_write(struct vty *vty) +{ + struct route_map *map; + struct route_map_index *index; + struct route_map_rule *rule; + int first = 1; + int write = 0; + + for (map = route_map_master.head; map; map = map->next) + for (index = map->head; index; index = index->next) { + if (!first) + vty_out(vty, "!\n"); + else + first = 0; + + vty_out(vty, "route-map %s %s %d\n", map->name, + route_map_type_str(index->type), index->pref); + + if (index->description) + vty_out(vty, " description %s\n", + index->description); + + for (rule = index->match_list.head; rule; + rule = rule->next) + vty_out(vty, " match %s %s\n", rule->cmd->str, + rule->rule_str ? rule->rule_str : ""); + + for (rule = index->set_list.head; rule; + rule = rule->next) + vty_out(vty, " set %s %s\n", rule->cmd->str, + rule->rule_str ? rule->rule_str : ""); + if (index->nextrm) + vty_out(vty, " call %s\n", index->nextrm); + if (index->exitpolicy == RMAP_GOTO) + vty_out(vty, " on-match goto %d\n", + index->nextpref); + if (index->exitpolicy == RMAP_NEXT) + vty_out(vty, " on-match next\n"); + + write++; + } + return write; } /* Route map node structure. */ -static struct cmd_node rmap_node = -{ - RMAP_NODE, - "%s(config-route-map)# ", - 1 -}; +static struct cmd_node rmap_node = {RMAP_NODE, "%s(config-route-map)# ", 1}; /* Common route map rules */ -void * -route_map_rule_tag_compile (const char *arg) +void *route_map_rule_tag_compile(const char *arg) { - unsigned long int tmp; - char *endptr; - route_tag_t *tag; + unsigned long int tmp; + char *endptr; + route_tag_t *tag; - errno = 0; - tmp = strtoul(arg, &endptr, 0); - if (arg[0] == '\0' || *endptr != '\0' || errno || tmp > ROUTE_TAG_MAX) - return NULL; + errno = 0; + tmp = strtoul(arg, &endptr, 0); + if (arg[0] == '\0' || *endptr != '\0' || errno || tmp > ROUTE_TAG_MAX) + return NULL; - tag = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*tag)); - *tag = tmp; + tag = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*tag)); + *tag = tmp; - return tag; + return tag; } -void -route_map_rule_tag_free (void *rule) +void route_map_rule_tag_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -void -route_map_finish (void) +void route_map_finish(void) { - int i; + int i; - vector_free (route_match_vec); - route_match_vec = NULL; - vector_free (route_set_vec); - route_set_vec = NULL; + vector_free(route_match_vec); + route_match_vec = NULL; + vector_free(route_set_vec); + route_set_vec = NULL; - /* cleanup route_map */ - while (route_map_master.head) - { - struct route_map *map = route_map_master.head; - map->to_be_processed = 0; - route_map_delete (map); - } + /* cleanup route_map */ + while (route_map_master.head) { + struct route_map *map = route_map_master.head; + map->to_be_processed = 0; + route_map_delete(map); + } - for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) - { - hash_free(route_map_dep_hash[i]); - route_map_dep_hash[i] = NULL; - } + for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) { + hash_free(route_map_dep_hash[i]); + route_map_dep_hash[i] = NULL; + } - hash_free (route_map_master_hash); - route_map_master_hash = NULL; + hash_free(route_map_master_hash); + route_map_master_hash = NULL; } static void rmap_autocomplete(vector comps, struct cmd_token *token) { - struct route_map *map; + struct route_map *map; - for (map = route_map_master.head; map; map = map->next) - vector_set (comps, XSTRDUP (MTYPE_COMPLETION, map->name)); + for (map = route_map_master.head; map; map = map->next) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, map->name)); } static const struct cmd_variable_handler rmap_var_handlers[] = { - { - /* "route-map WORD" */ - .varname = "route_map", - .completions = rmap_autocomplete - }, { - .tokenname = "ROUTEMAP_NAME", - .completions = rmap_autocomplete - }, { - .tokenname = "RMAP_NAME", - .completions = rmap_autocomplete - }, { - .completions = NULL - } -}; + {/* "route-map WORD" */ + .varname = "route_map", + .completions = rmap_autocomplete}, + {.tokenname = "ROUTEMAP_NAME", .completions = rmap_autocomplete}, + {.tokenname = "RMAP_NAME", .completions = rmap_autocomplete}, + {.completions = NULL}}; /* Initialization of route map vector. */ -void -route_map_init (void) +void route_map_init(void) { - int i; + int i; + + /* Make vector for match and set. */ + route_match_vec = vector_init(1); + route_set_vec = vector_init(1); + route_map_master_hash = + hash_create(route_map_hash_key_make, route_map_hash_cmp, NULL); + + for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) + route_map_dep_hash[i] = + hash_create(route_map_dep_hash_make_key, + route_map_dep_hash_cmp, NULL); - /* Make vector for match and set. */ - route_match_vec = vector_init (1); - route_set_vec = vector_init (1); - route_map_master_hash = hash_create(route_map_hash_key_make, route_map_hash_cmp, NULL); + cmd_variable_handler_register(rmap_var_handlers); - for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) - route_map_dep_hash[i] = hash_create(route_map_dep_hash_make_key, - route_map_dep_hash_cmp, NULL); + /* Install route map top node. */ + install_node(&rmap_node, route_map_config_write); - cmd_variable_handler_register(rmap_var_handlers); + /* Install route map commands. */ + install_default(RMAP_NODE); + install_element(CONFIG_NODE, &route_map_cmd); + install_element(CONFIG_NODE, &no_route_map_cmd); + install_element(CONFIG_NODE, &no_route_map_all_cmd); - /* Install route map top node. */ - install_node (&rmap_node, route_map_config_write); + /* Install the on-match stuff */ + install_element(RMAP_NODE, &route_map_cmd); + install_element(RMAP_NODE, &rmap_onmatch_next_cmd); + install_element(RMAP_NODE, &no_rmap_onmatch_next_cmd); + install_element(RMAP_NODE, &rmap_onmatch_goto_cmd); + install_element(RMAP_NODE, &no_rmap_onmatch_goto_cmd); + install_element(RMAP_NODE, &rmap_continue_cmd); + install_element(RMAP_NODE, &no_rmap_continue_cmd); - /* Install route map commands. */ - install_default (RMAP_NODE); - install_element (CONFIG_NODE, &route_map_cmd); - install_element (CONFIG_NODE, &no_route_map_cmd); - install_element (CONFIG_NODE, &no_route_map_all_cmd); + /* Install the continue stuff (ALIAS of on-match). */ - /* Install the on-match stuff */ - install_element (RMAP_NODE, &route_map_cmd); - install_element (RMAP_NODE, &rmap_onmatch_next_cmd); - install_element (RMAP_NODE, &no_rmap_onmatch_next_cmd); - install_element (RMAP_NODE, &rmap_onmatch_goto_cmd); - install_element (RMAP_NODE, &no_rmap_onmatch_goto_cmd); - install_element (RMAP_NODE, &rmap_continue_cmd); - install_element (RMAP_NODE, &no_rmap_continue_cmd); - - /* Install the continue stuff (ALIAS of on-match). */ - - /* Install the call stuff. */ - install_element (RMAP_NODE, &rmap_call_cmd); - install_element (RMAP_NODE, &no_rmap_call_cmd); + /* Install the call stuff. */ + install_element(RMAP_NODE, &rmap_call_cmd); + install_element(RMAP_NODE, &no_rmap_call_cmd); - /* Install description commands. */ - install_element (RMAP_NODE, &rmap_description_cmd); - install_element (RMAP_NODE, &no_rmap_description_cmd); - - /* Install show command */ - install_element (ENABLE_NODE, &rmap_show_name_cmd); + /* Install description commands. */ + install_element(RMAP_NODE, &rmap_description_cmd); + install_element(RMAP_NODE, &no_rmap_description_cmd); - install_element (RMAP_NODE, &match_interface_cmd); - install_element (RMAP_NODE, &no_match_interface_cmd); + /* Install show command */ + install_element(ENABLE_NODE, &rmap_show_name_cmd); - install_element (RMAP_NODE, &match_ip_address_cmd); - install_element (RMAP_NODE, &no_match_ip_address_cmd); + install_element(RMAP_NODE, &match_interface_cmd); + install_element(RMAP_NODE, &no_match_interface_cmd); - install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd); - install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd); + install_element(RMAP_NODE, &match_ip_address_cmd); + install_element(RMAP_NODE, &no_match_ip_address_cmd); - install_element (RMAP_NODE, &match_ip_next_hop_cmd); - install_element (RMAP_NODE, &no_match_ip_next_hop_cmd); + install_element(RMAP_NODE, &match_ip_address_prefix_list_cmd); + install_element(RMAP_NODE, &no_match_ip_address_prefix_list_cmd); - install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd); - install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd); + install_element(RMAP_NODE, &match_ip_next_hop_cmd); + install_element(RMAP_NODE, &no_match_ip_next_hop_cmd); - install_element (RMAP_NODE, &match_ipv6_address_cmd); - install_element (RMAP_NODE, &no_match_ipv6_address_cmd); + install_element(RMAP_NODE, &match_ip_next_hop_prefix_list_cmd); + install_element(RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd); - install_element (RMAP_NODE, &match_ipv6_address_prefix_list_cmd); - install_element (RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd); + install_element(RMAP_NODE, &match_ipv6_address_cmd); + install_element(RMAP_NODE, &no_match_ipv6_address_cmd); - install_element (RMAP_NODE, &match_metric_cmd); - install_element (RMAP_NODE, &no_match_metric_cmd); + install_element(RMAP_NODE, &match_ipv6_address_prefix_list_cmd); + install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd); - install_element (RMAP_NODE, &match_tag_cmd); - install_element (RMAP_NODE, &no_match_tag_cmd); + install_element(RMAP_NODE, &match_metric_cmd); + install_element(RMAP_NODE, &no_match_metric_cmd); - install_element (RMAP_NODE, &set_ip_nexthop_cmd); - install_element (RMAP_NODE, &no_set_ip_nexthop_cmd); + install_element(RMAP_NODE, &match_tag_cmd); + install_element(RMAP_NODE, &no_match_tag_cmd); - install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd); - install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd); + install_element(RMAP_NODE, &set_ip_nexthop_cmd); + install_element(RMAP_NODE, &no_set_ip_nexthop_cmd); - install_element (RMAP_NODE, &set_metric_cmd); - install_element (RMAP_NODE, &no_set_metric_cmd); + install_element(RMAP_NODE, &set_ipv6_nexthop_local_cmd); + install_element(RMAP_NODE, &no_set_ipv6_nexthop_local_cmd); - install_element (RMAP_NODE, &set_tag_cmd); - install_element (RMAP_NODE, &no_set_tag_cmd); + install_element(RMAP_NODE, &set_metric_cmd); + install_element(RMAP_NODE, &no_set_metric_cmd); + install_element(RMAP_NODE, &set_tag_cmd); + install_element(RMAP_NODE, &no_set_tag_cmd); } |