Changeset View
Changeset View
Standalone View
Standalone View
sys/net/rtsock.c
Show All 26 Lines | |||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
* | * | ||||
* @(#)rtsock.c 8.7 (Berkeley) 10/12/95 | * @(#)rtsock.c 8.7 (Berkeley) 10/12/95 | ||||
* $FreeBSD$ | * $FreeBSD$ | ||||
*/ | */ | ||||
#include "opt_ddb.h" | #include "opt_ddb.h" | ||||
#include "opt_mpath.h" | #include "opt_route.h" | ||||
#include "opt_inet.h" | #include "opt_inet.h" | ||||
#include "opt_inet6.h" | #include "opt_inet6.h" | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/jail.h> | #include <sys/jail.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/domain.h> | #include <sys/domain.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | |||||
struct mtx rtsock_mtx; | struct mtx rtsock_mtx; | ||||
MTX_SYSINIT(rtsock, &rtsock_mtx, "rtsock route_cb lock", MTX_DEF); | MTX_SYSINIT(rtsock, &rtsock_mtx, "rtsock route_cb lock", MTX_DEF); | ||||
#define RTSOCK_LOCK() mtx_lock(&rtsock_mtx) | #define RTSOCK_LOCK() mtx_lock(&rtsock_mtx) | ||||
#define RTSOCK_UNLOCK() mtx_unlock(&rtsock_mtx) | #define RTSOCK_UNLOCK() mtx_unlock(&rtsock_mtx) | ||||
#define RTSOCK_LOCK_ASSERT() mtx_assert(&rtsock_mtx, MA_OWNED) | #define RTSOCK_LOCK_ASSERT() mtx_assert(&rtsock_mtx, MA_OWNED) | ||||
static SYSCTL_NODE(_net, OID_AUTO, route, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | SYSCTL_NODE(_net, OID_AUTO, route, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, ""); | ||||
""); | |||||
struct walkarg { | struct walkarg { | ||||
int w_tmemsize; | int w_tmemsize; | ||||
int w_op, w_arg; | int w_op, w_arg; | ||||
caddr_t w_tmem; | caddr_t w_tmem; | ||||
struct sysctl_req *w_req; | struct sysctl_req *w_req; | ||||
}; | }; | ||||
static void rts_input(struct mbuf *m); | static void rts_input(struct mbuf *m); | ||||
static struct mbuf *rtsock_msg_mbuf(int type, struct rt_addrinfo *rtinfo); | static struct mbuf *rtsock_msg_mbuf(int type, struct rt_addrinfo *rtinfo); | ||||
static int rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, | static int rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, | ||||
struct walkarg *w, int *plen); | struct walkarg *w, int *plen); | ||||
static int rt_xaddrs(caddr_t cp, caddr_t cplim, | static int rt_xaddrs(caddr_t cp, caddr_t cplim, | ||||
struct rt_addrinfo *rtinfo); | struct rt_addrinfo *rtinfo); | ||||
static int sysctl_dumpentry(struct radix_node *rn, void *vw); | static int sysctl_dumpentry(struct radix_node *rn, void *vw); | ||||
static int sysctl_dumpnhop(struct rtentry *rt, struct nhop_object *nh, | |||||
uint32_t weight, struct walkarg *w); | |||||
static int sysctl_iflist(int af, struct walkarg *w); | static int sysctl_iflist(int af, struct walkarg *w); | ||||
static int sysctl_ifmalist(int af, struct walkarg *w); | static int sysctl_ifmalist(int af, struct walkarg *w); | ||||
static int route_output(struct mbuf *m, struct socket *so, ...); | static int route_output(struct mbuf *m, struct socket *so, ...); | ||||
static void rt_getmetrics(const struct rtentry *rt, | static void rt_getmetrics(const struct rtentry *rt, | ||||
const struct nhop_object *nh, struct rt_metrics *out); | const struct nhop_object *nh, struct rt_metrics *out); | ||||
static void rt_dispatch(struct mbuf *, sa_family_t); | static void rt_dispatch(struct mbuf *, sa_family_t); | ||||
static int handle_rtm_get(struct rt_addrinfo *info, u_int fibnum, | static int handle_rtm_get(struct rt_addrinfo *info, u_int fibnum, | ||||
struct rt_msghdr *rtm, struct rib_cmd_info *rc); | struct rt_msghdr *rtm, struct rib_cmd_info *rc); | ||||
▲ Show 20 Lines • Show All 457 Lines • ▼ Show 20 Lines | if (rib_lookup_info(fibnum, gdst, NHR_REF, 0, &ginfo) == 0) { | ||||
} | } | ||||
rib_free_info(&ginfo); | rib_free_info(&ginfo); | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static struct nhop_object * | |||||
select_nhop(struct nhop_object *nh, const struct sockaddr *gw) | |||||
{ | |||||
if (!NH_IS_NHGRP(nh)) | |||||
return (nh); | |||||
#ifdef ROUTE_MPATH | |||||
struct weightened_nhop *wn; | |||||
uint32_t num_nhops; | |||||
wn = nhgrp_get_nhops((struct nhgrp_object *)nh, &num_nhops); | |||||
if (gw == NULL) | |||||
return (wn[0].nh); | |||||
for (int i = 0; i < num_nhops; i++) { | |||||
if (match_nhop_gw(wn[i].nh, gw)) | |||||
return (wn[i].nh); | |||||
} | |||||
#endif | |||||
return (NULL); | |||||
} | |||||
/* | /* | ||||
* Handles RTM_GET message from routing socket, returning matching rt. | * Handles RTM_GET message from routing socket, returning matching rt. | ||||
* | * | ||||
* Returns: | * Returns: | ||||
* 0 on success, with locked and referenced matching rt in @rt_nrt | * 0 on success, with locked and referenced matching rt in @rt_nrt | ||||
* errno of failure | * errno of failure | ||||
*/ | */ | ||||
static int | static int | ||||
handle_rtm_get(struct rt_addrinfo *info, u_int fibnum, | handle_rtm_get(struct rt_addrinfo *info, u_int fibnum, | ||||
struct rt_msghdr *rtm, struct rib_cmd_info *rc) | struct rt_msghdr *rtm, struct rib_cmd_info *rc) | ||||
{ | { | ||||
RIB_RLOCK_TRACKER; | RIB_RLOCK_TRACKER; | ||||
struct rib_head *rnh; | struct rib_head *rnh; | ||||
struct nhop_object *nh; | |||||
sa_family_t saf; | sa_family_t saf; | ||||
saf = info->rti_info[RTAX_DST]->sa_family; | saf = info->rti_info[RTAX_DST]->sa_family; | ||||
rnh = rt_tables_get_rnh(fibnum, saf); | rnh = rt_tables_get_rnh(fibnum, saf); | ||||
if (rnh == NULL) | if (rnh == NULL) | ||||
return (EAFNOSUPPORT); | return (EAFNOSUPPORT); | ||||
Show All 11 Lines | if (info->rti_info[RTAX_NETMASK] == NULL) { | ||||
rc->rc_rt = (struct rtentry *) rnh->rnh_lookup( | rc->rc_rt = (struct rtentry *) rnh->rnh_lookup( | ||||
info->rti_info[RTAX_DST], | info->rti_info[RTAX_DST], | ||||
info->rti_info[RTAX_NETMASK], &rnh->head); | info->rti_info[RTAX_NETMASK], &rnh->head); | ||||
if (rc->rc_rt == NULL) { | if (rc->rc_rt == NULL) { | ||||
RIB_RUNLOCK(rnh); | RIB_RUNLOCK(rnh); | ||||
return (ESRCH); | return (ESRCH); | ||||
} | } | ||||
#ifdef RADIX_MPATH | |||||
/* | nh = select_nhop(rc->rc_rt->rt_nhop, info->rti_info[RTAX_GATEWAY]); | ||||
* for RTM_GET, gate is optional even with multipath. | if (nh == NULL) { | ||||
* if gate == NULL the first match is returned. | |||||
* (no need to call rt_mpath_matchgate if gate == NULL) | |||||
*/ | |||||
if (rt_mpath_capable(rnh) && info->rti_info[RTAX_GATEWAY]) { | |||||
rc->rc_rt = rt_mpath_matchgate(rc->rc_rt, | |||||
info->rti_info[RTAX_GATEWAY]); | |||||
if (rc->rc_rt == NULL) { | |||||
RIB_RUNLOCK(rnh); | RIB_RUNLOCK(rnh); | ||||
return (ESRCH); | return (ESRCH); | ||||
} | } | ||||
} | |||||
#endif | |||||
/* | /* | ||||
* If performing proxied L2 entry insertion, and | * If performing proxied L2 entry insertion, and | ||||
* the actual PPP host entry is found, perform | * the actual PPP host entry is found, perform | ||||
* another search to retrieve the prefix route of | * another search to retrieve the prefix route of | ||||
* the local end point of the PPP link. | * the local end point of the PPP link. | ||||
* TODO: move this logic to userland. | * TODO: move this logic to userland. | ||||
*/ | */ | ||||
if (rtm->rtm_flags & RTF_ANNOUNCE) { | if (rtm->rtm_flags & RTF_ANNOUNCE) { | ||||
Show All 19 Lines | if (rtm->rtm_flags & RTF_ANNOUNCE) { | ||||
* refactor rt and no lock operation necessary | * refactor rt and no lock operation necessary | ||||
*/ | */ | ||||
rc->rc_rt = (struct rtentry *)rnh->rnh_matchaddr(&laddr, | rc->rc_rt = (struct rtentry *)rnh->rnh_matchaddr(&laddr, | ||||
&rnh->head); | &rnh->head); | ||||
if (rc->rc_rt == NULL) { | if (rc->rc_rt == NULL) { | ||||
RIB_RUNLOCK(rnh); | RIB_RUNLOCK(rnh); | ||||
return (ESRCH); | return (ESRCH); | ||||
} | } | ||||
nh = select_nhop(rc->rc_rt->rt_nhop, info->rti_info[RTAX_GATEWAY]); | |||||
if (nh == NULL) { | |||||
RIB_RUNLOCK(rnh); | |||||
return (ESRCH); | |||||
} | } | ||||
rc->rc_nh_new = rc->rc_rt->rt_nhop; | } | ||||
rc->rc_nh_new = nh; | |||||
rc->rc_nh_weight = rc->rc_rt->rt_weight; | |||||
RIB_RUNLOCK(rnh); | RIB_RUNLOCK(rnh); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Update sockaddrs, flags, etc in @prtm based on @rc data. | * Update sockaddrs, flags, etc in @prtm based on @rc data. | ||||
* rtm can be reallocated. | * rtm can be reallocated. | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | update_rtm_from_rc(struct rt_addrinfo *info, struct rt_msghdr **prtm, | ||||
if (orig_rtm != NULL) | if (orig_rtm != NULL) | ||||
free(orig_rtm, M_TEMP); | free(orig_rtm, M_TEMP); | ||||
*prtm = rtm; | *prtm = rtm; | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | |||||
save_del_notification(struct rib_cmd_info *rc, void *_cbdata) | |||||
{ | |||||
struct rib_cmd_info *rc_new = (struct rib_cmd_info *)_cbdata; | |||||
if (rc->rc_cmd == RTM_DELETE) | |||||
*rc_new = *rc; | |||||
} | |||||
static void | |||||
save_add_notification(struct rib_cmd_info *rc, void *_cbdata) | |||||
{ | |||||
struct rib_cmd_info *rc_new = (struct rib_cmd_info *)_cbdata; | |||||
if (rc->rc_cmd == RTM_ADD) | |||||
*rc_new = *rc; | |||||
} | |||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
static int | static int | ||||
route_output(struct mbuf *m, struct socket *so, ...) | route_output(struct mbuf *m, struct socket *so, ...) | ||||
{ | { | ||||
struct rt_msghdr *rtm = NULL; | struct rt_msghdr *rtm = NULL; | ||||
struct rtentry *rt = NULL; | struct rtentry *rt = NULL; | ||||
struct rt_addrinfo info; | struct rt_addrinfo info; | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | if (rtm->rtm_type == RTM_ADD) { | ||||
if (info.rti_info[RTAX_GATEWAY] == NULL) | if (info.rti_info[RTAX_GATEWAY] == NULL) | ||||
senderr(EINVAL); | senderr(EINVAL); | ||||
} | } | ||||
error = rib_action(fibnum, rtm->rtm_type, &info, &rc); | error = rib_action(fibnum, rtm->rtm_type, &info, &rc); | ||||
if (error == 0) { | if (error == 0) { | ||||
#ifdef INET6 | #ifdef INET6 | ||||
rti_need_deembed = 1; | rti_need_deembed = 1; | ||||
#endif | #endif | ||||
#ifdef ROUTE_MPATH | |||||
if (NH_IS_NHGRP(rc.rc_nh_new) || | |||||
(rc.rc_nh_old && NH_IS_NHGRP(rc.rc_nh_old))) { | |||||
struct rib_cmd_info rc_simple = {}; | |||||
rib_decompose_notification(&rc, | |||||
save_add_notification, (void *)&rc_simple); | |||||
rc = rc_simple; | |||||
} | |||||
#endif | |||||
nh = rc.rc_nh_new; | nh = rc.rc_nh_new; | ||||
rtm->rtm_index = nh->nh_ifp->if_index; | rtm->rtm_index = nh->nh_ifp->if_index; | ||||
} | } | ||||
break; | break; | ||||
case RTM_DELETE: | case RTM_DELETE: | ||||
error = rib_action(fibnum, RTM_DELETE, &info, &rc); | error = rib_action(fibnum, RTM_DELETE, &info, &rc); | ||||
if (error == 0) { | if (error == 0) { | ||||
#ifdef ROUTE_MPATH | |||||
if (NH_IS_NHGRP(rc.rc_nh_old) || | |||||
(rc.rc_nh_new && NH_IS_NHGRP(rc.rc_nh_new))) { | |||||
struct rib_cmd_info rc_simple = {}; | |||||
rib_decompose_notification(&rc, | |||||
save_del_notification, (void *)&rc_simple); | |||||
rc = rc_simple; | |||||
} | |||||
#endif | |||||
nh = rc.rc_nh_old; | nh = rc.rc_nh_old; | ||||
goto report; | goto report; | ||||
} | } | ||||
#ifdef INET6 | #ifdef INET6 | ||||
/* rt_msg2() will not be used when RTM_DELETE fails. */ | /* rt_msg2() will not be used when RTM_DELETE fails. */ | ||||
rti_need_deembed = 1; | rti_need_deembed = 1; | ||||
#endif | #endif | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 756 Lines • ▼ Show 20 Lines | |||||
* This is used in dumping the kernel table via sysctl(). | * This is used in dumping the kernel table via sysctl(). | ||||
*/ | */ | ||||
static int | static int | ||||
sysctl_dumpentry(struct radix_node *rn, void *vw) | sysctl_dumpentry(struct radix_node *rn, void *vw) | ||||
{ | { | ||||
struct walkarg *w = vw; | struct walkarg *w = vw; | ||||
struct rtentry *rt = (struct rtentry *)rn; | struct rtentry *rt = (struct rtentry *)rn; | ||||
struct nhop_object *nh; | struct nhop_object *nh; | ||||
int error = 0, size; | int error = 0; | ||||
struct rt_addrinfo info; | |||||
struct sockaddr_storage ss; | |||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
if (w->w_op == NET_RT_FLAGS && !(rt->rte_flags & w->w_arg)) | if (w->w_op == NET_RT_FLAGS && !(rt->rte_flags & w->w_arg)) | ||||
return 0; | return 0; | ||||
if (!can_export_rte(w->w_req->td->td_ucred, rt)) | if (!can_export_rte(w->w_req->td->td_ucred, rt)) | ||||
return (0); | return (0); | ||||
nh = rt->rt_nhop; | nh = rt->rt_nhop; | ||||
#ifdef ROUTE_MPATH | |||||
if (NH_IS_NHGRP(nh)) { | |||||
struct weightened_nhop *wn; | |||||
uint32_t num_nhops; | |||||
wn = nhgrp_get_nhops((struct nhgrp_object *)nh, &num_nhops); | |||||
for (int i = 0; i < num_nhops; i++) { | |||||
error = sysctl_dumpnhop(rt, wn[i].nh, wn[i].weight, w); | |||||
if (error != 0) | |||||
return (error); | |||||
} | |||||
} else | |||||
#endif | |||||
error = sysctl_dumpnhop(rt, nh, rt->rt_weight, w); | |||||
return (0); | |||||
} | |||||
static int | |||||
sysctl_dumpnhop(struct rtentry *rt, struct nhop_object *nh, uint32_t weight, | |||||
struct walkarg *w) | |||||
{ | |||||
struct rt_addrinfo info; | |||||
int error = 0, size; | |||||
struct sockaddr_storage ss; | |||||
bzero((caddr_t)&info, sizeof(info)); | bzero((caddr_t)&info, sizeof(info)); | ||||
info.rti_info[RTAX_DST] = rt_key(rt); | info.rti_info[RTAX_DST] = rt_key(rt); | ||||
info.rti_info[RTAX_GATEWAY] = &nh->gw_sa; | info.rti_info[RTAX_GATEWAY] = &nh->gw_sa; | ||||
info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt), | info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt), | ||||
rt_mask(rt), &ss); | rt_mask(rt), &ss); | ||||
info.rti_info[RTAX_GENMASK] = 0; | info.rti_info[RTAX_GENMASK] = 0; | ||||
if (nh->nh_ifp && !(nh->nh_ifp->if_flags & IFF_DYING)) { | if (nh->nh_ifp && !(nh->nh_ifp->if_flags & IFF_DYING)) { | ||||
info.rti_info[RTAX_IFP] = nh->nh_ifp->if_addr->ifa_addr; | info.rti_info[RTAX_IFP] = nh->nh_ifp->if_addr->ifa_addr; | ||||
Show All 10 Lines | bzero(&rtm->rtm_index, | ||||
sizeof(*rtm) - offsetof(struct rt_msghdr, rtm_index)); | sizeof(*rtm) - offsetof(struct rt_msghdr, rtm_index)); | ||||
if (rt->rte_flags & RTF_GWFLAG_COMPAT) | if (rt->rte_flags & RTF_GWFLAG_COMPAT) | ||||
rtm->rtm_flags = RTF_GATEWAY | | rtm->rtm_flags = RTF_GATEWAY | | ||||
(rt->rte_flags & ~RTF_GWFLAG_COMPAT); | (rt->rte_flags & ~RTF_GWFLAG_COMPAT); | ||||
else | else | ||||
rtm->rtm_flags = rt->rte_flags; | rtm->rtm_flags = rt->rte_flags; | ||||
rtm->rtm_flags |= nhop_get_rtflags(nh); | rtm->rtm_flags |= nhop_get_rtflags(nh); | ||||
rt_getmetrics(rt, nh, &rtm->rtm_rmx); | rt_getmetrics(rt, nh, &rtm->rtm_rmx); | ||||
rtm->rtm_rmx.rmx_weight = weight; | |||||
rtm->rtm_index = nh->nh_ifp->if_index; | rtm->rtm_index = nh->nh_ifp->if_index; | ||||
rtm->rtm_addrs = info.rti_addrs; | rtm->rtm_addrs = info.rti_addrs; | ||||
error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size); | error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size); | ||||
return (error); | return (error); | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 264 Lines • ▼ Show 20 Lines | sysctl_rtsock(SYSCTL_HANDLER_ARGS) | ||||
int fib = 0; | int fib = 0; | ||||
u_char af; | u_char af; | ||||
struct walkarg w; | struct walkarg w; | ||||
name ++; | name ++; | ||||
namelen--; | namelen--; | ||||
if (req->newptr) | if (req->newptr) | ||||
return (EPERM); | return (EPERM); | ||||
if (name[1] == NET_RT_DUMP || name[1] == NET_RT_NHOP) { | if (name[1] == NET_RT_DUMP || name[1] == NET_RT_NHOP || name[1] == NET_RT_NHGRP) { | ||||
if (namelen == 3) | if (namelen == 3) | ||||
fib = req->td->td_proc->p_fibnum; | fib = req->td->td_proc->p_fibnum; | ||||
else if (namelen == 4) | else if (namelen == 4) | ||||
fib = (name[3] == RT_ALL_FIBS) ? | fib = (name[3] == RT_ALL_FIBS) ? | ||||
req->td->td_proc->p_fibnum : name[3]; | req->td->td_proc->p_fibnum : name[3]; | ||||
else | else | ||||
return ((namelen < 3) ? EISDIR : ENOTDIR); | return ((namelen < 3) ? EISDIR : ENOTDIR); | ||||
if (fib < 0 || fib >= rt_numfibs) | if (fib < 0 || fib >= rt_numfibs) | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | for (error = 0; error == 0 && i <= lim; i++) { | ||||
error = rnh->rnh_walktree(&rnh->head, | error = rnh->rnh_walktree(&rnh->head, | ||||
sysctl_dumpentry, &w); | sysctl_dumpentry, &w); | ||||
RIB_RUNLOCK(rnh); | RIB_RUNLOCK(rnh); | ||||
} else if (af != 0) | } else if (af != 0) | ||||
error = EAFNOSUPPORT; | error = EAFNOSUPPORT; | ||||
} | } | ||||
break; | break; | ||||
case NET_RT_NHOP: | case NET_RT_NHOP: | ||||
case NET_RT_NHGRP: | |||||
/* Allow dumping one specific af/fib at a time */ | /* Allow dumping one specific af/fib at a time */ | ||||
if (namelen < 4) { | if (namelen < 4) { | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
} | } | ||||
fib = name[3]; | fib = name[3]; | ||||
if (fib < 0 || fib > rt_numfibs) { | if (fib < 0 || fib > rt_numfibs) { | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
} | } | ||||
rnh = rt_tables_get_rnh(fib, af); | rnh = rt_tables_get_rnh(fib, af); | ||||
if (rnh == NULL) { | if (rnh == NULL) { | ||||
error = EAFNOSUPPORT; | error = EAFNOSUPPORT; | ||||
break; | break; | ||||
} | } | ||||
if (w.w_op == NET_RT_NHOP) | if (w.w_op == NET_RT_NHOP) | ||||
error = nhops_dump_sysctl(rnh, w.w_req); | error = nhops_dump_sysctl(rnh, w.w_req); | ||||
else | |||||
#ifdef ROUTE_MPATH | |||||
error = nhgrp_dump_sysctl(rnh, w.w_req); | |||||
#else | |||||
error = ENOTSUP; | |||||
#endif | |||||
break; | break; | ||||
case NET_RT_IFLIST: | case NET_RT_IFLIST: | ||||
case NET_RT_IFLISTL: | case NET_RT_IFLISTL: | ||||
error = sysctl_iflist(af, &w); | error = sysctl_iflist(af, &w); | ||||
break; | break; | ||||
case NET_RT_IFMALIST: | case NET_RT_IFMALIST: | ||||
error = sysctl_ifmalist(af, &w); | error = sysctl_ifmalist(af, &w); | ||||
Show All 37 Lines |