diff options
| author | David Lamparter <equinox@opensourcerouting.org> | 2020-01-16 22:24:27 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-01-16 22:24:27 +0100 |
| commit | 3b08fde9dd27470c365203a7fa575d5397709a3d (patch) | |
| tree | aa266a54271736b7a06f48e29905e7e924f7b6e7 | |
| parent | 7390ea4f6fc6d980af215b8d8b55eccb9a484ddb (diff) | |
| parent | 97af7d892c916656cee1e64765c7f7a628912797 (diff) | |
Merge pull request #5696 from qlyoung/stable-7.2-backport-more
More 7.2 bugfix backports
| -rw-r--r-- | bgpd/bgp_attr.c | 150 | ||||
| -rw-r--r-- | bgpd/bgp_attr.h | 4 | ||||
| -rw-r--r-- | bgpd/bgp_ecommunity.c | 220 | ||||
| -rw-r--r-- | bgpd/bgp_ecommunity.h | 2 | ||||
| -rw-r--r-- | bgpd/bgp_evpn.c | 4 | ||||
| -rw-r--r-- | bgpd/bgp_lcommunity.c | 36 | ||||
| -rw-r--r-- | bgpd/bgp_mpath.c | 2 | ||||
| -rw-r--r-- | bgpd/bgp_mplsvpn.c | 6 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 16 | ||||
| -rw-r--r-- | bgpd/bgp_updgrp_adv.c | 2 | ||||
| -rw-r--r-- | bgpd/bgp_zebra.c | 2 | ||||
| -rw-r--r-- | bgpd/rfapi/vnc_export_bgp.c | 4 | ||||
| -rw-r--r-- | bgpd/rfapi/vnc_import_bgp.c | 19 | ||||
| -rw-r--r-- | lib/plist.c | 2 | ||||
| -rw-r--r-- | ospfd/ospf_packet.c | 22 | ||||
| -rw-r--r-- | pimd/pim_igmp.c | 22 | ||||
| -rw-r--r-- | pimd/pim_igmp_mtrace.c | 10 | ||||
| -rw-r--r-- | pimd/pim_mroute.c | 3 |
18 files changed, 276 insertions, 250 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 53e6acc424..2e83f7d051 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -422,14 +422,15 @@ static struct transit *transit_intern(struct transit *transit) return find; } -void transit_unintern(struct transit *transit) +static void transit_unintern(struct transit **transit) { - if (transit->refcnt) - transit->refcnt--; + if ((*transit)->refcnt) + (*transit)->refcnt--; - if (transit->refcnt == 0) { - hash_release(transit_hash, transit); - transit_free(transit); + if ((*transit)->refcnt == 0) { + hash_release(transit_hash, *transit); + transit_free(*transit); + *transit = NULL; } } @@ -465,15 +466,6 @@ static void transit_finish(void) /* Attribute hash routines. */ static struct hash *attrhash; -/* Shallow copy of an attribute - * Though, not so shallow that it doesn't copy the contents - * of the attr_extra pointed to by 'extra' - */ -void bgp_attr_dup(struct attr *new, struct attr *orig) -{ - *new = *orig; -} - unsigned long int attr_count(void) { return attrhash->count; @@ -859,7 +851,7 @@ void bgp_attr_unintern_sub(struct attr *attr) UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)); if (attr->transit) - transit_unintern(attr->transit); + transit_unintern(&attr->transit); if (attr->encap_subtlvs) encap_unintern(&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE); @@ -2475,7 +2467,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); - return BGP_ATTR_PARSE_ERROR; + ret = BGP_ATTR_PARSE_ERROR; + goto done; } /* Fetch attribute flag and type. */ @@ -2498,7 +2491,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); - return BGP_ATTR_PARSE_ERROR; + ret = BGP_ATTR_PARSE_ERROR; + goto done; } /* Check extended attribue length bit. */ @@ -2519,7 +2513,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MAL_ATTR); - return BGP_ATTR_PARSE_ERROR; + ret = BGP_ATTR_PARSE_ERROR; + goto done; } /* Set type to bitmap to check duplicate attribute. `type' is @@ -2576,7 +2571,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, ndata, ndl + lfl + 1); - return BGP_ATTR_PARSE_ERROR; + ret = BGP_ATTR_PARSE_ERROR; + goto done; } struct bgp_attr_parser_args attr_args = { @@ -2601,7 +2597,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, attr_args.total); if (ret == BGP_ATTR_PARSE_PROCEED) continue; - return ret; + goto done; } /* OK check attribute and store it's value. */ @@ -2679,32 +2675,25 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MAL_ATTR); ret = BGP_ATTR_PARSE_ERROR; + goto done; } if (ret == BGP_ATTR_PARSE_EOR) { - if (as4_path) - aspath_unintern(&as4_path); - return ret; + goto done; } - /* If hard error occurred immediately return to the caller. */ if (ret == BGP_ATTR_PARSE_ERROR) { flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR, "%s: Attribute %s, parse error", peer->host, lookup_msg(attr_str, type, NULL)); - if (as4_path) - aspath_unintern(&as4_path); - return ret; + goto done; } if (ret == BGP_ATTR_PARSE_WITHDRAW) { - flog_warn( EC_BGP_ATTRIBUTE_PARSE_WITHDRAW, "%s: Attribute %s, parse error - treating as withdrawal", peer->host, lookup_msg(attr_str, type, NULL)); - if (as4_path) - aspath_unintern(&as4_path); - return ret; + goto done; } /* Check the fetched length. */ @@ -2714,9 +2703,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, peer->host, lookup_msg(attr_str, type, NULL)); bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); - if (as4_path) - aspath_unintern(&as4_path); - return BGP_ATTR_PARSE_ERROR; + ret = BGP_ATTR_PARSE_ERROR; + goto done; } } @@ -2727,9 +2715,9 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, lookup_msg(attr_str, type, NULL)); bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); - if (as4_path) - aspath_unintern(&as4_path); - return BGP_ATTR_PARSE_ERROR; + + ret = BGP_ATTR_PARSE_ERROR; + goto done; } /* @@ -2748,16 +2736,14 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI))) { if (bgp_attr_nexthop_valid(peer, attr) < 0) { - return BGP_ATTR_PARSE_ERROR; + ret = BGP_ATTR_PARSE_ERROR; + goto done; } } /* Check all mandatory well-known attributes are present */ - if ((ret = bgp_attr_check(peer, attr)) < 0) { - if (as4_path) - aspath_unintern(&as4_path); - return ret; - } + if ((ret = bgp_attr_check(peer, attr)) < 0) + goto done; /* * At this place we can see whether we got AS4_PATH and/or @@ -2780,28 +2766,10 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, &as4_aggregator_addr)) { bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MAL_ATTR); - if (as4_path) - aspath_unintern(&as4_path); - return BGP_ATTR_PARSE_ERROR; + ret = BGP_ATTR_PARSE_ERROR; + goto done; } - /* At this stage, we have done all fiddling with as4, and the - * resulting info is in attr->aggregator resp. attr->aspath - * so we can chuck as4_aggregator and as4_path alltogether in - * order to save memory - */ - if (as4_path) { - aspath_unintern(&as4_path); /* unintern - it is in the hash */ - /* The flag that we got this is still there, but that does not - * do any trouble - */ - } - /* - * The "rest" of the code does nothing with as4_aggregator. - * there is no memory attached specifically which is not part - * of the attr. - * so ignoring just means do nothing. - */ /* * Finally do the checks on the aspath we did not do yet * because we waited for a potentially synthesized aspath. @@ -2809,21 +2777,59 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) { ret = bgp_attr_aspath_check(peer, attr); if (ret != BGP_ATTR_PARSE_PROCEED) - return ret; + goto done; + } + + ret = BGP_ATTR_PARSE_PROCEED; +done: + + /* + * At this stage, we have done all fiddling with as4, and the + * resulting info is in attr->aggregator resp. attr->aspath so + * we can chuck as4_aggregator and as4_path alltogether in order + * to save memory + */ + if (as4_path) { + /* + * unintern - it is in the hash + * The flag that we got this is still there, but that + * does not do any trouble + */ + aspath_unintern(&as4_path); } - /* Finally intern unknown attribute. */ + + if (ret != BGP_ATTR_PARSE_ERROR) { + /* Finally intern unknown attribute. */ + if (attr->transit) + attr->transit = transit_intern(attr->transit); + if (attr->encap_subtlvs) + attr->encap_subtlvs = encap_intern(attr->encap_subtlvs, + ENCAP_SUBTLV_TYPE); +#if ENABLE_BGP_VNC + if (attr->vnc_subtlvs) + attr->vnc_subtlvs = encap_intern(attr->vnc_subtlvs, + VNC_SUBTLV_TYPE); +#endif + } else { + if (attr->transit) { + transit_free(attr->transit); + attr->transit = NULL; + } + + bgp_attr_flush_encap(attr); + }; + + /* Sanity checks */ if (attr->transit) - attr->transit = transit_intern(attr->transit); + assert(attr->transit->refcnt > 0); if (attr->encap_subtlvs) - attr->encap_subtlvs = - encap_intern(attr->encap_subtlvs, ENCAP_SUBTLV_TYPE); + assert(attr->encap_subtlvs->refcnt > 0); #if ENABLE_BGP_VNC if (attr->vnc_subtlvs) - attr->vnc_subtlvs = - encap_intern(attr->vnc_subtlvs, VNC_SUBTLV_TYPE); + assert(attr->vnc_subtlvs->refcnt > 0); #endif - return BGP_ATTR_PARSE_PROCEED; + return ret; } /* diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index f1a871fe43..2dda2e37d7 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -260,7 +260,6 @@ extern void bgp_attr_finish(void); extern bgp_attr_parse_ret_t bgp_attr_parse(struct peer *, struct attr *, bgp_size_t, struct bgp_nlri *, struct bgp_nlri *); -extern void bgp_attr_dup(struct attr *, struct attr *); extern void bgp_attr_undup(struct attr *new, struct attr *old); extern struct attr *bgp_attr_intern(struct attr *attr); extern void bgp_attr_unintern_sub(struct attr *); @@ -293,9 +292,6 @@ extern unsigned long int attr_unknown_count(void); extern int cluster_loop_check(struct cluster_list *, struct in_addr); extern void cluster_unintern(struct cluster_list *); -/* Transit attribute prototypes. */ -void transit_unintern(struct transit *); - /* Below exported for unit-test purposes only */ struct bgp_attr_parser_args { struct peer *peer; diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 850b85aa6a..b75676e86e 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -77,37 +77,36 @@ static void ecommunity_hash_free(struct ecommunity *ecom) else return 0. */ int ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval) { - uint8_t *p; - int ret; int c; - /* When this is fist value, just add it. */ + /* When this is fist value, just add it. */ if (ecom->val == NULL) { - ecom->size++; - ecom->val = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom_length(ecom)); + ecom->size = 1; + ecom->val = XCALLOC(MTYPE_ECOMMUNITY_VAL, ECOMMUNITY_SIZE); memcpy(ecom->val, eval->val, ECOMMUNITY_SIZE); return 1; } /* If the value already exists in the structure return 0. */ c = 0; - for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) { - ret = memcmp(p, eval->val, ECOMMUNITY_SIZE); + for (uint8_t *p = ecom->val; c < ecom->size; + p += ECOMMUNITY_SIZE, c++) { + int ret = memcmp(p, eval->val, ECOMMUNITY_SIZE); if (ret == 0) return 0; - if (ret > 0) + else if (ret > 0) break; } /* Add the value to the structure with numerical sorting. */ ecom->size++; - ecom->val = - XREALLOC(MTYPE_ECOMMUNITY_VAL, ecom->val, ecom_length(ecom)); + ecom->val = XREALLOC(MTYPE_ECOMMUNITY_VAL, ecom->val, + ecom->size * ECOMMUNITY_SIZE); - memmove(ecom->val + (c + 1) * ECOMMUNITY_SIZE, - ecom->val + c * ECOMMUNITY_SIZE, + memmove(ecom->val + ((c + 1) * ECOMMUNITY_SIZE), + ecom->val + (c * ECOMMUNITY_SIZE), (ecom->size - 1 - c) * ECOMMUNITY_SIZE); - memcpy(ecom->val + c * ECOMMUNITY_SIZE, eval->val, ECOMMUNITY_SIZE); + memcpy(ecom->val + (c * ECOMMUNITY_SIZE), eval->val, ECOMMUNITY_SIZE); return 1; } @@ -556,8 +555,8 @@ struct ecommunity *ecommunity_str2com(const char *str, int type, return ecom; } -static int ecommunity_rt_soo_str(char *buf, uint8_t *pnt, int type, - int sub_type, int format) +static int ecommunity_rt_soo_str(char *buf, size_t bufsz, uint8_t *pnt, + int type, int sub_type, int format) { int len = 0; const char *prefix; @@ -589,23 +588,25 @@ static int ecommunity_rt_soo_str(char *buf, uint8_t *pnt, int type, eas.val = (*pnt++ << 8); eas.val |= (*pnt++); - len = sprintf(buf, "%s%u:%u", prefix, eas.as, eas.val); + len = snprintf(buf, bufsz, "%s%u:%u", prefix, eas.as, eas.val); } else if (type == ECOMMUNITY_ENCODE_AS) { eas.as = (*pnt++ << 8); eas.as |= (*pnt++); pnt = ptr_get_be32(pnt, &eas.val); - len = sprintf(buf, "%s%u:%u", prefix, eas.as, eas.val); + len = snprintf(buf, bufsz, "%s%u:%u", prefix, eas.as, eas.val); } else if (type == ECOMMUNITY_ENCODE_IP) { memcpy(&eip.ip, pnt, 4); pnt += 4; eip.val = (*pnt++ << 8); eip.val |= (*pnt++); - len = sprintf(buf, "%s%s:%u", prefix, inet_ntoa(eip.ip), - eip.val); + len = snprintf(buf, bufsz, "%s%s:%u", prefix, inet_ntoa(eip.ip), + eip.val); } - (void)pnt; /* consume value */ + + /* consume value */ + (void)pnt; return len; } @@ -640,44 +641,31 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) uint8_t *pnt; uint8_t type = 0; uint8_t sub_type = 0; -#define ECOMMUNITY_STR_DEFAULT_LEN 64 +#define ECOMMUNITY_STRLEN 64 int str_size; - int str_pnt; char *str_buf; - int len = 0; - int first = 1; - if (ecom->size == 0) { - str_buf = XMALLOC(MTYPE_ECOMMUNITY_STR, 1); - str_buf[0] = '\0'; - return str_buf; - } + if (ecom->size == 0) + return XCALLOC(MTYPE_ECOMMUNITY_STR, 1); - /* Prepare buffer. */ - str_buf = XMALLOC(MTYPE_ECOMMUNITY_STR, ECOMMUNITY_STR_DEFAULT_LEN + 1); - str_size = ECOMMUNITY_STR_DEFAULT_LEN + 1; - str_buf[0] = '\0'; - str_pnt = 0; + /* ecom strlen + space + null term */ + str_size = (ecom->size * (ECOMMUNITY_STRLEN + 1)) + 1; + str_buf = XCALLOC(MTYPE_ECOMMUNITY_STR, str_size); + + char encbuf[128]; for (i = 0; i < ecom->size; i++) { int unk_ecom = 0; - - /* Make it sure size is enough. */ - while (str_pnt + ECOMMUNITY_STR_DEFAULT_LEN >= str_size) { - str_size *= 2; - str_buf = XREALLOC(MTYPE_ECOMMUNITY_STR, str_buf, - str_size); - } + memset(encbuf, 0x00, sizeof(encbuf)); /* Space between each value. */ - if (!first) { - str_buf[str_pnt++] = ' '; - len++; - } + if (i > 0) + strlcat(str_buf, " ", str_size); + /* Retrieve value field */ pnt = ecom->val + (i * 8); - /* High-order octet of type. */ + /* High-order octet is the type */ type = *pnt++; if (type == ECOMMUNITY_ENCODE_AS || type == ECOMMUNITY_ENCODE_IP @@ -696,15 +684,15 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) inet_ntop(AF_INET, ipv4, ipv4str, INET_ADDRSTRLEN); - len = sprintf(str_buf + str_pnt, - "NH:%s:%d", - ipv4str, pnt[5]); + snprintf(encbuf, sizeof(encbuf), + "NH:%s:%d", ipv4str, pnt[5]); } else unk_ecom = 1; - } else - len = ecommunity_rt_soo_str(str_buf + str_pnt, - pnt, type, sub_type, - format); + } else { + ecommunity_rt_soo_str(encbuf, sizeof(encbuf), + pnt, type, sub_type, + format); + } } else if (type == ECOMMUNITY_ENCODE_OPAQUE) { if (filter == ECOMMUNITY_ROUTE_TARGET) continue; @@ -712,13 +700,15 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) uint16_t tunneltype; memcpy(&tunneltype, pnt + 5, 2); tunneltype = ntohs(tunneltype); - len = sprintf(str_buf + str_pnt, "ET:%d", - tunneltype); + + snprintf(encbuf, sizeof(encbuf), "ET:%d", + tunneltype); } else if (*pnt == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW) { - len = sprintf(str_buf + str_pnt, - "Default Gateway"); - } else + strlcpy(encbuf, "Default Gateway", + sizeof(encbuf)); + } else { unk_ecom = 1; + } } else if (type == ECOMMUNITY_ENCODE_EVPN) { if (filter == ECOMMUNITY_ROUTE_TARGET) continue; @@ -726,15 +716,15 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) struct ethaddr rmac; pnt++; memcpy(&rmac, pnt, ETH_ALEN); - len = sprintf( - str_buf + str_pnt, - "Rmac:%02x:%02x:%02x:%02x:%02x:%02x", - (uint8_t)rmac.octet[0], - (uint8_t)rmac.octet[1], - (uint8_t)rmac.octet[2], - (uint8_t)rmac.octet[3], - (uint8_t)rmac.octet[4], - (uint8_t)rmac.octet[5]); + + snprintf(encbuf, sizeof(encbuf), + "Rmac:%02x:%02x:%02x:%02x:%02x:%02x", + (uint8_t)rmac.octet[0], + (uint8_t)rmac.octet[1], + (uint8_t)rmac.octet[2], + (uint8_t)rmac.octet[3], + (uint8_t)rmac.octet[4], + (uint8_t)rmac.octet[5]); } else if (*pnt == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY) { uint32_t seqnum; @@ -742,29 +732,30 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) memcpy(&seqnum, pnt + 2, 4); seqnum = ntohl(seqnum); - if (flags - & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY) - len = sprintf(str_buf + str_pnt, - "MM:%u, sticky MAC", - seqnum); - else - len = sprintf(str_buf + str_pnt, - "MM:%u", seqnum); + + snprintf(encbuf, sizeof(encbuf), "MM:%u", + seqnum); + + if (CHECK_FLAG( + flags, + ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)) + strlcat(encbuf, ", sticky MAC", + sizeof(encbuf)); } else if (*pnt == ECOMMUNITY_EVPN_SUBTYPE_ND) { uint8_t flags = *++pnt; - if (flags - & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG) - len = sprintf(str_buf + str_pnt, - "ND:Router Flag"); + if (CHECK_FLAG( + flags, + ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG)) + strlcpy(encbuf, "ND:Router Flag", + sizeof(encbuf)); } else unk_ecom = 1; } else if (type == ECOMMUNITY_ENCODE_REDIRECT_IP_NH) { sub_type = *pnt++; if (sub_type == ECOMMUNITY_REDIRECT_IP_NH) { - len = sprintf( - str_buf + str_pnt, - "FS:redirect IP 0x%x", *(pnt+5)); + snprintf(encbuf, sizeof(encbuf), + "FS:redirect IP 0x%x", *(pnt + 5)); } else unk_ecom = 1; } else if (type == ECOMMUNITY_ENCODE_TRANS_EXP || @@ -772,38 +763,35 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) type == ECOMMUNITY_EXTENDED_COMMUNITY_PART_3) { sub_type = *pnt++; if (sub_type == ECOMMUNITY_REDIRECT_VRF) { - char buf[16]; - - memset(buf, 0, sizeof(buf)); - ecommunity_rt_soo_str(buf, (uint8_t *)pnt, - type & - ~ECOMMUNITY_ENCODE_TRANS_EXP, - ECOMMUNITY_ROUTE_TARGET, - ECOMMUNITY_FORMAT_DISPLAY); - len = snprintf(str_buf + str_pnt, - str_size - len, - "FS:redirect VRF %s", buf); + char buf[16] = {}; + ecommunity_rt_soo_str( + buf, sizeof(buf), (uint8_t *)pnt, + type & ~ECOMMUNITY_ENCODE_TRANS_EXP, + ECOMMUNITY_ROUTE_TARGET, + ECOMMUNITY_FORMAT_DISPLAY); + snprintf(encbuf, sizeof(encbuf), + "FS:redirect VRF %s", buf); } else if (type != ECOMMUNITY_ENCODE_TRANS_EXP) unk_ecom = 1; else if (sub_type == ECOMMUNITY_TRAFFIC_ACTION) { char action[64]; - char *ptr = action; if (*(pnt+3) == 1 << FLOWSPEC_TRAFFIC_ACTION_TERMINAL) - ptr += snprintf(ptr, sizeof(action), - "terminate (apply)"); + strlcpy(action, "terminate (apply)", + sizeof(action)); else - ptr += snprintf(ptr, sizeof(action), - "eval stops"); + strlcpy(action, "eval stops", + sizeof(action)); + if (*(pnt+3) == 1 << FLOWSPEC_TRAFFIC_ACTION_SAMPLE) - snprintf(ptr, sizeof(action) - - (size_t)(ptr-action), - ", sample"); - len = snprintf(str_buf + str_pnt, - str_size - len, - "FS:action %s", action); + strlcat(action, ", sample", + sizeof(action)); + + + snprintf(encbuf, sizeof(encbuf), "FS:action %s", + action); } else if (sub_type == ECOMMUNITY_TRAFFIC_RATE) { union traffic_rate data; @@ -811,21 +799,19 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) data.rate_byte[2] = *(pnt+3); data.rate_byte[1] = *(pnt+4); data.rate_byte[0] = *(pnt+5); - len = sprintf( - str_buf + str_pnt, - "FS:rate %f", data.rate_float); + snprintf(encbuf, sizeof(encbuf), "FS:rate %f", + data.rate_float); } else if (sub_type == ECOMMUNITY_TRAFFIC_MARKING) { - len = sprintf( - str_buf + str_pnt, - "FS:marking %u", *(pnt+5)); + snprintf(encbuf, sizeof(encbuf), + "FS:marking %u", *(pnt + 5)); } else if (*pnt == ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT) { struct ethaddr mac; - pnt++; memcpy(&mac, pnt, ETH_ALEN); - len = sprintf( - str_buf + str_pnt, + + snprintf( + encbuf, sizeof(encbuf), "ES-Import-Rt:%02x:%02x:%02x:%02x:%02x:%02x", (uint8_t)mac.octet[0], (uint8_t)mac.octet[1], @@ -841,11 +827,11 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) } if (unk_ecom) - len = sprintf(str_buf + str_pnt, "UNK:%d, %d", - type, sub_type); + snprintf(encbuf, sizeof(encbuf), "UNK:%d, %d", type, + sub_type); - str_pnt += len; - first = 0; + int r = strlcat(str_buf, encbuf, str_size); + assert(r < str_size); } return str_buf; diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index 79be4ee422..a4c0f45c65 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -105,8 +105,6 @@ struct ecommunity_val { char val[ECOMMUNITY_SIZE]; }; -#define ecom_length(X) ((X)->size * ECOMMUNITY_SIZE) - /* * Encode BGP Route Target AS:nn. */ diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 739f8e605f..e86379d1d4 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1531,7 +1531,7 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp, * present, else treat as locally originated. */ if (src_attr) - bgp_attr_dup(&attr, src_attr); + attr = *src_attr; else { memset(&attr, 0, sizeof(struct attr)); bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); @@ -2497,7 +2497,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, * address for the rest of the code to flow through. In the case of IPv4, * make sure to set the flag for next hop attribute. */ - bgp_attr_dup(&attr, parent_pi->attr); + attr = *parent_pi->attr; if (afi == AFI_IP6) evpn_convert_nexthop_to_ipv6(&attr); else diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c index aeb290719a..8d99548fc2 100644 --- a/bgpd/bgp_lcommunity.c +++ b/bgpd/bgp_lcommunity.c @@ -177,15 +177,14 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json) { int i; int len; - bool first = true; char *str_buf; - char *str_pnt; uint8_t *pnt; uint32_t global, local1, local2; json_object *json_lcommunity_list = NULL; json_object *json_string = NULL; -#define LCOMMUNITY_STR_DEFAULT_LEN 32 + /* 3 32-bit integers, 2 colons, and a space */ +#define LCOMMUNITY_STRLEN (10 * 3 + 2 + 1) if (!lcom) return; @@ -196,8 +195,7 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json) } if (lcom->size == 0) { - str_buf = XMALLOC(MTYPE_LCOMMUNITY_STR, 1); - str_buf[0] = '\0'; + str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, 1); if (make_json) { json_object_string_add(lcom->json, "string", ""); @@ -209,15 +207,13 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json) return; } - str_buf = str_pnt = - XMALLOC(MTYPE_LCOMMUNITY_STR, - (LCOMMUNITY_STR_DEFAULT_LEN * lcom->size) + 1); + /* 1 space + lcom->size lcom strings + null terminator */ + size_t str_buf_sz = (LCOMMUNITY_STRLEN * lcom->size) + 2; + str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, str_buf_sz); for (i = 0; i < lcom->size; i++) { - if (first) - first = false; - else - *str_pnt++ = ' '; + if (i > 0) + strlcat(str_buf, " ", str_buf_sz); pnt = lcom->val + (i * LCOMMUNITY_SIZE); pnt = ptr_get_be32(pnt, &global); @@ -225,19 +221,21 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json) pnt = ptr_get_be32(pnt, &local2); (void)pnt; - len = sprintf(str_pnt, "%u:%u:%u", global, local1, local2); + char lcsb[LCOMMUNITY_STRLEN + 1]; + + snprintf(lcsb, sizeof(lcsb), "%u:%u:%u", global, local1, + local2); + + len = strlcat(str_buf, lcsb, str_buf_sz); + assert((unsigned int)len < str_buf_sz); + if (make_json) { - json_string = json_object_new_string(str_pnt); + json_string = json_object_new_string(lcsb); json_object_array_add(json_lcommunity_list, json_string); } - - str_pnt += len; } - str_buf = - XREALLOC(MTYPE_LCOMMUNITY_STR, str_buf, str_pnt - str_buf + 1); - if (make_json) { json_object_string_add(lcom->json, "string", str_buf); json_object_object_add(lcom->json, "list", diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 648c3be47e..90b37f0dd2 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -722,7 +722,7 @@ void bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best, return; } - bgp_attr_dup(&attr, new_best->attr); + attr = *new_best->attr; if (new_best->peer && bgp_flag_check(new_best->peer->bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET)) { diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 3ad41ca620..f99ffce1ad 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -700,7 +700,8 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ return; } - bgp_attr_dup(&static_attr, path_vrf->attr); /* shallow copy */ + /* shallow copy */ + static_attr = *path_vrf->attr; /* * route map handling @@ -1081,7 +1082,8 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ buf_prefix, bgp_vrf->name_pretty); } - bgp_attr_dup(&static_attr, path_vpn->attr); /* shallow copy */ + /* shallow copy */ + static_attr = *path_vpn->attr; /* * Nexthop: stash and clear diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index ea451f5f8d..2fe35d0b01 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1695,7 +1695,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, } /* For modify attribute, copy it to temporary structure. */ - bgp_attr_dup(attr, piattr); + *attr = *piattr; /* If local-preference is not set. */ if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) @@ -1814,7 +1814,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP) && !bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { - bgp_attr_dup(&dummy_attr, attr); + dummy_attr = *attr; rmap_path.attr = &dummy_attr; } @@ -3154,7 +3154,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, goto filtered; } - bgp_attr_dup(&new_attr, attr); + new_attr = *attr; /* Apply incoming route-map. * NB: new_attr may now contain newly allocated values from route-map @@ -4465,7 +4465,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr, if (addpath_encoded) { /* When packet overflow occurs return immediately. */ - if (pnt + BGP_ADDPATH_ID_LEN > lim) + if (pnt + BGP_ADDPATH_ID_LEN >= lim) return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN); @@ -6744,7 +6744,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, struct attr attr_new; /* Copy attribute for modification. */ - bgp_attr_dup(&attr_new, &attr); + attr_new = attr; if (red->redist_metric_flag) attr_new.med = red->redist_metric; @@ -9255,7 +9255,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, struct attr dummy_attr; route_map_result_t ret; - bgp_attr_dup(&dummy_attr, pi->attr); + dummy_attr = *pi->attr; path.peer = pi->peer; path.attr = &dummy_attr; @@ -11330,7 +11330,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, header2 = 0; } - bgp_attr_dup(&attr, ain->attr); + attr = *ain->attr; route_filtered = false; /* Filter prefix using distribute list, @@ -11431,7 +11431,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, header2 = 0; } - bgp_attr_dup(&attr, adj->attr); + attr = *adj->attr; ret = bgp_output_modifier( peer, &rn->p, &attr, afi, safi, rmap_name); diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 0cc2e354d5..6117d62ab5 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -755,7 +755,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) /* Provide dummy so the route-map can't modify * the attributes */ - bgp_attr_dup(&dummy_attr, ri->attr); + dummy_attr = *ri->attr; tmp_info.peer = ri->peer; tmp_info.attr = &dummy_attr; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 71f7f6d0e3..e561832e2d 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1726,7 +1726,7 @@ int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red, struct attr *old_attr; struct attr new_attr; - bgp_attr_dup(&new_attr, pi->attr); + new_attr = *pi->attr; new_attr.med = red->redist_metric; old_attr = pi->attr; pi->attr = bgp_attr_intern(&new_attr); diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c index 3d8d5bccb0..c85c78a77a 100644 --- a/bgpd/rfapi/vnc_export_bgp.c +++ b/bgpd/rfapi/vnc_export_bgp.c @@ -78,7 +78,7 @@ static void encap_attr_export_ce(struct attr *new, struct attr *orig, * Make "new" a ghost attr copy of "orig" */ memset(new, 0, sizeof(struct attr)); - bgp_attr_dup(new, orig); + *new = *orig; /* * Set nexthop @@ -616,7 +616,7 @@ encap_attr_export(struct attr *new, struct attr *orig, * Make "new" a ghost attr copy of "orig" */ memset(new, 0, sizeof(struct attr)); - bgp_attr_dup(new, orig); + *new = *orig; /* * Set nexthop diff --git a/bgpd/rfapi/vnc_import_bgp.c b/bgpd/rfapi/vnc_import_bgp.c index eb2d0fd889..f9bfe76d66 100644 --- a/bgpd/rfapi/vnc_import_bgp.c +++ b/bgpd/rfapi/vnc_import_bgp.c @@ -356,7 +356,8 @@ static int process_unicast_route(struct bgp *bgp, /* in */ * all of the possible returns above. */ memset(&hattr, 0, sizeof(struct attr)); - bgp_attr_dup(&hattr, attr); /* hattr becomes a ghost attr */ + /* hattr becomes a ghost attr */ + hattr = *attr; if (rmap) { struct bgp_path_info info; @@ -808,7 +809,8 @@ static void vnc_import_bgp_add_route_mode_plain(struct bgp *bgp, * all of the possible returns above. */ memset(&hattr, 0, sizeof(struct attr)); - bgp_attr_dup(&hattr, attr); /* hattr becomes a ghost attr */ + /* hattr becomes a ghost attr */ + hattr = *attr; if (rmap) { struct bgp_path_info info; @@ -1010,7 +1012,8 @@ vnc_import_bgp_add_route_mode_nvegroup(struct bgp *bgp, struct prefix *prefix, * all of the possible returns above. */ memset(&hattr, 0, sizeof(struct attr)); - bgp_attr_dup(&hattr, attr); /* hattr becomes a ghost attr */ + /* hattr becomes a ghost attr */ + hattr = *attr; if (rmap) { struct bgp_path_info path; @@ -1797,7 +1800,7 @@ static void vnc_import_bgp_exterior_add_route_it( /* use local_pref from unicast route */ memset(&new_attr, 0, sizeof(struct attr)); - bgp_attr_dup(&new_attr, bpi_interior->attr); + new_attr = *bpi_interior->attr; if (info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { new_attr.local_pref = @@ -2128,7 +2131,7 @@ void vnc_import_bgp_exterior_add_route_interior( /* use local_pref from unicast route */ memset(&new_attr, 0, sizeof(struct attr)); - bgp_attr_dup(&new_attr, bpi_interior->attr); + new_attr = *bpi_interior->attr; if (bpi_exterior && (bpi_exterior->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) { @@ -2265,7 +2268,7 @@ void vnc_import_bgp_exterior_add_route_interior( /* use local_pref from unicast route */ memset(&new_attr, 0, sizeof(struct attr)); - bgp_attr_dup(&new_attr, bpi_interior->attr); + new_attr = *bpi_interior->attr; if (bpi_exterior && (bpi_exterior->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) { @@ -2386,7 +2389,7 @@ void vnc_import_bgp_exterior_add_route_interior( /* use local_pref from unicast route */ memset(&new_attr, 0, sizeof(struct attr)); - bgp_attr_dup(&new_attr, bpi_interior->attr); + new_attr = *bpi_interior->attr; if (bpi_exterior && (bpi_exterior->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) { @@ -2577,7 +2580,7 @@ void vnc_import_bgp_exterior_del_route_interior( /* use local_pref from unicast route */ memset(&new_attr, 0, sizeof(struct attr)); - bgp_attr_dup(&new_attr, bpi->attr); + new_attr = *bpi->attr; if (bpi_exterior && (bpi_exterior->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) { diff --git a/lib/plist.c b/lib/plist.c index 64571a05b7..a0976cd6bd 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -1891,6 +1891,8 @@ int prefix_bgp_orf_set(char *name, afi_t afi, struct orf_prefix *orfp, if (!plist) return CMD_WARNING_CONFIG_FAILED; + apply_mask(&orfp->p); + if (set) { pentry = prefix_list_entry_make( &orfp->p, (permit ? PREFIX_PERMIT : PREFIX_DENY), diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 5a29c1fb07..e80d826a3c 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -2319,7 +2319,7 @@ static struct stream *ospf_recv_packet(struct ospf *ospf, int fd, safe_strerror(errno)); return NULL; } - if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */ + if ((unsigned int)ret < sizeof(struct ip)) { flog_warn( EC_OSPF_PACKET, @@ -2994,9 +2994,23 @@ int ospf_read(struct thread *thread) return 0; } - /* Advance from IP header to OSPF header (iph->ip_hl has been verified - by ospf_recv_packet() to be correct). */ - stream_forward_getp(ibuf, iph->ip_hl * 4); + /* Check that we have enough for an IP header */ + if ((unsigned int)(iph->ip_hl << 2) >= STREAM_READABLE(ibuf)) { + if ((unsigned int)(iph->ip_hl << 2) == STREAM_READABLE(ibuf)) { + flog_warn( + EC_OSPF_PACKET, + "Rx'd IP packet with OSPF protocol number but no payload"); + } else { + flog_warn( + EC_OSPF_PACKET, + "IP header length field claims header is %u bytes, but we only have %zu", + (unsigned int)(iph->ip_hl << 2), + STREAM_READABLE(ibuf)); + } + + return -1; + } + stream_forward_getp(ibuf, iph->ip_hl << 2); ospfh = (struct ospf_header *)stream_pnt(ibuf); if (MSG_OK diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 7dfd26ea65..d87cea0d35 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -478,10 +478,24 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len) ip_hdr->ip_p); } + if (ip_hlen > len) { + zlog_warn( + "IGMP packet header claims size %zu, but we only have %zu bytes", + ip_hlen, len); + return -1; + } + igmp_msg = buf + ip_hlen; - msg_type = *igmp_msg; igmp_msg_len = len - ip_hlen; + if (igmp_msg_len < PIM_IGMP_MIN_LEN) { + zlog_warn("IGMP message size=%d shorter than minimum=%d", + igmp_msg_len, PIM_IGMP_MIN_LEN); + return -1; + } + + msg_type = *igmp_msg; + if (PIM_DEBUG_IGMP_PACKETS) { zlog_debug( "Recv IGMP packet from %s to %s on %s: ttl=%d msg_type=%d msg_size=%d", @@ -489,12 +503,6 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len) msg_type, igmp_msg_len); } - if (igmp_msg_len < PIM_IGMP_MIN_LEN) { - zlog_warn("IGMP message size=%d shorter than minimum=%d", - igmp_msg_len, PIM_IGMP_MIN_LEN); - return -1; - } - switch (msg_type) { case PIM_IGMP_MEMBERSHIP_QUERY: { int max_resp_code = igmp_msg[1]; diff --git a/pimd/pim_igmp_mtrace.c b/pimd/pim_igmp_mtrace.c index 0758e2f784..695d04c7c2 100644 --- a/pimd/pim_igmp_mtrace.c +++ b/pimd/pim_igmp_mtrace.c @@ -864,6 +864,16 @@ int igmp_mtrace_recv_response(struct igmp_sock *igmp, struct ip *ip_hdr, pim_ifp = ifp->info; pim = pim_ifp->pim; + if (igmp_msg_len < (int)sizeof(struct igmp_mtrace)) { + if (PIM_DEBUG_MTRACE) + zlog_warn( + "Recv mtrace packet from %s on %s: too short," + " len=%d, min=%zu", + from_str, ifp->name, igmp_msg_len, + sizeof(struct igmp_mtrace)); + return -1; + } + mtracep = (struct igmp_mtrace *)igmp_msg; recv_checksum = mtracep->checksum; diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index f7f4b54aea..6472de42d4 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -585,6 +585,9 @@ static int pim_mroute_msg(struct pim_instance *pim, const char *buf, struct in_addr ifaddr; struct igmp_sock *igmp; + if (buf_size < (int)sizeof(struct ip)) + return 0; + ip_hdr = (const struct ip *)buf; if (ip_hdr->ip_p == IPPROTO_IGMP) { |
