From 60c0687a9a0608f828ce36134638ea6974d733ea Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 15 Apr 2018 10:57:19 -0400 Subject: [PATCH] zebra: Fix crash with certain types of tunnels 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 --- zebra/connected.c | 24 ++++++++++++++++++++---- zebra/connected.h | 7 ++++--- zebra/if_ioctl.c | 2 +- zebra/if_ioctl_solaris.c | 2 +- zebra/if_netlink.c | 2 ++ zebra/kernel_socket.c | 3 ++- 6 files changed, 30 insertions(+), 10 deletions(-) diff --git a/zebra/connected.c b/zebra/connected.c index 2198ddf5ea1c..35b3b0f4a96d 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -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); } diff --git a/zebra/connected.h b/zebra/connected.h index 9b69a3f2467c..2a2b0933951d 100644 --- a/zebra/connected.h +++ b/zebra/connected.h @@ -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 *); diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index b506315ebfcf..f5ed9455279c 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -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); } } diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c index e9182304ddd1..6cf98e85f58d 100644 --- a/zebra/if_ioctl_solaris.c +++ b/zebra/if_ioctl_solaris.c @@ -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; diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 4a37c14b9296..e28c189f8643 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -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); } diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 4ac3bed4b427..1a9480731724 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -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: