diff --git a/zebra/connected.c b/zebra/connected.c index d34fd9021a3e..cc6b7906430d 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -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,20 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr, p->prefixlen = prefixlen; ifc->address = (struct prefix *)p; + if (broad) { + p = prefix_ipv6_new(); + p->family = AF_INET6; + IPV6_ADDR_COPY(&p->prefix, broad); + p->prefixlen = prefixlen; + ifc->destination = (struct prefix *)p; + } else { + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) { + zlog_warn("warning: %s called for interface %s with peer flag set, but no peer address supplied", + __func__, ifp->name); + UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); + } + } + /* Label of this address. */ if (label) ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); @@ -527,9 +542,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 +552,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 d10a092984e1..c816969371c9 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, 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 *); diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index 1d108886de66..00f95498605f 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 94738664b344..ac146ca81db6 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 14905b738bf5..23122748a934 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -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); } diff --git a/zebra/ioctl.c b/zebra/ioctl.c index 8e3a1d1a0363..aebb31af7016 100644 --- a/zebra/ioctl.c +++ b/zebra/ioctl.c @@ -395,10 +395,13 @@ void if_get_flags(struct interface *ifp) strncpy(ifmr.ifm_name, ifp->name, IFNAMSIZ); /* Seems not all interfaces implement this ioctl */ - if (if_ioctl(SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) - zlog_err("if_ioctl(SIOCGIFMEDIA) failed: %s", - safe_strerror(errno)); - else if (ifmr.ifm_status & IFM_AVALID) /* Link state is valid */ + if (if_ioctl(SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { + /* Ignore EINVAL to avoid being too verbose */ + if (errno != EINVAL) + zlog_err("if_ioctl(SIOCGIFMEDIA) failed: %s", + safe_strerror(errno)); + } else if (ifmr.ifm_status + & IFM_AVALID) /* Link state is valid */ { if (ifmr.ifm_status & IFM_ACTIVE) SET_FLAG(ifreq.ifr_flags, IFF_RUNNING); diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 1ca5db83b4d9..f4ad6e220ed9 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: