summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_mpath.c11
-rw-r--r--bgpd/bgp_nb_config.c8
-rw-r--r--bgpd/bgp_route.c37
-rw-r--r--bgpd/bgp_route.h2
-rw-r--r--bgpd/bgp_routemap.c39
-rw-r--r--doc/developer/workflow.rst2
-rw-r--r--isisd/isis_lsp.c12
-rw-r--r--isisd/isis_lsp.h4
-rw-r--r--isisd/isis_misc.c77
-rw-r--r--isisd/isis_vty_fabricd.c2
-rw-r--r--lib/northbound.c60
-rw-r--r--lib/northbound.h13
-rw-r--r--lib/prefix.c4
-rw-r--r--lib/prefix.h2
-rw-r--r--lib/routing_nb.h7
-rw-r--r--lib/routing_nb_config.c61
-rw-r--r--lib/vrf.c7
-rw-r--r--lib/vrf.h3
-rw-r--r--lib/vty.c6
-rw-r--r--ospf6d/ospf6_abr.c6
-rw-r--r--ospf6d/ospf6_asbr.c9
-rw-r--r--ospf6d/ospf6_intra.c8
-rw-r--r--pimd/pim_main.c2
-rw-r--r--staticd/static_main.c2
-rw-r--r--tests/topotests/bgp-aggregator-zero/__init__.py0
-rw-r--r--tests/topotests/bgp-aggregator-zero/exabgp.env53
-rw-r--r--tests/topotests/bgp-aggregator-zero/peer1/exabgp.cfg18
-rw-r--r--tests/topotests/bgp-aggregator-zero/r1/bgpd.conf6
-rw-r--r--tests/topotests/bgp-aggregator-zero/r1/zebra.conf6
-rw-r--r--tests/topotests/bgp-aggregator-zero/test_bgp_aggregator_zero.py139
-rw-r--r--zebra/irdp_interface.c18
-rw-r--r--zebra/rt_netlink.c4
32 files changed, 505 insertions, 123 deletions
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index ff5cfe05fb..37639f4bce 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -616,7 +616,8 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest,
all_paths_lb = false;
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- cur_mpath, path_buf);
+ cur_mpath, path_buf,
+ sizeof(path_buf));
zlog_debug(
"%pRN: %s is still multipath, cur count %d",
bgp_dest_to_rnode(dest),
@@ -626,7 +627,8 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest,
mpath_changed = 1;
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- cur_mpath, path_buf);
+ cur_mpath, path_buf,
+ sizeof(path_buf));
zlog_debug(
"%pRN: remove mpath %s nexthop %s, cur count %d",
bgp_dest_to_rnode(dest),
@@ -660,7 +662,7 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest,
mpath_changed = 1;
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- cur_mpath, path_buf);
+ cur_mpath, path_buf, sizeof(path_buf));
zlog_debug(
"%pRN: remove mpath %s nexthop %s, cur count %d",
bgp_dest_to_rnode(dest), path_buf,
@@ -710,7 +712,8 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest,
all_paths_lb = false;
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- new_mpath, path_buf);
+ new_mpath, path_buf,
+ sizeof(path_buf));
zlog_debug(
"%pRN: add mpath %s nexthop %s, cur count %d",
bgp_dest_to_rnode(dest),
diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c
index a3f58db88f..721ce5b5c6 100644
--- a/bgpd/bgp_nb_config.c
+++ b/bgpd/bgp_nb_config.c
@@ -69,7 +69,7 @@ int bgp_router_create(struct nb_cb_create_args *args)
{
const struct lyd_node *vrf_dnode;
struct bgp *bgp;
- struct vrf *vrf;
+ const char *vrf_name;
const char *name = NULL;
as_t as;
enum bgp_instance_type inst_type;
@@ -87,12 +87,12 @@ int bgp_router_create(struct nb_cb_create_args *args)
case NB_EV_APPLY:
vrf_dnode = yang_dnode_get_parent(args->dnode,
"control-plane-protocol");
- vrf = nb_running_get_entry(vrf_dnode, NULL, true);
+ vrf_name = yang_dnode_get_string(vrf_dnode, "./vrf");
- if (strmatch(vrf->name, VRF_DEFAULT_NAME)) {
+ if (strmatch(vrf_name, VRF_DEFAULT_NAME)) {
name = NULL;
} else {
- name = vrf->name;
+ name = vrf_name;
inst_type = BGP_INSTANCE_TYPE_VRF;
}
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 0f135985ed..18a0b3fb7d 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -525,13 +525,14 @@ static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
}
}
-void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
+void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
+ size_t buf_len)
{
if (pi->addpath_rx_id)
- sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
- pi->addpath_rx_id);
+ snprintf(buf, buf_len, "path %s (addpath rxid %d)",
+ pi->peer->host, pi->addpath_rx_id);
else
- sprintf(buf, "path %s", pi->peer->host);
+ snprintf(buf, buf_len, "path %s", pi->peer->host);
}
/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
@@ -582,7 +583,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
if (debug)
- bgp_path_info_path_with_addpath_rx_str(new, new_buf);
+ bgp_path_info_path_with_addpath_rx_str(new, new_buf,
+ sizeof(new_buf));
if (exist == NULL) {
*reason = bgp_path_selection_first;
@@ -593,7 +595,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
if (debug) {
- bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
+ bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
+ sizeof(exist_buf));
zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
pfx_buf, new_buf, new->flags, exist_buf,
exist->flags);
@@ -621,10 +624,10 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
prefix2str(
bgp_dest_get_prefix(new->net), pfx_buf,
sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
- bgp_path_info_path_with_addpath_rx_str(new,
- new_buf);
bgp_path_info_path_with_addpath_rx_str(
- exist, exist_buf);
+ new, new_buf, sizeof(new_buf));
+ bgp_path_info_path_with_addpath_rx_str(
+ exist, exist_buf, sizeof(exist_buf));
}
if (newattr->sticky && !existattr->sticky) {
@@ -2348,7 +2351,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- new_select, path_buf);
+ new_select, path_buf, sizeof(path_buf));
zlog_debug(
"%pBD: %s is the bestpath from AS %u",
dest, path_buf,
@@ -2422,8 +2425,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
*/
if (debug) {
if (new_select)
- bgp_path_info_path_with_addpath_rx_str(new_select,
- path_buf);
+ bgp_path_info_path_with_addpath_rx_str(
+ new_select, path_buf, sizeof(path_buf));
else
snprintf(path_buf, sizeof(path_buf), "NONE");
zlog_debug(
@@ -2438,7 +2441,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
if (debug)
bgp_path_info_path_with_addpath_rx_str(
- pi, path_buf);
+ pi, path_buf, sizeof(path_buf));
if (pi == new_select) {
if (debug)
@@ -6389,7 +6392,8 @@ DEFPY_YANG (bgp_network, bgp_network_cmd,
int ret;
ret = netmask_str2prefix_str(address_str, netmask_str,
- addr_prefix_str);
+ addr_prefix_str,
+ sizeof(addr_prefix_str));
if (!ret) {
vty_out(vty, "%% Inconsistent address and mask\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -7780,7 +7784,8 @@ DEFPY_YANG(
char prefix_buf[PREFIX2STR_BUFFER];
if (addr_str) {
- if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
+ if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
+ sizeof(prefix_buf))
== 0) {
vty_out(vty, "%% Inconsistent address and mask\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -14398,7 +14403,7 @@ DEFUN (clear_ip_bgp_dampening_address_mask,
char prefix_str[BUFSIZ];
ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
- prefix_str);
+ prefix_str, sizeof(prefix_str));
if (!ret) {
vty_out(vty, "%% Inconsistent address and mask\n");
return CMD_WARNING;
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 1060d2e60d..766e5ade92 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -598,7 +598,7 @@ extern void bgp_path_info_set_flag(struct bgp_dest *dest,
extern void bgp_path_info_unset_flag(struct bgp_dest *dest,
struct bgp_path_info *path, uint32_t flag);
extern void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi,
- char *buf);
+ char *buf, size_t buf_len);
extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 3dc2cfbd5c..b7f3289ffc 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -4315,13 +4315,15 @@ DEFUN (match_community,
int idx_comm_list = 2;
int ret;
char *argstr;
+ size_t argstr_len;
if (argc == 4) {
- argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
- strlen(argv[idx_comm_list]->arg)
- + strlen("exact-match") + 2);
+ argstr_len = strlen(argv[idx_comm_list]->arg)
+ + strlen("exact-match") + 2;
+ argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
- sprintf(argstr, "%s exact-match", argv[idx_comm_list]->arg);
+ snprintf(argstr, argstr_len, "%s exact-match",
+ argv[idx_comm_list]->arg);
} else
argstr = argv[idx_comm_list]->arg;
@@ -4362,13 +4364,15 @@ DEFUN (match_lcommunity,
int idx_lcomm_list = 2;
int ret;
char *argstr;
+ size_t argstr_len;
if (argc == 4) {
- argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
- strlen(argv[idx_lcomm_list]->arg)
- + strlen("exact-match") + 2);
+ argstr_len = strlen(argv[idx_lcomm_list]->arg)
+ + strlen("exact-match") + 2;
+ argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
- sprintf(argstr, "%s exact-match", argv[idx_lcomm_list]->arg);
+ snprintf(argstr, argstr_len, "%s exact-match",
+ argv[idx_lcomm_list]->arg);
} else
argstr = argv[idx_lcomm_list]->arg;
@@ -5252,6 +5256,7 @@ DEFUN (set_aggregator_as,
int ret;
struct in_addr address;
char *argstr;
+ size_t argstr_len;
ret = inet_aton(argv[idx_ipv4]->arg, &address);
if (ret == 0) {
@@ -5259,11 +5264,12 @@ DEFUN (set_aggregator_as,
return CMD_WARNING_CONFIG_FAILED;
}
- argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
- strlen(argv[idx_number]->arg)
- + strlen(argv[idx_ipv4]->arg) + 2);
+ argstr_len =
+ strlen(argv[idx_number]->arg) + strlen(argv[idx_ipv4]->arg) + 2;
+ argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
- sprintf(argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
+ snprintf(argstr, argstr_len, "%s %s", argv[idx_number]->arg,
+ argv[idx_ipv4]->arg);
ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
"aggregator as", argstr);
@@ -5289,6 +5295,7 @@ DEFUN (no_set_aggregator_as,
int ret;
struct in_addr address;
char *argstr;
+ size_t argstr_len;
if (argc <= idx_asn)
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
@@ -5300,11 +5307,11 @@ DEFUN (no_set_aggregator_as,
return CMD_WARNING_CONFIG_FAILED;
}
- argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
- strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg)
- + 2);
+ argstr_len = strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg) + 2;
+ argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
- sprintf(argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
+ snprintf(argstr, argstr_len, "%s %s", argv[idx_asn]->arg,
+ argv[idx_ip]->arg);
ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
"aggregator as", argstr);
diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst
index 861d87b998..71e2b00448 100644
--- a/doc/developer/workflow.rst
+++ b/doc/developer/workflow.rst
@@ -563,7 +563,7 @@ In general, code submitted into FRR will be rejected if it uses unsafe
programming practices. While there is no enforced overall ruleset, the
following requirements have achieved consensus:
-- ``strcpy``, ``strcat`` and ``sprintf`` are inacceptable without exception.
+- ``strcpy``, ``strcat`` and ``sprintf`` are unacceptable without exception.
Use ``strlcpy``, ``strlcat`` and ``snprintf`` instead. (Rationale: even if
you know the operation cannot overflow the buffer, a future code change may
inadvertedly introduce an overflow.)
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 6d2303817b..a17d9a6ae2 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -691,8 +691,8 @@ static void lsp_set_time(struct isis_lsp *lsp)
stream_putw_at(lsp->pdu, 10, lsp->hdr.rem_lifetime);
}
-void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag,
- struct isis *isis)
+void lspid_print(uint8_t *lsp_id, char *dest, size_t dest_len, char dynhost,
+ char frag, struct isis *isis)
{
struct isis_dynhn *dyn = NULL;
char id[SYSID_STRLEN];
@@ -710,10 +710,10 @@ void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag,
memcpy(id, sysid_print(lsp_id), 15);
if (frag)
- sprintf(dest, "%s.%02x-%02x", id, LSP_PSEUDO_ID(lsp_id),
- LSP_FRAGMENT(lsp_id));
+ snprintf(dest, dest_len, "%s.%02x-%02x", id,
+ LSP_PSEUDO_ID(lsp_id), LSP_FRAGMENT(lsp_id));
else
- sprintf(dest, "%s.%02x", id, LSP_PSEUDO_ID(lsp_id));
+ snprintf(dest, dest_len, "%s.%02x", id, LSP_PSEUDO_ID(lsp_id));
}
/* Convert the lsp attribute bits to attribute string */
@@ -747,7 +747,7 @@ void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost,
char age_out[8];
char b[200];
- lspid_print(lsp->hdr.lsp_id, LSPid, dynhost, 1, isis);
+ lspid_print(lsp->hdr.lsp_id, LSPid, sizeof(LSPid), dynhost, 1, isis);
vty_out(vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' ');
vty_out(vty, "%5hu ", lsp->hdr.pdu_len);
vty_out(vty, "0x%08x ", lsp->hdr.seqno);
diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h
index 0783036e49..896d957607 100644
--- a/isisd/isis_lsp.h
+++ b/isisd/isis_lsp.h
@@ -116,8 +116,8 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
struct isis_tlvs *tlvs, struct stream *stream,
struct isis_area *area, int level, bool confusion);
void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno);
-void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag,
- struct isis *isis);
+void lspid_print(uint8_t *lsp_id, char *dest, size_t dest_len, char dynhost,
+ char frag, struct isis *isis);
void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost,
struct isis *isis);
void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost,
diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c
index 6e9cbaf98e..d3d081d376 100644
--- a/isisd/isis_misc.c
+++ b/isisd/isis_misc.c
@@ -59,27 +59,30 @@ char nlpidstring[30];
const char *isonet_print(const uint8_t *from, int len)
{
int i = 0;
- char *pos = isonet;
+ char tbuf[4];
+ isonet[0] = '\0';
if (!from)
return "unknown";
while (i < len) {
if (i & 1) {
- sprintf(pos, "%02x", *(from + i));
- pos += 2;
+ snprintf(tbuf, sizeof(tbuf), "%02x", *(from + i));
+ strlcat(isonet, tbuf, sizeof(isonet));
} else {
if (i == (len - 1)) { /* No dot at the end of address */
- sprintf(pos, "%02x", *(from + i));
- pos += 2;
+ snprintf(tbuf, sizeof(tbuf), "%02x",
+ *(from + i));
+ strlcat(isonet, tbuf, sizeof(isonet));
} else {
- sprintf(pos, "%02x.", *(from + i));
- pos += 3;
+ snprintf(tbuf, sizeof(tbuf), "%02x.",
+ *(from + i));
+ strlcat(isonet, tbuf, sizeof(isonet));
}
}
i++;
}
- *(pos) = '\0';
+
return isonet;
}
@@ -202,17 +205,18 @@ const char *nlpid2str(uint8_t nlpid)
char *nlpid2string(struct nlpids *nlpids)
{
- char *pos = nlpidstring;
int i;
+ char tbuf[256];
+ nlpidstring[0] = '\0';
for (i = 0; i < nlpids->count; i++) {
- pos += sprintf(pos, "%s", nlpid2str(nlpids->nlpids[i]));
+ snprintf(tbuf, sizeof(tbuf), "%s",
+ nlpid2str(nlpids->nlpids[i]));
+ strlcat(nlpidstring, tbuf, sizeof(nlpidstring));
if (nlpids->count - i > 1)
- pos += sprintf(pos, ", ");
+ strlcat(nlpidstring, ", ", sizeof(nlpidstring));
}
- *(pos) = '\0';
-
return nlpidstring;
}
@@ -359,34 +363,47 @@ const char *isis_format_id(const uint8_t *id, size_t len)
const char *time2string(uint32_t time)
{
- char *pos = datestring;
uint32_t rest;
+ char tbuf[32];
+ datestring[0] = '\0';
if (time == 0)
return "-";
- if (time / SECS_PER_YEAR)
- pos += sprintf(pos, "%uY", time / SECS_PER_YEAR);
+ if (time / SECS_PER_YEAR) {
+ snprintf(tbuf, sizeof(tbuf), "%uY", time / SECS_PER_YEAR);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = time % SECS_PER_YEAR;
- if (rest / SECS_PER_MONTH)
- pos += sprintf(pos, "%uM", rest / SECS_PER_MONTH);
+ if (rest / SECS_PER_MONTH) {
+ snprintf(tbuf, sizeof(tbuf), "%uM", rest / SECS_PER_MONTH);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_MONTH;
- if (rest / SECS_PER_WEEK)
- pos += sprintf(pos, "%uw", rest / SECS_PER_WEEK);
+ if (rest / SECS_PER_WEEK) {
+ snprintf(tbuf, sizeof(tbuf), "%uw", rest / SECS_PER_WEEK);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_WEEK;
- if (rest / SECS_PER_DAY)
- pos += sprintf(pos, "%ud", rest / SECS_PER_DAY);
+ if (rest / SECS_PER_DAY) {
+ snprintf(tbuf, sizeof(tbuf), "%ud", rest / SECS_PER_DAY);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_DAY;
- if (rest / SECS_PER_HOUR)
- pos += sprintf(pos, "%uh", rest / SECS_PER_HOUR);
+ if (rest / SECS_PER_HOUR) {
+ snprintf(tbuf, sizeof(tbuf), "%uh", rest / SECS_PER_HOUR);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_HOUR;
- if (rest / SECS_PER_MINUTE)
- pos += sprintf(pos, "%um", rest / SECS_PER_MINUTE);
+ if (rest / SECS_PER_MINUTE) {
+ snprintf(tbuf, sizeof(tbuf), "%um", rest / SECS_PER_MINUTE);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_MINUTE;
- if (rest)
- pos += sprintf(pos, "%us", rest);
-
- *(pos) = 0;
+ if (rest) {
+ snprintf(tbuf, sizeof(tbuf), "%us", rest);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
return datestring;
}
diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c
index d0a411a8db..6055984195 100644
--- a/isisd/isis_vty_fabricd.c
+++ b/isisd/isis_vty_fabricd.c
@@ -118,7 +118,7 @@ static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp,
char lspid[255];
char buf[MONOTIME_STRLEN];
- lspid_print(lsp->hdr.lsp_id, lspid, true, true, isis);
+ lspid_print(lsp->hdr.lsp_id, lspid, sizeof(lspid), true, true, isis);
vty_out(vty, "Flooding information for %s\n", lspid);
if (!lsp->flooding_neighbors[TX_LSP_NORMAL]) {
diff --git a/lib/northbound.c b/lib/northbound.c
index ecfa2c9d11..224951b22b 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -185,6 +185,25 @@ struct nb_node *nb_node_find(const char *xpath)
return snode->priv;
}
+void nb_node_set_dependency_cbs(const char *dependency_xpath,
+ const char *dependant_xpath,
+ struct nb_dependency_callbacks *cbs)
+{
+ struct nb_node *dependency = nb_node_find(dependency_xpath);
+ struct nb_node *dependant = nb_node_find(dependant_xpath);
+
+ if (!dependency || !dependant)
+ return;
+
+ dependency->dep_cbs.get_dependant_xpath = cbs->get_dependant_xpath;
+ dependant->dep_cbs.get_dependency_xpath = cbs->get_dependency_xpath;
+}
+
+bool nb_node_has_dependency(struct nb_node *node)
+{
+ return node->dep_cbs.get_dependency_xpath != NULL;
+}
+
static int nb_node_validate_cb(const struct nb_node *nb_node,
enum nb_operation operation,
int callback_implemented, bool optional)
@@ -532,8 +551,9 @@ int nb_candidate_edit(struct nb_config *candidate,
const struct yang_data *previous,
const struct yang_data *data)
{
- struct lyd_node *dnode;
+ struct lyd_node *dnode, *dep_dnode;
char xpath_edit[XPATH_MAXLEN];
+ char dep_xpath[XPATH_MAXLEN];
/* Use special notation for leaf-lists (RFC 6020, section 9.13.5). */
if (nb_node->snode->nodetype == LYS_LEAFLIST)
@@ -549,9 +569,33 @@ int nb_candidate_edit(struct nb_config *candidate,
dnode = lyd_new_path(candidate->dnode, ly_native_ctx,
xpath_edit, (void *)data->value, 0,
LYD_PATH_OPT_UPDATE);
- if (!dnode && ly_errno) {
- flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed",
- __func__);
+ if (dnode) {
+ /*
+ * create dependency
+ *
+ * dnode returned by the lyd_new_path may be from a
+ * different schema, so we need to update the nb_node
+ */
+ nb_node = dnode->schema->priv;
+ if (nb_node->dep_cbs.get_dependency_xpath) {
+ nb_node->dep_cbs.get_dependency_xpath(
+ dnode, dep_xpath);
+
+ ly_errno = 0;
+ dep_dnode = lyd_new_path(candidate->dnode,
+ ly_native_ctx,
+ dep_xpath, NULL, 0,
+ LYD_PATH_OPT_UPDATE);
+ if (!dep_dnode && ly_errno) {
+ flog_warn(EC_LIB_LIBYANG,
+ "%s: lyd_new_path(%s) failed",
+ __func__, dep_xpath);
+ return NB_ERR;
+ }
+ }
+ } else if (ly_errno) {
+ flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path(%s) failed",
+ __func__, xpath_edit);
return NB_ERR;
}
break;
@@ -563,6 +607,14 @@ int nb_candidate_edit(struct nb_config *candidate,
* whether to ignore it or not.
*/
return NB_ERR_NOT_FOUND;
+ /* destroy dependant */
+ if (nb_node->dep_cbs.get_dependant_xpath) {
+ nb_node->dep_cbs.get_dependant_xpath(dnode, dep_xpath);
+
+ dep_dnode = yang_dnode_get(candidate->dnode, dep_xpath);
+ if (dep_dnode)
+ lyd_free(dep_dnode);
+ }
lyd_free(dnode);
break;
case NB_OP_MOVE:
diff --git a/lib/northbound.h b/lib/northbound.h
index 8dd6b4c337..3e1342f985 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -509,6 +509,11 @@ struct nb_callbacks {
void (*cli_show_end)(struct vty *vty, struct lyd_node *dnode);
};
+struct nb_dependency_callbacks {
+ void (*get_dependant_xpath)(const struct lyd_node *dnode, char *xpath);
+ void (*get_dependency_xpath)(const struct lyd_node *dnode, char *xpath);
+};
+
/*
* Northbound-specific data that is allocated for each schema node of the native
* YANG modules.
@@ -523,6 +528,8 @@ struct nb_node {
/* Priority - lower priorities are processed first. */
uint32_t priority;
+ struct nb_dependency_callbacks dep_cbs;
+
/* Callbacks implemented for this node. */
struct nb_callbacks cbs;
@@ -722,6 +729,12 @@ void nb_nodes_delete(void);
*/
extern struct nb_node *nb_node_find(const char *xpath);
+extern void nb_node_set_dependency_cbs(const char *dependency_xpath,
+ const char *dependant_xpath,
+ struct nb_dependency_callbacks *cbs);
+
+bool nb_node_has_dependency(struct nb_node *node);
+
/*
* Create a new northbound configuration.
*
diff --git a/lib/prefix.c b/lib/prefix.c
index 663a87afde..c98e0c1c72 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -1160,7 +1160,7 @@ in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen)
ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
int netmask_str2prefix_str(const char *net_str, const char *mask_str,
- char *prefix_str)
+ char *prefix_str, size_t prefix_str_len)
{
struct in_addr network;
struct in_addr mask;
@@ -1193,7 +1193,7 @@ int netmask_str2prefix_str(const char *net_str, const char *mask_str,
return 0;
}
- sprintf(prefix_str, "%s/%d", net_str, prefixlen);
+ snprintf(prefix_str, prefix_str_len, "%s/%d", net_str, prefixlen);
return 1;
}
diff --git a/lib/prefix.h b/lib/prefix.h
index b7fdc26369..b2f3b0592f 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -491,7 +491,7 @@ extern void masklen2ip(const int, struct in_addr *);
* special treatment for /31 according to RFC3021 section 3.3 */
extern in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen);
-extern int netmask_str2prefix_str(const char *, const char *, char *);
+extern int netmask_str2prefix_str(const char *, const char *, char *, size_t);
extern struct prefix_ipv6 *prefix_ipv6_new(void);
extern void prefix_ipv6_free(struct prefix_ipv6 **p);
diff --git a/lib/routing_nb.h b/lib/routing_nb.h
index d1b59ea29e..ffba631a10 100644
--- a/lib/routing_nb.h
+++ b/lib/routing_nb.h
@@ -15,10 +15,17 @@ int routing_control_plane_protocols_control_plane_protocol_destroy(
#define FRR_ROUTING_KEY_XPATH \
"/frr-routing:routing/control-plane-protocols/" \
"control-plane-protocol[type='%s'][name='%s'][vrf='%s']"
+
+#define FRR_ROUTING_KEY_XPATH_VRF \
+ "/frr-routing:routing/control-plane-protocols/" \
+ "control-plane-protocol[vrf='%s']"
+
/*
* callbacks for routing to handle configuration events
* based on the control plane protocol
*/
DECLARE_HOOK(routing_conf_event, (struct nb_cb_create_args *args), (args))
+void routing_control_plane_protocols_register_vrf_dependency(void);
+
#endif /* _FRR_ROUTING_NB_H_ */
diff --git a/lib/routing_nb_config.c b/lib/routing_nb_config.c
index b789e8494e..17698d2b87 100644
--- a/lib/routing_nb_config.c
+++ b/lib/routing_nb_config.c
@@ -45,15 +45,21 @@ int routing_control_plane_protocols_control_plane_protocol_create(
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- vrfname = yang_dnode_get_string(args->dnode, "./vrf");
- vrf = vrf_lookup_by_name(vrfname);
- vrf = vrf ? vrf : vrf_get(VRF_UNKNOWN, vrfname);
- if (!vrf) {
- flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
- "vrf creation %s failed", vrfname);
- return NB_ERR;
+ /*
+ * If the daemon relies on the VRF pointer stored in this
+ * dnode, then it should register the dependency between this
+ * module and the VRF module using
+ * routing_control_plane_protocols_register_vrf_dependency.
+ * If such dependency is not registered, then nothing is
+ * stored in the dnode. If the dependency is registered,
+ * find the vrf and store the pointer.
+ */
+ if (nb_node_has_dependency(args->dnode->schema->priv)) {
+ vrfname = yang_dnode_get_string(args->dnode, "./vrf");
+ vrf = vrf_lookup_by_name(vrfname);
+ assert(vrf);
+ nb_running_set_entry(args->dnode, vrf);
}
- nb_running_set_entry(args->dnode, vrf);
break;
};
@@ -63,12 +69,45 @@ int routing_control_plane_protocols_control_plane_protocol_create(
int routing_control_plane_protocols_control_plane_protocol_destroy(
struct nb_cb_destroy_args *args)
{
- struct vrf *vrf __attribute__((unused));
-
if (args->event != NB_EV_APPLY)
return NB_OK;
- vrf = nb_running_unset_entry(args->dnode);
+ /*
+ * If dependency on VRF module is registered, then VRF
+ * pointer was stored and must be cleared.
+ */
+ if (nb_node_has_dependency(args->dnode->schema->priv))
+ nb_running_unset_entry(args->dnode);
return NB_OK;
}
+
+static void vrf_to_control_plane_protocol(const struct lyd_node *dnode,
+ char *xpath)
+{
+ const char *vrf;
+
+ vrf = yang_dnode_get_string(dnode, "./name");
+
+ snprintf(xpath, XPATH_MAXLEN, FRR_ROUTING_KEY_XPATH_VRF, vrf);
+}
+
+static void control_plane_protocol_to_vrf(const struct lyd_node *dnode,
+ char *xpath)
+{
+ const char *vrf;
+
+ vrf = yang_dnode_get_string(dnode, "./vrf");
+
+ snprintf(xpath, XPATH_MAXLEN, FRR_VRF_KEY_XPATH, vrf);
+}
+
+void routing_control_plane_protocols_register_vrf_dependency(void)
+{
+ struct nb_dependency_callbacks cbs;
+
+ cbs.get_dependant_xpath = vrf_to_control_plane_protocol;
+ cbs.get_dependency_xpath = control_plane_protocol_to_vrf;
+
+ nb_node_set_dependency_cbs(FRR_VRF_XPATH, FRR_ROUTING_XPATH, &cbs);
+}
diff --git a/lib/vrf.c b/lib/vrf.c
index 136938783f..0a91f4bc86 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -686,8 +686,8 @@ int vrf_handler_create(struct vty *vty, const char *vrfname,
}
if (vty) {
- snprintf(xpath_list, sizeof(xpath_list),
- "/frr-vrf:lib/vrf[name='%s']", vrfname);
+ snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH,
+ vrfname);
nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL);
ret = nb_cli_apply_changes(vty, xpath_list);
@@ -821,8 +821,7 @@ DEFUN_YANG (no_vrf,
return CMD_WARNING_CONFIG_FAILED;
}
- snprintf(xpath_list, sizeof(xpath_list), "/frr-vrf:lib/vrf[name='%s']",
- vrfname);
+ snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, vrfname);
nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, xpath_list);
diff --git a/lib/vrf.h b/lib/vrf.h
index 32e6fb4289..333d68ce96 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -52,6 +52,9 @@ enum { IFLA_VRF_UNSPEC, IFLA_VRF_TABLE, __IFLA_VRF_MAX };
#define VRF_ALL_CMD_HELP_STR "Specify the VRF\nAll VRFs\n"
#define VRF_FULL_CMD_HELP_STR "Specify the VRF\nThe VRF name\nAll VRFs\n"
+#define FRR_VRF_XPATH "/frr-vrf:lib/vrf"
+#define FRR_VRF_KEY_XPATH "/frr-vrf:lib/vrf[name='%s']"
+
/*
* Pass some OS specific data up through
* to the daemons
diff --git a/lib/vty.c b/lib/vty.c
index 65f8d78a96..df518422f0 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -2427,9 +2427,9 @@ bool vty_read_config(struct nb_config *config, const char *config_file,
__func__, errno);
goto tmp_free_and_out;
}
- tmp = XMALLOC(MTYPE_TMP,
- strlen(cwd) + strlen(config_file) + 2);
- sprintf(tmp, "%s/%s", cwd, config_file);
+ size_t tmp_len = strlen(cwd) + strlen(config_file) + 2;
+ tmp = XMALLOC(MTYPE_TMP, tmp_len);
+ snprintf(tmp, tmp_len, "%s/%s", cwd, config_file);
fullpath = tmp;
} else
fullpath = config_file;
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index abcdb40547..f6a246500b 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -1292,6 +1292,7 @@ static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
{
struct ospf6_inter_prefix_lsa *prefix_lsa;
struct in6_addr in6;
+ char tbuf[16];
if (lsa != NULL) {
prefix_lsa =
@@ -1301,8 +1302,9 @@ static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
ospf6_prefix_in6_addr(&in6, prefix_lsa, &prefix_lsa->prefix);
if (buf) {
inet_ntop(AF_INET6, &in6, buf, buflen);
- sprintf(&buf[strlen(buf)], "/%d",
- prefix_lsa->prefix.prefix_length);
+ snprintf(tbuf, sizeof(tbuf), "/%d",
+ prefix_lsa->prefix.prefix_length);
+ strlcat(buf, tbuf, buflen);
}
}
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 3449f48267..d0c93dd577 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -1865,6 +1865,7 @@ static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa *lsa,
struct ospf6_as_external_lsa *external;
struct in6_addr in6;
int prefix_length = 0;
+ char tbuf[16];
if (lsa) {
external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
@@ -1885,9 +1886,11 @@ static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa *lsa,
}
if (buf) {
inet_ntop(AF_INET6, &in6, buf, buflen);
- if (prefix_length)
- sprintf(&buf[strlen(buf)], "/%d",
- prefix_length);
+ if (prefix_length) {
+ snprintf(tbuf, sizeof(tbuf), "/%d",
+ prefix_length);
+ strlcat(buf, tbuf, buflen);
+ }
}
}
return (buf);
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index 5394ba9786..2cffc3a397 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -84,7 +84,7 @@ static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa *lsa, char *buf,
sizeof(buf1));
inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
buf2, sizeof(buf2));
- sprintf(buf, "%s/%s", buf2, buf1);
+ snprintf(buf, buflen, "%s/%s", buf2, buf1);
return buf;
}
@@ -866,6 +866,7 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
struct in6_addr in6;
int prefixnum, cnt = 0;
struct ospf6_prefix *prefix;
+ char tbuf[16];
if (lsa) {
intra_prefix_lsa =
@@ -898,8 +899,9 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
OSPF6_PREFIX_SPACE(
prefix->prefix_length));
inet_ntop(AF_INET6, &in6, buf, buflen);
- sprintf(&buf[strlen(buf)], "/%d",
- prefix->prefix_length);
+ snprintf(tbuf, sizeof(tbuf), "/%d",
+ prefix->prefix_length);
+ strlcat(buf, tbuf, buflen);
return (buf);
}
}
diff --git a/pimd/pim_main.c b/pimd/pim_main.c
index 9c11cc47d5..5a09e7a8ee 100644
--- a/pimd/pim_main.c
+++ b/pimd/pim_main.c
@@ -145,6 +145,8 @@ int main(int argc, char **argv, char **envp)
hook_register(routing_conf_event,
routing_control_plane_protocols_name_validate);
+ routing_control_plane_protocols_register_vrf_dependency();
+
frr_config_fork();
#ifdef PIM_DEBUG_BYDEFAULT
diff --git a/staticd/static_main.c b/staticd/static_main.c
index ac8f8ff029..560814771d 100644
--- a/staticd/static_main.c
+++ b/staticd/static_main.c
@@ -164,6 +164,8 @@ int main(int argc, char **argv, char **envp)
hook_register(routing_conf_event,
routing_control_plane_protocols_name_validate);
+ routing_control_plane_protocols_register_vrf_dependency();
+
snprintf(backup_config_file, sizeof(backup_config_file),
"%s/zebra.conf", frr_sysconfdir);
staticd_di.backup_config_file = backup_config_file;
diff --git a/tests/topotests/bgp-aggregator-zero/__init__.py b/tests/topotests/bgp-aggregator-zero/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/__init__.py
diff --git a/tests/topotests/bgp-aggregator-zero/exabgp.env b/tests/topotests/bgp-aggregator-zero/exabgp.env
new file mode 100644
index 0000000000..28e642360a
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/exabgp.env
@@ -0,0 +1,53 @@
+[exabgp.api]
+encoder = text
+highres = false
+respawn = false
+socket = ''
+
+[exabgp.bgp]
+openwait = 60
+
+[exabgp.cache]
+attributes = true
+nexthops = true
+
+[exabgp.daemon]
+daemonize = true
+pid = '/var/run/exabgp/exabgp.pid'
+user = 'exabgp'
+##daemonize = false
+
+[exabgp.log]
+all = false
+configuration = true
+daemon = true
+destination = '/var/log/exabgp.log'
+enable = true
+level = INFO
+message = false
+network = true
+packets = false
+parser = false
+processes = true
+reactor = true
+rib = false
+routes = false
+short = false
+timers = false
+
+[exabgp.pdb]
+enable = false
+
+[exabgp.profile]
+enable = false
+file = ''
+
+[exabgp.reactor]
+speed = 1.0
+
+[exabgp.tcp]
+acl = false
+bind = ''
+delay = 0
+once = false
+port = 179
diff --git a/tests/topotests/bgp-aggregator-zero/peer1/exabgp.cfg b/tests/topotests/bgp-aggregator-zero/peer1/exabgp.cfg
new file mode 100644
index 0000000000..b3f25272d2
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/peer1/exabgp.cfg
@@ -0,0 +1,18 @@
+neighbor 10.0.0.1 {
+ router-id 10.0.0.2;
+ local-address 10.0.0.2;
+ local-as 65001;
+ peer-as 65534;
+
+ static {
+ route 192.168.100.101/32 {
+ aggregator (0:10.0.0.2);
+ next-hop 10.0.0.2;
+ }
+
+ route 192.168.100.102/32 {
+ aggregator (65001:10.0.0.2);
+ next-hop 10.0.0.2;
+ }
+ }
+}
diff --git a/tests/topotests/bgp-aggregator-zero/r1/bgpd.conf b/tests/topotests/bgp-aggregator-zero/r1/bgpd.conf
new file mode 100644
index 0000000000..002a5c78c0
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/r1/bgpd.conf
@@ -0,0 +1,6 @@
+!
+router bgp 65534
+ no bgp ebgp-requires-policy
+ neighbor 10.0.0.2 remote-as external
+ neighbor 10.0.0.2 timers 3 10
+!
diff --git a/tests/topotests/bgp-aggregator-zero/r1/zebra.conf b/tests/topotests/bgp-aggregator-zero/r1/zebra.conf
new file mode 100644
index 0000000000..22a26ac610
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/r1/zebra.conf
@@ -0,0 +1,6 @@
+!
+interface r1-eth0
+ ip address 10.0.0.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp-aggregator-zero/test_bgp_aggregator_zero.py b/tests/topotests/bgp-aggregator-zero/test_bgp_aggregator_zero.py
new file mode 100644
index 0000000000..0db47da3f2
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/test_bgp_aggregator_zero.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2021 by
+# Donatas Abraitis <donatas.abraitis@gmail.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Test if BGP UPDATE with AGGREGATOR AS attribute with value zero (0)
+is continued to be processed, but AGGREGATOR attribute is discarded.
+"""
+
+import os
+import sys
+import json
+import time
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from mininet.topo import Topo
+
+
+class BgpAggregatorAsnZero(Topo):
+ def build(self, *_args, **_opts):
+ tgen = get_topogen(self)
+
+ r1 = tgen.add_router("r1")
+ peer1 = tgen.add_exabgp_peer(
+ "peer1", ip="10.0.0.2", defaultRoute="via 10.0.0.1"
+ )
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(r1)
+ switch.add_link(peer1)
+
+
+def setup_module(mod):
+ tgen = Topogen(BgpAggregatorAsnZero, mod.__name__)
+ tgen.start_topology()
+
+ router = tgen.gears["r1"]
+ router.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf"))
+ router.load_config(TopoRouter.RD_BGP, os.path.join(CWD, "r1/bgpd.conf"))
+ router.start()
+
+ peer = tgen.gears["peer1"]
+ peer.start(os.path.join(CWD, "peer1"), os.path.join(CWD, "exabgp.env"))
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_aggregator_zero():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _bgp_converge():
+ output = json.loads(
+ tgen.gears["r1"].vtysh_cmd("show ip bgp neighbor 10.0.0.2 json")
+ )
+ expected = {
+ "10.0.0.2": {
+ "bgpState": "Established",
+ "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+
+ assert result is None, 'Failed bgp convergence in "{}"'.format(tgen.gears["r1"])
+
+ def _bgp_has_correct_aggregator_route_with_asn_0():
+ output = json.loads(
+ tgen.gears["r1"].vtysh_cmd("show ip bgp 192.168.100.101/32 json")
+ )
+
+ if "aggregatorAs" in output["paths"][0].keys():
+ return False
+ else:
+ return True
+
+ assert (
+ _bgp_has_correct_aggregator_route_with_asn_0() is True
+ ), 'Aggregator AS attribute with ASN 0 found in "{}"'.format(tgen.gears["r1"])
+
+ def _bgp_has_correct_aggregator_route_with_good_asn():
+ output = json.loads(
+ tgen.gears["r1"].vtysh_cmd("show ip bgp 192.168.100.102/32 json")
+ )
+ expected = {"paths": [{"aggregatorAs": 65001, "aggregatorId": "10.0.0.2"}]}
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_has_correct_aggregator_route_with_good_asn)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+
+ assert result is None, 'Aggregator AS attribute not found in "{}"'.format(
+ tgen.gears["r1"]
+ )
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c
index 2ab5fd3a4c..5352c6214d 100644
--- a/zebra/irdp_interface.c
+++ b/zebra/irdp_interface.c
@@ -93,10 +93,10 @@ static int irdp_if_delete(struct interface *ifp)
return 0;
}
-static const char *inet_2a(uint32_t a, char *b)
+static const char *inet_2a(uint32_t a, char *b, size_t b_len)
{
- sprintf(b, "%u.%u.%u.%u", (a)&0xFF, (a >> 8) & 0xFF, (a >> 16) & 0xFF,
- (a >> 24) & 0xFF);
+ snprintf(b, b_len, "%u.%u.%u.%u", (a)&0xFF, (a >> 8) & 0xFF,
+ (a >> 16) & 0xFF, (a >> 24) & 0xFF);
return b;
}
@@ -140,7 +140,8 @@ static int if_group(struct interface *ifp, int sock, uint32_t group,
flog_err_sys(EC_LIB_SOCKET, "IRDP: %s can't setsockopt %s: %s",
add_leave == IP_ADD_MEMBERSHIP ? "join group"
: "leave group",
- inet_2a(group, b1), safe_strerror(errno));
+ inet_2a(group, b1, sizeof(b1)),
+ safe_strerror(errno));
return ret;
}
@@ -162,7 +163,8 @@ static int if_add_group(struct interface *ifp)
if (irdp->flags & IF_DEBUG_MISC)
zlog_debug("IRDP: Adding group %s for %s",
- inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), ifp->name);
+ inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1, sizeof(b1)),
+ ifp->name);
return 0;
}
@@ -183,7 +185,8 @@ static int if_drop_group(struct interface *ifp)
if (irdp->flags & IF_DEBUG_MISC)
zlog_debug("IRDP: Leaving group %s for %s",
- inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), ifp->name);
+ inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1, sizeof(b1)),
+ ifp->name);
return 0;
}
@@ -383,7 +386,8 @@ int irdp_config_write(struct vty *vty, struct interface *ifp)
for (ALL_LIST_ELEMENTS_RO(irdp->AdvPrefList, node, adv))
vty_out(vty, " ip irdp address %s preference %d\n",
- inet_2a(adv->ip.s_addr, b1), adv->pref);
+ inet_2a(adv->ip.s_addr, b1, sizeof(b1)),
+ adv->pref);
vty_out(vty, " ip irdp holdtime %d\n", irdp->Lifetime);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 602805be3c..46a751ce69 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1132,8 +1132,8 @@ static int build_label_stack(struct mpls_label_stack *nh_label,
if (IS_ZEBRA_DEBUG_KERNEL) {
if (!num_labels)
- sprintf(label_buf, "label %u",
- nh_label->label[i]);
+ snprintf(label_buf, label_buf_size, "label %u",
+ nh_label->label[i]);
else {
snprintf(label_buf1, sizeof(label_buf1), "/%u",
nh_label->label[i]);