Diff below converts two custom uses of rtrequest(9) to rt_ifa_add(9). These are used to automagically install and remove the RTF_CONNECTED route obtained from a router advertisement.
This changes the existing logic a bit to match the netinet behavior. The route will now be attached to the ``ifa'' matching the prefix announced: -2001::/64 fe80::5054:ff:fe12:3456%vio0 UC 0 2 - 4 vio0 +2001::/64 2001::5054:ff:fe12:3456 UC 0 0 - 4 vio0 This should be fine as the "gateway" field does not matter for RTF_CLONING routes. ok? Index: netinet6/nd6_rtr.c =================================================================== RCS file: /cvs/src/sys/netinet6/nd6_rtr.c,v retrieving revision 1.134 diff -u -p -r1.134 nd6_rtr.c --- netinet6/nd6_rtr.c 24 Nov 2015 13:37:16 -0000 1.134 +++ netinet6/nd6_rtr.c 1 Dec 2015 12:22:56 -0000 @@ -1697,15 +1697,11 @@ pfxlist_onlink_check(void) int nd6_prefix_onlink(struct nd_prefix *pr) { - struct rt_addrinfo info; - struct ifaddr *ifa; struct ifnet *ifp = pr->ndpr_ifp; - struct sockaddr_in6 mask6; + struct ifaddr *ifa; struct nd_prefix *opr; - struct rtentry *rt; char addr[INET6_ADDRSTRLEN]; - u_long rtflags = 0; - int error; + int error, rtflags = 0; /* sanity check */ if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) @@ -1731,18 +1727,11 @@ nd6_prefix_onlink(struct nd_prefix *pr) return (0); } - /* - * We prefer link-local addresses as the associated interface address. - */ - /* search for a link-local addr */ - ifa = &in6ifa_ifpforlinklocal(ifp, - IN6_IFF_NOTREADY | IN6_IFF_ANYCAST)->ia_ifa; - if (ifa == NULL) { - TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { - if (ifa->ifa_addr->sa_family == AF_INET6) - break; - } - /* should we care about ia6_flags? */ + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { + if (ifa->ifa_addr->sa_family != AF_INET6) + continue; + if (ifatoia6(ifa)->ia6_ndpr == pr) + break; } if (ifa == NULL) { /* @@ -1760,25 +1749,12 @@ nd6_prefix_onlink(struct nd_prefix *pr) return (0); } - bzero(&mask6, sizeof(mask6)); - mask6.sin6_len = sizeof(mask6); - mask6.sin6_addr = pr->ndpr_mask; - if (nd6_need_cache(ifp)) rtflags = RTF_CLONING | RTF_CONNECTED; - bzero(&info, sizeof(info)); - info.rti_flags = rtflags; - info.rti_info[RTAX_DST] = sin6tosa(&pr->ndpr_prefix); - info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; - info.rti_info[RTAX_NETMASK] = sin6tosa(&mask6); - - error = rtrequest(RTM_ADD, &info, RTP_CONNECTED, &rt, ifp->if_rdomain); - if (error == 0) { + error = rt_ifa_add(ifa, rtflags, sin6tosa(&pr->ndpr_prefix)); + if (error == 0) pr->ndpr_stateflags |= NDPRF_ONLINK; - rt_sendmsg(rt, RTM_ADD, ifp->if_rdomain); - rtfree(rt); - } return (error); } @@ -1786,13 +1762,11 @@ nd6_prefix_onlink(struct nd_prefix *pr) int nd6_prefix_offlink(struct nd_prefix *pr) { - struct rt_addrinfo info; struct ifnet *ifp = pr->ndpr_ifp; + struct ifaddr *ifa; struct nd_prefix *opr; - struct sockaddr_in6 sa6, mask6; - struct rtentry *rt; char addr[INET6_ADDRSTRLEN]; - int error; + int error, rtflags = 0; /* sanity check */ if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) { @@ -1804,27 +1778,22 @@ nd6_prefix_offlink(struct nd_prefix *pr) return (EEXIST); } - bzero(&sa6, sizeof(sa6)); - sa6.sin6_family = AF_INET6; - sa6.sin6_len = sizeof(sa6); - bcopy(&pr->ndpr_prefix.sin6_addr, &sa6.sin6_addr, - sizeof(struct in6_addr)); - bzero(&mask6, sizeof(mask6)); - mask6.sin6_family = AF_INET6; - mask6.sin6_len = sizeof(sa6); - bcopy(&pr->ndpr_mask, &mask6.sin6_addr, sizeof(struct in6_addr)); - bzero(&info, sizeof(info)); - info.rti_info[RTAX_DST] = sin6tosa(&sa6); - info.rti_info[RTAX_NETMASK] = sin6tosa(&mask6); + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { + if (ifa->ifa_addr->sa_family != AF_INET6) + continue; + if (ifatoia6(ifa)->ia6_ndpr == pr) + break; + } + if (ifa == NULL) + return (EINVAL); - error = rtrequest(RTM_DELETE, &info, RTP_CONNECTED, &rt, - ifp->if_rdomain); + if (nd6_need_cache(ifp)) + rtflags = RTF_CLONING | RTF_CONNECTED; + + error = rt_ifa_del(ifa, rtflags, sin6tosa(&pr->ndpr_prefix)); if (error == 0) { pr->ndpr_stateflags &= ~NDPRF_ONLINK; - rt_sendmsg(rt, RTM_DELETE, ifp->if_rdomain); - rtfree(rt); - /* * There might be the same prefix on another interface, * the prefix which could not be on-link just because we have @@ -1864,13 +1833,6 @@ nd6_prefix_offlink(struct nd_prefix *pr) } } } - } else { - /* XXX: can we still set the NDPRF_ONLINK flag? */ - nd6log((LOG_ERR, - "nd6_prefix_offlink: failed to delete route: " - "%s/%d on %s (errno = %d)\n", - inet_ntop(AF_INET6, &sa6.sin6_addr, addr, sizeof(addr)), - pr->ndpr_plen, ifp->if_xname, error)); } return (error);