From: Donald Sharp Date: Wed, 19 Sep 2018 15:09:18 +0000 (-0400) Subject: zebra: Trust the mac address received in some situations X-Git-Tag: frr-7.1-dev~337^2~1 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=71974bf5612447abbb14971752217e2cf7ee7934;p=mirror%2Ffrr.git zebra: Trust the mac address received in some situations When we receive a v6 RA packet with an optional ND_OPT_SOURCE_LINKADDR take that data and construct the v4 to v6 neighbor entry for that interface to allow v4 w/ v6 nexthops to work with only global v6 addresses on an interface. Signed-off-by: Donald Sharp --- diff --git a/zebra/rtadv.c b/zebra/rtadv.c index f9bd5ad1bb..3bb75f3446 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -455,6 +455,38 @@ static void rtadv_process_solicit(struct interface *ifp) rtadv_send_packet(zns->rtadv.sock, ifp); } +/* + * This function processes optional attributes off of + * end of a RA packet received. At this point in + * time we only care about this in one situation + * which is when a interface does not have a LL + * v6 address. We still need to be able to install + * the mac address for v4 to v6 resolution + */ +static void rtadv_process_optional(uint8_t *optional, unsigned int len, + struct interface *ifp, + struct sockaddr_in6 *addr) +{ + char *mac; + + while (len > 0) { + struct nd_opt_hdr *opt_hdr = (struct nd_opt_hdr *)optional; + + switch(opt_hdr->nd_opt_type) { + case ND_OPT_SOURCE_LINKADDR: + mac = (char *)(optional+2); + if_nbr_mac_to_ipv4ll_neigh_update(ifp, mac, + &addr->sin6_addr, 1); + break; + default: + break; + } + + len -= 8 * opt_hdr->nd_opt_len; + optional += 8 * opt_hdr->nd_opt_len; + } +} + static void rtadv_process_advert(uint8_t *msg, unsigned int len, struct interface *ifp, struct sockaddr_in6 *addr) @@ -469,14 +501,19 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len, inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN); if (len < sizeof(struct nd_router_advert)) { - zlog_debug("%s(%u): Rx RA with invalid length %d from %s", - ifp->name, ifp->ifindex, len, addr_str); + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug("%s(%u): Rx RA with invalid length %d from %s", + ifp->name, ifp->ifindex, len, addr_str); return; } + if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { - zlog_debug( - "%s(%u): Rx RA with non-linklocal source address from %s", - ifp->name, ifp->ifindex, addr_str); + rtadv_process_optional(msg + sizeof(struct nd_router_advert), + len - sizeof(struct nd_router_advert), + ifp, addr); + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug("%s(%u): Rx RA with non-linklocal source address from %s", + ifp->name, ifp->ifindex, addr_str); return; }