diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/bfd.c | 2 | ||||
-rw-r--r-- | lib/command.c | 41 | ||||
-rw-r--r-- | lib/command.h | 3 | ||||
-rw-r--r-- | lib/ferr.c | 8 | ||||
-rw-r--r-- | lib/filter.c | 56 | ||||
-rw-r--r-- | lib/if.c | 43 | ||||
-rw-r--r-- | lib/if.h | 8 | ||||
-rw-r--r-- | lib/json.c | 24 | ||||
-rw-r--r-- | lib/json.h | 48 | ||||
-rw-r--r-- | lib/log_vty.c | 23 | ||||
-rw-r--r-- | lib/nexthop_group.c | 17 | ||||
-rw-r--r-- | lib/northbound.c | 3 | ||||
-rw-r--r-- | lib/plist.c | 9 | ||||
-rw-r--r-- | lib/routemap.c | 90 | ||||
-rw-r--r-- | lib/routemap.h | 34 | ||||
-rw-r--r-- | lib/routemap_cli.c | 4 | ||||
-rw-r--r-- | lib/vty.c | 18 | ||||
-rw-r--r-- | lib/vty.h | 8 | ||||
-rw-r--r-- | lib/zclient.c | 2 | ||||
-rw-r--r-- | lib/zclient.h | 2 |
20 files changed, 269 insertions, 174 deletions
@@ -801,7 +801,7 @@ void bfd_sess_show(struct vty *vty, struct json_object *json, * * Use this as `zclient` `bfd_dest_replay` callback. */ -int zclient_bfd_session_reply(ZAPI_CALLBACK_ARGS) +int zclient_bfd_session_replay(ZAPI_CALLBACK_ARGS) { struct bfd_session_params *bsp; diff --git a/lib/command.c b/lib/command.c index ea66a17bb..9cf93ea19 100644 --- a/lib/command.c +++ b/lib/command.c @@ -145,31 +145,6 @@ static struct cmd_node config_node = { .node_exit = vty_config_node_exit, }; -static bool vty_check_node_for_xpath_decrement(enum node_type target_node, - enum node_type node) -{ - /* bgp afi-safi (`address-family <afi> <safi>`) node - * does not increment xpath_index. - * In order to use (`router bgp`) BGP_NODE's xpath as a base, - * retain xpath_index as 1 upon exiting from - * afi-safi node. - */ - - if (target_node == BGP_NODE - && (node == BGP_IPV4_NODE || node == BGP_IPV6_NODE - || node == BGP_IPV4M_NODE || node == BGP_IPV6M_NODE - || node == BGP_VPNV4_NODE || node == BGP_VPNV6_NODE - || node == BGP_EVPN_NODE || node == BGP_IPV4L_NODE - || node == BGP_IPV6L_NODE || node == BGP_FLOWSPECV4_NODE - || node == BGP_FLOWSPECV6_NODE)) - return false; - - if (target_node == INTERFACE_NODE && node == LINK_PARAMS_NODE) - return false; - - return true; -} - /* This is called from main when a daemon is invoked with -v or --version. */ void print_version(const char *progname) { @@ -922,13 +897,15 @@ static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter, * a match before calling node_exit handlers below */ for (i = 0; i < up_level; i++) { + struct cmd_node *cnode; + if (node <= CONFIG_NODE) return CMD_NO_LEVEL_UP; + cnode = vector_slot(cmdvec, node); node = node_parent(node); - if (xpath_index > 0 - && vty_check_node_for_xpath_decrement(node, vty->node)) + if (xpath_index > 0 && !cnode->no_xpath) xpath_index--; } @@ -1062,12 +1039,13 @@ int cmd_execute_command(vector vline, struct vty *vty, /* This assumes all nodes above CONFIG_NODE are childs of * CONFIG_NODE */ while (vty->node > CONFIG_NODE) { + struct cmd_node *cnode = vector_slot(cmdvec, try_node); + try_node = node_parent(try_node); vty->node = try_node; - if (vty->xpath_index > 0 - && vty_check_node_for_xpath_decrement(try_node, - onode)) + if (vty->xpath_index > 0 && !cnode->no_xpath) vty->xpath_index--; + ret = cmd_execute_command_real(vline, FILTER_RELAXED, vty, cmd, 0); if (ret == CMD_SUCCESS || ret == CMD_WARNING @@ -1386,8 +1364,7 @@ void cmd_exit(struct vty *vty) } if (cnode->parent_node) vty->node = cnode->parent_node; - if (vty->xpath_index > 0 - && vty_check_node_for_xpath_decrement(vty->node, cnode->node)) + if (vty->xpath_index > 0 && !cnode->no_xpath) vty->xpath_index--; } diff --git a/lib/command.h b/lib/command.h index e2086701a..c888356d6 100644 --- a/lib/command.h +++ b/lib/command.h @@ -213,6 +213,9 @@ struct cmd_node { /* set as soon as any command is in cmdgraph */ bool graph_built; + + /* don't decrement vty->xpath_index on leaving this node */ + bool no_xpath; }; /* Return value of the commands. */ diff --git a/lib/ferr.c b/lib/ferr.c index 513ef5ebe..e5b6d7552 100644 --- a/lib/ferr.c +++ b/lib/ferr.c @@ -157,13 +157,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json) } } - if (json) { - const char *str = json_object_to_json_string_ext( - top, JSON_C_TO_STRING_PRETTY); - vty_out(vty, "%s\n", str); - json_object_free(top); - } - + vty_json(vty, top); list_delete(&errlist); } diff --git a/lib/filter.c b/lib/filter.c index 9c80808fe..fc4b578e7 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -558,18 +558,12 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi, json_rule); else { if (json) { - char buf[BUFSIZ]; - - json_object_string_add( - json_rule, "address", - inet_ntop(AF_INET, - &filter->addr, buf, - sizeof(buf))); - json_object_string_add( - json_rule, "mask", - inet_ntop(AF_INET, - &filter->addr_mask, - buf, sizeof(buf))); + json_object_string_addf( + json_rule, "address", "%pI4", + &filter->addr); + json_object_string_addf( + json_rule, "mask", "%pI4", + &filter->addr_mask); } else { if (filter->addr_mask.s_addr == 0xffffffff) @@ -589,14 +583,7 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi, } } - if (json) { - vty_out(vty, "%s\n", - json_object_to_json_string_ext( - json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - - return CMD_SUCCESS; + return vty_json(vty, json); } /* show MAC access list - this only has MAC filters for now*/ @@ -681,21 +668,15 @@ static void config_write_access_cisco(struct vty *vty, struct filter *mfilter, filter = &mfilter->u.cfilter; if (json) { - char buf[BUFSIZ]; - json_object_boolean_add(json, "extended", !!filter->extended); - json_object_string_add( - json, "sourceAddress", - inet_ntop(AF_INET, &filter->addr, buf, sizeof(buf))); - json_object_string_add(json, "sourceMask", - inet_ntop(AF_INET, &filter->addr_mask, - buf, sizeof(buf))); - json_object_string_add( - json, "destinationAddress", - inet_ntop(AF_INET, &filter->mask, buf, sizeof(buf))); - json_object_string_add(json, "destinationMask", - inet_ntop(AF_INET, &filter->mask_mask, - buf, sizeof(buf))); + json_object_string_addf(json, "sourceAddress", "%pI4", + &filter->addr); + json_object_string_addf(json, "sourceMask", "%pI4", + &filter->addr_mask); + json_object_string_addf(json, "destinationAddress", "%pI4", + &filter->mask); + json_object_string_addf(json, "destinationMask", "%pI4", + &filter->mask_mask); } else { vty_out(vty, " ip"); if (filter->addr_mask.s_addr == 0xffffffff) @@ -730,16 +711,13 @@ static void config_write_access_zebra(struct vty *vty, struct filter *mfilter, p = &filter->prefix; if (json) { - json_object_string_add(json, "prefix", - prefix2str(p, buf, sizeof(buf))); + json_object_string_addf(json, "prefix", "%pFX", p); json_object_boolean_add(json, "exact-match", !!filter->exact); } else { if (p->prefixlen == 0 && !filter->exact) vty_out(vty, " any"); else if (p->family == AF_INET6 || p->family == AF_INET) - vty_out(vty, " %s/%d%s", - inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen, + vty_out(vty, " %pFX%s", p, filter->exact ? " exact-match" : ""); else if (p->family == AF_ETHERNET) { if (p->prefixlen == 0) @@ -455,36 +455,51 @@ static struct interface *if_lookup_by_index_all_vrf(ifindex_t ifindex) return NULL; } -/* Lookup interface by IP address. */ -struct interface *if_lookup_exact_address(const void *src, int family, +/* Lookup interface by IP address. + * + * supersedes if_lookup_exact_address(), which didn't care about up/down + * state. but all users we have either only care if the address is local + * (=> use if_address_is_local() please), or care about UP interfaces before + * anything else + * + * to accept only UP interfaces, check if_is_up() on the returned ifp. + */ +struct interface *if_lookup_address_local(const void *src, int family, vrf_id_t vrf_id) { struct vrf *vrf = vrf_lookup_by_id(vrf_id); struct listnode *cnode; - struct interface *ifp; + struct interface *ifp, *best_down = NULL; struct prefix *p; struct connected *c; + if (family != AF_INET && family != AF_INET6) + return NULL; + FOR_ALL_INTERFACES (vrf, ifp) { for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { p = c->address; - if (p && (p->family == family)) { - if (family == AF_INET) { - if (IPV4_ADDR_SAME( - &p->u.prefix4, + if (!p || p->family != family) + continue; + + if (family == AF_INET) { + if (!IPV4_ADDR_SAME(&p->u.prefix4, (struct in_addr *)src)) - return ifp; - } else if (family == AF_INET6) { - if (IPV6_ADDR_SAME( - &p->u.prefix6, + continue; + } else if (family == AF_INET6) { + if (!IPV6_ADDR_SAME(&p->u.prefix6, (struct in6_addr *)src)) - return ifp; - } + continue; } + + if (if_is_up(ifp)) + return ifp; + if (!best_down) + best_down = ifp; } } - return NULL; + return best_down; } /* Lookup interface by IP address. */ @@ -511,7 +511,7 @@ extern void if_update_to_new_vrf(struct interface *, vrf_id_t vrf_id); extern struct interface *if_lookup_by_index(ifindex_t, vrf_id_t vrf_id); extern struct interface *if_vrf_lookup_by_index_next(ifindex_t ifindex, vrf_id_t vrf_id); -extern struct interface *if_lookup_exact_address(const void *matchaddr, +extern struct interface *if_lookup_address_local(const void *matchaddr, int family, vrf_id_t vrf_id); extern struct connected *if_lookup_address(const void *matchaddr, int family, vrf_id_t vrf_id); @@ -520,6 +520,12 @@ extern struct interface *if_lookup_prefix(const struct prefix *prefix, size_t if_lookup_by_hwaddr(const uint8_t *hw_addr, size_t addrsz, struct interface ***result, vrf_id_t vrf_id); +static inline bool if_address_is_local(const void *matchaddr, int family, + vrf_id_t vrf_id) +{ + return if_lookup_address_local(matchaddr, family, vrf_id) != NULL; +} + struct vrf; extern struct interface *if_lookup_by_name_vrf(const char *name, struct vrf *vrf); extern struct interface *if_lookup_by_name(const char *ifname, vrf_id_t vrf_id); diff --git a/lib/json.c b/lib/json.c index cfba6ea3b..854a3d59d 100644 --- a/lib/json.c +++ b/lib/json.c @@ -39,17 +39,41 @@ bool use_json(const int argc, struct cmd_token *argv[]) return false; } +struct json_object *json_object_new_stringv(const char *fmt, va_list args) +{ + struct json_object *ret; + char *text, buf[256]; + + text = vasnprintfrr(MTYPE_TMP, buf, sizeof(buf), fmt, args); + ret = json_object_new_string(text); + + if (text != buf) + XFREE(MTYPE_TMP, text); + return ret; +} + void json_array_string_add(json_object *json, const char *str) { json_object_array_add(json, json_object_new_string(str)); } +void json_array_string_addv(json_object *json, const char *fmt, va_list args) +{ + json_object_array_add(json, json_object_new_stringv(fmt, args)); +} + void json_object_string_add(struct json_object *obj, const char *key, const char *s) { json_object_object_add(obj, key, json_object_new_string(s)); } +void json_object_string_addv(struct json_object *obj, const char *key, + const char *fmt, va_list args) +{ + json_object_object_add(obj, key, json_object_new_stringv(fmt, args)); +} + void json_object_int_add(struct json_object *obj, const char *key, int64_t i) { json_object_object_add(obj, key, json_object_new_int64(i)); diff --git a/lib/json.h b/lib/json.h index fe208f4fa..9d33ac7ae 100644 --- a/lib/json.h +++ b/lib/json.h @@ -26,6 +26,7 @@ extern "C" { #endif #include "command.h" +#include "printfrr.h" #include <json-c/json.h> /* @@ -59,6 +60,53 @@ extern struct json_object *json_object_lock(struct json_object *obj); extern void json_object_free(struct json_object *obj); extern void json_array_string_add(json_object *json, const char *str); +/* printfrr => json helpers */ + +PRINTFRR(3, 0) +extern void json_object_string_addv(struct json_object *obj, const char *key, + const char *fmt, va_list args); +PRINTFRR(3, 4) +static inline void json_object_string_addf(struct json_object *obj, + const char *key, const char *fmt, + ...) +{ + va_list args; + + va_start(args, fmt); + json_object_string_addv(obj, key, fmt, args); + va_end(args); +} + +PRINTFRR(2, 0) +extern void json_array_string_addv(json_object *json, const char *fmt, + va_list args); +PRINTFRR(2, 3) +static inline void json_array_string_addf(struct json_object *obj, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + json_array_string_addv(obj, fmt, args); + va_end(args); +} + +PRINTFRR(1, 0) +extern struct json_object *json_object_new_stringv(const char *fmt, + va_list args); +PRINTFRR(1, 2) +static inline struct json_object *json_object_new_stringf(const char *fmt, ...) +{ + struct json_object *ret; + va_list args; + + va_start(args, fmt); + ret = json_object_new_stringv(fmt, args); + va_end(args); + + return ret; +} + #define JSON_STR "JavaScript Object Notation\n" /* NOTE: json-c lib has following commit 316da85 which diff --git a/lib/log_vty.c b/lib/log_vty.c index 991132355..621949ab5 100644 --- a/lib/log_vty.c +++ b/lib/log_vty.c @@ -269,14 +269,14 @@ DEFUN_HIDDEN (no_config_log_monitor, return CMD_SUCCESS; } -DEFPY (debug_uid_backtrace, - debug_uid_backtrace_cmd, - "[no] debug unique-id UID backtrace", - NO_STR - DEBUG_STR - "Options per individual log message, by unique ID\n" - "Log message unique ID (XXXXX-XXXXX)\n" - "Add backtrace to log when message is printed\n") +DEFPY_NOSH (debug_uid_backtrace, + debug_uid_backtrace_cmd, + "[no] debug unique-id UID backtrace", + NO_STR + DEBUG_STR + "Options per individual log message, by unique ID\n" + "Log message unique ID (XXXXX-XXXXX)\n" + "Add backtrace to log when message is printed\n") { struct xrefdata search, *xrd; struct xrefdata_logmsg *xrdl; @@ -285,10 +285,9 @@ DEFPY (debug_uid_backtrace, strlcpy(search.uid, uid, sizeof(search.uid)); xrd = xrefdata_uid_find(&xrefdata_uid, &search); - if (!xrd) { - vty_out(vty, "%% no log message with ID \"%s\" found\n", uid); - return CMD_WARNING; - } + if (!xrd) + return CMD_ERR_NOTHING_TODO; + if (xrd->xref->type != XREFT_LOGMSG) { vty_out(vty, "%% ID \"%s\" is not a log message\n", uid); return CMD_WARNING; diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index af9cd2d79..e8c678ad7 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -1035,7 +1035,6 @@ void nexthop_group_write_nexthop(struct vty *vty, const struct nexthop *nh) void nexthop_group_json_nexthop(json_object *j, const struct nexthop *nh) { - char buf[100]; struct vrf *vrf; json_object *json_backups = NULL; int i; @@ -1046,26 +1045,18 @@ void nexthop_group_json_nexthop(json_object *j, const struct nexthop *nh) ifindex2ifname(nh->ifindex, nh->vrf_id)); break; case NEXTHOP_TYPE_IPV4: - json_object_string_add( - j, "nexthop", - inet_ntop(AF_INET, &nh->gate.ipv4, buf, sizeof(buf))); + json_object_string_addf(j, "nexthop", "%pI4", &nh->gate.ipv4); break; case NEXTHOP_TYPE_IPV4_IFINDEX: - json_object_string_add( - j, "nexthop", - inet_ntop(AF_INET, &nh->gate.ipv4, buf, sizeof(buf))); + json_object_string_addf(j, "nexthop", "%pI4", &nh->gate.ipv4); json_object_string_add(j, "vrfId", ifindex2ifname(nh->ifindex, nh->vrf_id)); break; case NEXTHOP_TYPE_IPV6: - json_object_string_add( - j, "nexthop", - inet_ntop(AF_INET6, &nh->gate.ipv6, buf, sizeof(buf))); + json_object_string_addf(j, "nexthop", "%pI6", &nh->gate.ipv6); break; case NEXTHOP_TYPE_IPV6_IFINDEX: - json_object_string_add( - j, "nexthop", - inet_ntop(AF_INET6, &nh->gate.ipv6, buf, sizeof(buf))); + json_object_string_addf(j, "nexthop", "%pI6", &nh->gate.ipv6); json_object_string_add(j, "vrfId", ifindex2ifname(nh->ifindex, nh->vrf_id)); break; diff --git a/lib/northbound.c b/lib/northbound.c index 6edd5184e..49adea6d5 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -830,8 +830,7 @@ int nb_candidate_validate(struct nb_context *context, struct nb_config_cbs changes; int ret; - if (nb_candidate_validate_yang(candidate, errmsg, sizeof(errmsg_len)) - != NB_OK) + if (nb_candidate_validate_yang(candidate, errmsg, errmsg_len) != NB_OK) return NB_ERR_VALIDATION; RB_INIT(nb_config_cbs, &changes); diff --git a/lib/plist.c b/lib/plist.c index a53b087a4..0b3de88d9 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -1127,14 +1127,7 @@ static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name, master, dtype, seqnum); } - if (uj) { - vty_out(vty, "%s\n", - json_object_to_json_string_ext( - json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - - return CMD_SUCCESS; + return vty_json(vty, json); } static int vty_show_prefix_list_prefix(struct vty *vty, afi_t afi, diff --git a/lib/routemap.c b/lib/routemap.c index 6227ebf15..09da095af 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -34,6 +34,7 @@ #include "lib_errors.h" #include "table.h" #include "json.h" +#include "jhash.h" DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP, "Route map"); DEFINE_MTYPE(LIB, ROUTE_MAP_NAME, "Route map name"); @@ -47,6 +48,27 @@ DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_DEP_DATA, "Route map dependency data"); DEFINE_QOBJ_TYPE(route_map_index); DEFINE_QOBJ_TYPE(route_map); +static int rmap_cmd_name_cmp(const struct route_map_rule_cmd_proxy *a, + const struct route_map_rule_cmd_proxy *b) +{ + return strcmp(a->cmd->str, b->cmd->str); +} + +static uint32_t rmap_cmd_name_hash(const struct route_map_rule_cmd_proxy *item) +{ + return jhash(item->cmd->str, strlen(item->cmd->str), 0xbfd69320); +} + +DECLARE_HASH(rmap_cmd_name, struct route_map_rule_cmd_proxy, itm, + rmap_cmd_name_cmp, rmap_cmd_name_hash); + +static struct rmap_cmd_name_head rmap_match_cmds[1] = { + INIT_HASH(rmap_match_cmds[0]), +}; +static struct rmap_cmd_name_head rmap_set_cmds[1] = { + INIT_HASH(rmap_set_cmds[0]), +}; + #define IPv4_PREFIX_LIST "ip address prefix-list" #define IPv6_PREFIX_LIST "ipv6 address prefix-list" @@ -61,12 +83,6 @@ struct route_map_pentry_dep { route_map_event_t event; }; -/* Vector for route match rules. */ -static vector route_match_vec; - -/* Vector for route set rules. */ -static vector route_set_vec; - static void route_map_pfx_tbl_update(route_map_event_t event, struct route_map_index *index, afi_t afi, const char *plist_name); @@ -1026,14 +1042,7 @@ static int vty_show_route_map(struct vty *vty, const char *name, bool use_json) list_delete(&maplist); } - if (use_json) { - vty_out(vty, "%s\n", - json_object_to_json_string_ext( - json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - - return CMD_SUCCESS; + return vty_json(vty, json); } /* Unused route map details */ @@ -1231,40 +1240,40 @@ static struct route_map_rule *route_map_rule_new(void) } /* Install rule command to the match list. */ -void route_map_install_match(const struct route_map_rule_cmd *cmd) +void _route_map_install_match(struct route_map_rule_cmd_proxy *proxy) { - vector_set(route_match_vec, (void *)cmd); + rmap_cmd_name_add(rmap_match_cmds, proxy); } /* Install rule command to the set list. */ -void route_map_install_set(const struct route_map_rule_cmd *cmd) +void _route_map_install_set(struct route_map_rule_cmd_proxy *proxy) { - vector_set(route_set_vec, (void *)cmd); + rmap_cmd_name_add(rmap_set_cmds, proxy); } /* Lookup rule command from match list. */ static const struct route_map_rule_cmd *route_map_lookup_match(const char *name) { - unsigned int i; - const struct route_map_rule_cmd *rule; + struct route_map_rule_cmd refcmd = {.str = name}; + struct route_map_rule_cmd_proxy ref = {.cmd = &refcmd}; + struct route_map_rule_cmd_proxy *res; - 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; + res = rmap_cmd_name_find(rmap_match_cmds, &ref); + if (res) + return res->cmd; return NULL; } /* Lookup rule command from set list. */ static const struct route_map_rule_cmd *route_map_lookup_set(const char *name) { - unsigned int i; - const struct route_map_rule_cmd *rule; + struct route_map_rule_cmd refcmd = {.str = name}; + struct route_map_rule_cmd_proxy ref = {.cmd = &refcmd}; + struct route_map_rule_cmd_proxy *res; - 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; + res = rmap_cmd_name_find(rmap_set_cmds, &ref); + if (res) + return res->cmd; return NULL; } @@ -3161,11 +3170,21 @@ void route_map_rule_tag_free(void *rule) void route_map_finish(void) { int i; + struct route_map_rule_cmd_proxy *proxy; + + /* these 2 hash tables have INIT_HASH initializers, so the "default" + * state is "initialized & empty" => fini() followed by init() to + * return to that same state + */ + while ((proxy = rmap_cmd_name_pop(rmap_match_cmds))) + (void)proxy; + rmap_cmd_name_fini(rmap_match_cmds); + rmap_cmd_name_init(rmap_match_cmds); - vector_free(route_match_vec); - route_match_vec = NULL; - vector_free(route_set_vec); - route_set_vec = NULL; + while ((proxy = rmap_cmd_name_pop(rmap_set_cmds))) + (void)proxy; + rmap_cmd_name_fini(rmap_set_cmds); + rmap_cmd_name_init(rmap_set_cmds); /* * All protocols are setting these to NULL @@ -3309,9 +3328,6 @@ void route_map_init(void) { 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_size(8, route_map_hash_key_make, route_map_hash_cmp, "Route Map Master Hash"); diff --git a/lib/routemap.h b/lib/routemap.h index f8fdc67d5..7e17e14fa 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -21,6 +21,7 @@ #ifndef _ZEBRA_ROUTEMAP_H #define _ZEBRA_ROUTEMAP_H +#include "typesafe.h" #include "prefix.h" #include "memory.h" #include "qobj.h" @@ -422,8 +423,37 @@ extern enum rmap_compile_rets route_map_delete_set(struct route_map_index *index, const char *set_name, const char *set_arg); +/* struct route_map_rule_cmd is kept const in order to not have writable + * function pointers (which is a security benefit.) Hence, below struct is + * used as proxy for hashing these for by-name lookup. + */ + +PREDECL_HASH(rmap_cmd_name); + +struct route_map_rule_cmd_proxy { + struct rmap_cmd_name_item itm; + const struct route_map_rule_cmd *cmd; +}; + +/* ... and just automatically create a proxy struct for each call location + * to route_map_install_{match,set} to avoid unnecessarily added boilerplate + * for each route-map user + */ + +#define route_map_install_match(c) \ + do { \ + static struct route_map_rule_cmd_proxy proxy = {.cmd = c}; \ + _route_map_install_match(&proxy); \ + } while (0) + +#define route_map_install_set(c) \ + do { \ + static struct route_map_rule_cmd_proxy proxy = {.cmd = c}; \ + _route_map_install_set(&proxy); \ + } while (0) + /* Install rule command to the match list. */ -extern void route_map_install_match(const struct route_map_rule_cmd *cmd); +extern void _route_map_install_match(struct route_map_rule_cmd_proxy *proxy); /* * Install rule command to the set list. @@ -434,7 +464,7 @@ extern void route_map_install_match(const struct route_map_rule_cmd *cmd); * in the apply command). See 'set metric' command * as it is handled in ripd/ripngd and ospfd. */ -extern void route_map_install_set(const struct route_map_rule_cmd *cmd); +extern void _route_map_install_set(struct route_map_rule_cmd_proxy *proxy); /* Lookup route map by name. */ extern struct route_map *route_map_lookup_by_name(const char *name); diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c index d7d4a9a81..f85be05f5 100644 --- a/lib/routemap_cli.c +++ b/lib/routemap_cli.c @@ -791,12 +791,12 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode, vty_out(vty, " match extcommunity %s\n", acl); } else if (IS_MATCH_IPV4_NH(condition)) { - vty_out(vty, " match ip next-hop %s\n", + vty_out(vty, " match ip next-hop address %s\n", yang_dnode_get_string( dnode, "./rmap-match-condition/frr-bgp-route-map:ipv4-address")); } else if (IS_MATCH_IPV6_NH(condition)) { - vty_out(vty, " match ipv6 next-hop %s\n", + vty_out(vty, " match ipv6 next-hop address %s\n", yang_dnode_get_string( dnode, "./rmap-match-condition/frr-bgp-route-map:ipv6-address")); @@ -48,6 +48,7 @@ #include "lib_errors.h" #include "northbound_cli.h" #include "printfrr.h" +#include "json.h" #include <arpa/telnet.h> #include <termios.h> @@ -280,6 +281,21 @@ done: return len; } +int vty_json(struct vty *vty, struct json_object *json) +{ + const char *text; + + if (!json) + return CMD_SUCCESS; + + text = json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_NOSLASHESCAPE); + vty_out(vty, "%s\n", text); + json_object_free(json); + + return CMD_SUCCESS; +} + /* Output current time to the vty. */ void vty_time_print(struct vty *vty, int cr) { @@ -2998,7 +3014,7 @@ static void vty_save_cwd(void) * the whole world is coming down around us * Hence not worrying about it too much. */ - if (!chdir(SYSCONFDIR)) { + if (chdir(SYSCONFDIR)) { flog_err_sys(EC_LIB_SYSTEM_CALL, "Failure to chdir to %s, errno: %d", SYSCONFDIR, errno); @@ -39,6 +39,8 @@ extern "C" { #endif +struct json_object; + #define VTY_BUFSIZ 4096 #define VTY_MAXHIST 20 #define VTY_MAXDEPTH 8 @@ -321,7 +323,11 @@ extern struct vty *vty_stdio(void (*atclose)(int isexit)); extern int vty_out(struct vty *, const char *, ...) PRINTFRR(2, 3); extern void vty_frame(struct vty *, const char *, ...) PRINTFRR(2, 3); extern void vty_endframe(struct vty *, const char *); -bool vty_set_include(struct vty *vty, const char *regexp); +extern bool vty_set_include(struct vty *vty, const char *regexp); +/* returns CMD_SUCCESS so you can do a one-line "return vty_json(...)" + * NULL check and json_object_free() is included. + */ +extern int vty_json(struct vty *vty, struct json_object *json); extern bool vty_read_config(struct nb_config *config, const char *config_file, char *config_default_dir); diff --git a/lib/zclient.c b/lib/zclient.c index 24546f3c4..a6103cfee 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -3862,7 +3862,7 @@ static zclient_handler *const lib_handlers[] = { [ZEBRA_INTERFACE_DOWN] = zclient_interface_down, /* BFD */ - [ZEBRA_BFD_DEST_REPLAY] = zclient_bfd_session_reply, + [ZEBRA_BFD_DEST_REPLAY] = zclient_bfd_session_replay, [ZEBRA_INTERFACE_BFD_DEST_UPDATE] = zclient_bfd_session_update, }; diff --git a/lib/zclient.h b/lib/zclient.h index 82eaefda4..ca62b1afe 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -368,7 +368,7 @@ struct zclient { }; /* lib handlers added in bfd.c */ -extern int zclient_bfd_session_reply(ZAPI_CALLBACK_ARGS); +extern int zclient_bfd_session_replay(ZAPI_CALLBACK_ARGS); extern int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS); /* Zebra API message flag. */ |