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: