Index: sys/net/if_spppsubr.c =================================================================== --- sys/net/if_spppsubr.c +++ sys/net/if_spppsubr.c @@ -45,8 +45,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -4881,9 +4883,12 @@ if (ifa != NULL) { int error; + int fibnum = ifp->if_fib; + rt_addrmsg(RTM_DELETE, ifa, fibnum); /* delete old route */ - error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); + ia = ifatoia(ifa); + error = in_handle_ifaddr_rtrequest(RTM_DELETE, ia); if (debug && error) { log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", SPP_ARGS(ifp), error); @@ -4891,14 +4896,14 @@ /* set new address */ si->sin_addr.s_addr = htonl(src); - ia = ifatoia(ifa); IN_IFADDR_WLOCK(); LIST_REMOVE(ia, ia_hash); LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); IN_IFADDR_WUNLOCK(); + rt_addrmsg(RTM_ADD, ifa, fibnum); /* add new route */ - error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); + error = in_handle_ifaddr_rtrequest(RTM_ADD, ia); if (debug && error) { log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", SPP_ARGS(ifp), error); Index: sys/net/route.h =================================================================== --- sys/net/route.h +++ sys/net/route.h @@ -415,7 +415,6 @@ void rt_ifmsg(struct ifnet *); void rt_missmsg(int, struct rt_addrinfo *, int, int); void rt_missmsg_fib(int, struct rt_addrinfo *, int, int, int); -void rt_newaddrmsg_fib(int, struct ifaddr *, struct rtentry *, int); int rt_addrmsg(int, struct ifaddr *, int); int rt_routemsg(int, struct rtentry *, struct nhop_object *, int); int rt_routemsg_info(int, struct rt_addrinfo *, int); @@ -433,10 +432,6 @@ void rt_flushifroutes_af(struct ifnet *, int); void rt_flushifroutes(struct ifnet *ifp); -/* XXX MRT COMPAT VERSIONS THAT SET UNIVERSE to 0 */ -/* Thes are used by old code not yet converted to use multiple FIBS */ -int rtinit(struct ifaddr *, int, int); - /* XXX MRT NEW VERSIONS THAT USE FIBs * For now the protocol indepedent versions are the same as the AF_INET ones * but this will change.. Index: sys/net/route.c =================================================================== --- sys/net/route.c +++ sys/net/route.c @@ -767,27 +767,3 @@ return (rtsock_routemsg_info(cmd, info, fibnum)); } - -/* - * This is called to generate messages from the routing socket - * indicating a network interface has had addresses associated with it. - */ -void -rt_newaddrmsg_fib(int cmd, struct ifaddr *ifa, struct rtentry *rt, int fibnum) -{ - - KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE, - ("unexpected cmd %u", cmd)); - KASSERT((fibnum >= 0 && fibnum < rt_numfibs), - ("%s: fib out of range 0 <=%d<%d", __func__, fibnum, rt_numfibs)); - - if (cmd == RTM_ADD) { - rt_addrmsg(cmd, ifa, fibnum); - if (rt != NULL) - rt_routemsg(cmd, rt, nhop_select(rt->rt_nhop, 0), fibnum); - } else { - if (rt != NULL) - rt_routemsg(cmd, rt, nhop_select(rt->rt_nhop, 0), fibnum); - rt_addrmsg(cmd, ifa, fibnum); - } -} Index: sys/net/route/route_ctl.h =================================================================== --- sys/net/route/route_ctl.h +++ sys/net/route/route_ctl.h @@ -52,6 +52,7 @@ struct rib_cmd_info *rc); int rib_action(uint32_t fibnum, int action, struct rt_addrinfo *info, struct rib_cmd_info *rc); +int rib_handle_ifaddr_info(uint32_t fibnum, int cmd, struct rt_addrinfo *info); typedef void route_notification_t(struct rib_cmd_info *rc, void *); void rib_decompose_notification(struct rib_cmd_info *rc, Index: sys/net/route/route_ifaddrs.c =================================================================== --- sys/net/route/route_ifaddrs.c +++ sys/net/route/route_ifaddrs.c @@ -64,177 +64,62 @@ SYSCTL_UINT(_net, OID_AUTO, add_addr_allfibs, CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(rt_add_addr_allfibs), 0, ""); -/* - * Set up a routing table entry, normally - * for an interface. - */ -static inline int -rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum) +static int +rib_handle_ifaddr_one(uint32_t fibnum, int cmd, struct rt_addrinfo *info) { - RIB_RLOCK_TRACKER; - struct epoch_tracker et; - struct sockaddr *dst; - struct sockaddr *netmask; struct rib_cmd_info rc; - struct rt_addrinfo info; - int error = 0; - int startfib, endfib; - struct sockaddr_storage ss; - int didwork = 0; - int a_failure = 0; - struct sockaddr_dl_short sdl; - struct rib_head *rnh; + struct nhop_object *nh; + int error; - if (flags & RTF_HOST) { - dst = ifa->ifa_dstaddr; - netmask = NULL; - } else { - dst = ifa->ifa_addr; - netmask = ifa->ifa_netmask; - } - if (dst->sa_len == 0) - return(EINVAL); - switch (dst->sa_family) { - case AF_INET6: - case AF_INET: - /* We support multiple FIBs. */ - break; - default: - fibnum = RT_DEFAULT_FIB; - break; - } - if (fibnum == RT_ALL_FIBS) { - if (V_rt_add_addr_allfibs == 0 && cmd == (int)RTM_ADD) - startfib = endfib = ifa->ifa_ifp->if_fib; - else { - startfib = 0; - endfib = rt_numfibs - 1; - } - } else { - KASSERT((fibnum < rt_numfibs), ("rtinit1: bad fibnum")); - startfib = fibnum; - endfib = fibnum; + error = rib_action(fibnum, cmd, info, &rc); + if (error == 0) { + if (cmd == RTM_ADD) + nh = nhop_select(rc.rc_nh_new, 0); + else + nh = nhop_select(rc.rc_nh_old, 0); + rt_routemsg(cmd, rc.rc_rt, nh, fibnum); } - /* - * If it's a delete, check that if it exists, - * it's on the correct interface or we might scrub - * a route to another ifa which would - * be confusing at best and possibly worse. - */ - if (cmd == RTM_DELETE) { - /* - * It's a delete, so it should already exist.. - * If it's a net, mask off the host bits - * (Assuming we have a mask) - * XXX this is kinda inet specific.. - */ - if (netmask != NULL) { - rt_maskedcopy(dst, (struct sockaddr *)&ss, netmask); - dst = (struct sockaddr *)&ss; - } - } - bzero(&sdl, sizeof(struct sockaddr_dl_short)); - sdl.sdl_family = AF_LINK; - sdl.sdl_len = sizeof(struct sockaddr_dl_short); - sdl.sdl_type = ifa->ifa_ifp->if_type; - sdl.sdl_index = ifa->ifa_ifp->if_index; - /* - * Now go through all the requested tables (fibs) and do the - * requested action. Realistically, this will either be fib 0 - * for protocols that don't do multiple tables or all the - * tables for those that do. - */ - for ( fibnum = startfib; fibnum <= endfib; fibnum++) { - if (cmd == RTM_DELETE) { - struct radix_node *rn; - /* - * Look up an rtentry that is in the routing tree and - * contains the correct info. - */ - rnh = rt_tables_get_rnh(fibnum, dst->sa_family); - if (rnh == NULL) - /* this table doesn't exist but others might */ - continue; - RIB_RLOCK(rnh); - rn = rnh->rnh_lookup(dst, netmask, &rnh->head); - error = (rn == NULL || - (rn->rn_flags & RNF_ROOT) || - RNTORT(rn)->rt_nhop->nh_ifa != ifa); - RIB_RUNLOCK(rnh); - if (error) { - /* this is only an error if bad on ALL tables */ - continue; - } - } - /* - * Do the actual request - */ - bzero((caddr_t)&info, sizeof(info)); - info.rti_ifa = ifa; - info.rti_flags = flags | - (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED; - info.rti_info[RTAX_DST] = dst; - info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sdl; - info.rti_info[RTAX_NETMASK] = netmask; - NET_EPOCH_ENTER(et); - error = rib_action(fibnum, cmd, &info, &rc); - if (error == 0 && rc.rc_rt != NULL) { - /* - * notify any listening routing agents of the change - */ + return (error); +} - /* TODO: interface routes/aliases */ - rt_newaddrmsg_fib(cmd, ifa, rc.rc_rt, fibnum); - didwork = 1; +int +rib_handle_ifaddr_info(uint32_t fibnum, int cmd, struct rt_addrinfo *info) +{ + bool allfibs = V_rt_add_addr_allfibs != 0; + bool didwork; + int error, last_error = 0; + + if (!allfibs) { + error = rib_handle_ifaddr_one(fibnum, cmd, info); + didwork = (error == 0); + } else { + for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { + error = rib_handle_ifaddr_one(fibnum, cmd, info); + if (error == 0) + didwork = true; + else + last_error = error; } - NET_EPOCH_EXIT(et); - if (error) - a_failure = error; } + if (cmd == RTM_DELETE) { if (didwork) { error = 0; } else { /* we only give an error if it wasn't in any table */ - error = ((flags & RTF_HOST) ? + error = ((info->rti_flags & RTF_HOST) ? EHOSTUNREACH : ENETUNREACH); } } else { - if (a_failure) { + if (last_error != 0) { /* return an error if any of them failed */ - error = a_failure; + error = last_error; } } return (error); } -/* - * Set up a routing table entry, normally - * for an interface. - */ -int -rtinit(struct ifaddr *ifa, int cmd, int flags) -{ - struct sockaddr *dst; - int fib = RT_DEFAULT_FIB; - - if (flags & RTF_HOST) { - dst = ifa->ifa_dstaddr; - } else { - dst = ifa->ifa_addr; - } - - switch (dst->sa_family) { - case AF_INET6: - case AF_INET: - /* We do support multiple FIBs. */ - fib = RT_ALL_FIBS; - break; - } - return (rtinit1(ifa, cmd, flags, fib)); -} - static int ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa, struct sockaddr *ia) Index: sys/netinet/in.c =================================================================== --- sys/netinet/in.c +++ sys/netinet/in.c @@ -58,6 +58,8 @@ #include #include #include +#include +#include #include #include @@ -709,6 +711,125 @@ return (0); } +static int +in_match_ifaddr(const struct rtentry *rt, const struct nhop_object *nh, void *arg) +{ + + if (nh->nh_ifa == (struct ifaddr *)arg) + return (1); + + return (0); +} + +static int +in_handle_ifaddr_rtrequest_prefix(uint32_t fibnum, int cmd, + struct sockaddr_in *dst, struct sockaddr_in *netmask, struct ifaddr *ifa) +{ + + NET_EPOCH_ASSERT(); + + /* Prepare gateway */ + struct sockaddr_dl_short sdl = { + .sdl_family = AF_LINK, + .sdl_len = sizeof(struct sockaddr_dl_short), + .sdl_type = ifa->ifa_ifp->if_type, + .sdl_index = ifa->ifa_ifp->if_index, + }; + + struct rt_addrinfo info = { + .rti_ifa = ifa, + .rti_flags = RTF_PINNED | ((netmask != NULL) ? 0 : RTF_HOST), + .rti_info = { + [RTAX_DST] = (struct sockaddr *)dst, + [RTAX_NETMASK] = (struct sockaddr *)netmask, + [RTAX_GATEWAY] = (struct sockaddr *)&sdl, + }, + /* Ensure we delete the prefix IFF prefix ifa is the right one */ + .rti_filter = in_match_ifaddr, + .rti_filterdata = ifa, + }; + + return (rib_handle_ifaddr_info(fibnum, cmd, &info)); +} + +/* + * Adds or delete interface route corresponding to @ifa. + * There can be multiple options: + * 1) Adding addr with prefix on non-p2p/non-lo interface. + * Example: 192.0.2.1/24. Action: add route towards + * 192.0.2.0/24 via this interface, using ifa as an address source. + * Note: route to 192.0.2.1 will be installed separately via + * ifa_maintain_loopback_route(). + * 2) Adding addr with "host" mask. + * Example: 192.0.2.2/32. In this case no action is performed, + * as the route should be installed by ifa_maintain_loopback_route(). + * Returns 0 to indicate success. + * 3) Adding address with or without prefix to p2p interface. + * Example: 10.0.0.1/24->10.0.0.2. In this case, all other addresses + * covered by prefix, does not make sense in the context of p2p link. + * Action: add route towards 10.0.0.2 via this interface, using ifa as an + * address source. + * Similar to (1), route to 10.0.0.1 will be installed by + * ifa_maintain_loopback_route(). + * 4) Adding address with or without prefix to loopback interface. + * Example: 192.0.2.1/24. In this case, trafic to non-host addresses cannot + * be forwarded, as it would introduce an infinite cycle. + * Similar to (2), perform no action and return 0. Loopback route + * will be installed by ifa_maintain_loopback_route(). + */ +int +in_handle_ifaddr_rtrequest(int cmd, struct in_ifaddr *ia) +{ + struct ifaddr *ifa = &ia->ia_ifa; + struct in_addr daddr, maddr; + struct sockaddr_in *pmask; + struct epoch_tracker et; + int error; + + /* Case 4: ignore loopbacks */ + if (ifa->ifa_ifp->if_flags & IFF_LOOPBACK) + return (0); + + if (ifa->ifa_ifp->if_flags & IFF_POINTOPOINT) { + /* Case 3: install route towards dst addr */ + daddr = ia->ia_dstaddr.sin_addr; + pmask = NULL; + maddr.s_addr = INADDR_BROADCAST; + } else { + daddr = ia->ia_addr.sin_addr; + pmask = &ia->ia_sockmask; + maddr = pmask->sin_addr; + + if (maddr.s_addr == INADDR_BROADCAST) { + /* Case 2: ignore /32 routes */ + return (0); + } + } + + struct sockaddr_in mask = { + .sin_family = AF_INET, + .sin_len = sizeof(struct sockaddr_in), + .sin_addr = maddr, + }; + + if (pmask != NULL) + pmask = &mask; + + struct sockaddr_in dst = { + .sin_family = AF_INET, + .sin_len = sizeof(struct sockaddr_in), + .sin_addr.s_addr = daddr.s_addr & maddr.s_addr, + }; + + uint32_t fibnum = ifa->ifa_ifp->if_fib; + NET_EPOCH_ENTER(et); + error = in_handle_ifaddr_rtrequest_prefix(fibnum, cmd, &dst, pmask, ifa); + NET_EPOCH_EXIT(et); + + return (error); +} + + #define rtinitflags(x) \ ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \ ? RTF_HOST : 0) @@ -785,7 +906,8 @@ /* * No-one seem to have this prefix route, so we try to insert it. */ - error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags); + rt_addrmsg(RTM_ADD, &target->ia_ifa, target->ia_ifp->if_fib); + error = in_handle_ifaddr_rtrequest(RTM_ADD, target); if (!error) target->ia_flags |= IFA_ROUTE; return (error); @@ -917,8 +1039,7 @@ if ((ia->ia_flags & IFA_ROUTE) == 0) { ifa_ref(&ia->ia_ifa); IN_IFADDR_RUNLOCK(&in_ifa_tracker); - error = rtinit(&(target->ia_ifa), (int)RTM_DELETE, - rtinitflags(target)); + error = in_handle_ifaddr_rtrequest(RTM_DELETE, target); if (error == 0) target->ia_flags &= ~IFA_ROUTE; else @@ -927,8 +1048,7 @@ /* Scrub all entries IFF interface is different */ in_scrubprefixlle(target, target->ia_ifp != ia->ia_ifp, flags); - error = rtinit(&ia->ia_ifa, (int)RTM_ADD, - rtinitflags(ia) | RTF_UP); + error = in_handle_ifaddr_rtrequest(RTM_ADD, ia); if (error == 0) ia->ia_flags |= IFA_ROUTE; else @@ -948,7 +1068,8 @@ /* * As no-one seem to have this prefix, we can remove the route. */ - error = rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target)); + rt_addrmsg(RTM_DELETE, &target->ia_ifa, target->ia_ifp->if_fib); + error = in_handle_ifaddr_rtrequest(RTM_DELETE, target); if (error == 0) target->ia_flags &= ~IFA_ROUTE; else Index: sys/netinet/in_var.h =================================================================== --- sys/netinet/in_var.h +++ sys/netinet/in_var.h @@ -464,6 +464,7 @@ int in_addprefix(struct in_ifaddr *, int); int in_scrubprefix(struct in_ifaddr *, u_int); void in_ifscrub_all(void); +int in_handle_ifaddr_rtrequest(int, struct in_ifaddr *); void ip_input(struct mbuf *); void ip_direct_input(struct mbuf *); void in_ifadown(struct ifaddr *ifa, int); Index: sys/netinet/raw_ip.c =================================================================== --- sys/netinet/raw_ip.c +++ sys/netinet/raw_ip.c @@ -64,6 +64,7 @@ #include #include #include +#include #include #include @@ -864,7 +865,8 @@ err = ifa_del_loopback_route((struct ifaddr *)ia, sa); - err = rtinit(&ia->ia_ifa, RTM_ADD, flags); + rt_addrmsg(RTM_ADD, &ia->ia_ifa, ia->ia_ifp->if_fib); + err = in_handle_ifaddr_rtrequest(RTM_ADD, ia); if (err == 0) ia->ia_flags |= IFA_ROUTE; Index: sys/netinet6/in6.c =================================================================== --- sys/netinet6/in6.c +++ sys/netinet6/in6.c @@ -91,6 +91,7 @@ #include #include #include +#include #include #include #include @@ -1272,6 +1273,44 @@ return (error); } +static int +in6_handle_dstaddr_rtrequest(int cmd, struct in6_ifaddr *ia) +{ + struct epoch_tracker et; + struct ifaddr *ifa = &ia->ia_ifa; + int error; + + /* Prepare gateway */ + struct sockaddr_dl_short sdl = { + .sdl_family = AF_LINK, + .sdl_len = sizeof(struct sockaddr_dl_short), + .sdl_type = ifa->ifa_ifp->if_type, + .sdl_index = ifa->ifa_ifp->if_index, + }; + + struct sockaddr_in6 dst = { + .sin6_family = AF_INET6, + .sin6_len = sizeof(struct sockaddr_in6), + .sin6_addr = ia->ia_dstaddr.sin6_addr, + }; + + struct rt_addrinfo info = { + .rti_ifa = ifa, + .rti_flags = RTF_PINNED | RTF_HOST, + .rti_info = { + [RTAX_DST] = (struct sockaddr *)&dst, + [RTAX_GATEWAY] = (struct sockaddr *)&sdl, + }, + }; + /* Don't set additional per-gw filters on removal */ + + NET_EPOCH_ENTER(et); + error = rib_handle_ifaddr_info(ifa->ifa_ifp->if_fib, cmd, &info); + NET_EPOCH_EXIT(et); + + return (error); +} + void in6_purgeaddr(struct ifaddr *ifa) { @@ -1305,10 +1344,12 @@ in6_leavegroup(imm->i6mm_maddr, NULL); free(imm, M_IP6MADDR); } + /* Check if we need to remove p2p route */ plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */ + if (ia->ia_dstaddr.sin6_family != AF_INET6) + plen = 0; if ((ia->ia_flags & IFA_ROUTE) && plen == 128) { - error = rtinit(&(ia->ia_ifa), RTM_DELETE, ia->ia_flags | - (ia->ia_dstaddr.sin6_family == AF_INET6 ? RTF_HOST : 0)); + error = in6_handle_dstaddr_rtrequest(RTM_DELETE, ia); if (error != 0) log(LOG_INFO, "%s: err=%d, destination address delete " "failed\n", __func__, error); @@ -1416,7 +1457,7 @@ if (pdst->sin6_family == AF_INET6 && !IN6_ARE_ADDR_EQUAL(&pdst->sin6_addr, &ia->ia_dstaddr.sin6_addr)) { if ((ia->ia_flags & IFA_ROUTE) != 0 && - (rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST) != 0)) { + (in6_handle_dstaddr_rtrequest(RTM_DELETE, ia) != 0)) { nd6log((LOG_ERR, "in6_update_ifa_internal: failed to " "remove a route to the old destination: %s\n", ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); @@ -1436,13 +1477,12 @@ plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */ if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 && ia->ia_dstaddr.sin6_family == AF_INET6) { - int rtflags = RTF_UP | RTF_HOST; /* * Handle the case for ::1 . */ if (ifp->if_flags & IFF_LOOPBACK) ia->ia_flags |= IFA_RTSELF; - error = rtinit(&ia->ia_ifa, RTM_ADD, ia->ia_flags | rtflags); + error = in6_handle_dstaddr_rtrequest(RTM_ADD, ia); if (error) goto done; ia->ia_flags |= IFA_ROUTE; Index: sys/netinet6/nd6_rtr.c =================================================================== --- sys/netinet6/nd6_rtr.c +++ sys/netinet6/nd6_rtr.c @@ -2020,73 +2020,63 @@ ND6_ONLINK_UNLOCK(); } +/* + * + * ifa can be NULL + */ +static int +nd6_prefix_rtrequest(uint32_t fibnum, int cmd, struct sockaddr_in6 *dst, + struct sockaddr_in6 *netmask, struct ifnet *ifp, struct ifaddr *ifa) +{ + struct epoch_tracker et; + int error; + + /* Prepare gateway */ + struct sockaddr_dl_short sdl = { + .sdl_family = AF_LINK, + .sdl_len = sizeof(struct sockaddr_dl_short), + .sdl_type = ifp->if_type, + .sdl_index = ifp->if_index, + }; + + struct rt_addrinfo info = { + .rti_ifa = ifa, + .rti_flags = RTF_PINNED | ((netmask != NULL) ? 0 : RTF_HOST), + .rti_info = { + [RTAX_DST] = (struct sockaddr *)dst, + [RTAX_NETMASK] = (struct sockaddr *)netmask, + [RTAX_GATEWAY] = (struct sockaddr *)&sdl, + }, + }; + /* Don't set additional per-gw filters on removal */ + + NET_EPOCH_ENTER(et); + error = rib_handle_ifaddr_info(fibnum, cmd, &info); + NET_EPOCH_EXIT(et); + return (error); +} + static int nd6_prefix_onlink_rtrequest(struct nd_prefix *pr, struct ifaddr *ifa) { - struct sockaddr_dl_short sdl; - struct sockaddr_in6 mask6; - u_long rtflags; - int error, a_failure, fibnum, maxfib; - - bzero(&mask6, sizeof(mask6)); - mask6.sin6_len = sizeof(mask6); - mask6.sin6_addr = pr->ndpr_mask; - rtflags = (ifa->ifa_flags & ~IFA_RTSELF) | RTF_UP; - - bzero(&sdl, sizeof(struct sockaddr_dl_short)); - sdl.sdl_len = sizeof(struct sockaddr_dl_short); - sdl.sdl_family = AF_LINK; - sdl.sdl_type = ifa->ifa_ifp->if_type; - sdl.sdl_index = ifa->ifa_ifp->if_index; - - if(V_rt_add_addr_allfibs) { - fibnum = 0; - maxfib = rt_numfibs; - } else { - fibnum = ifa->ifa_ifp->if_fib; - maxfib = fibnum + 1; - } - a_failure = 0; - for (; fibnum < maxfib; fibnum++) { - struct rt_addrinfo info; - struct rib_cmd_info rc; - - bzero((caddr_t)&info, sizeof(info)); - info.rti_flags = rtflags; - info.rti_info[RTAX_DST] = (struct sockaddr *)&pr->ndpr_prefix; - info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sdl; - info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&mask6; - - NET_EPOCH_ASSERT(); - error = rib_action(fibnum, RTM_ADD, &info, &rc); - if (error != 0) { - char ip6buf[INET6_ADDRSTRLEN]; - char ip6bufg[INET6_ADDRSTRLEN]; - char ip6bufm[INET6_ADDRSTRLEN]; - struct sockaddr_in6 *sin6; - - sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; - nd6log((LOG_ERR, "%s: failed to add " - "route for a prefix (%s/%d) on %s, gw=%s, mask=%s, " - "flags=%lx errno = %d\n", __func__, - ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr), - pr->ndpr_plen, if_name(pr->ndpr_ifp), - ip6_sprintf(ip6bufg, &sin6->sin6_addr), - ip6_sprintf(ip6bufm, &mask6.sin6_addr), - rtflags, error)); + uint32_t fibnum; + int error; - /* Save last error to return, see rtinit(). */ - a_failure = error; - continue; - } + struct sockaddr_in6 mask6 = { + .sin6_family = AF_INET6, + .sin6_len = sizeof(struct sockaddr_in6), + .sin6_addr = pr->ndpr_mask, + }; + + struct sockaddr_in6 *pmask6 = (pr->ndpr_plen != 128) ? &mask6 : NULL; + fibnum = ifa->ifa_ifp->if_fib; + error = nd6_prefix_rtrequest(fibnum, RTM_ADD, &pr->ndpr_prefix, pmask6, + pr->ndpr_ifp, ifa); + if (error == 0) pr->ndpr_stateflags |= NDPRF_ONLINK; - struct nhop_object *nh = nhop_select(rc.rc_nh_new, 0); - rt_routemsg(RTM_ADD, rc.rc_rt, nh, fibnum); - } - /* Return the last error we got. */ - return (a_failure); + return (error); } static int @@ -2178,11 +2168,10 @@ int error = 0; struct ifnet *ifp = pr->ndpr_ifp; struct nd_prefix *opr; - struct sockaddr_in6 sa6, mask6; + struct sockaddr_in6 sa6; char ip6buf[INET6_ADDRSTRLEN]; uint64_t genid; - int fibnum, maxfib, a_failure; - struct epoch_tracker et; + int a_failure; ND6_ONLINK_LOCK_ASSERT(); ND6_UNLOCK_ASSERT(); @@ -2190,50 +2179,16 @@ if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) 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)); - - if (V_rt_add_addr_allfibs) { - fibnum = 0; - maxfib = rt_numfibs; - } else { - fibnum = ifp->if_fib; - maxfib = fibnum + 1; - } + struct sockaddr_in6 mask6 = { + .sin6_family = AF_INET6, + .sin6_len = sizeof(struct sockaddr_in6), + .sin6_addr = pr->ndpr_mask, + }; + struct sockaddr_in6 *pmask6 = (pr->ndpr_plen != 128) ? &mask6 : NULL; - a_failure = 0; - NET_EPOCH_ENTER(et); - for (; fibnum < maxfib; fibnum++) { - struct rt_addrinfo info; - struct rib_cmd_info rc; - - bzero((caddr_t)&info, sizeof(info)); - info.rti_flags = RTF_GATEWAY; - info.rti_info[RTAX_DST] = (struct sockaddr *)&sa6; - info.rti_info[RTAX_GATEWAY] = NULL; - info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&mask6; - - NET_EPOCH_ASSERT(); - error = rib_action(fibnum, RTM_DELETE, &info, &rc); - if (error != 0) { - /* Save last error to return, see rtinit(). */ - a_failure = error; - continue; - } + error = nd6_prefix_rtrequest(ifp->if_fib, RTM_DELETE, + &pr->ndpr_prefix, pmask6, ifp, NULL); - /* report route deletion to the routing socket. */ - struct nhop_object *nh = nhop_select(rc.rc_nh_old, 0); - rt_routemsg(RTM_DELETE, rc.rc_rt, nh, fibnum); - } - NET_EPOCH_EXIT(et); - error = a_failure; a_failure = 1; if (error == 0) { pr->ndpr_stateflags &= ~NDPRF_ONLINK; @@ -2283,7 +2238,7 @@ /* XXX: can we still set the NDPRF_ONLINK flag? */ nd6log((LOG_ERR, "%s: failed to delete route: %s/%d on %s (errno=%d)\n", - __func__, ip6_sprintf(ip6buf, &sa6.sin6_addr), + __func__, ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr), pr->ndpr_plen, if_name(ifp), error)); }