summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/net/rtsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/net/rtsock.c')
-rw-r--r--freebsd/sys/net/rtsock.c342
1 files changed, 277 insertions, 65 deletions
diff --git a/freebsd/sys/net/rtsock.c b/freebsd/sys/net/rtsock.c
index bfdecf87..beca84da 100644
--- a/freebsd/sys/net/rtsock.c
+++ b/freebsd/sys/net/rtsock.c
@@ -116,7 +116,34 @@ struct if_msghdr32 {
uint16_t ifm_index;
struct if_data32 ifm_data;
};
-#endif
+
+struct if_msghdrl32 {
+ uint16_t ifm_msglen;
+ uint8_t ifm_version;
+ uint8_t ifm_type;
+ int32_t ifm_addrs;
+ int32_t ifm_flags;
+ uint16_t ifm_index;
+ uint16_t _ifm_spare1;
+ uint16_t ifm_len;
+ uint16_t ifm_data_off;
+ struct if_data32 ifm_data;
+};
+
+struct ifa_msghdrl32 {
+ uint16_t ifam_msglen;
+ uint8_t ifam_version;
+ uint8_t ifam_type;
+ int32_t ifam_addrs;
+ int32_t ifam_flags;
+ uint16_t ifam_index;
+ uint16_t _ifam_spare1;
+ uint16_t ifam_len;
+ uint16_t ifam_data_off;
+ int32_t ifam_metric;
+ struct if_data32 ifam_data;
+};
+#endif /* COMPAT_FREEBSD32 */
MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
@@ -124,6 +151,13 @@ MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
static struct sockaddr route_src = { 2, PF_ROUTE, };
static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, };
+/*
+ * Used by rtsock/raw_input callback code to decide whether to filter the update
+ * notification to a socket bound to a particular FIB.
+ */
+#define RTS_FILTER_FIB M_PROTO8
+#define RTS_ALLFIBS -1
+
static struct {
int ip_count; /* attached w/ AF_INET */
int ip6_count; /* attached w/ AF_INET6 */
@@ -161,7 +195,7 @@ static void rt_setmetrics(u_long which, const struct rt_metrics *in,
struct rt_metrics_lite *out);
static void rt_getmetrics(const struct rt_metrics_lite *in,
struct rt_metrics *out);
-static void rt_dispatch(struct mbuf *, const struct sockaddr *);
+static void rt_dispatch(struct mbuf *, sa_family_t);
static struct netisr_handler rtsock_nh = {
.nh_name = "rtsock",
@@ -200,6 +234,31 @@ rts_init(void)
}
SYSINIT(rtsock, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, rts_init, 0);
+static int
+raw_input_rts_cb(struct mbuf *m, struct sockproto *proto, struct sockaddr *src,
+ struct rawcb *rp)
+{
+ int fibnum;
+
+ KASSERT(m != NULL, ("%s: m is NULL", __func__));
+ KASSERT(proto != NULL, ("%s: proto is NULL", __func__));
+ KASSERT(rp != NULL, ("%s: rp is NULL", __func__));
+
+ /* No filtering requested. */
+ if ((m->m_flags & RTS_FILTER_FIB) == 0)
+ return (0);
+
+ /* Check if it is a rts and the fib matches the one of the socket. */
+ fibnum = M_GETFIB(m);
+ if (proto->sp_family != PF_ROUTE ||
+ rp->rcb_socket == NULL ||
+ rp->rcb_socket->so_fibnum == fibnum)
+ return (0);
+
+ /* Filtering requested and no match, the socket shall be skipped. */
+ return (1);
+}
+
static void
rts_input(struct mbuf *m)
{
@@ -216,7 +275,7 @@ rts_input(struct mbuf *m)
} else
route_proto.sp_protocol = 0;
- raw_input(m, &route_proto, &route_src);
+ raw_input_ext(m, &route_proto, &route_src, raw_input_rts_cb);
}
/*
@@ -428,7 +487,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp,
* Try to find an address on the given outgoing interface
* that belongs to the jail.
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct sockaddr *sa;
sa = ifa->ifa_addr;
@@ -440,7 +499,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp,
break;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (!found) {
/*
* As a last resort return the 'default' jail address.
@@ -470,7 +529,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp,
* Try to find an address on the given outgoing interface
* that belongs to the jail.
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct sockaddr *sa;
sa = ifa->ifa_addr;
@@ -483,7 +542,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp,
break;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (!found) {
/*
* As a last resort return the 'default' jail address.
@@ -521,6 +580,7 @@ route_output(struct mbuf *m, struct socket *so)
int len, error = 0;
struct ifnet *ifp = NULL;
union sockaddr_union saun;
+ sa_family_t saf = AF_UNSPEC;
#define senderr(e) { error = e; goto flush;}
if (m == NULL || ((m->m_len < sizeof(long)) &&
@@ -561,6 +621,7 @@ route_output(struct mbuf *m, struct socket *so)
(info.rti_info[RTAX_GATEWAY] != NULL &&
info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX))
senderr(EINVAL);
+ saf = info.rti_info[RTAX_DST]->sa_family;
/*
* Verify that the caller has the appropriate privilege; RTM_GET
* is the only operation the non-superuser is allowed.
@@ -898,6 +959,8 @@ flush:
Free(rtm);
}
if (m) {
+ M_SETFIB(m, so->so_fibnum);
+ m->m_flags |= RTS_FILTER_FIB;
if (rp) {
/*
* XXX insure we don't get a copy by
@@ -905,10 +968,10 @@ flush:
*/
unsigned short family = rp->rcb_proto.sp_family;
rp->rcb_proto.sp_family = 0;
- rt_dispatch(m, info.rti_info[RTAX_DST]);
+ rt_dispatch(m, saf);
rp->rcb_proto.sp_family = family;
} else
- rt_dispatch(m, info.rti_info[RTAX_DST]);
+ rt_dispatch(m, saf);
}
}
return (error);
@@ -984,6 +1047,9 @@ rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
return (0);
}
+/*
+ * Used by the routing socket.
+ */
static struct mbuf *
rt_msg1(int type, struct rt_addrinfo *rtinfo)
{
@@ -1051,6 +1117,9 @@ rt_msg1(int type, struct rt_addrinfo *rtinfo)
return (m);
}
+/*
+ * Used by the sysctl code and routing socket.
+ */
static int
rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w)
{
@@ -1064,17 +1133,31 @@ again:
case RTM_DELADDR:
case RTM_NEWADDR:
- len = sizeof(struct ifa_msghdr);
+ if (w != NULL && w->w_op == NET_RT_IFLISTL) {
+#ifdef COMPAT_FREEBSD32
+ if (w->w_req->flags & SCTL_MASK32)
+ len = sizeof(struct ifa_msghdrl32);
+ else
+#endif
+ len = sizeof(struct ifa_msghdrl);
+ } else
+ len = sizeof(struct ifa_msghdr);
break;
case RTM_IFINFO:
#ifdef COMPAT_FREEBSD32
if (w != NULL && w->w_req->flags & SCTL_MASK32) {
- len = sizeof(struct if_msghdr32);
+ if (w->w_op == NET_RT_IFLISTL)
+ len = sizeof(struct if_msghdrl32);
+ else
+ len = sizeof(struct if_msghdr32);
break;
}
#endif
- len = sizeof(struct if_msghdr);
+ if (w != NULL && w->w_op == NET_RT_IFLISTL)
+ len = sizeof(struct if_msghdrl);
+ else
+ len = sizeof(struct if_msghdr);
break;
case RTM_NEWMADDR:
@@ -1137,7 +1220,8 @@ again:
* destination.
*/
void
-rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
+rt_missmsg_fib(int type, struct rt_addrinfo *rtinfo, int flags, int error,
+ int fibnum)
{
struct rt_msghdr *rtm;
struct mbuf *m;
@@ -1148,11 +1232,26 @@ rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
m = rt_msg1(type, rtinfo);
if (m == NULL)
return;
+
+ if (fibnum != RTS_ALLFIBS) {
+ KASSERT(fibnum >= 0 && fibnum < rt_numfibs, ("%s: fibnum out "
+ "of range 0 <= %d < %d", __func__, fibnum, rt_numfibs));
+ M_SETFIB(m, fibnum);
+ m->m_flags |= RTS_FILTER_FIB;
+ }
+
rtm = mtod(m, struct rt_msghdr *);
rtm->rtm_flags = RTF_DONE | flags;
rtm->rtm_errno = error;
rtm->rtm_addrs = rtinfo->rti_addrs;
- rt_dispatch(m, sa);
+ rt_dispatch(m, sa ? sa->sa_family : AF_UNSPEC);
+}
+
+void
+rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
+{
+
+ rt_missmsg_fib(type, rtinfo, flags, error, RTS_ALLFIBS);
}
/*
@@ -1177,7 +1276,7 @@ rt_ifmsg(struct ifnet *ifp)
ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
ifm->ifm_data = ifp->if_data;
ifm->ifm_addrs = 0;
- rt_dispatch(m, NULL);
+ rt_dispatch(m, AF_UNSPEC);
}
/*
@@ -1189,7 +1288,8 @@ rt_ifmsg(struct ifnet *ifp)
* copies of it.
*/
void
-rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
+rt_newaddrmsg_fib(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt,
+ int fibnum)
{
struct rt_addrinfo info;
struct sockaddr *sa = NULL;
@@ -1247,10 +1347,24 @@ rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
rtm->rtm_errno = error;
rtm->rtm_addrs = info.rti_addrs;
}
- rt_dispatch(m, sa);
+ if (fibnum != RTS_ALLFIBS) {
+ KASSERT(fibnum >= 0 && fibnum < rt_numfibs, ("%s: "
+ "fibnum out of range 0 <= %d < %d", __func__,
+ fibnum, rt_numfibs));
+ M_SETFIB(m, fibnum);
+ m->m_flags |= RTS_FILTER_FIB;
+ }
+ rt_dispatch(m, sa ? sa->sa_family : AF_UNSPEC);
}
}
+void
+rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
+{
+
+ rt_newaddrmsg_fib(cmd, ifa, error, rt, RTS_ALLFIBS);
+}
+
/*
* This is the analogue to the rt_newaddrmsg which performs the same
* function but for multicast group memberhips. This is easier since
@@ -1283,7 +1397,7 @@ rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
__func__));
ifmam->ifmam_index = ifp->if_index;
ifmam->ifmam_addrs = info.rti_addrs;
- rt_dispatch(m, ifma->ifma_addr);
+ rt_dispatch(m, ifma->ifma_addr ? ifma->ifma_addr->sa_family : AF_UNSPEC);
}
static struct mbuf *
@@ -1343,7 +1457,7 @@ rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len)
if (m->m_flags & M_PKTHDR)
m->m_pkthdr.len += data_len;
mtod(m, struct if_announcemsghdr *)->ifan_msglen += data_len;
- rt_dispatch(m, NULL);
+ rt_dispatch(m, AF_UNSPEC);
}
}
@@ -1359,11 +1473,11 @@ rt_ifannouncemsg(struct ifnet *ifp, int what)
m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info);
if (m != NULL)
- rt_dispatch(m, NULL);
+ rt_dispatch(m, AF_UNSPEC);
}
static void
-rt_dispatch(struct mbuf *m, const struct sockaddr *sa)
+rt_dispatch(struct mbuf *m, sa_family_t saf)
{
struct m_tag *tag;
@@ -1372,14 +1486,14 @@ rt_dispatch(struct mbuf *m, const struct sockaddr *sa)
* use when injecting the mbuf into the routing socket buffer from
* the netisr.
*/
- if (sa != NULL) {
+ if (saf != AF_UNSPEC) {
tag = m_tag_get(PACKET_TAG_RTSOCKFAM, sizeof(unsigned short),
M_NOWAIT);
if (tag == NULL) {
m_freem(m);
return;
}
- *(unsigned short *)(tag + 1) = sa->sa_family;
+ *(unsigned short *)(tag + 1) = saf;
m_tag_prepend(m, tag);
}
#ifdef VIMAGE
@@ -1473,6 +1587,127 @@ copy_ifdata32(struct if_data *src, struct if_data32 *dst)
#endif
static int
+sysctl_iflist_ifml(struct ifnet *ifp, struct rt_addrinfo *info,
+ struct walkarg *w, int len)
+{
+ struct if_msghdrl *ifm;
+
+#ifdef COMPAT_FREEBSD32
+ if (w->w_req->flags & SCTL_MASK32) {
+ struct if_msghdrl32 *ifm32;
+
+ ifm32 = (struct if_msghdrl32 *)w->w_tmem;
+ ifm32->ifm_addrs = info->rti_addrs;
+ ifm32->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+ ifm32->ifm_index = ifp->if_index;
+ ifm32->_ifm_spare1 = 0;
+ ifm32->ifm_len = sizeof(*ifm32);
+ ifm32->ifm_data_off = offsetof(struct if_msghdrl32, ifm_data);
+
+ copy_ifdata32(&ifp->if_data, &ifm32->ifm_data);
+
+ return (SYSCTL_OUT(w->w_req, (caddr_t)ifm32, len));
+ }
+#endif
+ ifm = (struct if_msghdrl *)w->w_tmem;
+ ifm->ifm_addrs = info->rti_addrs;
+ ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+ ifm->ifm_index = ifp->if_index;
+ ifm->_ifm_spare1 = 0;
+ ifm->ifm_len = sizeof(*ifm);
+ ifm->ifm_data_off = offsetof(struct if_msghdrl, ifm_data);
+
+ ifm->ifm_data = ifp->if_data;
+
+ return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len));
+}
+
+static int
+sysctl_iflist_ifm(struct ifnet *ifp, struct rt_addrinfo *info,
+ struct walkarg *w, int len)
+{
+ struct if_msghdr *ifm;
+
+#ifdef COMPAT_FREEBSD32
+ if (w->w_req->flags & SCTL_MASK32) {
+ struct if_msghdr32 *ifm32;
+
+ ifm32 = (struct if_msghdr32 *)w->w_tmem;
+ ifm32->ifm_addrs = info->rti_addrs;
+ ifm32->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+ ifm32->ifm_index = ifp->if_index;
+
+ copy_ifdata32(&ifp->if_data, &ifm32->ifm_data);
+
+ return (SYSCTL_OUT(w->w_req, (caddr_t)ifm32, len));
+ }
+#endif
+ ifm = (struct if_msghdr *)w->w_tmem;
+ ifm->ifm_addrs = info->rti_addrs;
+ ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+ ifm->ifm_index = ifp->if_index;
+
+ ifm->ifm_data = ifp->if_data;
+
+ return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len));
+}
+
+static int
+sysctl_iflist_ifaml(struct ifaddr *ifa, struct rt_addrinfo *info,
+ struct walkarg *w, int len)
+{
+ struct ifa_msghdrl *ifam;
+
+#ifdef COMPAT_FREEBSD32
+ if (w->w_req->flags & SCTL_MASK32) {
+ struct ifa_msghdrl32 *ifam32;
+
+ ifam32 = (struct ifa_msghdrl32 *)w->w_tmem;
+ ifam32->ifam_addrs = info->rti_addrs;
+ ifam32->ifam_flags = ifa->ifa_flags;
+ ifam32->ifam_index = ifa->ifa_ifp->if_index;
+ ifam32->_ifam_spare1 = 0;
+ ifam32->ifam_len = sizeof(*ifam32);
+ ifam32->ifam_data_off =
+ offsetof(struct ifa_msghdrl32, ifam_data);
+ ifam32->ifam_metric = ifa->ifa_metric;
+
+ copy_ifdata32(&ifa->ifa_ifp->if_data, &ifam32->ifam_data);
+
+ return (SYSCTL_OUT(w->w_req, (caddr_t)ifam32, len));
+ }
+#endif
+
+ ifam = (struct ifa_msghdrl *)w->w_tmem;
+ ifam->ifam_addrs = info->rti_addrs;
+ ifam->ifam_flags = ifa->ifa_flags;
+ ifam->ifam_index = ifa->ifa_ifp->if_index;
+ ifam->_ifam_spare1 = 0;
+ ifam->ifam_len = sizeof(*ifam);
+ ifam->ifam_data_off = offsetof(struct ifa_msghdrl, ifam_data);
+ ifam->ifam_metric = ifa->ifa_metric;
+
+ ifam->ifam_data = ifa->if_data;
+
+ return (SYSCTL_OUT(w->w_req, w->w_tmem, len));
+}
+
+static int
+sysctl_iflist_ifam(struct ifaddr *ifa, struct rt_addrinfo *info,
+ struct walkarg *w, int len)
+{
+ struct ifa_msghdr *ifam;
+
+ ifam = (struct ifa_msghdr *)w->w_tmem;
+ ifam->ifam_addrs = info->rti_addrs;
+ ifam->ifam_flags = ifa->ifa_flags;
+ ifam->ifam_index = ifa->ifa_ifp->if_index;
+ ifam->ifam_metric = ifa->ifa_metric;
+
+ return (SYSCTL_OUT(w->w_req, w->w_tmem, len));
+}
+
+static int
sysctl_iflist(int af, struct walkarg *w)
{
struct ifnet *ifp;
@@ -1485,38 +1720,16 @@ sysctl_iflist(int af, struct walkarg *w)
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (w->w_arg && w->w_arg != ifp->if_index)
continue;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
ifa = ifp->if_addr;
info.rti_info[RTAX_IFP] = ifa->ifa_addr;
len = rt_msg2(RTM_IFINFO, &info, NULL, w);
info.rti_info[RTAX_IFP] = NULL;
if (w->w_req && w->w_tmem) {
- struct if_msghdr *ifm;
-
-#ifdef COMPAT_FREEBSD32
- if (w->w_req->flags & SCTL_MASK32) {
- struct if_msghdr32 *ifm32;
-
- ifm32 = (struct if_msghdr32 *)w->w_tmem;
- ifm32->ifm_index = ifp->if_index;
- ifm32->ifm_flags = ifp->if_flags |
- ifp->if_drv_flags;
- copy_ifdata32(&ifp->if_data, &ifm32->ifm_data);
- ifm32->ifm_addrs = info.rti_addrs;
- error = SYSCTL_OUT(w->w_req, (caddr_t)ifm32,
- len);
- goto sysctl_out;
- }
-#endif
- ifm = (struct if_msghdr *)w->w_tmem;
- ifm->ifm_index = ifp->if_index;
- ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
- ifm->ifm_data = ifp->if_data;
- ifm->ifm_addrs = info.rti_addrs;
- error = SYSCTL_OUT(w->w_req, (caddr_t)ifm, len);
-#ifdef COMPAT_FREEBSD32
- sysctl_out:
-#endif
+ if (w->w_op == NET_RT_IFLISTL)
+ error = sysctl_iflist_ifml(ifp, &info, w, len);
+ else
+ error = sysctl_iflist_ifm(ifp, &info, w, len);
if (error)
goto done;
}
@@ -1531,25 +1744,23 @@ sysctl_iflist(int af, struct walkarg *w)
info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
len = rt_msg2(RTM_NEWADDR, &info, NULL, w);
if (w->w_req && w->w_tmem) {
- struct ifa_msghdr *ifam;
-
- ifam = (struct ifa_msghdr *)w->w_tmem;
- ifam->ifam_index = ifa->ifa_ifp->if_index;
- ifam->ifam_flags = ifa->ifa_flags;
- ifam->ifam_metric = ifa->ifa_metric;
- ifam->ifam_addrs = info.rti_addrs;
- error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
+ if (w->w_op == NET_RT_IFLISTL)
+ error = sysctl_iflist_ifaml(ifa, &info,
+ w, len);
+ else
+ error = sysctl_iflist_ifam(ifa, &info,
+ w, len);
if (error)
goto done;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
info.rti_info[RTAX_BRD] = NULL;
}
done:
if (ifp != NULL)
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
IFNET_RUNLOCK();
return (error);
}
@@ -1570,7 +1781,7 @@ sysctl_ifmalist(int af, struct walkarg *w)
continue;
ifa = ifp->if_addr;
info.rti_info[RTAX_IFP] = ifa ? ifa->ifa_addr : NULL;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (af && af != ifma->ifma_addr->sa_family)
continue;
@@ -1591,12 +1802,12 @@ sysctl_ifmalist(int af, struct walkarg *w)
ifmam->ifmam_addrs = info.rti_addrs;
error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
if (error) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto done;
}
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
}
done:
IFNET_RUNLOCK();
@@ -1662,16 +1873,17 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS)
rnh = rt_tables_get_rnh(BSD_DEFAULT_FIB, i);
#endif /* __rtems__ */
if (rnh != NULL) {
- RADIX_NODE_HEAD_LOCK(rnh);
+ RADIX_NODE_HEAD_RLOCK(rnh);
error = rnh->rnh_walktree(rnh,
sysctl_dumpentry, &w);
- RADIX_NODE_HEAD_UNLOCK(rnh);
+ RADIX_NODE_HEAD_RUNLOCK(rnh);
} else if (af != 0)
error = EAFNOSUPPORT;
}
break;
case NET_RT_IFLIST:
+ case NET_RT_IFLISTL:
error = sysctl_iflist(af, &w);
break;