Index: in6.c =================================================================== --- in6.c +++ in6.c @@ -920,6 +920,8 @@ if (hostIsNew) error = in6_broadcast_ifa(ifp, ifra, ia, flags); + else + rt_addrmsg(RTM_ADD, (struct ifaddr *)ia, 0); return (error); } Index: nd6.c =================================================================== --- nd6.c +++ nd6.c @@ -935,6 +935,8 @@ int oldflags = ia6->ia6_flags; ia6->ia6_flags |= IN6_IFF_DEPRECATED; + if (ia6->ia6_flags != oldflags) + rt_addrmsg(RTM_ADD, (struct ifaddr *)ia6, 0); /* * If a temporary address has just become deprecated, @@ -972,6 +974,8 @@ (MAX_RTR_SOLICITATION_DELAY * hz); nd6_dad_start((struct ifaddr *)ia6, delay); } else { + int oldflags = ia6->ia6_flags; + /* * Check status of the interface. If it is down, * mark the address as tentative for future DAD. @@ -989,6 +993,10 @@ * preferred. */ ia6->ia6_flags &= ~IN6_IFF_DEPRECATED; + + /* Notify the routing socket of a flag change. */ + if (ia6->ia6_flags != oldflags) + rt_addrmsg(RTM_ADD, (struct ifaddr *)ia6, 0); } } @@ -1644,7 +1652,13 @@ AF_INET6) continue; ia = (struct in6_ifaddr *)ifa; - ia->ia6_flags |= IN6_IFF_TENTATIVE; + if (!(ia->ia6_flags & + IN6_IFF_TENTATIVE)) + { + ia->ia6_flags |= + IN6_IFF_TENTATIVE; + rt_addrmsg(RTM_ADD, ifa, 0); + } } IF_ADDR_RUNLOCK(ifp); } Index: nd6_nbr.c =================================================================== --- nd6_nbr.c +++ nd6_nbr.c @@ -1240,24 +1240,25 @@ ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); return; } - if (ia->ia6_flags & IN6_IFF_ANYCAST) { - ia->ia6_flags &= ~IN6_IFF_TENTATIVE; - return; - } - if (!V_ip6_dad_count) { - ia->ia6_flags &= ~IN6_IFF_TENTATIVE; - return; - } if (ifa->ifa_ifp == NULL) panic("nd6_dad_start: ifa->ifa_ifp == NULL"); - if (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_NO_DAD) { - ia->ia6_flags &= ~IN6_IFF_TENTATIVE; + if (ia->ia6_flags & IN6_IFF_ANYCAST || + !V_ip6_dad_count || + ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_NO_DAD) + { + if (ia->ia6_flags & IN6_IFF_TENTATIVE) { + ia->ia6_flags &= ~IN6_IFF_TENTATIVE; + rt_addrmsg(RTM_ADD, ifa, 0); + } return; } if (!(ifa->ifa_ifp->if_flags & IFF_UP) || !(ifa->ifa_ifp->if_drv_flags & IFF_DRV_RUNNING) || (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_IFDISABLED)) { - ia->ia6_flags |= IN6_IFF_TENTATIVE; + if (!(ia->ia6_flags & IN6_IFF_TENTATIVE)) { + ia->ia6_flags |= IN6_IFF_TENTATIVE; + rt_addrmsg(RTM_ADD, ifa, 0); + } return; } if ((dp = nd6_dad_find(ifa, NULL)) != NULL) { @@ -1426,8 +1427,10 @@ * again in case that it is changed between the * beginning of this function and here. */ - if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) == 0) + if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) == 0) { ia->ia6_flags &= ~IN6_IFF_TENTATIVE; + rt_addrmsg(RTM_ADD, ifa, 0); + } nd6log((LOG_DEBUG, "%s: DAD complete for %s - no duplicates found\n", @@ -1501,6 +1504,8 @@ break; } } + + rt_addrmsg(RTM_ADD, ifa, 0); } static void Index: nd6_rtr.c =================================================================== --- nd6_rtr.c +++ nd6_rtr.c @@ -1489,10 +1489,13 @@ if (ifa->ia6_flags & IN6_IFF_DETACHED) { ifa->ia6_flags &= ~IN6_IFF_DETACHED; ifa->ia6_flags |= IN6_IFF_TENTATIVE; + rt_addrmsg(RTM_ADD, + (struct ifaddr *)ifa, 0); nd6_dad_start((struct ifaddr *)ifa, 0); } - } else { + } else if (!(ifa->ia6_flags & IN6_IFF_DETACHED)) { ifa->ia6_flags |= IN6_IFF_DETACHED; + rt_addrmsg(RTM_ADD, (struct ifaddr *)ifa, 0); } } } @@ -1504,6 +1507,7 @@ if (ifa->ia6_flags & IN6_IFF_DETACHED) { ifa->ia6_flags &= ~IN6_IFF_DETACHED; ifa->ia6_flags |= IN6_IFF_TENTATIVE; + rt_addrmsg(RTM_ADD, (struct ifaddr *)ifa, 0); /* Do we need a delay in this case? */ nd6_dad_start((struct ifaddr *)ifa, 0); }