mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-02 13:18:52 +00:00
*: fix segfault when sending more than MULTIPATH_NUM nexthops
This is a fallout from PR #1022 (zapi consolidation). In the early days, the client daemons would allocate enough memory to send all nexthops to zebra. Then zebra would add all nexthops to the RIB and respect MULTIPATH_NUM only when installing the routes in the kernel. Now things are different and the client daemons can send at most MULTIPATH_NUM nexthops to zebra, and failure to respect that will result in a buffer overflow. The MULTIPATH_NUM limit in the new zebra API is a small price we pay to avoid allocating memory for each route sent to zebra. Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
parent
484aafd43f
commit
a74e593b35
@ -956,7 +956,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
|||||||
struct zapi_route api;
|
struct zapi_route api;
|
||||||
struct zapi_nexthop *api_nh;
|
struct zapi_nexthop *api_nh;
|
||||||
int nh_family;
|
int nh_family;
|
||||||
int valid_nh_count = 0;
|
unsigned int valid_nh_count = 0;
|
||||||
int has_valid_label = 0;
|
int has_valid_label = 0;
|
||||||
u_char distance;
|
u_char distance;
|
||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
@ -1010,6 +1010,9 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
|||||||
/* Metric is currently based on the best-path only */
|
/* Metric is currently based on the best-path only */
|
||||||
metric = info->attr->med;
|
metric = info->attr->med;
|
||||||
for (mpinfo = info; mpinfo; mpinfo = bgp_info_mpath_next(mpinfo)) {
|
for (mpinfo = info; mpinfo; mpinfo = bgp_info_mpath_next(mpinfo)) {
|
||||||
|
if (valid_nh_count >= multipath_num)
|
||||||
|
break;
|
||||||
|
|
||||||
*mpinfo_cp = *mpinfo;
|
*mpinfo_cp = *mpinfo;
|
||||||
|
|
||||||
/* Get nexthop address-family */
|
/* Get nexthop address-family */
|
||||||
|
@ -368,8 +368,8 @@ static int vnc_zebra_read_route(int command, struct zclient *zclient,
|
|||||||
/*
|
/*
|
||||||
* low-level message builder
|
* low-level message builder
|
||||||
*/
|
*/
|
||||||
static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary,
|
static void vnc_zebra_route_msg(struct prefix *p, unsigned int nhp_count,
|
||||||
int add) /* 1 = add, 0 = del */
|
void *nhp_ary, int add) /* 1 = add, 0 = del */
|
||||||
{
|
{
|
||||||
struct zapi_route api;
|
struct zapi_route api;
|
||||||
struct zapi_nexthop *api_nh;
|
struct zapi_nexthop *api_nh;
|
||||||
@ -389,8 +389,8 @@ static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary,
|
|||||||
|
|
||||||
/* Nexthops */
|
/* Nexthops */
|
||||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
api.nexthop_num = nhp_count;
|
api.nexthop_num = MIN(nhp_count, multipath_num);
|
||||||
for (i = 0; i < nhp_count; i++) {
|
for (i = 0; i < api.nexthop_num; i++) {
|
||||||
struct in_addr *nhp_ary4;
|
struct in_addr *nhp_ary4;
|
||||||
struct in6_addr *nhp_ary6;
|
struct in6_addr *nhp_ary6;
|
||||||
|
|
||||||
@ -426,7 +426,8 @@ static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary,
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nve_list_to_nh_array(u_char family, struct list *nve_list, int *nh_count_ret,
|
nve_list_to_nh_array(u_char family, struct list *nve_list,
|
||||||
|
unsigned int *nh_count_ret,
|
||||||
void **nh_ary_ret, /* returned address array */
|
void **nh_ary_ret, /* returned address array */
|
||||||
void **nhp_ary_ret) /* returned pointer array */
|
void **nhp_ary_ret) /* returned pointer array */
|
||||||
{
|
{
|
||||||
@ -549,7 +550,7 @@ static void vnc_zebra_add_del_prefix(struct bgp *bgp,
|
|||||||
{
|
{
|
||||||
struct list *nves;
|
struct list *nves;
|
||||||
|
|
||||||
int nexthop_count = 0;
|
unsigned int nexthop_count = 0;
|
||||||
void *nh_ary = NULL;
|
void *nh_ary = NULL;
|
||||||
void *nhp_ary = NULL;
|
void *nhp_ary = NULL;
|
||||||
|
|
||||||
@ -713,7 +714,7 @@ static void vnc_zebra_add_del_group_afi(struct bgp *bgp,
|
|||||||
uint8_t family = afi2family(afi);
|
uint8_t family = afi2family(afi);
|
||||||
|
|
||||||
struct list *nves = NULL;
|
struct list *nves = NULL;
|
||||||
int nexthop_count = 0;
|
unsigned int nexthop_count = 0;
|
||||||
void *nh_ary = NULL;
|
void *nh_ary = NULL;
|
||||||
void *nhp_ary = NULL;
|
void *nhp_ary = NULL;
|
||||||
|
|
||||||
|
@ -379,10 +379,11 @@ void eigrp_zebra_route_add(struct prefix *p, struct list *successors)
|
|||||||
memcpy(&api.prefix, p, sizeof(*p));
|
memcpy(&api.prefix, p, sizeof(*p));
|
||||||
|
|
||||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
api.nexthop_num = successors->count;
|
|
||||||
|
|
||||||
/* Nexthop, ifindex, distance and metric information. */
|
/* Nexthop, ifindex, distance and metric information. */
|
||||||
for (ALL_LIST_ELEMENTS_RO(successors, node, te)) {
|
for (ALL_LIST_ELEMENTS_RO(successors, node, te)) {
|
||||||
|
if (count >= MULTIPATH_NUM)
|
||||||
|
break;
|
||||||
api_nh = &api.nexthops[count];
|
api_nh = &api.nexthops[count];
|
||||||
if (te->adv_router->src.s_addr) {
|
if (te->adv_router->src.s_addr) {
|
||||||
api_nh->gate.ipv4 = te->adv_router->src;
|
api_nh->gate.ipv4 = te->adv_router->src;
|
||||||
@ -393,6 +394,7 @@ void eigrp_zebra_route_add(struct prefix *p, struct list *successors)
|
|||||||
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
api.nexthop_num = count;
|
||||||
|
|
||||||
if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
|
if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
|
||||||
char buf[2][PREFIX_STRLEN];
|
char buf[2][PREFIX_STRLEN];
|
||||||
|
@ -277,6 +277,8 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
|
|||||||
case AF_INET:
|
case AF_INET:
|
||||||
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node,
|
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node,
|
||||||
nexthop)) {
|
nexthop)) {
|
||||||
|
if (count >= MULTIPATH_NUM)
|
||||||
|
break;
|
||||||
api_nh = &api.nexthops[count];
|
api_nh = &api.nexthops[count];
|
||||||
/* FIXME: can it be ? */
|
/* FIXME: can it be ? */
|
||||||
if (nexthop->ip.s_addr != INADDR_ANY) {
|
if (nexthop->ip.s_addr != INADDR_ANY) {
|
||||||
@ -292,6 +294,8 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
|
|||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node,
|
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node,
|
||||||
nexthop6)) {
|
nexthop6)) {
|
||||||
|
if (count >= MULTIPATH_NUM)
|
||||||
|
break;
|
||||||
if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6)
|
if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6)
|
||||||
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) {
|
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -915,9 +915,10 @@ int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api)
|
|||||||
|
|
||||||
prefix2str(&api->prefix, buf, sizeof(buf));
|
prefix2str(&api->prefix, buf, sizeof(buf));
|
||||||
zlog_warn(
|
zlog_warn(
|
||||||
"%s: prefix %s: encoding %u nexthops out of %u",
|
"%s: prefix %s: can't encode %u nexthops "
|
||||||
__func__, buf, MULTIPATH_NUM, api->nexthop_num);
|
"(maximum is %u)",
|
||||||
api->nexthop_num = MULTIPATH_NUM;
|
__func__, buf, api->nexthop_num, MULTIPATH_NUM);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_putw(s, api->nexthop_num);
|
stream_putw(s, api->nexthop_num);
|
||||||
|
@ -341,8 +341,8 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
|
|||||||
api.safi = SAFI_UNICAST;
|
api.safi = SAFI_UNICAST;
|
||||||
api.prefix = *dest;
|
api.prefix = *dest;
|
||||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
api.nexthop_num = nhcount;
|
api.nexthop_num = MIN(nhcount, MULTIPATH_NUM);
|
||||||
ospf6_route_zebra_copy_nexthops(request, api.nexthops, nhcount);
|
ospf6_route_zebra_copy_nexthops(request, api.nexthops, api.nexthop_num);
|
||||||
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
||||||
api.metric = (request->path.metric_type == 2 ? request->path.u.cost_e2
|
api.metric = (request->path.metric_type == 2 ? request->path.u.cost_e2
|
||||||
: request->path.cost);
|
: request->path.cost);
|
||||||
|
@ -349,7 +349,6 @@ void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or)
|
|||||||
|
|
||||||
memcpy(&api.prefix, p, sizeof(*p));
|
memcpy(&api.prefix, p, sizeof(*p));
|
||||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
api.nexthop_num = or->paths->count;
|
|
||||||
|
|
||||||
/* Metric value. */
|
/* Metric value. */
|
||||||
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
||||||
@ -377,6 +376,8 @@ void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or)
|
|||||||
|
|
||||||
/* Nexthop, ifindex, distance and metric information. */
|
/* Nexthop, ifindex, distance and metric information. */
|
||||||
for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) {
|
for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) {
|
||||||
|
if (count >= MULTIPATH_NUM)
|
||||||
|
break;
|
||||||
api_nh = &api.nexthops[count];
|
api_nh = &api.nexthops[count];
|
||||||
#ifdef HAVE_NETLINK
|
#ifdef HAVE_NETLINK
|
||||||
if (path->unnumbered || (path->nexthop.s_addr != INADDR_ANY
|
if (path->unnumbered || (path->nexthop.s_addr != INADDR_ANY
|
||||||
@ -407,6 +408,7 @@ void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or)
|
|||||||
path->ifindex);
|
path->ifindex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
api.nexthop_num = count;
|
||||||
|
|
||||||
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
|
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,8 @@ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd)
|
|||||||
|
|
||||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
|
for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
|
||||||
|
if (count >= MULTIPATH_NUM)
|
||||||
|
break;
|
||||||
api_nh = &api.nexthops[count];
|
api_nh = &api.nexthops[count];
|
||||||
api_nh->gate.ipv4 = rinfo->nexthop;
|
api_nh->gate.ipv4 = rinfo->nexthop;
|
||||||
api_nh->type = NEXTHOP_TYPE_IPV4;
|
api_nh->type = NEXTHOP_TYPE_IPV4;
|
||||||
|
@ -54,6 +54,8 @@ static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd)
|
|||||||
|
|
||||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
|
for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
|
||||||
|
if (count >= MULTIPATH_NUM)
|
||||||
|
break;
|
||||||
api_nh = &api.nexthops[count];
|
api_nh = &api.nexthops[count];
|
||||||
api_nh->gate.ipv6 = rinfo->nexthop;
|
api_nh->gate.ipv6 = rinfo->nexthop;
|
||||||
api_nh->ifindex = rinfo->ifindex;
|
api_nh->ifindex = rinfo->ifindex;
|
||||||
|
Loading…
Reference in New Issue
Block a user