]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: Trust the mac address received in some situations
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 19 Sep 2018 15:09:18 +0000 (11:09 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 19 Sep 2018 15:25:22 +0000 (11:25 -0400)
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 <sharpd@cumulusnetworks.com>
zebra/rtadv.c

index f9bd5ad1bb00481a36e929692b95e1f3b7eb2194..3bb75f344654ff12d8839a3a156c48b43a630abe 100644 (file)
@@ -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;
        }