From: paulzlabn Date: Wed, 14 Mar 2018 20:31:58 +0000 (-0700) Subject: Merge branch 'master' into working/master/bgp-vpn-vrf-leaking X-Git-Tag: frr-5.0-dev~153^2~2 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=3f1224cd1a9408bdad6aca8c0c205211cb548d5c;p=mirror_frr.git Merge branch 'master' into working/master/bgp-vpn-vrf-leaking --- 3f1224cd1a9408bdad6aca8c0c205211cb548d5c diff --cc bgpd/bgpd.h index 41ae8e916,9e1d27909..664f8c9da --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@@ -317,8 -311,14 +317,15 @@@ struct bgp /* BGP Per AF flags */ u_int16_t af_flags[AFI_MAX][SAFI_MAX]; #define BGP_CONFIG_DAMPENING (1 << 0) +#define BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT (1 << 1) + /* l2vpn evpn flags - 1 << 0 is used for DAMPENNG */ + #define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST (1 << 1) + #define BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST (1 << 2) + #define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4 (1 << 3) + #define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6 (1 << 4) + + /* Route table for next-hop lookup cache. */ struct bgp_table *nexthop_cache_table[AFI_MAX]; diff --cc zebra/redistribute.c index 36168a5f2,5a239306f..3a66aea45 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@@ -251,16 -249,10 +250,16 @@@ void zebra_redistribute_add(ZAPI_HANDLE int type = 0; u_short instance; - STREAM_GETC(client->ibuf, afi); - STREAM_GETC(client->ibuf, type); - STREAM_GETW(client->ibuf, instance); + STREAM_GETC(msg, afi); + STREAM_GETC(msg, type); + STREAM_GETW(msg, instance); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s: client proto %s afi=%d, wants %s, vrf %d, instance=%d", + __func__, zebra_route_string(client->proto), afi, + zebra_route_string(type), zvrf_id(zvrf), instance); + if (afi == 0 || afi > AFI_MAX) { zlog_warn("%s: Specified afi %d does not exist", __PRETTY_FUNCTION__, afi); diff --cc zebra/zserv.c index 54e688ebc,0def90380..2f2c09112 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@@ -660,492 -592,510 +592,547 @@@ int zsend_redistribute_route(int cmd, s SET_FLAG(api.message, ZAPI_MESSAGE_MTU); api.mtu = re->mtu; + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); + /* Encode route and send. */ - if (zapi_route_encode(cmd, client->obuf, &api) < 0) + if (zapi_route_encode(cmd, s, &api) < 0) return -1; - return zebra_server_send_message(client, s); + + if (IS_ZEBRA_DEBUG_SEND) { + char buf_prefix[PREFIX_STRLEN]; + prefix2str(&api.prefix, buf_prefix, sizeof(buf_prefix)); + + zlog_debug("%s: %s to client %s: type %s, vrf_id %d, p %s", + __func__, zserv_command_string(cmd), + zebra_route_string(client->proto), + zebra_route_string(api.type), api.vrf_id, + buf_prefix); + } + return zebra_server_send_message(client); +} + +static int zsend_write_nexthop(struct stream *s, struct nexthop *nexthop) +{ + stream_putc(s, nexthop->type); + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + stream_put_in_addr(s, &nexthop->gate.ipv4); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV6: + stream_put(s, &nexthop->gate.ipv6, 16); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_put(s, &nexthop->gate.ipv6, 16); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IFINDEX: + stream_putl(s, nexthop->ifindex); + break; + default: + /* do nothing */ + break; + } + return 1; } - /* Nexthop register */ - static int zserv_rnh_register(struct zserv *client, u_short length, - rnh_type_t type, struct zebra_vrf *zvrf) + /* + * Modified version of zsend_ipv4_nexthop_lookup(): Query unicast rib if + * nexthop is not found on mrib. Returns both route metric and protocol + * distance. + */ + static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, + struct in_addr addr, + struct route_entry *re, + struct zebra_vrf *zvrf) { - struct rnh *rnh; struct stream *s; - struct prefix p; - u_short l = 0; - u_char flags = 0; - - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug( - "rnh_register msg from client %s: length=%d, type=%s\n", - zebra_route_string(client->proto), length, - (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route"); + unsigned long nump; + u_char num; + struct nexthop *nexthop; - s = client->ibuf; + /* Get output stream. */ + s = stream_new(ZEBRA_MAX_PACKET_SIZ); + stream_reset(s); - client->nh_reg_time = monotime(NULL); + /* Fill in result. */ + zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf)); + stream_put_in_addr(s, &addr); - while (l < length) { - STREAM_GETC(s, flags); - STREAM_GETW(s, p.family); - STREAM_GETC(s, p.prefixlen); - l += 4; - if (p.family == AF_INET) { - 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) { - 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( - "rnh_register: Received unknown family type %d\n", - p.family); - return -1; - } - rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type); - if (type == RNH_NEXTHOP_TYPE) { - if (flags - && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) - SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); - else if (!flags - && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) - UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); - } else if (type == RNH_IMPORT_CHECK_TYPE) { - if (flags - && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) - SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); - else if (!flags && CHECK_FLAG(rnh->flags, - ZEBRA_NHT_EXACT_MATCH)) - UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); - } + if (re) { + stream_putc(s, re->distance); + stream_putl(s, re->metric); + num = 0; + nump = stream_get_endp( + s); /* remember position for nexthop_num */ + stream_putc(s, 0); /* reserve room for nexthop_num */ + /* Only non-recursive routes are elegible to resolve the nexthop + * we + * are looking up. Therefore, we will just iterate over the top + * chain of nexthops. */ + for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + num += zserv_encode_nexthop(s, nexthop); - zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); - /* Anything not AF_INET/INET6 has been filtered out above */ - zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p); + stream_putc_at(s, nump, num); /* store nexthop_num */ + } else { + stream_putc(s, 0); /* distance */ + stream_putl(s, 0); /* metric */ + stream_putc(s, 0); /* nexthop_num */ } - stream_failure: - return 0; + stream_putw_at(s, 0, stream_get_endp(s)); + + return zebra_server_send_message(client, s); } - /* Nexthop register */ - static int zserv_rnh_unregister(struct zserv *client, u_short length, - rnh_type_t type, struct zebra_vrf *zvrf) + int zsend_route_notify_owner(struct route_entry *re, struct prefix *p, + enum zapi_route_notify_owner note) { - struct rnh *rnh; + struct zserv *client; struct stream *s; - struct prefix p; - u_short l = 0; + uint8_t blen; - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("rnh_unregister msg from client %s: length=%d\n", - zebra_route_string(client->proto), length); + client = zebra_find_client(re->type, re->instance); + if (!client || !client->notify_owner) { + if (IS_ZEBRA_DEBUG_PACKET) { + char buff[PREFIX_STRLEN]; - s = client->ibuf; + zlog_debug( + "Not Notifying Owner: %u about prefix %s(%u) %d", + re->type, prefix2str(p, buff, sizeof(buff)), + re->table, note); + } + return 0; + } - while (l < length) { - uint8_t flags; + if (IS_ZEBRA_DEBUG_PACKET) { + char buff[PREFIX_STRLEN]; - STREAM_GETC(s, flags); - if (flags != 0) - goto stream_failure; + zlog_debug("Notifying Owner: %u about prefix %s(%u) %d", + re->type, prefix2str(p, buff, sizeof(buff)), + re->table, note); + } - STREAM_GETW(s, p.family); - STREAM_GETC(s, p.prefixlen); - l += 4; - if (p.family == AF_INET) { - 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) { - 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( - "rnh_register: Received unknown family type %d\n", - p.family); - return -1; - } - rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type); - if (rnh) { - client->nh_dereg_time = monotime(NULL); - zebra_remove_rnh_client(rnh, client, type); - } - } - stream_failure: - return 0; - } + s = stream_new(ZEBRA_MAX_PACKET_SIZ); + stream_reset(s); - #define ZEBRA_MIN_FEC_LENGTH 5 + zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, re->vrf_id); - /* FEC register */ - static int zserv_fec_register(struct zserv *client, u_short length) - { - struct stream *s; - struct zebra_vrf *zvrf; - u_short l = 0; - struct prefix p; - u_int16_t flags; - u_int32_t label_index = MPLS_INVALID_LABEL_INDEX; + stream_put(s, ¬e, sizeof(note)); - s = client->ibuf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - return 0; // unexpected + stream_putc(s, p->family); - /* - * The minimum amount of data that can be sent for one fec - * registration - */ - if (length < ZEBRA_MIN_FEC_LENGTH) { - zlog_err( - "fec_register: Received a fec register of length %d, it is of insufficient size to properly decode", - length); - return -1; - } + blen = prefix_blen(p); + stream_putc(s, p->prefixlen); + stream_put(s, &p->u.prefix, blen); - while (l < length) { - STREAM_GETW(s, flags); - memset(&p, 0, sizeof(p)); - 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; - } - 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)); - l += PSIZE(p.prefixlen); - if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) { - STREAM_GETL(s, label_index); - l += 4; - } else - label_index = MPLS_INVALID_LABEL_INDEX; - zebra_mpls_fec_register(zvrf, &p, label_index, client); - } + stream_putl(s, re->table); - stream_failure: - return 0; + stream_putw_at(s, 0, stream_get_endp(s)); + + return zebra_server_send_message(client, s); } - /* FEC unregister */ - static int zserv_fec_unregister(struct zserv *client, u_short length) + void zsend_rule_notify_owner(struct zebra_pbr_rule *rule, + enum zapi_rule_notify_owner note) { + struct listnode *node; + struct zserv *client; struct stream *s; - struct zebra_vrf *zvrf; - u_short l = 0; - struct prefix p; - uint16_t flags; - s = client->ibuf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - return 0; // unexpected + if (IS_ZEBRA_DEBUG_PACKET) { + zlog_debug("%s: Notifying %u", __PRETTY_FUNCTION__, + rule->unique); + } - /* - * The minimum amount of data that can be sent for one - * fec unregistration - */ - if (length < ZEBRA_MIN_FEC_LENGTH) { - zlog_err( - "fec_unregister: Received a fec unregister of length %d, it is of insufficient size to properly decode", - length); - return -1; + for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) { + if (rule->sock == client->sock) + break; } - while (l < length) { - STREAM_GETW(s, flags); - if (flags != 0) - goto stream_failure; + if (!client) + return; - memset(&p, 0, sizeof(p)); - 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; - } - 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)); - l += PSIZE(p.prefixlen); - zebra_mpls_fec_unregister(zvrf, &p, client); - } + s = stream_new(ZEBRA_MAX_PACKET_SIZ); + stream_reset(s); - stream_failure: - return 0; + zclient_create_header(s, ZEBRA_RULE_NOTIFY_OWNER, VRF_DEFAULT); + stream_put(s, ¬e, sizeof(note)); + stream_putl(s, rule->seq); + stream_putl(s, rule->priority); + stream_putl(s, rule->unique); + if (rule->ifp) + stream_putl(s, rule->ifp->ifindex); + else + stream_putl(s, 0); + + stream_putw_at(s, 0, stream_get_endp(s)); + + zebra_server_send_message(client, s); } - /* - Modified version of zsend_ipv4_nexthop_lookup(): - Query unicast rib if nexthop is not found on mrib. - Returns both route metric and protocol distance. - */ - static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, - struct in_addr addr, - struct route_entry *re, - struct zebra_vrf *zvrf) + /* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */ + int zsend_router_id_update(struct zserv *client, struct prefix *p, + vrf_id_t vrf_id) { - struct stream *s; - unsigned long nump; - u_char num; - struct nexthop *nexthop; + int blen; - /* Get output stream. */ - s = client->obuf; - stream_reset(s); + /* Check this client need interface information. */ + if (!vrf_bitmap_check(client->ridinfo, vrf_id)) + return 0; - /* Fill in result. */ - zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf)); - stream_put_in_addr(s, &addr); + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); - if (re) { - stream_putc(s, re->distance); - stream_putl(s, re->metric); - num = 0; - nump = stream_get_endp( - s); /* remember position for nexthop_num */ - stream_putc(s, 0); /* reserve room for nexthop_num */ - /* Only non-recursive routes are elegible to resolve the nexthop - * we - * are looking up. Therefore, we will just iterate over the top - * chain of nexthops. */ - for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - num += zsend_write_nexthop(s, nexthop); + /* Message type. */ + zclient_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id); - stream_putc_at(s, nump, num); /* store nexthop_num */ - } else { - stream_putc(s, 0); /* distance */ - stream_putl(s, 0); /* metric */ - stream_putc(s, 0); /* nexthop_num */ - } + /* Prefix information. */ + stream_putc(s, p->family); + blen = prefix_blen(p); + stream_put(s, &p->u.prefix, blen); + stream_putc(s, p->prefixlen); + /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } - int zsend_route_notify_owner(struct route_entry *re, struct prefix *p, - enum zapi_route_notify_owner note) + /* + * Function used by Zebra to send a PW status update to LDP daemon + */ + int zsend_pw_update(struct zserv *client, struct zebra_pw *pw) { - struct zserv *client; - struct stream *s; - uint8_t blen; + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); - client = zebra_find_client(re->type, re->instance); - if (!client || !client->notify_owner) { - if (IS_ZEBRA_DEBUG_PACKET) { - char buff[PREFIX_STRLEN]; + zclient_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id); + stream_write(s, pw->ifname, IF_NAMESIZE); + stream_putl(s, pw->ifindex); + stream_putl(s, pw->status); - zlog_debug( - "Not Notifying Owner: %u about prefix %s(%u) %d", - re->type, prefix2str(p, buff, sizeof(buff)), - re->table, note); - } - return 0; - } + /* Put length at the first point of the stream. */ + stream_putw_at(s, 0, stream_get_endp(s)); - if (IS_ZEBRA_DEBUG_PACKET) { - char buff[PREFIX_STRLEN]; + return zebra_server_send_message(client, s); + } - zlog_debug("Notifying Owner: %u about prefix %s(%u) %d", - re->type, prefix2str(p, buff, sizeof(buff)), - re->table, note); - } + /* Send response to a get label chunk request to client */ + static int zsend_assign_label_chunk_response(struct zserv *client, + vrf_id_t vrf_id, + struct label_manager_chunk *lmc) + { + int ret; + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); - s = client->obuf; - stream_reset(s); + zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id); - zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, re->vrf_id); + if (lmc) { + /* keep */ + stream_putc(s, lmc->keep); + /* start and end labels */ + stream_putl(s, lmc->start); + stream_putl(s, lmc->end); + } - stream_put(s, ¬e, sizeof(note)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - stream_putc(s, p->family); + ret = writen(client->sock, s->data, stream_get_endp(s)); + stream_free(s); + return ret; + } - blen = prefix_blen(p); - stream_putc(s, p->prefixlen); - stream_put(s, &p->u.prefix, blen); + /* Send response to a label manager connect request to client */ + static int zsend_label_manager_connect_response(struct zserv *client, + vrf_id_t vrf_id, u_short result) + { + int ret; + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); - stream_putl(s, re->table); + zclient_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id); + /* result */ + stream_putc(s, result); + + /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client); + ret = writen(client->sock, s->data, stream_get_endp(s)); + stream_free(s); + + return ret; } - void zsend_rule_notify_owner(struct zebra_pbr_rule *rule, - enum zapi_rule_notify_owner note) + /* Inbound message handling ------------------------------------------------ */ + + int cmd2type[] = { + [ZEBRA_NEXTHOP_REGISTER] = RNH_NEXTHOP_TYPE, + [ZEBRA_NEXTHOP_UNREGISTER] = RNH_NEXTHOP_TYPE, + [ZEBRA_IMPORT_ROUTE_REGISTER] = RNH_IMPORT_CHECK_TYPE, + [ZEBRA_IMPORT_ROUTE_UNREGISTER] = RNH_IMPORT_CHECK_TYPE, + }; + + /* Nexthop register */ + static void zread_rnh_register(ZAPI_HANDLER_ARGS) { - struct listnode *node; - struct zserv *client; + struct rnh *rnh; struct stream *s; + struct prefix p; + u_short l = 0; + u_char flags = 0; + uint16_t type = cmd2type[hdr->command]; - if (IS_ZEBRA_DEBUG_PACKET) { - zlog_debug("%s: Notifying %u", - __PRETTY_FUNCTION__, rule->unique); - } + if (IS_ZEBRA_DEBUG_NHT) + zlog_debug( + "rnh_register msg from client %s: hdr->length=%d, type=%s\n", + zebra_route_string(client->proto), hdr->length, + (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route"); - for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) { - if (rule->sock == client->sock) - break; + s = msg; + + client->nh_reg_time = monotime(NULL); + + while (l < hdr->length) { + STREAM_GETC(s, flags); + STREAM_GETW(s, p.family); + STREAM_GETC(s, p.prefixlen); + l += 4; + if (p.family == AF_INET) { + if (p.prefixlen > IPV4_MAX_BITLEN) { + zlog_warn( + "%s: Specified prefix hdr->length %d is too large for a v4 address", + __PRETTY_FUNCTION__, p.prefixlen); + return; + } + STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); + l += IPV4_MAX_BYTELEN; + } else if (p.family == AF_INET6) { + if (p.prefixlen > IPV6_MAX_BITLEN) { + zlog_warn( + "%s: Specified prefix hdr->length %d is to large for a v6 address", + __PRETTY_FUNCTION__, p.prefixlen); + return; + } + STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN); + l += IPV6_MAX_BYTELEN; + } else { + zlog_err( + "rnh_register: Received unknown family type %d\n", + p.family); + return; + } + rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type); + if (type == RNH_NEXTHOP_TYPE) { + if (flags + && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) + SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); + else if (!flags + && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) + UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); + } else if (type == RNH_IMPORT_CHECK_TYPE) { + if (flags + && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) + SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); + else if (!flags + && CHECK_FLAG(rnh->flags, + ZEBRA_NHT_EXACT_MATCH)) + UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); + } + + zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); + /* Anything not AF_INET/INET6 has been filtered out above */ + zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p); } - if (!client) - return; + stream_failure: + return; + } - s = client->obuf; - stream_reset(s); + /* Nexthop register */ + static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) + { + struct rnh *rnh; + struct stream *s; + struct prefix p; + u_short l = 0; + uint16_t type = cmd2type[hdr->command]; - zclient_create_header(s, ZEBRA_RULE_NOTIFY_OWNER, VRF_DEFAULT); - stream_put(s, ¬e, sizeof(note)); - stream_putl(s, rule->seq); - stream_putl(s, rule->priority); - stream_putl(s, rule->unique); - if (rule->ifp) - stream_putl(s, rule->ifp->ifindex); - else - stream_putl(s, 0); + if (IS_ZEBRA_DEBUG_NHT) + zlog_debug( + "rnh_unregister msg from client %s: hdr->length=%d\n", + zebra_route_string(client->proto), hdr->length); - stream_putw_at(s, 0, stream_get_endp(s)); + s = msg; + + while (l < hdr->length) { + uint8_t flags; + + STREAM_GETC(s, flags); + if (flags != 0) + goto stream_failure; - zebra_server_send_message(client); + STREAM_GETW(s, p.family); + STREAM_GETC(s, p.prefixlen); + l += 4; + if (p.family == AF_INET) { + if (p.prefixlen > IPV4_MAX_BITLEN) { + zlog_warn( + "%s: Specified prefix hdr->length %d is to large for a v4 address", + __PRETTY_FUNCTION__, p.prefixlen); + return; + } + STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); + l += IPV4_MAX_BYTELEN; + } else if (p.family == AF_INET6) { + if (p.prefixlen > IPV6_MAX_BITLEN) { + zlog_warn( + "%s: Specified prefix hdr->length %d is to large for a v6 address", + __PRETTY_FUNCTION__, p.prefixlen); + return; + } + STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN); + l += IPV6_MAX_BYTELEN; + } else { + zlog_err( + "rnh_register: Received unknown family type %d\n", + p.family); + return; + } + rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type); + if (rnh) { + client->nh_dereg_time = monotime(NULL); + zebra_remove_rnh_client(rnh, client, type); + } + } + stream_failure: + return; } - /* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */ - int zsend_router_id_update(struct zserv *client, struct prefix *p, - vrf_id_t vrf_id) + #define ZEBRA_MIN_FEC_LENGTH 5 + + /* FEC register */ + static void zread_fec_register(ZAPI_HANDLER_ARGS) { struct stream *s; - int blen; - - /* Check this client need interface information. */ - if (!vrf_bitmap_check(client->ridinfo, vrf_id)) - return 0; - - s = client->obuf; - stream_reset(s); + u_short l = 0; + struct prefix p; + uint16_t flags; + uint32_t label_index = MPLS_INVALID_LABEL_INDEX; - /* Message type. */ - zclient_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id); + s = msg; + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) + return; // unexpected - /* Prefix information. */ - stream_putc(s, p->family); - blen = prefix_blen(p); - stream_put(s, &p->u.prefix, blen); - stream_putc(s, p->prefixlen); + /* + * The minimum amount of data that can be sent for one fec + * registration + */ + if (hdr->length < ZEBRA_MIN_FEC_LENGTH) { + zlog_err( + "fec_register: Received a fec register of hdr->length %d, it is of insufficient size to properly decode", + hdr->length); + return; + } - /* Write packet size. */ - stream_putw_at(s, 0, stream_get_endp(s)); + while (l < hdr->length) { + STREAM_GETW(s, flags); + memset(&p, 0, sizeof(p)); + 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; + } + 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 hdr->length: %d is to long for %d", + __PRETTY_FUNCTION__, p.prefixlen, p.family); + return; + } + l += 5; + STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen)); + l += PSIZE(p.prefixlen); + if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) { + STREAM_GETL(s, label_index); + l += 4; + } else + label_index = MPLS_INVALID_LABEL_INDEX; + zebra_mpls_fec_register(zvrf, &p, label_index, client); + } - return zebra_server_send_message(client); + stream_failure: + return; } - /* - * Function used by Zebra to send a PW status update to LDP daemon - */ - int zsend_pw_update(struct zserv *client, struct zebra_pw *pw) + /* FEC unregister */ + static void zread_fec_unregister(ZAPI_HANDLER_ARGS) { struct stream *s; + u_short l = 0; + struct prefix p; + uint16_t flags; - s = client->obuf; - stream_reset(s); + s = msg; + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) + return; // unexpected - zclient_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id); - stream_write(s, pw->ifname, IF_NAMESIZE); - stream_putl(s, pw->ifindex); - stream_putl(s, pw->status); + /* + * The minimum amount of data that can be sent for one + * fec unregistration + */ + if (hdr->length < ZEBRA_MIN_FEC_LENGTH) { + zlog_err( + "fec_unregister: Received a fec unregister of hdr->length %d, it is of insufficient size to properly decode", + hdr->length); + return; + } - /* Put length at the first point of the stream. */ - stream_putw_at(s, 0, stream_get_endp(s)); + while (l < hdr->length) { + STREAM_GETW(s, flags); + if (flags != 0) + goto stream_failure; - return zebra_server_send_message(client); + memset(&p, 0, sizeof(p)); + 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; + } + 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 hdr->length %d which is greater than %d can support", + __PRETTY_FUNCTION__, p.prefixlen, p.family); + return; + } + l += 5; + STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen)); + l += PSIZE(p.prefixlen); + zebra_mpls_fec_unregister(zvrf, &p, client); + } + + stream_failure: + return; } - /* Register zebra server interface information. Send current all - interface and address information. */ - static int zread_interface_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) + + /* + * Register zebra server interface information. + * Send current all interface and address information. + */ + static void zread_interface_add(ZAPI_HANDLER_ARGS) { struct vrf *vrf; struct interface *ifp; @@@ -1201,21 -1144,11 +1181,21 @@@ static void zread_route_add(ZAPI_HANDLE struct nexthop *nexthop = NULL; int i, ret; vrf_id_t vrf_id = 0; + struct ipaddr vtep_ip; - s = client->ibuf; - if (zapi_route_decode(s, &api) < 0) - return -1; + s = msg; + zapi_route_decode(s, &api); + if (IS_ZEBRA_DEBUG_RECV) { + char buf_prefix[PREFIX_STRLEN]; + prefix2str(&api.prefix, buf_prefix, sizeof(buf_prefix)); + zlog_debug("%s: p=%s, ZAPI_MESSAGE_LABEL: %sset, flags=0x%x", + __func__, buf_prefix, + (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL) ? "" + : "un"), + api.flags); + } + /* Allocate new route. */ vrf_id = zvrf_id(zvrf); re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));