From: Donald Sharp Date: Fri, 10 Nov 2017 13:51:34 +0000 (-0500) Subject: lib, zebra: Modify zebra to use STREAM_GET for zapi X-Git-Tag: frr-4.0-dev~153^2~3 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=ec93aa120e7f1e817cbbe0498a719d5392a049ba;p=matthieu%2Ffrr.git lib, zebra: Modify zebra to use STREAM_GET for zapi This code modifies zebra to use the STREAM_GET functionality. This will allow zebra to continue functioning in the case of bad input data from higher level protocols instead of crashing. Signed-off-by: Donald Sharp --- diff --git a/lib/zclient.c b/lib/zclient.c index 8ada2cf978..ce4886efdc 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -297,11 +297,12 @@ int zclient_read_header(struct stream *s, int sock, u_int16_t *size, if (stream_read(s, sock, ZEBRA_HEADER_SIZE) != ZEBRA_HEADER_SIZE) return -1; - *size = stream_getw(s) - ZEBRA_HEADER_SIZE; - *marker = stream_getc(s); - *version = stream_getc(s); - *vrf_id = stream_getw(s); - *cmd = stream_getw(s); + STREAM_GETW(s, *size); + *size -= ZEBRA_HEADER_SIZE; + STREAM_GETC(s, *marker); + STREAM_GETC(s, *version); + STREAM_GETW(s, *vrf_id); + STREAM_GETW(s, *cmd); if (*version != ZSERV_VERSION || *marker != ZEBRA_HEADER_MARKER) { zlog_err( @@ -313,6 +314,7 @@ int zclient_read_header(struct stream *s, int sock, u_int16_t *size, if (*size && stream_read(s, sock, *size) != *size) return -1; +stream_failure: return 0; } @@ -956,6 +958,10 @@ int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api) 16); stream_putl(s, api_nh->ifindex); break; + default: + zlog_warn("%s: Specified Nexthop type %d does not exist", + __PRETTY_FUNCTION__, api_nh->type); + return -1; } /* MPLS labels for BGP-LU or Segment Routing */ @@ -1005,37 +1011,66 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api) memset(api, 0, sizeof(*api)); /* Type, flags, message. */ - api->type = stream_getc(s); - api->instance = stream_getw(s); - api->flags = stream_getl(s); - api->message = stream_getc(s); - api->safi = stream_getw(s); + STREAM_GETC(s, api->type); + if (api->type > ZEBRA_ROUTE_MAX) { + zlog_warn("%s: Specified route type: %d is not a legal value\n", + __PRETTY_FUNCTION__, api->type); + return -1; + } + + STREAM_GETW(s, api->instance); + STREAM_GETL(s, api->flags); + STREAM_GETC(s, api->message); + STREAM_GETW(s, api->safi); /* Prefix. */ - api->prefix.family = stream_getc(s); + STREAM_GETC(s, api->prefix.family); + STREAM_GETC(s, api->prefix.prefixlen); switch (api->prefix.family) { case AF_INET: - api->prefix.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); + if (api->prefix.prefixlen > IPV4_MAX_PREFIXLEN) { + zlog_warn("%s: V4 prefixlen is %d which should not be more than 32", + __PRETTY_FUNCTION__, api->prefix.prefixlen); + return -1; + } break; case AF_INET6: - api->prefix.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); + if (api->prefix.prefixlen > IPV6_MAX_PREFIXLEN) { + zlog_warn("%s: v6 prefixlen is %d which should not be more than 128", + __PRETTY_FUNCTION__, api->prefix.prefixlen); + return -1; + } break; + default: + zlog_warn("%s: Specified family %d is not v4 or v6", + __PRETTY_FUNCTION__, api->prefix.family); + return -1; } - stream_get(&api->prefix.u.prefix, s, PSIZE(api->prefix.prefixlen)); + STREAM_GET(&api->prefix.u.prefix, s, PSIZE(api->prefix.prefixlen)); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) { api->src_prefix.family = AF_INET6; - api->src_prefix.prefixlen = stream_getc(s); - stream_get(&api->src_prefix.prefix, s, + STREAM_GETC(s, api->src_prefix.prefixlen); + if (api->src_prefix.prefixlen > IPV6_MAX_PREFIXLEN) { + zlog_warn("%s: SRC Prefix prefixlen received: %d is too large", + __PRETTY_FUNCTION__, + api->src_prefix.prefixlen); + return -1; + } + STREAM_GET(&api->src_prefix.prefix, s, PSIZE(api->src_prefix.prefixlen)); if (api->prefix.family != AF_INET6 - || api->src_prefix.prefixlen == 0) - UNSET_FLAG(api->message, ZAPI_MESSAGE_SRCPFX); + || api->src_prefix.prefixlen == 0) { + zlog_warn("%s: SRC prefix specified in some manner that makes no sense", + __PRETTY_FUNCTION__); + return -1; + } } /* Nexthops. */ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { - api->nexthop_num = stream_getw(s); + STREAM_GETW(s, api->nexthop_num); if (api->nexthop_num > MULTIPATH_NUM) { zlog_warn("%s: invalid number of nexthops (%u)", __func__, api->nexthop_num); @@ -1045,33 +1080,40 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api) for (i = 0; i < api->nexthop_num; i++) { api_nh = &api->nexthops[i]; - api_nh->type = stream_getc(s); + STREAM_GETC(s, api_nh->type); switch (api_nh->type) { case NEXTHOP_TYPE_BLACKHOLE: - api_nh->bh_type = stream_getc(s); + STREAM_GETC(s, api_nh->bh_type); break; case NEXTHOP_TYPE_IPV4: - api_nh->gate.ipv4.s_addr = stream_get_ipv4(s); + STREAM_GET(&api_nh->gate.ipv4.s_addr, s, + IPV4_MAX_BYTELEN); break; case NEXTHOP_TYPE_IPV4_IFINDEX: - api_nh->gate.ipv4.s_addr = stream_get_ipv4(s); - api_nh->ifindex = stream_getl(s); + STREAM_GET(&api_nh->gate.ipv4.s_addr, s, + IPV4_MAX_BYTELEN); + STREAM_GETL(s, api_nh->ifindex); break; case NEXTHOP_TYPE_IFINDEX: - api_nh->ifindex = stream_getl(s); + STREAM_GETL(s, api_nh->ifindex); break; case NEXTHOP_TYPE_IPV6: - stream_get(&api_nh->gate.ipv6, s, 16); + STREAM_GET(&api_nh->gate.ipv6, s, 16); break; case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_get(&api_nh->gate.ipv6, s, 16); - api_nh->ifindex = stream_getl(s); + STREAM_GET(&api_nh->gate.ipv6, s, 16); + STREAM_GETL(s, api_nh->ifindex); break; + default: + zlog_warn("%s: Specified nexthop type %d does not exist", + __PRETTY_FUNCTION__, + api_nh->type); + return -1; } /* MPLS labels for BGP-LU or Segment Routing */ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) { - api_nh->label_num = stream_getc(s); + STREAM_GETC(s, api_nh->label_num); if (api_nh->label_num > MPLS_MAX_LABELS) { zlog_warn( @@ -1081,7 +1123,7 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api) return -1; } - stream_get(&api_nh->labels[0], s, + STREAM_GET(&api_nh->labels[0], s, api_nh->label_num * sizeof(mpls_label_t)); } @@ -1090,14 +1132,15 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api) /* Attributes. */ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE)) - api->distance = stream_getc(s); + STREAM_GETC(s, api->distance); if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC)) - api->metric = stream_getl(s); + STREAM_GETL(s, api->metric); if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG)) - api->tag = stream_getl(s); + STREAM_GETL(s, api->tag); if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU)) - api->mtu = stream_getl(s); + STREAM_GETL(s, api->mtu); +stream_failure: return 0; } @@ -1136,17 +1179,23 @@ static void zclient_stream_get_prefix(struct stream *s, struct prefix *p) return; stream_get(&p->u.prefix, s, plen); - c = stream_getc(s); + STREAM_GETC(s, c); p->prefixlen = MIN(plen * 8, c); + +stream_failure: + return; } /* Router-id update from zebra daemon. */ void zebra_router_id_update_read(struct stream *s, struct prefix *rid) { /* Fetch interface address. */ - rid->family = stream_getc(s); + STREAM_GETC(s, rid->family); zclient_stream_get_prefix(s, rid); + +stream_failure: + return; } /* Interface addition from zebra daemon. */ diff --git a/zebra/redistribute.c b/zebra/redistribute.c index cc679142f7..cbf77765a3 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -246,16 +246,25 @@ void redistribute_delete(struct prefix *p, struct prefix *src_p, void zebra_redistribute_add(int command, struct zserv *client, int length, struct zebra_vrf *zvrf) { - afi_t afi; - int type; + afi_t afi = 0; + int type = 0; u_short instance; - afi = stream_getc(client->ibuf); - type = stream_getc(client->ibuf); - instance = stream_getw(client->ibuf); + STREAM_GETC(client->ibuf, afi); + STREAM_GETC(client->ibuf, type); + STREAM_GETW(client->ibuf, instance); - if (type == 0 || type >= ZEBRA_ROUTE_MAX) + if (afi == 0 || afi > AFI_MAX) { + zlog_warn("%s: Specified afi %d does not exist", + __PRETTY_FUNCTION__, afi); return; + } + + if (type == 0 || type >= ZEBRA_ROUTE_MAX) { + zlog_warn("%s: Specified Route Type %d does not exist", + __PRETTY_FUNCTION__, type); + return; + } if (instance) { if (!redist_check_instance(&client->mi_redist[afi][type], @@ -273,21 +282,33 @@ void zebra_redistribute_add(int command, struct zserv *client, int length, zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi); } } + +stream_failure: + return; } void zebra_redistribute_delete(int command, struct zserv *client, int length, struct zebra_vrf *zvrf) { - afi_t afi; - int type; + afi_t afi = 0; + int type = 0; u_short instance; - afi = stream_getc(client->ibuf); - type = stream_getc(client->ibuf); - instance = stream_getw(client->ibuf); + STREAM_GETC(client->ibuf, afi); + STREAM_GETC(client->ibuf, type); + STREAM_GETW(client->ibuf, instance); - if (type == 0 || type >= ZEBRA_ROUTE_MAX) + if (afi == 0 || afi > AFI_MAX) { + zlog_warn("%s: Specified afi %d does not exist", + __PRETTY_FUNCTION__, afi); return; + } + + if (type == 0 || type >= ZEBRA_ROUTE_MAX) { + zlog_warn("%s: Specified Route Type %d does not exist", + __PRETTY_FUNCTION__, type); + return; + } /* * NOTE: no need to withdraw the previously advertised routes. The @@ -299,6 +320,9 @@ void zebra_redistribute_delete(int command, struct zserv *client, int length, redist_del_instance(&client->mi_redist[afi][type], instance); else vrf_bitmap_unset(client->redist[afi][type], zvrf_id(zvrf)); + +stream_failure: + return; } void zebra_redistribute_default_add(int command, struct zserv *client, diff --git a/zebra/rtadv.c b/zebra/rtadv.c index a1e1602bf8..40219599dd 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -804,7 +804,7 @@ void zebra_interface_radv_set(struct zserv *client, u_short length, struct zebra_vrf *zvrf, int enable) { struct stream *s; - unsigned int ifindex; + ifindex_t ifindex; struct interface *ifp; struct zebra_if *zif; int ra_interval; @@ -812,8 +812,8 @@ void zebra_interface_radv_set(struct zserv *client, u_short length, s = client->ibuf; /* Get interface index and RA interval. */ - ifindex = stream_getl(s); - ra_interval = stream_getl(s); + STREAM_GETL(s, ifindex); + STREAM_GETL(s, ra_interval); if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("%u: IF %u RA %s from client %s, interval %ds", @@ -849,6 +849,8 @@ void zebra_interface_radv_set(struct zserv *client, u_short length, ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS); } } +stream_failure: + return; } DEFUN (ipv6_nd_suppress_ra, diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c index 8fa00b83c9..519c120a67 100644 --- a/zebra/zebra_mroute.c +++ b/zebra/zebra_mroute.c @@ -37,12 +37,12 @@ int zebra_ipmr_route_stats(struct zserv *client, u_short length, { struct mcast_route_data mroute; struct stream *s; - int suc; + int suc = -1; memset(&mroute, 0, sizeof(mroute)); - stream_get(&mroute.sg.src, client->ibuf, 4); - stream_get(&mroute.sg.grp, client->ibuf, 4); - mroute.ifindex = stream_getl(client->ibuf); + STREAM_GET(&mroute.sg.src, client->ibuf, 4); + STREAM_GET(&mroute.sg.grp, client->ibuf, 4); + STREAM_GETL(client->ibuf, mroute.ifindex); if (IS_ZEBRA_DEBUG_KERNEL) { char sbuf[40]; @@ -56,6 +56,7 @@ int zebra_ipmr_route_stats(struct zserv *client, u_short length, suc = kernel_get_ipmr_sg_stats(zvrf, &mroute); +stream_failure: s = client->obuf; stream_reset(s); diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 464a8cf875..dcd4fb0239 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -705,19 +705,19 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, s = client->ibuf; - pid = stream_getl(s); + STREAM_GETL(s, pid); sprintf(tmp_buf, "%d", pid); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, tmp_buf); - dst_p.family = stream_getw(s); + STREAM_GETW(s, dst_p.family); if (dst_p.family == AF_INET) dst_p.prefixlen = IPV4_MAX_BYTELEN; else dst_p.prefixlen = IPV6_MAX_BYTELEN; - stream_get(&dst_p.u.prefix, s, dst_p.prefixlen); + STREAM_GET(&dst_p.u.prefix, s, dst_p.prefixlen); if (dst_p.family == AF_INET) { inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf)); ptm_lib_append_msg(ptm_hdl, out_ctxt, @@ -728,32 +728,32 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, ZEBRA_PTM_BFD_DST_IP_FIELD, buf); } - min_rx_timer = stream_getl(s); + STREAM_GETL(s, min_rx_timer); sprintf(tmp_buf, "%d", min_rx_timer); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_RX_FIELD, tmp_buf); - min_tx_timer = stream_getl(s); + STREAM_GETL(s, min_tx_timer); sprintf(tmp_buf, "%d", min_tx_timer); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_TX_FIELD, tmp_buf); - detect_mul = stream_getc(s); + STREAM_GETC(s, detect_mul); sprintf(tmp_buf, "%d", detect_mul); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DETECT_MULT_FIELD, tmp_buf); - multi_hop = stream_getc(s); + STREAM_GETC(s, multi_hop); if (multi_hop) { sprintf(tmp_buf, "%d", 1); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MULTI_HOP_FIELD, tmp_buf); - src_p.family = stream_getw(s); + STREAM_GETW(s, src_p.family); if (src_p.family == AF_INET) src_p.prefixlen = IPV4_MAX_BYTELEN; else src_p.prefixlen = IPV6_MAX_BYTELEN; - stream_get(&src_p.u.prefix, s, src_p.prefixlen); + STREAM_GET(&src_p.u.prefix, s, src_p.prefixlen); if (src_p.family == AF_INET) { inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); ptm_lib_append_msg(ptm_hdl, out_ctxt, @@ -764,7 +764,7 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); } - multi_hop_cnt = stream_getc(s); + STREAM_GETC(s, multi_hop_cnt); sprintf(tmp_buf, "%d", multi_hop_cnt); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD, tmp_buf); @@ -775,14 +775,14 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, zvrf_name(zvrf)); } else { if (dst_p.family == AF_INET6) { - src_p.family = stream_getw(s); + STREAM_GETW(s, src_p.family); if (src_p.family == AF_INET) src_p.prefixlen = IPV4_MAX_BYTELEN; else src_p.prefixlen = IPV6_MAX_BYTELEN; - stream_get(&src_p.u.prefix, s, src_p.prefixlen); + STREAM_GET(&src_p.u.prefix, s, src_p.prefixlen); if (src_p.family == AF_INET) { inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); @@ -797,8 +797,8 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, buf); } } - len = stream_getc(s); - stream_get(if_name, s, len); + STREAM_GETC(s, len); + STREAM_GET(if_name, s, len); if_name[len] = '\0'; ptm_lib_append_msg(ptm_hdl, out_ctxt, @@ -815,6 +815,8 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, zlog_debug("%s: Sent message (%d) %s", __func__, data_len, ptm_cb.out_data); zebra_ptm_send_message(ptm_cb.out_data, data_len); + +stream_failure: return 0; } @@ -858,19 +860,19 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, s = client->ibuf; - pid = stream_getl(s); + STREAM_GETL(s, pid); sprintf(tmp_buf, "%d", pid); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, tmp_buf); - dst_p.family = stream_getw(s); + STREAM_GETW(s, dst_p.family); if (dst_p.family == AF_INET) dst_p.prefixlen = IPV4_MAX_BYTELEN; else dst_p.prefixlen = IPV6_MAX_BYTELEN; - stream_get(&dst_p.u.prefix, s, dst_p.prefixlen); + STREAM_GET(&dst_p.u.prefix, s, dst_p.prefixlen); if (dst_p.family == AF_INET) inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf)); else @@ -878,20 +880,20 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DST_IP_FIELD, buf); - multi_hop = stream_getc(s); + STREAM_GETC(s, multi_hop); if (multi_hop) { sprintf(tmp_buf, "%d", 1); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MULTI_HOP_FIELD, tmp_buf); - src_p.family = stream_getw(s); + STREAM_GETW(s, src_p.family); if (src_p.family == AF_INET) src_p.prefixlen = IPV4_MAX_BYTELEN; else src_p.prefixlen = IPV6_MAX_BYTELEN; - stream_get(&src_p.u.prefix, s, src_p.prefixlen); + STREAM_GET(&src_p.u.prefix, s, src_p.prefixlen); if (src_p.family == AF_INET) inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); else @@ -905,14 +907,14 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, zvrf_name(zvrf)); } else { if (dst_p.family == AF_INET6) { - src_p.family = stream_getw(s); + STREAM_GETW(s, src_p.family); if (src_p.family == AF_INET) src_p.prefixlen = IPV4_MAX_BYTELEN; else src_p.prefixlen = IPV6_MAX_BYTELEN; - stream_get(&src_p.u.prefix, s, src_p.prefixlen); + STREAM_GET(&src_p.u.prefix, s, src_p.prefixlen); if (src_p.family == AF_INET) { inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); @@ -928,8 +930,8 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, } } - len = stream_getc(s); - stream_get(if_name, s, len); + STREAM_GETC(s, len); + STREAM_GET(if_name, s, len); if_name[len] = '\0'; ptm_lib_append_msg(ptm_hdl, out_ctxt, @@ -942,6 +944,8 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, ptm_cb.out_data); zebra_ptm_send_message(ptm_cb.out_data, data_len); + +stream_failure: return 0; } @@ -962,7 +966,7 @@ int zebra_ptm_bfd_client_register(struct zserv *client, zebra_route_string(client->proto), length); s = client->ibuf; - pid = stream_getl(s); + STREAM_GETL(s, pid); if (ptm_cb.ptm_sock == -1) { ptm_cb.t_timer = NULL; @@ -993,6 +997,7 @@ int zebra_ptm_bfd_client_register(struct zserv *client, SET_FLAG(ptm_cb.client_flags[client->proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG); +stream_failure: return 0; } diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index bd430423b3..f5caf9d0b9 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -3055,16 +3055,16 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length, mac = NULL; n = NULL; memset(&ip, 0, sizeof(ip)); - vni = (vni_t)stream_getl(s); - stream_get(&macaddr.octet, s, ETH_ALEN); - ipa_len = stream_getl(s); + STREAM_GETL(s, vni); + STREAM_GET(&macaddr.octet, s, ETH_ALEN); + STREAM_GETL(s, ipa_len); if (ipa_len) { ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 : IPADDR_V6; - stream_get(&ip.ip.addr, s, ipa_len); + STREAM_GET(&ip.ip.addr, s, ipa_len); } l += 4 + ETH_ALEN + 4 + ipa_len; - vtep_ip.s_addr = stream_get_ipv4(s); + STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN); l += IPV4_MAX_BYTELEN; if (IS_ZEBRA_DEBUG_VXLAN) @@ -3160,6 +3160,7 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length, } } +stream_failure: return 0; } @@ -3188,7 +3189,11 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, struct interface *ifp = NULL; struct zebra_if *zif = NULL; - assert(EVPN_ENABLED(zvrf)); + if (!EVPN_ENABLED(zvrf)) { + zlog_warn("%s: EVPN Not turned on yet we have received a remote_macip add zapi callback", + __PRETTY_FUNCTION__); + return -1; + } s = client->ibuf; @@ -3201,20 +3206,20 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, mac = NULL; n = NULL; memset(&ip, 0, sizeof(ip)); - vni = (vni_t)stream_getl(s); - stream_get(&macaddr.octet, s, ETH_ALEN); - ipa_len = stream_getl(s); + STREAM_GETL(s, vni); + STREAM_GET(&macaddr.octet, s, ETH_ALEN); + STREAM_GETL(s, ipa_len); if (ipa_len) { ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 : IPADDR_V6; - stream_get(&ip.ip.addr, s, ipa_len); + STREAM_GET(&ip.ip.addr, s, ipa_len); } l += 4 + ETH_ALEN + 4 + ipa_len; - vtep_ip.s_addr = stream_get_ipv4(s); + STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN); l += IPV4_MAX_BYTELEN; /* Get 'sticky' flag. */ - sticky = stream_getc(s); + STREAM_GETC(s, sticky); l++; if (IS_ZEBRA_DEBUG_VXLAN) @@ -3367,6 +3372,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, } } +stream_failure: return 0; } @@ -3683,7 +3689,12 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, struct interface *ifp; struct zebra_if *zif; - assert(is_evpn_enabled()); + if (!is_evpn_enabled()) { + zlog_warn("%s: EVPN is not enabled yet we have received a vtep del command", + __PRETTY_FUNCTION__); + return -1; + } + if (zvrf_id(zvrf) != VRF_DEFAULT) { zlog_err("Recv MACIP DEL for non-default VRF %u", zvrf_id(zvrf)); @@ -3694,9 +3705,9 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, while (l < length) { /* Obtain each remote VTEP and process. */ - vni = (vni_t)stream_getl(s); + STREAM_GETL(s, vni); l += 4; - vtep_ip.s_addr = stream_get_ipv4(s); + STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN); l += IPV4_MAX_BYTELEN; if (IS_ZEBRA_DEBUG_VXLAN) @@ -3744,6 +3755,7 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, zvni_vtep_del(zvni, zvtep); } +stream_failure: return 0; } @@ -3761,7 +3773,12 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, struct interface *ifp; struct zebra_if *zif; - assert(is_evpn_enabled()); + if (!is_evpn_enabled()) { + zlog_warn("%s: EVPN not enabled yet we received a vtep_add zapi call", + __PRETTY_FUNCTION__); + return -1; + } + if (zvrf_id(zvrf) != VRF_DEFAULT) { zlog_err("Recv MACIP ADD for non-default VRF %u", zvrf_id(zvrf)); @@ -3772,9 +3789,9 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, while (l < length) { /* Obtain each remote VTEP and process. */ - vni = (vni_t)stream_getl(s); + STREAM_GETL(s, vni); l += 4; - vtep_ip.s_addr = stream_get_ipv4(s); + STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN); l += IPV4_MAX_BYTELEN; if (IS_ZEBRA_DEBUG_VXLAN) @@ -3820,6 +3837,7 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, zvni_vtep_install(zvni, &vtep_ip); } +stream_failure: return 0; } @@ -4296,8 +4314,8 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, } s = client->ibuf; - advertise = stream_getc(s); - vni = stream_get3(s); + STREAM_GETC(s, advertise); + STREAM_GET(&vni, s, 3); if (!vni) { if (IS_ZEBRA_DEBUG_VXLAN) @@ -4378,6 +4396,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, } } +stream_failure: return 0; } @@ -4401,7 +4420,7 @@ int zebra_vxlan_advertise_all_vni(struct zserv *client, } s = client->ibuf; - advertise = stream_getc(s); + STREAM_GETC(s, advertise); if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug("EVPN VNI Adv %s, currently %s", @@ -4432,6 +4451,7 @@ int zebra_vxlan_advertise_all_vni(struct zserv *client, hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf); } +stream_failure: return 0; } diff --git a/zebra/zserv.c b/zebra/zserv.c index cbd532339d..5387c9c380 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -714,15 +714,25 @@ static int zserv_rnh_register(struct zserv *client, u_short length, client->nh_reg_time = monotime(NULL); while (l < length) { - flags = stream_getc(s); - p.family = stream_getw(s); - p.prefixlen = stream_getc(s); + STREAM_GETC(s, flags); + STREAM_GETW(s, p.family); + STREAM_GETC(s, p.prefixlen); l += 4; if (p.family == AF_INET) { - p.u.prefix4.s_addr = stream_get_ipv4(s); + if (p.prefixlen > IPV4_MAX_BITLEN) { + zlog_warn("%s: Specified prefix length %d is too large for a v4 address", + __PRETTY_FUNCTION__, p.prefixlen); + return -1; + } + STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); l += IPV4_MAX_BYTELEN; } else if (p.family == AF_INET6) { - stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN); + if (p.prefixlen > IPV6_MAX_BITLEN) { + zlog_warn("%s: Specified prefix length %d is to large for a v6 address", + __PRETTY_FUNCTION__, p.prefixlen); + return -1; + } + STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN); l += IPV6_MAX_BYTELEN; } else { zlog_err( @@ -751,6 +761,8 @@ static int zserv_rnh_register(struct zserv *client, u_short length, /* Anything not AF_INET/INET6 has been filtered out above */ zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p); } + +stream_failure: return 0; } @@ -770,16 +782,27 @@ static int zserv_rnh_unregister(struct zserv *client, u_short length, s = client->ibuf; while (l < length) { - (void)stream_getc( - s); // Connected or not. Not used in this function - p.family = stream_getw(s); - p.prefixlen = stream_getc(s); + u_char noval; + + STREAM_GETC(s, noval); + STREAM_GETW(s, p.family); + STREAM_GETC(s, p.prefixlen); l += 4; if (p.family == AF_INET) { - p.u.prefix4.s_addr = stream_get_ipv4(s); + if (p.prefixlen > IPV4_MAX_BITLEN) { + zlog_warn("%s: Specified prefix length %d is to large for a v4 address", + __PRETTY_FUNCTION__, p.prefixlen); + return -1; + } + STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); l += IPV4_MAX_BYTELEN; } else if (p.family == AF_INET6) { - stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN); + if (p.prefixlen > IPV6_MAX_BITLEN) { + zlog_warn("%s: Specified prefix length %d is to large for a v6 address", + __PRETTY_FUNCTION__, p.prefixlen); + return -1; + } + STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN); l += IPV6_MAX_BYTELEN; } else { zlog_err( @@ -793,6 +816,7 @@ static int zserv_rnh_unregister(struct zserv *client, u_short length, zebra_remove_rnh_client(rnh, client, type); } } +stream_failure: return 0; } @@ -825,27 +849,34 @@ static int zserv_fec_register(struct zserv *client, u_short length) } while (l < length) { - flags = stream_getw(s); + STREAM_GETW(s, flags); memset(&p, 0, sizeof(p)); - p.family = stream_getw(s); + STREAM_GETW(s, p.family); if (p.family != AF_INET && p.family != AF_INET6) { zlog_err( "fec_register: Received unknown family type %d\n", p.family); return -1; } - p.prefixlen = stream_getc(s); + STREAM_GETC(s, p.prefixlen); + if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN) || + (p.family == AF_INET6 && p.prefixlen > IPV6_MAX_BITLEN)) { + zlog_warn("%s: Specified prefix length: %d is to long for %d", + __PRETTY_FUNCTION__, p.prefixlen, p.family); + return -1; + } l += 5; - stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); + STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen)); l += PSIZE(p.prefixlen); if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) { - label_index = stream_getl(s); + STREAM_GETL(s, label_index); l += 4; } else label_index = MPLS_INVALID_LABEL_INDEX; zebra_mpls_fec_register(zvrf, &p, label_index, client); } +stream_failure: return 0; } @@ -856,7 +887,7 @@ static int zserv_fec_unregister(struct zserv *client, u_short length) struct zebra_vrf *zvrf; u_short l = 0; struct prefix p; - // u_int16_t flags; + uint16_t flags; s = client->ibuf; zvrf = vrf_info_lookup(VRF_DEFAULT); @@ -875,23 +906,29 @@ static int zserv_fec_unregister(struct zserv *client, u_short length) } while (l < length) { - // flags = stream_getw(s); - (void)stream_getw(s); + STREAM_GETW(s, flags); memset(&p, 0, sizeof(p)); - p.family = stream_getw(s); + STREAM_GETW(s, p.family); if (p.family != AF_INET && p.family != AF_INET6) { zlog_err( "fec_unregister: Received unknown family type %d\n", p.family); return -1; } - p.prefixlen = stream_getc(s); + STREAM_GETC(s, p.prefixlen); + if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN) || + (p.family == AF_INET6 && p.prefixlen > IPV6_MAX_BITLEN)) { + zlog_warn("%s: Received prefix length %d which is greater than %d can support", + __PRETTY_FUNCTION__, p.prefixlen, p.family); + return -1; + } l += 5; - stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); + STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen)); l += PSIZE(p.prefixlen); zebra_mpls_fec_unregister(zvrf, &p, client); } +stream_failure: return 0; } @@ -1073,7 +1110,7 @@ static int zread_route_add(struct zserv *client, u_short length, switch (api_nh->type) { case NEXTHOP_TYPE_IFINDEX: - route_entry_nexthop_ifindex_add( + nexthop = route_entry_nexthop_ifindex_add( re, api_nh->ifindex); break; case NEXTHOP_TYPE_IPV4: @@ -1095,11 +1132,18 @@ static int zread_route_add(struct zserv *client, u_short length, api_nh->ifindex); break; case NEXTHOP_TYPE_BLACKHOLE: - route_entry_nexthop_blackhole_add( + nexthop = route_entry_nexthop_blackhole_add( re, api_nh->bh_type); break; } + if (!nexthop) { + zlog_warn("%s: Nexthops Specified: %d but we failed to properly create one", + __PRETTY_FUNCTION__, api.nexthop_num); + nexthops_free(re->nexthop); + XFREE(MTYPE_RE, re); + return -1; + } /* MPLS labels for BGP-LU or Segment Routing */ if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL) && api_nh->type != NEXTHOP_TYPE_IFINDEX @@ -1125,6 +1169,13 @@ static int zread_route_add(struct zserv *client, u_short length, re->mtu = api.mtu; afi = family2afi(api.prefix.family); + if (afi != AFI_IP6 && CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { + zlog_warn("%s: Received SRC Prefix but afi is not v6", + __PRETTY_FUNCTION__); + nexthops_free(re->nexthop); + XFREE(MTYPE_RE, re); + return -1; + } if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) src_p = &api.src_prefix; @@ -1162,6 +1213,11 @@ static int zread_route_del(struct zserv *client, u_short length, return -1; afi = family2afi(api.prefix.family); + if (afi != AFI_IP6 && CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { + zlog_warn("%s: Received a src prefix while afi is not v6", + __PRETTY_FUNCTION__); + return -1; + } if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) src_p = &api.src_prefix; @@ -1213,25 +1269,37 @@ static int zread_ipv4_add(struct zserv *client, u_short length, re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); /* Type, flags, message. */ - re->type = stream_getc(s); - re->instance = stream_getw(s); - re->flags = stream_getl(s); - message = stream_getc(s); - safi = stream_getw(s); + STREAM_GETC(s, re->type); + if (re->type > ZEBRA_ROUTE_MAX) { + zlog_warn("%s: Specified route type %d is not a legal value\n", + __PRETTY_FUNCTION__, re->type); + XFREE(MTYPE_RE, re); + return -1; + } + STREAM_GETW(s, re->instance); + STREAM_GETL(s, re->flags); + STREAM_GETC(s, message); + STREAM_GETW(s, safi); re->uptime = time(NULL); /* IPv4 prefix. */ memset(&p, 0, sizeof(struct prefix_ipv4)); p.family = AF_INET; - p.prefixlen = stream_getc(s); - stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen)); + STREAM_GETC(s, p.prefixlen); + if (p.prefixlen > IPV4_MAX_BITLEN) { + zlog_warn("%s: Specified prefix length %d is greater than what v4 can be", + __PRETTY_FUNCTION__, p.prefixlen); + XFREE(MTYPE_RE, re); + return -1; + } + STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen)); /* VRF ID */ re->vrf_id = zvrf_id(zvrf); /* Nexthop parse. */ if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) { - nexthop_num = stream_getc(s); + STREAM_GETC(s, nexthop_num); zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); @@ -1239,57 +1307,69 @@ static int zread_ipv4_add(struct zserv *client, u_short length, label_type = lsp_type_from_re_type(client->proto); for (i = 0; i < nexthop_num; i++) { - nexthop_type = stream_getc(s); + STREAM_GETC(s, nexthop_type); switch (nexthop_type) { case NEXTHOP_TYPE_IFINDEX: - ifindex = stream_getl(s); + STREAM_GETL(s, ifindex); route_entry_nexthop_ifindex_add(re, ifindex); break; case NEXTHOP_TYPE_IPV4: - nhop_addr.s_addr = stream_get_ipv4(s); + STREAM_GET(&nhop_addr.s_addr, s, + IPV4_MAX_BYTELEN); nexthop = route_entry_nexthop_ipv4_add( re, &nhop_addr, NULL); /* For labeled-unicast, each nexthop is followed * by label. */ if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) { - label = (mpls_label_t)stream_getl(s); + STREAM_GETL(s, label); nexthop_add_labels(nexthop, label_type, 1, &label); } break; case NEXTHOP_TYPE_IPV4_IFINDEX: - nhop_addr.s_addr = stream_get_ipv4(s); - ifindex = stream_getl(s); + STREAM_GET(&nhop_addr.s_addr, s, + IPV4_MAX_BYTELEN); + STREAM_GETL(s, ifindex); route_entry_nexthop_ipv4_ifindex_add( re, &nhop_addr, NULL, ifindex); break; case NEXTHOP_TYPE_IPV6: - stream_forward_getp(s, IPV6_MAX_BYTELEN); + zlog_warn("%s: Please use ZEBRA_ROUTE_ADD if you want to pass v6 nexthops", + __PRETTY_FUNCTION__); + nexthops_free(re->nexthop); + XFREE(MTYPE_RE, re); + return -1; break; case NEXTHOP_TYPE_BLACKHOLE: route_entry_nexthop_blackhole_add(re, bh_type); break; + default: + zlog_warn("%s: Specified nexthop type: %d does not exist", + __PRETTY_FUNCTION__, nexthop_type); + nexthops_free(re->nexthop); + XFREE(MTYPE_RE, re); + return -1; } } } /* Distance. */ if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - re->distance = stream_getc(s); + STREAM_GETC(s, re->distance); /* Metric. */ if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) - re->metric = stream_getl(s); + STREAM_GETL(s, re->metric); /* Tag */ if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) - re->tag = stream_getl(s); + STREAM_GETL(s, re->tag); else re->tag = 0; if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU)) - re->mtu = stream_getl(s); + STREAM_GETL(s, re->mtu); else re->mtu = 0; @@ -1303,7 +1383,13 @@ static int zread_ipv4_add(struct zserv *client, u_short length, client->v4_route_add_cnt++; else if (ret < 0) client->v4_route_upd8_cnt++; + return 0; + +stream_failure: + nexthops_free(re->nexthop); + XFREE(MTYPE_RE, re); + return -1; } /* Zebra server IPv4 prefix delete function. */ @@ -1318,23 +1404,30 @@ static int zread_ipv4_delete(struct zserv *client, u_short length, s = client->ibuf; /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); - api.safi = stream_getw(s); + STREAM_GETC(s, api.type); + STREAM_GETW(s, api.instance); + STREAM_GETL(s, api.flags); + STREAM_GETC(s, api.message); + STREAM_GETW(s, api.safi); /* IPv4 prefix. */ memset(&p, 0, sizeof(struct prefix)); p.family = AF_INET; - p.prefixlen = stream_getc(s); - stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen)); + STREAM_GETC(s, p.prefixlen); + if (p.prefixlen > IPV4_MAX_BITLEN) { + zlog_warn("%s: Passed in prefixlen %d is impossible", + __PRETTY_FUNCTION__, p.prefixlen); + return -1; + } + STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen)); table_id = zvrf->table_id; rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance, api.flags, &p, NULL, NULL, table_id, 0, false); client->v4_route_del_cnt++; + +stream_failure: return 0; } @@ -1345,9 +1438,12 @@ static int zread_ipv4_nexthop_lookup_mrib(struct zserv *client, u_short length, struct in_addr addr; struct route_entry *re; - addr.s_addr = stream_get_ipv4(client->ibuf); + STREAM_GET(&addr.s_addr, client->ibuf, IPV4_MAX_BYTELEN); re = rib_match_ipv4_multicast(zvrf_id(zvrf), addr, NULL); return zsend_ipv4_nexthop_lookup_mrib(client, addr, re, zvrf); + +stream_failure: + return -1; } /* Zebra server IPv6 prefix add function. */ @@ -1382,18 +1478,30 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); /* Type, flags, message. */ - re->type = stream_getc(s); - re->instance = stream_getw(s); - re->flags = stream_getl(s); - message = stream_getc(s); - safi = stream_getw(s); + STREAM_GETC(s, re->type); + if (re->type > ZEBRA_ROUTE_MAX) { + zlog_warn("%s: Specified route type: %d is not a legal value\n", + __PRETTY_FUNCTION__, re->type); + XFREE(MTYPE_RE, re); + return -1; + } + STREAM_GETW(s, re->instance); + STREAM_GETL(s, re->flags); + STREAM_GETC(s, message); + STREAM_GETW(s, safi); re->uptime = time(NULL); /* IPv4 prefix. */ memset(&p, 0, sizeof(struct prefix_ipv4)); p.family = AF_INET; - p.prefixlen = stream_getc(s); - stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen)); + STREAM_GETC(s, p.prefixlen); + if (p.prefixlen > IPV4_MAX_BITLEN) { + zlog_warn("%s: Prefix Length %d is greater than what a v4 address can use", + __PRETTY_FUNCTION__, p.prefixlen); + XFREE(MTYPE_RE, re); + return -1; + } + STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen)); /* VRF ID */ re->vrf_id = zvrf_id(zvrf); @@ -1407,7 +1515,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, unsigned int if_count = 0; unsigned int max_nh_if = 0; - nexthop_num = stream_getc(s); + STREAM_GETC(s, nexthop_num); zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); @@ -1415,18 +1523,17 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, label_type = lsp_type_from_re_type(client->proto); for (i = 0; i < nexthop_num; i++) { - nexthop_type = stream_getc(s); + STREAM_GETC(s, nexthop_type); switch (nexthop_type) { case NEXTHOP_TYPE_IPV6: - stream_get(&nhop_addr, s, 16); + STREAM_GET(&nhop_addr, s, 16); if (nh_count < MULTIPATH_NUM) { /* For labeled-unicast, each nexthop is * followed by label. */ if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) { - label = (mpls_label_t) - stream_getl(s); + STREAM_GETL(s, label); labels[nh_count] = label; } nexthops[nh_count] = nhop_addr; @@ -1435,12 +1542,18 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, break; case NEXTHOP_TYPE_IFINDEX: if (if_count < multipath_num) { - ifindices[if_count++] = stream_getl(s); + STREAM_GETL(s, ifindices[if_count++]); } break; case NEXTHOP_TYPE_BLACKHOLE: route_entry_nexthop_blackhole_add(re, bh_type); break; + default: + zlog_warn("%s: Please use ZEBRA_ROUTE_ADD if you want to pass non v6 nexthops", + __PRETTY_FUNCTION__); + nexthops_free(re->nexthop); + XFREE(MTYPE_RE, re); + return -1; } } @@ -1470,20 +1583,20 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, /* Distance. */ if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - re->distance = stream_getc(s); + STREAM_GETC(s, re->distance); /* Metric. */ if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) - re->metric = stream_getl(s); + STREAM_GETL(s, re->metric); /* Tag */ if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) - re->tag = stream_getl(s); + STREAM_GETL(s, re->tag); else re->tag = 0; if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU)) - re->mtu = stream_getl(s); + STREAM_GETL(s, re->mtu); else re->mtu = 0; @@ -1498,6 +1611,11 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, client->v4_route_upd8_cnt++; return 0; + +stream_failure: + nexthops_free(re->nexthop); + XFREE(MTYPE_RE, re); + return -1; } static int zread_ipv6_add(struct zserv *client, u_short length, @@ -1532,24 +1650,42 @@ static int zread_ipv6_add(struct zserv *client, u_short length, re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); /* Type, flags, message. */ - re->type = stream_getc(s); - re->instance = stream_getw(s); - re->flags = stream_getl(s); - message = stream_getc(s); - safi = stream_getw(s); + STREAM_GETC(s, re->type); + if (re->type > ZEBRA_ROUTE_MAX) { + zlog_warn("%s: Specified route type: %d is not a legal value\n", + __PRETTY_FUNCTION__, re->type); + XFREE(MTYPE_RE, re); + return -1; + } + STREAM_GETW(s, re->instance); + STREAM_GETL(s, re->flags); + STREAM_GETC(s, message); + STREAM_GETW(s, safi); re->uptime = time(NULL); /* IPv6 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv6)); + memset(&p, 0, sizeof(p)); p.family = AF_INET6; - p.prefixlen = stream_getc(s); - stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen)); + STREAM_GETC(s, p.prefixlen); + if (p.prefixlen > IPV6_MAX_BITLEN) { + zlog_warn("%s: Specified prefix length %d is to large for v6 prefix", + __PRETTY_FUNCTION__, p.prefixlen); + XFREE(MTYPE_RE, re); + return -1; + } + STREAM_GET(&p.u.prefix6, s, PSIZE(p.prefixlen)); if (CHECK_FLAG(message, ZAPI_MESSAGE_SRCPFX)) { - memset(&src_p, 0, sizeof(struct prefix_ipv6)); + memset(&src_p, 0, sizeof(src_p)); src_p.family = AF_INET6; - src_p.prefixlen = stream_getc(s); - stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); + STREAM_GETC(s, src_p.prefixlen); + if (src_p.prefixlen > IPV6_MAX_BITLEN) { + zlog_warn("%s: Specified src prefix length %d is to large for v6 prefix", + __PRETTY_FUNCTION__, src_p.prefixlen); + XFREE(MTYPE_RE, re); + return -1; + } + STREAM_GET(&src_p.prefix, s, PSIZE(src_p.prefixlen)); src_pp = &src_p; } else src_pp = NULL; @@ -1563,7 +1699,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length, unsigned int if_count = 0; unsigned int max_nh_if = 0; - nexthop_num = stream_getc(s); + STREAM_GETC(s, nexthop_num); zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); @@ -1571,37 +1707,42 @@ static int zread_ipv6_add(struct zserv *client, u_short length, label_type = lsp_type_from_re_type(client->proto); for (i = 0; i < nexthop_num; i++) { - nexthop_type = stream_getc(s); + STREAM_GETC(s, nexthop_type); switch (nexthop_type) { case NEXTHOP_TYPE_IPV6: - stream_get(&nhop_addr, s, 16); + STREAM_GET(&nhop_addr, s, 16); if (nh_count < MULTIPATH_NUM) { /* For labeled-unicast, each nexthop is * followed by label. */ if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) { - label = (mpls_label_t) - stream_getl(s); + STREAM_GETL(s, label); labels[nh_count] = label; } nexthops[nh_count++] = nhop_addr; } break; case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_get(&nhop_addr, s, 16); - ifindex = stream_getl(s); + STREAM_GET(&nhop_addr, s, 16); + STREAM_GETL(s, ifindex); route_entry_nexthop_ipv6_ifindex_add( re, &nhop_addr, ifindex); break; case NEXTHOP_TYPE_IFINDEX: if (if_count < multipath_num) { - ifindices[if_count++] = stream_getl(s); + STREAM_GETL(s, ifindices[if_count++]); } break; case NEXTHOP_TYPE_BLACKHOLE: route_entry_nexthop_blackhole_add(re, bh_type); break; + default: + zlog_warn("%s: Please use ZEBRA_ROUTE_ADD if you want to pass non v6 nexthops", + __PRETTY_FUNCTION__); + nexthops_free(re->nexthop); + XFREE(MTYPE_RE, re); + return -1; } } @@ -1630,20 +1771,20 @@ static int zread_ipv6_add(struct zserv *client, u_short length, /* Distance. */ if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - re->distance = stream_getc(s); + STREAM_GETC(s, re->distance); /* Metric. */ if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) - re->metric = stream_getl(s); + STREAM_GETL(s, re->metric); /* Tag */ if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) - re->tag = stream_getl(s); + STREAM_GETL(s, re->tag); else re->tag = 0; if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU)) - re->mtu = stream_getl(s); + STREAM_GETL(s, re->mtu); else re->mtu = 0; @@ -1659,6 +1800,12 @@ static int zread_ipv6_add(struct zserv *client, u_short length, client->v6_route_upd8_cnt++; return 0; + +stream_failure: + nexthops_free(re->nexthop); + XFREE(MTYPE_RE, re); + + return -1; } /* Zebra server IPv6 prefix delete function. */ @@ -1673,23 +1820,23 @@ static int zread_ipv6_delete(struct zserv *client, u_short length, s = client->ibuf; /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); - api.safi = stream_getw(s); + STREAM_GETC(s, api.type); + STREAM_GETW(s, api.instance); + STREAM_GETL(s, api.flags); + STREAM_GETC(s, api.message); + STREAM_GETW(s, api.safi); /* IPv4 prefix. */ memset(&p, 0, sizeof(struct prefix)); p.family = AF_INET6; - p.prefixlen = stream_getc(s); - stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen)); + STREAM_GETC(s, p.prefixlen); + STREAM_GET(&p.u.prefix6, s, PSIZE(p.prefixlen)); if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { memset(&src_p, 0, sizeof(struct prefix_ipv6)); src_p.family = AF_INET6; - src_p.prefixlen = stream_getc(s); - stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); + STREAM_GETC(s, src_p.prefixlen); + STREAM_GET(&src_p.prefix, s, PSIZE(src_p.prefixlen)); src_pp = &src_p; } else src_pp = NULL; @@ -1698,6 +1845,8 @@ static int zread_ipv6_delete(struct zserv *client, u_short length, api.flags, &p, src_pp, NULL, client->rtm_table, 0, false); client->v6_route_del_cnt++; + +stream_failure: return 0; } @@ -1730,8 +1879,8 @@ static void zread_hello(struct zserv *client) u_char proto; u_short instance; - proto = stream_getc(client->ibuf); - instance = stream_getw(client->ibuf); + STREAM_GETC(client->ibuf, proto); + STREAM_GETW(client->ibuf, instance); /* accept only dynamic routing protocols */ if ((proto < ZEBRA_ROUTE_MAX) && (proto > ZEBRA_ROUTE_STATIC)) { @@ -1744,6 +1893,9 @@ static void zread_hello(struct zserv *client) client->proto = proto; client->instance = instance; } + +stream_failure: + return; } /* Unregister all information in a VRF. */ @@ -1779,26 +1931,40 @@ static void zread_mpls_labels(int command, struct zserv *client, u_short length, s = client->ibuf; /* Get data. */ - type = stream_getc(s); - prefix.family = stream_getl(s); + STREAM_GETC(s, type); + STREAM_GETL(s, prefix.family); switch (prefix.family) { case AF_INET: - prefix.u.prefix4.s_addr = stream_get_ipv4(s); - prefix.prefixlen = stream_getc(s); - gate.ipv4.s_addr = stream_get_ipv4(s); + STREAM_GET(&prefix.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); + STREAM_GETC(s, prefix.prefixlen); + if (prefix.prefixlen > IPV4_MAX_BITLEN) { + zlog_warn("%s: Specified prefix length %d is greater than a v4 address can support", + __PRETTY_FUNCTION__, + prefix.prefixlen); + return; + } + STREAM_GET(&gate.ipv4.s_addr, s, IPV4_MAX_BYTELEN); break; case AF_INET6: - stream_get(&prefix.u.prefix6, s, 16); - prefix.prefixlen = stream_getc(s); - stream_get(&gate.ipv6, s, 16); + STREAM_GET(&prefix.u.prefix6, s, 16); + STREAM_GETC(s, prefix.prefixlen); + if (prefix.prefixlen > IPV6_MAX_BITLEN) { + zlog_warn("%s: Specified prefix length %d is greater than a v6 address can support", + __PRETTY_FUNCTION__, + prefix.prefixlen); + return; + } + STREAM_GET(&gate.ipv6, s, 16); break; default: + zlog_warn("%s: Specified AF %d is not supported for this call", + __PRETTY_FUNCTION__, prefix.family); return; } - ifindex = stream_getl(s); - distance = stream_getc(s); - in_label = stream_getl(s); - out_label = stream_getl(s); + STREAM_GETL(s, ifindex); + STREAM_GETC(s, distance); + STREAM_GETL(s, in_label); + STREAM_GETL(s, out_label); switch (prefix.family) { case AF_INET: @@ -1830,6 +1996,8 @@ static void zread_mpls_labels(int command, struct zserv *client, u_short length, mpls_ftn_update(0, zvrf, type, &prefix, gtype, &gate, ifindex, distance, out_label); } +stream_failure: + return; } /* Send response to a label manager connect request to client */ static int zsend_label_manager_connect_response(struct zserv *client, @@ -1862,8 +2030,8 @@ static void zread_label_manager_connect(struct zserv *client, vrf_id_t vrf_id) s = client->ibuf; /* Get data. */ - proto = stream_getc(s); - instance = stream_getw(s); + STREAM_GETC(s, proto); + STREAM_GETW(s, instance); /* accept only dynamic routing protocols */ if ((proto >= ZEBRA_ROUTE_MAX) || (proto <= ZEBRA_ROUTE_STATIC)) { @@ -1888,6 +2056,9 @@ static void zread_label_manager_connect(struct zserv *client, vrf_id_t vrf_id) client->sock, zebra_route_string(proto), instance); /* send response back */ zsend_label_manager_connect_response(client, vrf_id, 0); + +stream_failure: + return; } /* Send response to a get label chunk request to client */ static int zsend_assign_label_chunk_response(struct zserv *client, @@ -1926,8 +2097,8 @@ static void zread_get_label_chunk(struct zserv *client, vrf_id_t vrf_id) s = client->ibuf; /* Get data. */ - keep = stream_getc(s); - size = stream_getl(s); + STREAM_GETC(s, keep); + STREAM_GETL(s, size); lmc = assign_label_chunk(client->proto, client->instance, keep, size); if (!lmc) @@ -1938,6 +2109,9 @@ static void zread_get_label_chunk(struct zserv *client, vrf_id_t vrf_id) lmc->end, keep); /* send response back */ zsend_assign_label_chunk_response(client, vrf_id, lmc); + +stream_failure: + return; } static void zread_release_label_chunk(struct zserv *client) @@ -1949,10 +2123,13 @@ static void zread_release_label_chunk(struct zserv *client) s = client->ibuf; /* Get data. */ - start = stream_getl(s); - end = stream_getl(s); + STREAM_GETL(s, start); + STREAM_GETL(s, end); release_label_chunk(client->proto, client->instance, start, end); + +stream_failure: + return; } static void zread_label_manager_request(int cmd, struct zserv *client, struct zebra_vrf *zvrf) @@ -2006,24 +2183,24 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length, s = client->ibuf; /* Get data. */ - stream_get(ifname, s, IF_NAMESIZE); - ifindex = stream_getl(s); - type = stream_getl(s); - af = stream_getl(s); + STREAM_GET(ifname, s, IF_NAMESIZE); + STREAM_GETL(s, ifindex); + STREAM_GETL(s, type); + STREAM_GETL(s, af); switch (af) { case AF_INET: - nexthop.ipv4.s_addr = stream_get_ipv4(s); + STREAM_GET(&nexthop.ipv4.s_addr, s, IPV4_MAX_BYTELEN); break; case AF_INET6: - stream_get(&nexthop.ipv6, s, 16); + STREAM_GET(&nexthop.ipv6, s, 16); break; default: return -1; } - local_label = stream_getl(s); - remote_label = stream_getl(s); - flags = stream_getc(s); - stream_get(&data, s, sizeof(data)); + STREAM_GETL(s, local_label); + STREAM_GETL(s, remote_label); + STREAM_GETC(s, flags); + STREAM_GET(&data, s, sizeof(data)); protocol = client->proto; pw = zebra_pw_find(zvrf, ifname); @@ -2069,6 +2246,7 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length, break; } +stream_failure: return 0; } @@ -2213,12 +2391,12 @@ static int zread_interface_set_master(struct zserv *client, int ifindex; vrf_id_t vrf_id; - vrf_id = stream_getw(s); - ifindex = stream_getl(s); + STREAM_GETW(s, vrf_id); + STREAM_GETL(s, ifindex); master = if_lookup_by_index(ifindex, vrf_id); - vrf_id = stream_getw(s); - ifindex = stream_getl(s); + STREAM_GETW(s, vrf_id); + STREAM_GETL(s, ifindex); slave = if_lookup_by_index(ifindex, vrf_id); if (!master || !slave) @@ -2226,6 +2404,7 @@ static int zread_interface_set_master(struct zserv *client, kernel_interface_set_master(master, slave); +stream_failure: return 1; } @@ -2427,11 +2606,11 @@ static int zebra_client_read(struct thread *thread) stream_set_getp(client->ibuf, 0); /* Fetch header values */ - length = stream_getw(client->ibuf); - marker = stream_getc(client->ibuf); - version = stream_getc(client->ibuf); - vrf_id = stream_getw(client->ibuf); - command = stream_getw(client->ibuf); + STREAM_GETW(client->ibuf, length); + STREAM_GETC(client->ibuf, marker); + STREAM_GETC(client->ibuf, version); + STREAM_GETW(client->ibuf, vrf_id); + STREAM_GETW(client->ibuf, command); if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) { zlog_err( @@ -2509,6 +2688,7 @@ static int zebra_client_read(struct thread *thread) stream_reset(client->ibuf); } +stream_failure: zclient_read_out: stream_reset(client->ibuf); zebra_event(ZEBRA_READ, sock, client);