]> git.puffer.fish Git - mirror/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)
committerRenato Westphal <renato@opensourcerouting.org>
Fri, 29 Jun 2018 19:07:35 +0000 (16:07 -0300)
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 d34fd9021a3e96eb48a264ae2083e7d68c438a39..446883bb0ff512832b99a57e4df5909b7f994a9d 100644 (file)
@@ -486,7 +486,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,
-                       u_char prefixlen, const char *label)
+                       struct in6_addr *broad, uint8_t prefixlen,
+                       const char *label)
 {
        struct prefix_ipv6 *p;
        struct connected *ifc;
@@ -509,6 +510,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);
@@ -527,9 +536,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,
-                          u_char prefixlen)
+                          struct in6_addr *broad, uint8_t prefixlen)
 {
-       struct prefix p;
+       struct prefix p, d;
        struct connected *ifc;
 
        memset(&p, 0, sizeof(struct prefix));
@@ -537,7 +546,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 d10a092984e1557f49b7b147ec5f5258972ba277..c816969371c98f57a0ffc48b2d32fd8e59418cf0 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, u_char 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, u_char prefixlen);
+                                 struct in6_addr *address,
+                                 struct in6_addr *broad, uint8_t prefixlen);
 
 extern int connected_is_unnumbered(struct interface *);
 
index 1d108886de669532f3f7dcbb166b30ac611c9b07..00f95498605fa5d726458abd7b5a1572c80b843c 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 94738664b344a52cbd5d5cc76f0fef934f518abc..ac146ca81db67873bc571fb381b8ac6066c4004b 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 14905b738bf537929eb5ebb1944472dabd19b833..23122748a9341ff1b5b6c06bf2bbf409b06467fb 100644 (file)
@@ -985,9 +985,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 1ca5db83b4d970d8661e3e40826cca39aa7632ed..f4ad6e220ed974339e25f71b0f0f9986138ecaeb 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: