summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/bfd.c2
-rw-r--r--lib/command.c41
-rw-r--r--lib/command.h3
-rw-r--r--lib/ferr.c8
-rw-r--r--lib/filter.c56
-rw-r--r--lib/if.c43
-rw-r--r--lib/if.h8
-rw-r--r--lib/json.c24
-rw-r--r--lib/json.h48
-rw-r--r--lib/log_vty.c23
-rw-r--r--lib/nexthop_group.c17
-rw-r--r--lib/northbound.c3
-rw-r--r--lib/plist.c9
-rw-r--r--lib/routemap.c90
-rw-r--r--lib/routemap.h34
-rw-r--r--lib/routemap_cli.c4
-rw-r--r--lib/vty.c18
-rw-r--r--lib/vty.h8
-rw-r--r--lib/zclient.c2
-rw-r--r--lib/zclient.h2
20 files changed, 269 insertions, 174 deletions
diff --git a/lib/bfd.c b/lib/bfd.c
index 5b62d9ea2..dea39d2e2 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -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)
diff --git a/lib/if.c b/lib/if.c
index a40f04f5a..6bfbdf914 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -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. */
diff --git a/lib/if.h b/lib/if.h
index 1012bf555..5f0dc2755 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -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"));
diff --git a/lib/vty.c b/lib/vty.c
index b702fa785..8eaf13619 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -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);
diff --git a/lib/vty.h b/lib/vty.h
index 62e251895..9ffbce326 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -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. */