Changeset View
Changeset View
Standalone View
Standalone View
sys/net/if.c
Show First 20 Lines • Show All 345 Lines • ▼ Show 20 Lines | ifnet_byindex(u_short idx) | ||||
ifp = ifnet_byindex_locked(idx); | ifp = ifnet_byindex_locked(idx); | ||||
return (ifp); | return (ifp); | ||||
} | } | ||||
struct ifnet * | struct ifnet * | ||||
ifnet_byindex_ref(u_short idx) | ifnet_byindex_ref(u_short idx) | ||||
{ | { | ||||
struct epoch_tracker et; | |||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
NET_EPOCH_ENTER(et); | NET_EPOCH_ASSERT(); | ||||
ifp = ifnet_byindex_locked(idx); | ifp = ifnet_byindex_locked(idx); | ||||
if (ifp == NULL || (ifp->if_flags & IFF_DYING)) { | if (ifp == NULL || (ifp->if_flags & IFF_DYING)) | ||||
NET_EPOCH_EXIT(et); | |||||
return (NULL); | return (NULL); | ||||
} | |||||
if_ref(ifp); | if_ref(ifp); | ||||
NET_EPOCH_EXIT(et); | |||||
return (ifp); | return (ifp); | ||||
} | } | ||||
/* | /* | ||||
* Allocate an ifindex array entry; return 0 on success or an error on | * Allocate an ifindex array entry; return 0 on success or an error on | ||||
* failure. | * failure. | ||||
*/ | */ | ||||
static u_short | static u_short | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
V_ifindex_table[idx] = ifp; | V_ifindex_table[idx] = ifp; | ||||
} | } | ||||
struct ifaddr * | struct ifaddr * | ||||
ifaddr_byindex(u_short idx) | ifaddr_byindex(u_short idx) | ||||
{ | { | ||||
struct epoch_tracker et; | |||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
struct ifaddr *ifa = NULL; | struct ifaddr *ifa = NULL; | ||||
NET_EPOCH_ENTER(et); | NET_EPOCH_ASSERT(); | ||||
ifp = ifnet_byindex_locked(idx); | ifp = ifnet_byindex_locked(idx); | ||||
if (ifp != NULL && (ifa = ifp->if_addr) != NULL) | if (ifp != NULL && (ifa = ifp->if_addr) != NULL) | ||||
ifa_ref(ifa); | ifa_ref(ifa); | ||||
NET_EPOCH_EXIT(et); | |||||
return (ifa); | return (ifa); | ||||
} | } | ||||
/* | /* | ||||
* Network interface utility routines. | * Network interface utility routines. | ||||
* | * | ||||
* Routines with ifa_ifwith* names take sockaddr *'s as | * Routines with ifa_ifwith* names take sockaddr *'s as | ||||
* parameters. | * parameters. | ||||
▲ Show 20 Lines • Show All 518 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Remove any unicast or broadcast network addresses from an interface. | * Remove any unicast or broadcast network addresses from an interface. | ||||
*/ | */ | ||||
void | void | ||||
if_purgeaddrs(struct ifnet *ifp) | if_purgeaddrs(struct ifnet *ifp) | ||||
{ | { | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
while (1) { | NET_EPOCH_ASSERT(); | ||||
struct epoch_tracker et; | |||||
NET_EPOCH_ENTER(et); | while (1) { | ||||
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | ||||
if (ifa->ifa_addr->sa_family != AF_LINK) | if (ifa->ifa_addr->sa_family != AF_LINK) | ||||
break; | break; | ||||
} | } | ||||
NET_EPOCH_EXIT(et); | |||||
if (ifa == NULL) | if (ifa == NULL) | ||||
break; | break; | ||||
#ifdef INET | #ifdef INET | ||||
/* XXX: Ugly!! ad hoc just for INET */ | /* XXX: Ugly!! ad hoc just for INET */ | ||||
if (ifa->ifa_addr->sa_family == AF_INET) { | if (ifa->ifa_addr->sa_family == AF_INET) { | ||||
struct ifaliasreq ifr; | struct ifaliasreq ifr; | ||||
▲ Show 20 Lines • Show All 620 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* Stores all groups from an interface in memory pointed to by ifgr. | * Stores all groups from an interface in memory pointed to by ifgr. | ||||
*/ | */ | ||||
static int | static int | ||||
if_getgroup(struct ifgroupreq *ifgr, struct ifnet *ifp) | if_getgroup(struct ifgroupreq *ifgr, struct ifnet *ifp) | ||||
{ | { | ||||
struct epoch_tracker et; | |||||
int len, error; | int len, error; | ||||
struct ifg_list *ifgl; | struct ifg_list *ifgl; | ||||
struct ifg_req ifgrq, *ifgp; | struct ifg_req ifgrq, *ifgp; | ||||
NET_EPOCH_ASSERT(); | |||||
if (ifgr->ifgr_len == 0) { | if (ifgr->ifgr_len == 0) { | ||||
NET_EPOCH_ENTER(et); | |||||
CK_STAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) | CK_STAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) | ||||
ifgr->ifgr_len += sizeof(struct ifg_req); | ifgr->ifgr_len += sizeof(struct ifg_req); | ||||
NET_EPOCH_EXIT(et); | |||||
return (0); | return (0); | ||||
} | } | ||||
len = ifgr->ifgr_len; | len = ifgr->ifgr_len; | ||||
ifgp = ifgr_groups_get(ifgr); | ifgp = ifgr_groups_get(ifgr); | ||||
/* XXX: wire */ | /* XXX: wire */ | ||||
NET_EPOCH_ENTER(et); | |||||
CK_STAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) { | CK_STAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) { | ||||
if (len < sizeof(ifgrq)) { | if (len < sizeof(ifgrq)) | ||||
NET_EPOCH_EXIT(et); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | |||||
bzero(&ifgrq, sizeof ifgrq); | bzero(&ifgrq, sizeof ifgrq); | ||||
strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group, | strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group, | ||||
sizeof(ifgrq.ifgrq_group)); | sizeof(ifgrq.ifgrq_group)); | ||||
if ((error = copyout(&ifgrq, ifgp, sizeof(struct ifg_req)))) { | if ((error = copyout(&ifgrq, ifgp, sizeof(struct ifg_req)))) | ||||
NET_EPOCH_EXIT(et); | |||||
return (error); | return (error); | ||||
} | |||||
len -= sizeof(ifgrq); | len -= sizeof(ifgrq); | ||||
ifgp++; | ifgp++; | ||||
} | } | ||||
NET_EPOCH_EXIT(et); | |||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Stores all members of a group in memory pointed to by igfr | * Stores all members of a group in memory pointed to by igfr | ||||
*/ | */ | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 203 Lines • ▼ Show 20 Lines | if (refcount_release(&ifa->ifa_refcnt)) | ||||
epoch_call(net_epoch_preempt, &ifa->ifa_epoch_ctx, ifa_destroy); | epoch_call(net_epoch_preempt, &ifa->ifa_epoch_ctx, ifa_destroy); | ||||
} | } | ||||
static int | static int | ||||
ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa, | ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa, | ||||
struct sockaddr *ia) | struct sockaddr *ia) | ||||
{ | { | ||||
int error; | struct epoch_tracker et; | ||||
struct rt_addrinfo info; | struct rt_addrinfo info; | ||||
struct sockaddr_dl null_sdl; | struct sockaddr_dl null_sdl; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
int error; | |||||
ifp = ifa->ifa_ifp; | ifp = ifa->ifa_ifp; | ||||
bzero(&info, sizeof(info)); | bzero(&info, sizeof(info)); | ||||
if (cmd != RTM_DELETE) | if (cmd != RTM_DELETE) | ||||
info.rti_ifp = V_loif; | info.rti_ifp = V_loif; | ||||
info.rti_flags = ifa->ifa_flags | RTF_HOST | RTF_STATIC | RTF_PINNED; | info.rti_flags = ifa->ifa_flags | RTF_HOST | RTF_STATIC | RTF_PINNED; | ||||
info.rti_info[RTAX_DST] = ia; | info.rti_info[RTAX_DST] = ia; | ||||
info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl; | info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl; | ||||
link_init_sdl(ifp, (struct sockaddr *)&null_sdl, ifp->if_type); | link_init_sdl(ifp, (struct sockaddr *)&null_sdl, ifp->if_type); | ||||
NET_EPOCH_ENTER(et); | |||||
error = rtrequest1_fib(cmd, &info, NULL, ifp->if_fib); | error = rtrequest1_fib(cmd, &info, NULL, ifp->if_fib); | ||||
NET_EPOCH_EXIT(et); | |||||
if (error != 0 && | if (error != 0 && | ||||
!(cmd == RTM_ADD && error == EEXIST) && | !(cmd == RTM_ADD && error == EEXIST) && | ||||
!(cmd == RTM_DELETE && error == ENOENT)) | !(cmd == RTM_DELETE && error == ENOENT)) | ||||
if_printf(ifp, "%s failed: %d\n", otype, error); | if_printf(ifp, "%s failed: %d\n", otype, error); | ||||
return (error); | return (error); | ||||
} | } | ||||
Show All 37 Lines | |||||
*/ | */ | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
struct ifaddr * | struct ifaddr * | ||||
ifa_ifwithaddr(const struct sockaddr *addr) | ifa_ifwithaddr(const struct sockaddr *addr) | ||||
{ | { | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
MPASS(in_epoch(net_epoch_preempt)); | NET_EPOCH_ASSERT(); | ||||
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { | CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { | ||||
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | ||||
if (ifa->ifa_addr->sa_family != addr->sa_family) | if (ifa->ifa_addr->sa_family != addr->sa_family) | ||||
continue; | continue; | ||||
if (sa_equal(addr, ifa->ifa_addr)) { | if (sa_equal(addr, ifa->ifa_addr)) { | ||||
goto done; | goto done; | ||||
} | } | ||||
/* IP6 doesn't have broadcast */ | /* IP6 doesn't have broadcast */ | ||||
▲ Show 20 Lines • Show All 242 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Default action when installing a route with a Link Level gateway. | * Default action when installing a route with a Link Level gateway. | ||||
* Lookup an appropriate real ifa to point to. | * Lookup an appropriate real ifa to point to. | ||||
* This should be moved to /sys/net/link.c eventually. | * This should be moved to /sys/net/link.c eventually. | ||||
*/ | */ | ||||
static void | static void | ||||
link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) | link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) | ||||
{ | { | ||||
struct epoch_tracker et; | |||||
struct ifaddr *ifa, *oifa; | struct ifaddr *ifa, *oifa; | ||||
struct sockaddr *dst; | struct sockaddr *dst; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
NET_EPOCH_ASSERT(); | |||||
if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == NULL) || | if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == NULL) || | ||||
((ifp = ifa->ifa_ifp) == NULL) || ((dst = rt_key(rt)) == NULL)) | ((ifp = ifa->ifa_ifp) == NULL) || ((dst = rt_key(rt)) == NULL)) | ||||
return; | return; | ||||
NET_EPOCH_ENTER(et); | |||||
ifa = ifaof_ifpforaddr(dst, ifp); | ifa = ifaof_ifpforaddr(dst, ifp); | ||||
if (ifa) { | if (ifa) { | ||||
oifa = rt->rt_ifa; | oifa = rt->rt_ifa; | ||||
if (oifa != ifa) { | if (oifa != ifa) { | ||||
ifa_free(oifa); | ifa_free(oifa); | ||||
ifa_ref(ifa); | ifa_ref(ifa); | ||||
} | } | ||||
rt->rt_ifa = ifa; | rt->rt_ifa = ifa; | ||||
if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) | if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) | ||||
ifa->ifa_rtrequest(cmd, rt, info); | ifa->ifa_rtrequest(cmd, rt, info); | ||||
} | } | ||||
NET_EPOCH_EXIT(et); | |||||
} | } | ||||
struct sockaddr_dl * | struct sockaddr_dl * | ||||
link_alloc_sdl(size_t size, int flags) | link_alloc_sdl(size_t size, int flags) | ||||
{ | { | ||||
return (malloc(size, M_TEMP, flags)); | return (malloc(size, M_TEMP, flags)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | |||||
if_link_state_change(struct ifnet *ifp, int link_state) | if_link_state_change(struct ifnet *ifp, int link_state) | ||||
{ | { | ||||
/* Return if state hasn't changed. */ | /* Return if state hasn't changed. */ | ||||
if (ifp->if_link_state == link_state) | if (ifp->if_link_state == link_state) | ||||
return; | return; | ||||
ifp->if_link_state = link_state; | ifp->if_link_state = link_state; | ||||
/* XXXGL: reference ifp? */ | |||||
taskqueue_enqueue(taskqueue_swi, &ifp->if_linktask); | taskqueue_enqueue(taskqueue_swi, &ifp->if_linktask); | ||||
} | } | ||||
static void | static void | ||||
do_link_state_change(void *arg, int pending) | do_link_state_change(void *arg, int pending) | ||||
{ | { | ||||
struct ifnet *ifp = (struct ifnet *)arg; | struct epoch_tracker et; | ||||
int link_state = ifp->if_link_state; | struct ifnet *ifp; | ||||
CURVNET_SET(ifp->if_vnet); | int link_state; | ||||
/* Notify that the link state has changed. */ | NET_EPOCH_ENTER(et); | ||||
ifp = arg; | |||||
link_state = ifp->if_link_state; | |||||
CURVNET_SET(ifp->if_vnet); | |||||
rt_ifmsg(ifp); | rt_ifmsg(ifp); | ||||
if (ifp->if_vlantrunk != NULL) | if (ifp->if_vlantrunk != NULL) | ||||
(*vlan_link_state_p)(ifp); | (*vlan_link_state_p)(ifp); | ||||
if ((ifp->if_type == IFT_ETHER || ifp->if_type == IFT_L2VLAN) && | if ((ifp->if_type == IFT_ETHER || ifp->if_type == IFT_L2VLAN) && | ||||
ifp->if_l2com != NULL) | ifp->if_l2com != NULL) | ||||
(*ng_ether_link_state_p)(ifp, link_state); | (*ng_ether_link_state_p)(ifp, link_state); | ||||
if (ifp->if_carp) | if (ifp->if_carp) | ||||
Show All 9 Lines | devctl_notify("IFNET", ifp->if_xname, | ||||
NULL); | NULL); | ||||
if (pending > 1) | if (pending > 1) | ||||
if_printf(ifp, "%d link states coalesced\n", pending); | if_printf(ifp, "%d link states coalesced\n", pending); | ||||
if (log_link_state_change) | if (log_link_state_change) | ||||
if_printf(ifp, "link state changed to %s\n", | if_printf(ifp, "link state changed to %s\n", | ||||
(link_state == LINK_STATE_UP) ? "UP" : "DOWN" ); | (link_state == LINK_STATE_UP) ? "UP" : "DOWN" ); | ||||
EVENTHANDLER_INVOKE(ifnet_link_event, ifp, link_state); | EVENTHANDLER_INVOKE(ifnet_link_event, ifp, link_state); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
NET_EPOCH_EXIT(et); | |||||
} | } | ||||
/* | /* | ||||
* Mark an interface down and notify protocols of | * Mark an interface down and notify protocols of | ||||
* the transition. | * the transition. | ||||
*/ | */ | ||||
void | void | ||||
if_down(struct ifnet *ifp) | if_down(struct ifnet *ifp) | ||||
▲ Show 20 Lines • Show All 533 Lines • ▼ Show 20 Lines | case CASE_IOC_IFGROUPREQ(SIOCAIFGROUP): | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
if ((error = if_addgroup(ifp, | if ((error = if_addgroup(ifp, | ||||
ifgr_group_get((struct ifgroupreq *)data)))) | ifgr_group_get((struct ifgroupreq *)data)))) | ||||
return (error); | return (error); | ||||
break; | break; | ||||
case CASE_IOC_IFGROUPREQ(SIOCGIFGROUP): | case CASE_IOC_IFGROUPREQ(SIOCGIFGROUP): | ||||
if ((error = if_getgroup((struct ifgroupreq *)data, ifp))) | { | ||||
return (error); | struct epoch_tracker et; | ||||
NET_EPOCH_ENTER(et); | |||||
error = if_getgroup((struct ifgroupreq *)data, ifp); | |||||
NET_EPOCH_EXIT(et); | |||||
break; | break; | ||||
} | |||||
case CASE_IOC_IFGROUPREQ(SIOCDIFGROUP): | case CASE_IOC_IFGROUPREQ(SIOCDIFGROUP): | ||||
error = priv_check(td, PRIV_NET_DELIFGROUP); | error = priv_check(td, PRIV_NET_DELIFGROUP); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
if ((error = if_delgroup(ifp, | if ((error = if_delgroup(ifp, | ||||
ifgr_group_get((struct ifgroupreq *)data)))) | ifgr_group_get((struct ifgroupreq *)data)))) | ||||
return (error); | return (error); | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
* Interface ioctls. | * Interface ioctls. | ||||
*/ | */ | ||||
int | int | ||||
ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) | ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) | ||||
{ | { | ||||
#ifdef COMPAT_FREEBSD32 | #ifdef COMPAT_FREEBSD32 | ||||
caddr_t saved_data = NULL; | caddr_t saved_data = NULL; | ||||
struct ifmediareq ifmr; | struct ifmediareq ifmr; | ||||
struct ifmediareq *ifmrp; | struct ifmediareq *ifmrp = NULL; | ||||
#endif | #endif | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
struct ifreq *ifr; | struct ifreq *ifr; | ||||
int error; | int error; | ||||
int oif_flags; | int oif_flags; | ||||
#ifdef VIMAGE | #ifdef VIMAGE | ||||
int shutdown; | int shutdown; | ||||
#endif | #endif | ||||
CURVNET_SET(so->so_vnet); | CURVNET_SET(so->so_vnet); | ||||
#ifdef VIMAGE | #ifdef VIMAGE | ||||
/* Make sure the VNET is stable. */ | /* Make sure the VNET is stable. */ | ||||
shutdown = (so->so_vnet->vnet_state > SI_SUB_VNET && | shutdown = (so->so_vnet->vnet_state > SI_SUB_VNET && | ||||
so->so_vnet->vnet_state < SI_SUB_VNET_DONE) ? 1 : 0; | so->so_vnet->vnet_state < SI_SUB_VNET_DONE) ? 1 : 0; | ||||
if (shutdown) { | if (shutdown) { | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return (EBUSY); | return (EBUSY); | ||||
} | } | ||||
#endif | #endif | ||||
switch (cmd) { | switch (cmd) { | ||||
case SIOCGIFCONF: | case SIOCGIFCONF: | ||||
error = ifconf(cmd, data); | error = ifconf(cmd, data); | ||||
CURVNET_RESTORE(); | goto out_noref; | ||||
return (error); | |||||
#ifdef COMPAT_FREEBSD32 | #ifdef COMPAT_FREEBSD32 | ||||
case SIOCGIFCONF32: | case SIOCGIFCONF32: | ||||
{ | { | ||||
struct ifconf32 *ifc32; | struct ifconf32 *ifc32; | ||||
struct ifconf ifc; | struct ifconf ifc; | ||||
ifc32 = (struct ifconf32 *)data; | ifc32 = (struct ifconf32 *)data; | ||||
ifc.ifc_len = ifc32->ifc_len; | ifc.ifc_len = ifc32->ifc_len; | ||||
ifc.ifc_buf = PTRIN(ifc32->ifc_buf); | ifc.ifc_buf = PTRIN(ifc32->ifc_buf); | ||||
error = ifconf(SIOCGIFCONF, (void *)&ifc); | error = ifconf(SIOCGIFCONF, (void *)&ifc); | ||||
CURVNET_RESTORE(); | |||||
if (error == 0) | if (error == 0) | ||||
ifc32->ifc_len = ifc.ifc_len; | ifc32->ifc_len = ifc.ifc_len; | ||||
return (error); | goto out_noref; | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
#ifdef COMPAT_FREEBSD32 | #ifdef COMPAT_FREEBSD32 | ||||
ifmrp = NULL; | |||||
switch (cmd) { | switch (cmd) { | ||||
case SIOCGIFMEDIA32: | case SIOCGIFMEDIA32: | ||||
case SIOCGIFXMEDIA32: | case SIOCGIFXMEDIA32: | ||||
ifmrp = &ifmr; | ifmrp = &ifmr; | ||||
ifmr_init(ifmrp, data); | ifmr_init(ifmrp, data); | ||||
cmd = _IOC_NEWTYPE(cmd, struct ifmediareq); | cmd = _IOC_NEWTYPE(cmd, struct ifmediareq); | ||||
saved_data = data; | saved_data = data; | ||||
data = (caddr_t)ifmrp; | data = (caddr_t)ifmrp; | ||||
▲ Show 20 Lines • Show All 575 Lines • ▼ Show 20 Lines | |||||
* Network-layer protocol domains must use if_delmulti_ifma(). | * Network-layer protocol domains must use if_delmulti_ifma(). | ||||
*/ | */ | ||||
int | int | ||||
if_delmulti(struct ifnet *ifp, struct sockaddr *sa) | if_delmulti(struct ifnet *ifp, struct sockaddr *sa) | ||||
{ | { | ||||
struct ifmultiaddr *ifma; | struct ifmultiaddr *ifma; | ||||
int lastref; | int lastref; | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
struct epoch_tracker et; | |||||
struct ifnet *oifp; | struct ifnet *oifp; | ||||
NET_EPOCH_ENTER(et); | NET_EPOCH_ASSERT(); | ||||
CK_STAILQ_FOREACH(oifp, &V_ifnet, if_link) | CK_STAILQ_FOREACH(oifp, &V_ifnet, if_link) | ||||
if (ifp == oifp) | if (ifp == oifp) | ||||
break; | break; | ||||
if (ifp != oifp) | if (ifp != oifp) | ||||
ifp = NULL; | ifp = NULL; | ||||
NET_EPOCH_EXIT(et); | |||||
KASSERT(ifp != NULL, ("%s: ifnet went away", __func__)); | KASSERT(ifp != NULL, ("%s: ifnet went away", __func__)); | ||||
#endif | #endif | ||||
if (ifp == NULL) | if (ifp == NULL) | ||||
return (ENOENT); | return (ENOENT); | ||||
IF_ADDR_WLOCK(ifp); | IF_ADDR_WLOCK(ifp); | ||||
lastref = 0; | lastref = 0; | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
#ifdef INET | #ifdef INET | ||||
IN_MULTI_LIST_UNLOCK_ASSERT(); | IN_MULTI_LIST_UNLOCK_ASSERT(); | ||||
#endif | #endif | ||||
ifp = ifma->ifma_ifp; | ifp = ifma->ifma_ifp; | ||||
#ifdef DIAGNOSTIC | #ifdef DIAGNOSTIC | ||||
if (ifp == NULL) { | if (ifp == NULL) { | ||||
printf("%s: ifma_ifp seems to be detached\n", __func__); | printf("%s: ifma_ifp seems to be detached\n", __func__); | ||||
} else { | } else { | ||||
struct epoch_tracker et; | |||||
struct ifnet *oifp; | struct ifnet *oifp; | ||||
NET_EPOCH_ENTER(et); | NET_EPOCH_ASSERT(); | ||||
CK_STAILQ_FOREACH(oifp, &V_ifnet, if_link) | CK_STAILQ_FOREACH(oifp, &V_ifnet, if_link) | ||||
if (ifp == oifp) | if (ifp == oifp) | ||||
break; | break; | ||||
if (ifp != oifp) | if (ifp != oifp) | ||||
ifp = NULL; | ifp = NULL; | ||||
NET_EPOCH_EXIT(et); | |||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* If and only if the ifnet instance exists: Acquire the address lock. | * If and only if the ifnet instance exists: Acquire the address lock. | ||||
*/ | */ | ||||
if (ifp != NULL) | if (ifp != NULL) | ||||
IF_ADDR_WLOCK(ifp); | IF_ADDR_WLOCK(ifp); | ||||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | |||||
* Set noinline to be dtrace-friendly | * Set noinline to be dtrace-friendly | ||||
*/ | */ | ||||
__noinline int | __noinline int | ||||
if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len) | if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len) | ||||
{ | { | ||||
struct sockaddr_dl *sdl; | struct sockaddr_dl *sdl; | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
struct ifreq ifr; | struct ifreq ifr; | ||||
struct epoch_tracker et; | |||||
int rc; | int rc; | ||||
NET_EPOCH_ASSERT(); | |||||
rc = 0; | rc = 0; | ||||
NET_EPOCH_ENTER(et); | |||||
ifa = ifp->if_addr; | ifa = ifp->if_addr; | ||||
if (ifa == NULL) { | if (ifa == NULL) { | ||||
rc = EINVAL; | rc = EINVAL; | ||||
goto out; | goto out; | ||||
} | } | ||||
sdl = (struct sockaddr_dl *)ifa->ifa_addr; | sdl = (struct sockaddr_dl *)ifa->ifa_addr; | ||||
if (sdl == NULL) { | if (sdl == NULL) { | ||||
Show All 17 Lines | default: | ||||
goto out; | goto out; | ||||
} | } | ||||
/* | /* | ||||
* If the interface is already up, we need | * If the interface is already up, we need | ||||
* to re-init it in order to reprogram its | * to re-init it in order to reprogram its | ||||
* address filter. | * address filter. | ||||
*/ | */ | ||||
NET_EPOCH_EXIT(et); | |||||
if ((ifp->if_flags & IFF_UP) != 0) { | if ((ifp->if_flags & IFF_UP) != 0) { | ||||
if (ifp->if_ioctl) { | if (ifp->if_ioctl) { | ||||
ifp->if_flags &= ~IFF_UP; | ifp->if_flags &= ~IFF_UP; | ||||
ifr.ifr_flags = ifp->if_flags & 0xffff; | ifr.ifr_flags = ifp->if_flags & 0xffff; | ||||
ifr.ifr_flagshigh = ifp->if_flags >> 16; | ifr.ifr_flagshigh = ifp->if_flags >> 16; | ||||
(*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); | (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); | ||||
ifp->if_flags |= IFF_UP; | ifp->if_flags |= IFF_UP; | ||||
ifr.ifr_flags = ifp->if_flags & 0xffff; | ifr.ifr_flags = ifp->if_flags & 0xffff; | ||||
ifr.ifr_flagshigh = ifp->if_flags >> 16; | ifr.ifr_flagshigh = ifp->if_flags >> 16; | ||||
(*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); | (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); | ||||
} | } | ||||
} | } | ||||
EVENTHANDLER_INVOKE(iflladdr_event, ifp); | EVENTHANDLER_INVOKE(iflladdr_event, ifp); | ||||
return (0); | return (0); | ||||
out: | out: | ||||
NET_EPOCH_EXIT(et); | |||||
return (rc); | return (rc); | ||||
} | } | ||||
/* | /* | ||||
* Compat function for handling basic encapsulation requests. | * Compat function for handling basic encapsulation requests. | ||||
* Not converted stacks (FDDI, IB, ..) supports traditional | * Not converted stacks (FDDI, IB, ..) supports traditional | ||||
* output model: ARP (and other similar L2 protocols) are handled | * output model: ARP (and other similar L2 protocols) are handled | ||||
* inside output routine, arpresolve/nd6_resolve() returns MAC | * inside output routine, arpresolve/nd6_resolve() returns MAC | ||||
▲ Show 20 Lines • Show All 707 Lines • Show Last 20 Lines |