Changeset View
Changeset View
Standalone View
Standalone View
sys/net80211/ieee80211_ioctl.c
Context not available. | |||||
setmlme_dropsta(struct ieee80211vap *vap, | setmlme_dropsta(struct ieee80211vap *vap, | ||||
const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop) | const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop) | ||||
{ | { | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta; | ||||
struct ieee80211_node_table *nt = &ic->ic_sta; | |||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
int error = 0; | int error = 0; | ||||
/* NB: the broadcast address means do 'em all */ | /* NB: the broadcast address means do 'em all */ | ||||
if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) { | if (!IEEE80211_ADDR_EQ(mac, vap->iv_ifp->if_broadcastaddr)) { | ||||
IEEE80211_NODE_LOCK(nt); | IEEE80211_NODE_LOCK(nt); | ||||
ni = ieee80211_find_node_locked(nt, mac); | ni = ieee80211_find_node_locked(nt, mac); | ||||
IEEE80211_NODE_UNLOCK(nt); | IEEE80211_NODE_UNLOCK(nt); | ||||
Context not available. | |||||
static __noinline int | static __noinline int | ||||
ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq) | ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq) | ||||
{ | { | ||||
struct ieee80211com *ic = vap->iv_ic; | |||||
struct ieee80211_scan_req sr; /* XXX off stack? */ | struct ieee80211_scan_req sr; /* XXX off stack? */ | ||||
int error; | int error; | ||||
avos: Without this check net80211 enters SCAN state even when device is not initialized (for example… | |||||
Not Done Inline ActionsThe device should check its internal RUNNING flag in the handler. glebius: The device should check its internal RUNNING flag in the handler. | |||||
/* NB: parent must be running */ | |||||
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | |||||
return ENXIO; | |||||
if (ireq->i_len != sizeof(sr)) | if (ireq->i_len != sizeof(sr)) | ||||
return EINVAL; | return EINVAL; | ||||
error = copyin(ireq->i_data, &sr, sizeof(sr)); | error = copyin(ireq->i_data, &sr, sizeof(sr)); | ||||
Context not available. | |||||
return error; | return error; | ||||
} | } | ||||
/* | |||||
* Rebuild the parent's multicast address list after an add/del | |||||
* of a multicast address for a vap. We have no way to tell | |||||
* what happened above to optimize the work so we purge the entire | |||||
* list and rebuild from scratch. This is way expensive. | |||||
* Note also the half-baked workaround for if_addmulti calling | |||||
* back to the parent device; there's no way to insert mcast | |||||
* entries quietly and/or cheaply. | |||||
*/ | |||||
static void | |||||
ieee80211_ioctl_updatemulti(struct ieee80211com *ic) | |||||
{ | |||||
struct ifnet *parent = ic->ic_ifp; | |||||
struct ieee80211vap *vap; | |||||
void *ioctl; | |||||
IEEE80211_LOCK(ic); | |||||
if_delallmulti(parent); | |||||
ioctl = parent->if_ioctl; /* XXX WAR if_allmulti */ | |||||
parent->if_ioctl = NULL; | |||||
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { | |||||
struct ifnet *ifp = vap->iv_ifp; | |||||
struct ifmultiaddr *ifma; | |||||
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { | |||||
if (ifma->ifma_addr->sa_family != AF_LINK) | |||||
continue; | |||||
(void) if_addmulti(parent, ifma->ifma_addr, NULL); | |||||
} | |||||
} | |||||
parent->if_ioctl = ioctl; | |||||
ieee80211_runtask(ic, &ic->ic_mcast_task); | |||||
IEEE80211_UNLOCK(ic); | |||||
} | |||||
int | int | ||||
ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) | ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) | ||||
{ | { | ||||
Context not available. | |||||
switch (cmd) { | switch (cmd) { | ||||
case SIOCSIFFLAGS: | case SIOCSIFFLAGS: | ||||
IEEE80211_LOCK(ic); | IEEE80211_LOCK(ic); | ||||
ieee80211_syncifflag_locked(ic, IFF_PROMISC); | if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_PROMISC) | ||||
ieee80211_syncifflag_locked(ic, IFF_ALLMULTI); | ieee80211_promisc(vap, ifp->if_flags & IFF_PROMISC); | ||||
if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_ALLMULTI) | |||||
ieee80211_allmulti(vap, ifp->if_flags & IFF_ALLMULTI); | |||||
vap->iv_ifflags = ifp->if_flags; | |||||
if (ifp->if_flags & IFF_UP) { | if (ifp->if_flags & IFF_UP) { | ||||
/* | /* | ||||
* Bring ourself up unless we're already operational. | * Bring ourself up unless we're already operational. | ||||
Context not available. | |||||
break; | break; | ||||
case SIOCADDMULTI: | case SIOCADDMULTI: | ||||
case SIOCDELMULTI: | case SIOCDELMULTI: | ||||
ieee80211_ioctl_updatemulti(ic); | ieee80211_runtask(ic, &ic->ic_mcast_task); | ||||
break; | break; | ||||
case SIOCSIFMEDIA: | case SIOCSIFMEDIA: | ||||
case SIOCGIFMEDIA: | case SIOCGIFMEDIA: | ||||
Context not available. | |||||
break; | break; | ||||
} | } | ||||
break; | break; | ||||
/* Pass NDIS ioctls up to the driver */ | |||||
case SIOCGDRVSPEC: | |||||
case SIOCSDRVSPEC: | |||||
case SIOCGPRIVATE_0: { | |||||
struct ifnet *parent = vap->iv_ic->ic_ifp; | |||||
error = parent->if_ioctl(parent, cmd, data); | |||||
break; | |||||
} | |||||
default: | default: | ||||
/* | |||||
* Pass unknown ioctls first to the driver, and if it | |||||
* returns ENOTTY, then to the generic Ethernet handler. | |||||
*/ | |||||
if (ic->ic_ioctl != NULL && | |||||
(error = ic->ic_ioctl(ic, cmd, data)) != ENOTTY) | |||||
break; | |||||
error = ether_ioctl(ifp, cmd, data); | error = ether_ioctl(ifp, cmd, data); | ||||
break; | break; | ||||
} | } | ||||
return error; | return (error); | ||||
} | } | ||||
Context not available. |
Without this check net80211 enters SCAN state even when device is not initialized (for example, issue wlandebug scan+state and then turn device off with RF switch)