diff --git a/lib/zclient.c b/lib/zclient.c index 2a7d2a8c5b..25c6e2b8e5 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -4709,7 +4709,7 @@ static int zclient_neigh_ip_read_entry(struct stream *s, struct ipaddr *add) int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in, union sockunion *out, struct interface *ifp, - int ndm_state) + int ndm_state, int ip_len) { int ret = 0; @@ -4722,6 +4722,7 @@ int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in, sockunion_get_addrlen(out)); } else stream_putc(s, AF_UNSPEC); + stream_putl(s, ip_len); stream_putl(s, ifp->ifindex); if (out) stream_putl(s, ndm_state); @@ -4739,6 +4740,7 @@ int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api) return -1; zclient_neigh_ip_read_entry(s, &api->ip_out); + STREAM_GETL(s, api->ip_len); STREAM_GETL(s, api->index); STREAM_GETL(s, api->ndm_state); return 0; @@ -4885,3 +4887,23 @@ enum zclient_send_status zclient_opaque_drop_notify(struct zclient *zclient, return zclient_send_message(zclient); } + +void zclient_register_neigh(struct zclient *zclient, vrf_id_t vrf_id, afi_t afi, + bool reg) +{ + struct stream *s; + + if (!zclient || zclient->sock < 0) + return; + + s = zclient->obuf; + stream_reset(s); + + zclient_create_header(s, + reg ? ZEBRA_NEIGH_REGISTER + : ZEBRA_NEIGH_UNREGISTER, + vrf_id); + stream_putw(s, afi); + stream_putw_at(s, 0, stream_get_endp(s)); + zclient_send_message(zclient); +} diff --git a/lib/zclient.h b/lib/zclient.h index f616dcda5d..3027c2c378 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -867,6 +867,7 @@ extern const struct zclient_options zclient_options_auxiliary; struct zapi_neigh_ip { int cmd; + int ip_len; struct ipaddr ip_in; struct ipaddr ip_out; ifindex_t index; @@ -875,7 +876,7 @@ struct zapi_neigh_ip { int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api); int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in, union sockunion *out, struct interface *ifp, - int ndm_state); + int ndm_state, int ip_len); /* * We reserve the top 4 bits for l2-NHG, everything else @@ -1322,6 +1323,9 @@ enum zapi_opaque_registry { */ extern enum zclient_send_status zclient_send_hello(struct zclient *client); +extern void zclient_register_neigh(struct zclient *zclient, vrf_id_t vrf_id, + afi_t afi, bool reg); + extern enum zclient_send_status zclient_send_neigh_discovery_req(struct zclient *zclient, const struct interface *ifp, diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c index c0d77e62d2..88628999ab 100644 --- a/nhrpd/netlink_arp.c +++ b/nhrpd/netlink_arp.c @@ -154,6 +154,10 @@ int nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS) struct zapi_neigh_ip api = {}; zclient_neigh_ip_decode(zclient->ibuf, &api); + + if (api.ip_len != IPV4_MAX_BYTELEN && api.ip_len != 0) + return 0; + if (api.ip_in.ipa_type == AF_UNSPEC) return 0; sockunion_family(&addr) = api.ip_in.ipa_type; diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index edc3629723..c05a8a3ba2 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -75,25 +75,6 @@ static void nhrp_route_update_zebra(const struct prefix *p, } } -static void nhrp_zebra_register_neigh(vrf_id_t vrf_id, afi_t afi, bool reg) -{ - struct stream *s; - - if (!zclient || zclient->sock < 0) - return; - - s = zclient->obuf; - stream_reset(s); - - zclient_create_header(s, - reg ? ZEBRA_NEIGH_REGISTER - : ZEBRA_NEIGH_UNREGISTER, - vrf_id); - stream_putw(s, afi); - stream_putw_at(s, 0, stream_get_endp(s)); - zclient_send_message(zclient); -} - void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp) { struct route_node *rn; @@ -369,8 +350,8 @@ static void nhrp_zebra_connected(struct zclient *zclient) ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT); zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT); - nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP, true); - nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP6, true); + zclient_register_neigh(zclient, VRF_DEFAULT, AFI_IP, true); + zclient_register_neigh(zclient, VRF_DEFAULT, AFI_IP6, true); } static zclient_handler *const nhrp_handlers[] = { @@ -457,10 +438,11 @@ void nhrp_send_zebra_nbr(union sockunion *in, return; s = zclient->obuf; stream_reset(s); - zclient_neigh_ip_encode(s, out ? ZEBRA_NEIGH_IP_ADD : - ZEBRA_NEIGH_IP_DEL, in, out, - ifp, out ? ZEBRA_NEIGH_STATE_REACHABLE - : ZEBRA_NEIGH_STATE_FAILED); + zclient_neigh_ip_encode(s, out ? ZEBRA_NEIGH_IP_ADD : ZEBRA_NEIGH_IP_DEL, + in, out, ifp, + out ? ZEBRA_NEIGH_STATE_REACHABLE + : ZEBRA_NEIGH_STATE_FAILED, + 0); stream_putw_at(s, 0, stream_get_endp(s)); zclient_send_message(zclient); } @@ -472,8 +454,8 @@ int nhrp_send_zebra_gre_request(struct interface *ifp) void nhrp_zebra_terminate(void) { - nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP, false); - nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP6, false); + zclient_register_neigh(zclient, VRF_DEFAULT, AFI_IP, false); + zclient_register_neigh(zclient, VRF_DEFAULT, AFI_IP6, false); zclient_stop(zclient); zclient_free(zclient); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 711ceae6d6..f092fc5c85 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -4256,20 +4256,18 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) /* copy LLADDR information */ l2_len = RTA_PAYLOAD(tb[NDA_LLADDR]); } - if (l2_len == IPV4_MAX_BYTELEN || l2_len == 0) { - union sockunion link_layer_ipv4; - if (l2_len) { - sockunion_family(&link_layer_ipv4) = AF_INET; - memcpy((void *)sockunion_get_addr(&link_layer_ipv4), - RTA_DATA(tb[NDA_LLADDR]), l2_len); - } else - sockunion_family(&link_layer_ipv4) = AF_UNSPEC; - zsend_neighbor_notify(cmd, ifp, &ip, - netlink_nbr_entry_state_to_zclient( - ndm->ndm_state), - &link_layer_ipv4); - } + union sockunion link_layer_ipv4; + + if (l2_len) { + sockunion_family(&link_layer_ipv4) = AF_INET; + memcpy((void *)sockunion_get_addr(&link_layer_ipv4), + RTA_DATA(tb[NDA_LLADDR]), l2_len); + } else + sockunion_family(&link_layer_ipv4) = AF_UNSPEC; + zsend_neighbor_notify(cmd, ifp, &ip, + netlink_nbr_entry_state_to_zclient(ndm->ndm_state), + &link_layer_ipv4, l2_len); if (h->nlmsg_type == RTM_GETNEIGH) return 0; diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index f40413dc51..296bf12bb5 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -968,8 +968,9 @@ void zsend_ipset_entry_notify_owner(const struct zebra_dplane_ctx *ctx, zserv_send_message(client, s); } -void zsend_neighbor_notify(int cmd, struct interface *ifp, struct ipaddr *ipaddr, - int ndm_state, union sockunion *link_layer_ipv4) +void zsend_neighbor_notify(int cmd, struct interface *ifp, + struct ipaddr *ipaddr, int ndm_state, + union sockunion *link_layer_ipv4, int ip_len) { struct stream *s; struct listnode *node, *nnode; @@ -992,7 +993,7 @@ void zsend_neighbor_notify(int cmd, struct interface *ifp, struct ipaddr *ipaddr s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_neigh_ip_encode(s, cmd, &ip, link_layer_ipv4, ifp, - ndm_state); + ndm_state, ip_len); stream_putw_at(s, 0, stream_get_endp(s)); zserv_send_message(client, s); } diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index c750c27515..43f734d26e 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -93,7 +93,7 @@ extern int zsend_sr_policy_notify_status(uint32_t color, int status); extern void zsend_neighbor_notify(int cmd, struct interface *ifp, struct ipaddr *ipaddr, int ndm_state, - union sockunion *link_layer_ipv4); + union sockunion *link_layer_ipv4, int ip_len); extern int zsend_client_close_notify(struct zserv *client, struct zserv *closed_client);