]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: Fix crash with certain types of tunnels
authorDonald Sharp <sharpd@cumulusnetworks.com>
Sun, 15 Apr 2018 14:57:19 +0000 (10:57 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Sun, 15 Apr 2018 14:57:19 +0000 (10:57 -0400)
Zebra did not have a handler for tunnels in v6 for
some reason.  Add code to handle the broadcast address
for both addition and deletion.

This appears to fix the crash.  There might still need
to be some work to make the code `work` properly for
this type of tunnel.

Fixes: #2063
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
zebra/connected.c
zebra/connected.h
zebra/if_ioctl.c
zebra/if_ioctl_solaris.c
zebra/if_netlink.c
zebra/kernel_socket.c

index 2198ddf5ea1c513b87d81c18dc0059d30741242a..35b3b0f4a96df748417d89c8587f6e27680a8847 100644 (file)
@@ -495,7 +495,8 @@ void connected_delete_ipv4(struct interface *ifp, int flags,
 
 /* Add connected IPv6 route to the interface. */
 void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
-                       uint8_t prefixlen, const char *label)
+                       struct in6_addr *broad, uint8_t prefixlen,
+                       const char *label)
 {
        struct prefix_ipv6 *p;
        struct connected *ifc;
@@ -518,6 +519,14 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
        p->prefixlen = prefixlen;
        ifc->address = (struct prefix *)p;
 
+       if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) {
+               p = prefix_ipv6_new();
+               p->family = AF_INET6;
+               IPV6_ADDR_COPY(&p->prefix, broad);
+               p->prefixlen = prefixlen;
+               ifc->destination = (struct prefix *)p;
+       }
+
        /* Label of this address. */
        if (label)
                ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
@@ -536,9 +545,9 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
 }
 
 void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address,
-                          uint8_t prefixlen)
+                          struct in6_addr *broad, uint8_t prefixlen)
 {
-       struct prefix p;
+       struct prefix p, d;
        struct connected *ifc;
 
        memset(&p, 0, sizeof(struct prefix));
@@ -546,7 +555,14 @@ void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address,
        memcpy(&p.u.prefix6, address, sizeof(struct in6_addr));
        p.prefixlen = prefixlen;
 
-       ifc = connected_check(ifp, &p);
+       if (broad) {
+               memset(&d, 0, sizeof(struct prefix));
+               d.family = AF_INET6;
+               IPV6_ADDR_COPY(&d.u.prefix, broad);
+               d.prefixlen = prefixlen;
+               ifc = connected_check_ptp(ifp, &p, &d);
+       } else
+               ifc = connected_check_ptp(ifp, &p, NULL);
 
        connected_delete_helper(ifc, &p);
 }
index 9b69a3f2467c81d32a63e07c22fc48f90579aa95..2a2b0933951df16c226a8d88aa0a812b13ae7061 100644 (file)
@@ -42,10 +42,11 @@ extern void connected_up(struct interface *ifp, struct connected *ifc);
 extern void connected_down(struct interface *ifp, struct connected *ifc);
 
 extern void connected_add_ipv6(struct interface *ifp, int flags,
-                              struct in6_addr *address, uint8_t prefixlen,
-                              const char *label);
+                              struct in6_addr *address, struct in6_addr *broad,
+                              uint8_t prefixlen, const char *label);
 extern void connected_delete_ipv6(struct interface *ifp,
-                                 struct in6_addr *address, uint8_t prefixlen);
+                                 struct in6_addr *address,
+                                 struct in6_addr *broad, uint8_t prefixlen);
 
 extern int connected_is_unnumbered(struct interface *);
 
index b506315ebfcf7e720cbd9b758ffc8d0f98f3d82b..f5ed9455279c0fc90c542752da32f765facb2a59 100644 (file)
@@ -249,7 +249,7 @@ static int if_getaddrs(void)
                        }
 #endif
 
-                       connected_add_ipv6(ifp, flags, &addr->sin6_addr,
+                       connected_add_ipv6(ifp, flags, &addr->sin6_addr, NULL,
                                           prefixlen, NULL);
                }
        }
index e9182304ddd167b1dd2966b69631c5350a399e93..6cf98e85f58da359dd6a92c1ec9a49838ff24a6b 100644 (file)
@@ -315,7 +315,7 @@ static int if_get_addr(struct interface *ifp, struct sockaddr *addr,
                connected_add_ipv4(ifp, flags, &SIN(addr)->sin_addr, prefixlen,
                                   (struct in_addr *)dest_pnt, label);
        else if (af == AF_INET6)
-               connected_add_ipv6(ifp, flags, &SIN6(addr)->sin6_addr,
+               connected_add_ipv6(ifp, flags, &SIN6(addr)->sin6_addr, NULL,
                                   prefixlen, label);
 
        return 0;
index 4a37c14b9296aaf839c5a4ba6235679d413aa499..e28c189f8643647be215f4884c6e34675c80545c 100644 (file)
@@ -1006,9 +1006,11 @@ int netlink_interface_addr(struct sockaddr_nl *snl, struct nlmsghdr *h,
                              & (IFA_F_DADFAILED | IFA_F_TENTATIVE)))
                                connected_add_ipv6(ifp, flags,
                                                   (struct in6_addr *)addr,
+                                                  (struct in6_addr *)broad,
                                                   ifa->ifa_prefixlen, label);
                } else
                        connected_delete_ipv6(ifp, (struct in6_addr *)addr,
+                                             (struct in6_addr *)broad,
                                              ifa->ifa_prefixlen);
        }
 
index 4ac3bed4b42735ff7edf2cade0e6b3fd87c2c82c..1a94807317242f6f9a850d334cc0c2b071ad0d30 100644 (file)
@@ -771,10 +771,11 @@ int ifam_read(struct ifa_msghdr *ifam)
 
                if (ifam->ifam_type == RTM_NEWADDR)
                        connected_add_ipv6(ifp, flags, &addr.sin6.sin6_addr,
+                                          NULL,
                                           ip6_masklen(mask.sin6.sin6_addr),
                                           (isalias ? ifname : NULL));
                else
-                       connected_delete_ipv6(ifp, &addr.sin6.sin6_addr,
+                       connected_delete_ipv6(ifp, &addr.sin6.sin6_addr, NULL,
                                              ip6_masklen(mask.sin6.sin6_addr));
                break;
        default: