On Tue, Dec 01, 2015 at 01:34:15PM +0100, Martin Pieuchot wrote:
> 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?
OK bluhm@
>
> 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);