summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet6/nd6_rtr.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet6/nd6_rtr.c')
-rw-r--r--freebsd/sys/netinet6/nd6_rtr.c274
1 files changed, 157 insertions, 117 deletions
diff --git a/freebsd/sys/netinet6/nd6_rtr.c b/freebsd/sys/netinet6/nd6_rtr.c
index f2a07d96..4da54fa6 100644
--- a/freebsd/sys/netinet6/nd6_rtr.c
+++ b/freebsd/sys/netinet6/nd6_rtr.c
@@ -86,6 +86,9 @@ static int in6_init_prefix_ltimes(struct nd_prefix *);
static void in6_init_address_ltimes __P((struct nd_prefix *,
struct in6_addrlifetime *));
+static int nd6_prefix_onlink(struct nd_prefix *);
+static int nd6_prefix_offlink(struct nd_prefix *);
+
static int rt6_deleteroute(struct radix_node *, void *);
VNET_DECLARE(int, nd6_recalc_reachtm_interval);
@@ -443,21 +446,21 @@ nd6_rtmsg(int cmd, struct rtentry *rt)
info.rti_info[RTAX_NETMASK] = rt_mask(rt);
ifp = rt->rt_ifp;
if (ifp != NULL) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
ifa = TAILQ_FIRST(&ifp->if_addrhead);
info.rti_info[RTAX_IFP] = ifa->ifa_addr;
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
} else
ifa = NULL;
- rt_missmsg(cmd, &info, rt->rt_flags, 0);
+ rt_missmsg_fib(cmd, &info, rt->rt_flags, 0, rt->rt_fibnum);
if (ifa != NULL)
ifa_free(ifa);
}
-void
+static void
defrouter_addreq(struct nd_defrouter *new)
{
struct sockaddr_in6 def, mask, gate;
@@ -475,9 +478,9 @@ defrouter_addreq(struct nd_defrouter *new)
gate.sin6_addr = new->rtaddr;
s = splnet();
- error = rtrequest(RTM_ADD, (struct sockaddr *)&def,
+ error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&def,
(struct sockaddr *)&gate, (struct sockaddr *)&mask,
- RTF_GATEWAY, &newrt);
+ RTF_GATEWAY, &newrt, RT_DEFAULT_FIB);
if (newrt) {
nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
RTFREE(newrt);
@@ -493,8 +496,7 @@ defrouter_lookup(struct in6_addr *addr, struct ifnet *ifp)
{
struct nd_defrouter *dr;
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
- dr = TAILQ_NEXT(dr, dr_entry)) {
+ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr))
return (dr);
}
@@ -522,9 +524,9 @@ defrouter_delreq(struct nd_defrouter *dr)
def.sin6_family = gate.sin6_family = AF_INET6;
gate.sin6_addr = dr->rtaddr;
- rtrequest(RTM_DELETE, (struct sockaddr *)&def,
+ in6_rtrequest(RTM_DELETE, (struct sockaddr *)&def,
(struct sockaddr *)&gate,
- (struct sockaddr *)&mask, RTF_GATEWAY, &oldrt);
+ (struct sockaddr *)&mask, RTF_GATEWAY, &oldrt, RT_DEFAULT_FIB);
if (oldrt) {
nd6_rtmsg(RTM_DELETE, oldrt);
RTFREE(oldrt);
@@ -541,8 +543,7 @@ defrouter_reset(void)
{
struct nd_defrouter *dr;
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
- dr = TAILQ_NEXT(dr, dr_entry))
+ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry)
defrouter_delreq(dr);
/*
@@ -573,7 +574,7 @@ defrtrlist_del(struct nd_defrouter *dr)
/*
* Also delete all the pointers to the router in each prefix lists.
*/
- for (pr = V_nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
+ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
struct nd_pfxrouter *pfxrtr;
if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL)
pfxrtr_del(pfxrtr);
@@ -637,7 +638,7 @@ defrouter_select(void)
* Let's handle easy case (3) first:
* If default router list is empty, there's nothing to be done.
*/
- if (!TAILQ_FIRST(&V_nd_defrouter)) {
+ if (TAILQ_EMPTY(&V_nd_defrouter)) {
splx(s);
return;
}
@@ -647,15 +648,14 @@ defrouter_select(void)
* We just pick up the first reachable one (if any), assuming that
* the ordering rule of the list described in defrtrlist_update().
*/
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
- dr = TAILQ_NEXT(dr, dr_entry)) {
- IF_AFDATA_LOCK(dr->ifp);
+ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
+ IF_AFDATA_RLOCK(dr->ifp);
if (selected_dr == NULL &&
(ln = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) &&
ND6_IS_LLINFO_PROBREACH(ln)) {
selected_dr = dr;
}
- IF_AFDATA_UNLOCK(dr->ifp);
+ IF_AFDATA_RUNLOCK(dr->ifp);
if (ln != NULL) {
LLE_RUNLOCK(ln);
ln = NULL;
@@ -683,13 +683,13 @@ defrouter_select(void)
else
selected_dr = TAILQ_NEXT(installed_dr, dr_entry);
} else if (installed_dr) {
- IF_AFDATA_LOCK(installed_dr->ifp);
+ IF_AFDATA_RLOCK(installed_dr->ifp);
if ((ln = nd6_lookup(&installed_dr->rtaddr, 0, installed_dr->ifp)) &&
ND6_IS_LLINFO_PROBREACH(ln) &&
rtpref(selected_dr) <= rtpref(installed_dr)) {
selected_dr = installed_dr;
}
- IF_AFDATA_UNLOCK(installed_dr->ifp);
+ IF_AFDATA_RUNLOCK(installed_dr->ifp);
if (ln != NULL)
LLE_RUNLOCK(ln);
}
@@ -757,9 +757,10 @@ defrtrlist_update(struct nd_defrouter *new)
/*
* If the preference does not change, there's no need
- * to sort the entries.
+ * to sort the entries. Also make sure the selected
+ * router is still installed in the kernel.
*/
- if (rtpref(new) == oldpref) {
+ if (dr->installed && rtpref(new) == oldpref) {
splx(s);
return (dr);
}
@@ -804,8 +805,7 @@ insert:
*/
/* insert at the end of the group */
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
- dr = TAILQ_NEXT(dr, dr_entry)) {
+ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
if (rtpref(n) > rtpref(dr))
break;
}
@@ -826,7 +826,7 @@ pfxrtr_lookup(struct nd_prefix *pr, struct nd_defrouter *dr)
{
struct nd_pfxrouter *search;
- for (search = pr->ndpr_advrtrs.lh_first; search; search = search->pfr_next) {
+ LIST_FOREACH(search, &pr->ndpr_advrtrs, pfr_entry) {
if (search->router == dr)
break;
}
@@ -862,8 +862,7 @@ nd6_prefix_lookup(struct nd_prefixctl *key)
{
struct nd_prefix *search;
- for (search = V_nd_prefix.lh_first;
- search; search = search->ndpr_next) {
+ LIST_FOREACH(search, &V_nd_prefix, ndpr_entry) {
if (key->ndpr_ifp == search->ndpr_ifp &&
key->ndpr_plen == search->ndpr_plen &&
in6_are_prefix_equal(&key->ndpr_prefix.sin6_addr,
@@ -969,9 +968,7 @@ prelist_remove(struct nd_prefix *pr)
LIST_REMOVE(pr, ndpr_entry);
/* free list of routers that adversed the prefix */
- for (pfr = pr->ndpr_advrtrs.lh_first; pfr; pfr = next) {
- next = pfr->pfr_next;
-
+ LIST_FOREACH_SAFE(pfr, &pr->ndpr_advrtrs, pfr_entry, next) {
free(pfr, M_IP6NDP);
}
splx(s);
@@ -1119,7 +1116,7 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
* consider autoconfigured addresses while RFC2462 simply said
* "address".
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct in6_ifaddr *ifa6;
u_int32_t remaininglifetime;
@@ -1242,7 +1239,7 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
ifa6->ia6_lifetime = lt6_tmp;
ifa6->ia6_updatetime = time_second;
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (ia6_match == NULL && new->ndpr_vltime) {
int ifidlen;
@@ -1334,11 +1331,10 @@ find_pfxlist_reachable_router(struct nd_prefix *pr)
struct llentry *ln;
int canreach;
- for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr != NULL;
- pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
- IF_AFDATA_LOCK(pfxrtr->router->ifp);
+ LIST_FOREACH(pfxrtr, &pr->ndpr_advrtrs, pfr_entry) {
+ IF_AFDATA_RLOCK(pfxrtr->router->ifp);
ln = nd6_lookup(&pfxrtr->router->rtaddr, 0, pfxrtr->router->ifp);
- IF_AFDATA_UNLOCK(pfxrtr->router->ifp);
+ IF_AFDATA_RUNLOCK(pfxrtr->router->ifp);
if (ln == NULL)
continue;
canreach = ND6_IS_LLINFO_PROBREACH(ln);
@@ -1374,7 +1370,7 @@ pfxlist_onlink_check()
* Check if there is a prefix that has a reachable advertising
* router.
*/
- for (pr = V_nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
+ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
if (pr->ndpr_raf_onlink && find_pfxlist_reachable_router(pr))
break;
}
@@ -1384,12 +1380,10 @@ pfxlist_onlink_check()
* that does not advertise any prefixes.
*/
if (pr == NULL) {
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
- dr = TAILQ_NEXT(dr, dr_entry)) {
+ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
struct nd_prefix *pr0;
- for (pr0 = V_nd_prefix.lh_first; pr0;
- pr0 = pr0->ndpr_next) {
+ LIST_FOREACH(pr0, &V_nd_prefix, ndpr_entry) {
if ((pfxrtr = pfxrtr_lookup(pr0, dr)) != NULL)
break;
}
@@ -1397,7 +1391,7 @@ pfxlist_onlink_check()
break;
}
}
- if (pr != NULL || (TAILQ_FIRST(&V_nd_defrouter) && pfxrtr == NULL)) {
+ if (pr != NULL || (!TAILQ_EMPTY(&V_nd_defrouter) && pfxrtr == NULL)) {
/*
* There is at least one prefix that has a reachable router,
* or at least a router which probably does not advertise
@@ -1407,7 +1401,7 @@ pfxlist_onlink_check()
* Detach prefixes which have no reachable advertising
* router, and attach other prefixes.
*/
- for (pr = V_nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
+ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
/* XXX: a link-local prefix should never be detached */
if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
continue;
@@ -1431,7 +1425,7 @@ pfxlist_onlink_check()
}
} else {
/* there is no prefix that has a reachable router */
- for (pr = V_nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
+ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
continue;
@@ -1454,7 +1448,7 @@ pfxlist_onlink_check()
* interfaces. Such cases will be handled in nd6_prefix_onlink,
* so we don't have to care about them.
*/
- for (pr = V_nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
+ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
int e;
char ip6buf[INET6_ADDRSTRLEN];
@@ -1552,19 +1546,92 @@ pfxlist_onlink_check()
}
}
-int
+static int
+nd6_prefix_onlink_rtrequest(struct nd_prefix *pr, struct ifaddr *ifa)
+{
+ static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
+ struct radix_node_head *rnh;
+ struct rtentry *rt;
+ struct sockaddr_in6 mask6;
+ u_long rtflags;
+ int error, a_failure, fibnum;
+
+ /*
+ * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
+ * ifa->ifa_rtrequest = nd6_rtrequest;
+ */
+ bzero(&mask6, sizeof(mask6));
+ mask6.sin6_len = sizeof(mask6);
+ mask6.sin6_addr = pr->ndpr_mask;
+ rtflags = (ifa->ifa_flags & ~IFA_RTSELF) | RTF_UP;
+
+ a_failure = 0;
+ for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
+
+ rt = NULL;
+ error = in6_rtrequest(RTM_ADD,
+ (struct sockaddr *)&pr->ndpr_prefix, ifa->ifa_addr,
+ (struct sockaddr *)&mask6, rtflags, &rt, fibnum);
+ if (error == 0) {
+ KASSERT(rt != NULL, ("%s: in6_rtrequest return no "
+ "error(%d) but rt is NULL, pr=%p, ifa=%p", __func__,
+ error, pr, ifa));
+
+ rnh = rt_tables_get_rnh(rt->rt_fibnum, AF_INET6);
+ /* XXX what if rhn == NULL? */
+ RADIX_NODE_HEAD_LOCK(rnh);
+ RT_LOCK(rt);
+ if (rt_setgate(rt, rt_key(rt),
+ (struct sockaddr *)&null_sdl) == 0) {
+ struct sockaddr_dl *dl;
+
+ dl = (struct sockaddr_dl *)rt->rt_gateway;
+ dl->sdl_type = rt->rt_ifp->if_type;
+ dl->sdl_index = rt->rt_ifp->if_index;
+ }
+ RADIX_NODE_HEAD_UNLOCK(rnh);
+ nd6_rtmsg(RTM_ADD, rt);
+ RT_UNLOCK(rt);
+ pr->ndpr_stateflags |= NDPRF_ONLINK;
+ } else {
+ 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, "nd6_prefix_onlink: failed to add "
+ "route for a prefix (%s/%d) on %s, gw=%s, mask=%s, "
+ "flags=%lx errno = %d\n",
+ 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));
+
+ /* Save last error to return, see rtinit(). */
+ a_failure = error;
+ }
+
+ if (rt != NULL) {
+ RT_LOCK(rt);
+ RT_REMREF(rt);
+ RT_UNLOCK(rt);
+ }
+ }
+
+ /* Return the last error we got. */
+ return (a_failure);
+}
+
+static int
nd6_prefix_onlink(struct nd_prefix *pr)
{
struct ifaddr *ifa;
struct ifnet *ifp = pr->ndpr_ifp;
- struct sockaddr_in6 mask6;
struct nd_prefix *opr;
- u_long rtflags;
int error = 0;
- struct radix_node_head *rnh;
- struct rtentry *rt = NULL;
char ip6buf[INET6_ADDRSTRLEN];
- struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
/* sanity check */
if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
@@ -1582,7 +1649,7 @@ nd6_prefix_onlink(struct nd_prefix *pr)
* Although such a configuration is expected to be rare, we explicitly
* allow it.
*/
- for (opr = V_nd_prefix.lh_first; opr; opr = opr->ndpr_next) {
+ LIST_FOREACH(opr, &V_nd_prefix, ndpr_entry) {
if (opr == pr)
continue;
@@ -1603,14 +1670,14 @@ nd6_prefix_onlink(struct nd_prefix *pr)
IN6_IFF_NOTREADY | IN6_IFF_ANYCAST);
if (ifa == NULL) {
/* XXX: freebsd does not have ifa_ifwithaf */
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family == AF_INET6)
break;
}
if (ifa != NULL)
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
/* should we care about ia6_flags? */
}
if (ifa == NULL) {
@@ -1628,64 +1695,24 @@ nd6_prefix_onlink(struct nd_prefix *pr)
return (0);
}
- /*
- * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
- * ifa->ifa_rtrequest = nd6_rtrequest;
- */
- bzero(&mask6, sizeof(mask6));
- mask6.sin6_len = sizeof(mask6);
- mask6.sin6_addr = pr->ndpr_mask;
- rtflags = (ifa->ifa_flags & ~IFA_RTSELF) | RTF_UP;
- error = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
- ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt);
- if (error == 0) {
- if (rt != NULL) /* this should be non NULL, though */ {
- rnh = rt_tables_get_rnh(rt->rt_fibnum, AF_INET6);
- /* XXX what if rhn == NULL? */
- RADIX_NODE_HEAD_LOCK(rnh);
- RT_LOCK(rt);
- if (!rt_setgate(rt, rt_key(rt), (struct sockaddr *)&null_sdl)) {
- ((struct sockaddr_dl *)rt->rt_gateway)->sdl_type =
- rt->rt_ifp->if_type;
- ((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
- rt->rt_ifp->if_index;
- }
- RADIX_NODE_HEAD_UNLOCK(rnh);
- nd6_rtmsg(RTM_ADD, rt);
- RT_UNLOCK(rt);
- }
- pr->ndpr_stateflags |= NDPRF_ONLINK;
- } else {
- char ip6bufg[INET6_ADDRSTRLEN], ip6bufm[INET6_ADDRSTRLEN];
- nd6log((LOG_ERR, "nd6_prefix_onlink: failed to add route for a"
- " prefix (%s/%d) on %s, gw=%s, mask=%s, flags=%lx "
- "errno = %d\n",
- ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
- pr->ndpr_plen, if_name(ifp),
- ip6_sprintf(ip6bufg, &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr),
- ip6_sprintf(ip6bufm, &mask6.sin6_addr), rtflags, error));
- }
+ error = nd6_prefix_onlink_rtrequest(pr, ifa);
- if (rt != NULL) {
- RT_LOCK(rt);
- RT_REMREF(rt);
- RT_UNLOCK(rt);
- }
if (ifa != NULL)
ifa_free(ifa);
return (error);
}
-int
+static int
nd6_prefix_offlink(struct nd_prefix *pr)
{
int error = 0;
struct ifnet *ifp = pr->ndpr_ifp;
struct nd_prefix *opr;
struct sockaddr_in6 sa6, mask6;
- struct rtentry *rt = NULL;
+ struct rtentry *rt;
char ip6buf[INET6_ADDRSTRLEN];
+ int fibnum, a_failure;
/* sanity check */
if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
@@ -1705,15 +1732,28 @@ nd6_prefix_offlink(struct nd_prefix *pr)
mask6.sin6_family = AF_INET6;
mask6.sin6_len = sizeof(sa6);
bcopy(&pr->ndpr_mask, &mask6.sin6_addr, sizeof(struct in6_addr));
- error = rtrequest(RTM_DELETE, (struct sockaddr *)&sa6, NULL,
- (struct sockaddr *)&mask6, 0, &rt);
+
+ a_failure = 0;
+ for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
+ rt = NULL;
+ error = in6_rtrequest(RTM_DELETE, (struct sockaddr *)&sa6, NULL,
+ (struct sockaddr *)&mask6, 0, &rt, fibnum);
+ if (error == 0) {
+ /* report the route deletion to the routing socket. */
+ if (rt != NULL)
+ nd6_rtmsg(RTM_DELETE, rt);
+ } else {
+ /* Save last error to return, see rtinit(). */
+ a_failure = error;
+ }
+ if (rt != NULL) {
+ RTFREE(rt);
+ }
+ }
+ error = a_failure;
if (error == 0) {
pr->ndpr_stateflags &= ~NDPRF_ONLINK;
- /* report the route deletion to the routing socket. */
- if (rt != NULL)
- nd6_rtmsg(RTM_DELETE, rt);
-
/*
* There might be the same prefix on another interface,
* the prefix which could not be on-link just because we have
@@ -1721,7 +1761,7 @@ nd6_prefix_offlink(struct nd_prefix *pr)
* If there's one, try to make the prefix on-link on the
* interface.
*/
- for (opr = V_nd_prefix.lh_first; opr; opr = opr->ndpr_next) {
+ LIST_FOREACH(opr, &V_nd_prefix, ndpr_entry) {
if (opr == pr)
continue;
@@ -1761,10 +1801,6 @@ nd6_prefix_offlink(struct nd_prefix *pr)
if_name(ifp), error));
}
- if (rt != NULL) {
- RTFREE(rt);
- }
-
return (error);
}
@@ -2081,6 +2117,7 @@ void
rt6_flush(struct in6_addr *gateway, struct ifnet *ifp)
{
struct radix_node_head *rnh;
+ u_int fibnum;
int s = splnet();
/* We'll care only link-local addresses */
@@ -2089,13 +2126,16 @@ rt6_flush(struct in6_addr *gateway, struct ifnet *ifp)
return;
}
- rnh = rt_tables_get_rnh(0, AF_INET6);
- if (rnh == NULL)
- return;
+ /* XXX Do we really need to walk any but the default FIB? */
+ for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
+ rnh = rt_tables_get_rnh(fibnum, AF_INET6);
+ if (rnh == NULL)
+ continue;
- RADIX_NODE_HEAD_LOCK(rnh);
- rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway);
- RADIX_NODE_HEAD_UNLOCK(rnh);
+ RADIX_NODE_HEAD_LOCK(rnh);
+ rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway);
+ RADIX_NODE_HEAD_UNLOCK(rnh);
+ }
splx(s);
}
@@ -2128,8 +2168,8 @@ rt6_deleteroute(struct radix_node *rn, void *arg)
if ((rt->rt_flags & RTF_HOST) == 0)
return (0);
- return (rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
- rt_mask(rt), rt->rt_flags, 0));
+ return (in6_rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
+ rt_mask(rt), rt->rt_flags, NULL, rt->rt_fibnum));
#undef SIN6
}