Changeset View
Changeset View
Standalone View
Standalone View
sys/net80211/ieee80211_freebsd.c
Context not available. | |||||
static const char wlanname[] = "wlan"; | static const char wlanname[] = "wlan"; | ||||
static struct if_clone *wlan_cloner; | static struct if_clone *wlan_cloner; | ||||
/* | |||||
* Allocate/free com structure in conjunction with ifnet; | |||||
* these routines are registered with if_register_com_alloc | |||||
* below and are called automatically by the ifnet code | |||||
* when the ifnet of the parent device is created. | |||||
*/ | |||||
static void * | |||||
wlan_alloc(u_char type, struct ifnet *ifp) | |||||
{ | |||||
struct ieee80211com *ic; | |||||
ic = IEEE80211_MALLOC(sizeof(struct ieee80211com), M_80211_COM, | |||||
IEEE80211_M_WAITOK | IEEE80211_M_ZERO); | |||||
ic->ic_ifp = ifp; | |||||
return (ic); | |||||
} | |||||
static void | |||||
wlan_free(void *ic, u_char type) | |||||
{ | |||||
IEEE80211_FREE(ic, M_80211_COM); | |||||
} | |||||
static int | static int | ||||
wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params) | wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params) | ||||
{ | { | ||||
Context not available. | |||||
struct ieee80211_clone_params cp; | struct ieee80211_clone_params cp; | ||||
struct ieee80211vap *vap; | struct ieee80211vap *vap; | ||||
struct ieee80211com *ic; | struct ieee80211com *ic; | ||||
struct ifnet *ifp; | |||||
int error; | int error; | ||||
error = copyin(params, &cp, sizeof(cp)); | error = copyin(params, &cp, sizeof(cp)); | ||||
if (error) | if (error) | ||||
return error; | return error; | ||||
ifp = ifunit(cp.icp_parent); | ic = ieee80211_find_com(cp.icp_parent); | ||||
if (ifp == NULL) | if (ic == NULL) | ||||
return ENXIO; | return ENXIO; | ||||
/* XXX move printfs to DIAGNOSTIC before release */ | |||||
if (ifp->if_type != IFT_IEEE80211) { | |||||
if_printf(ifp, "%s: reject, not an 802.11 device\n", __func__); | |||||
return ENXIO; | |||||
} | |||||
if (cp.icp_opmode >= IEEE80211_OPMODE_MAX) { | if (cp.icp_opmode >= IEEE80211_OPMODE_MAX) { | ||||
if_printf(ifp, "%s: invalid opmode %d\n", | ic_printf(ic, "%s: invalid opmode %d\n", __func__, | ||||
__func__, cp.icp_opmode); | cp.icp_opmode); | ||||
return EINVAL; | return EINVAL; | ||||
} | } | ||||
ic = ifp->if_l2com; | |||||
if ((ic->ic_caps & ieee80211_opcap[cp.icp_opmode]) == 0) { | if ((ic->ic_caps & ieee80211_opcap[cp.icp_opmode]) == 0) { | ||||
if_printf(ifp, "%s mode not supported\n", | ic_printf(ic, "%s mode not supported\n", | ||||
ieee80211_opmode_name[cp.icp_opmode]); | ieee80211_opmode_name[cp.icp_opmode]); | ||||
return EOPNOTSUPP; | return EOPNOTSUPP; | ||||
} | } | ||||
Context not available. | |||||
(1) | (1) | ||||
#endif | #endif | ||||
) { | ) { | ||||
if_printf(ifp, "TDMA not supported\n"); | ic_printf(ic, "TDMA not supported\n"); | ||||
return EOPNOTSUPP; | return EOPNOTSUPP; | ||||
} | } | ||||
vap = ic->ic_vap_create(ic, wlanname, unit, | vap = ic->ic_vap_create(ic, wlanname, unit, | ||||
cp.icp_opmode, cp.icp_flags, cp.icp_bssid, | cp.icp_opmode, cp.icp_flags, cp.icp_bssid, | ||||
cp.icp_flags & IEEE80211_CLONE_MACADDR ? | cp.icp_flags & IEEE80211_CLONE_MACADDR ? | ||||
cp.icp_macaddr : (const uint8_t *)IF_LLADDR(ifp)); | cp.icp_macaddr : ic->ic_macaddr); | ||||
return (vap == NULL ? EIO : 0); | return (vap == NULL ? EIO : 0); | ||||
} | } | ||||
Context not available. | |||||
* (the callers will first need modifying.) | * (the callers will first need modifying.) | ||||
*/ | */ | ||||
int | int | ||||
ieee80211_parent_xmitpkt(struct ieee80211com *ic, | ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m) | ||||
struct mbuf *m) | |||||
{ | { | ||||
struct ifnet *parent = ic->ic_ifp; | int error; | ||||
/* | /* | ||||
* Assert the IC TX lock is held - this enforces the | * Assert the IC TX lock is held - this enforces the | ||||
* processing -> queuing order is maintained | * processing -> queuing order is maintained | ||||
*/ | */ | ||||
IEEE80211_TX_LOCK_ASSERT(ic); | IEEE80211_TX_LOCK_ASSERT(ic); | ||||
error = ic->ic_transmit(ic, m); | |||||
return (parent->if_transmit(parent, m)); | if (error) | ||||
m_freem(m); | |||||
return (error); | |||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
} | } | ||||
static eventhandler_tag wlan_bpfevent; | static eventhandler_tag wlan_bpfevent; | ||||
static eventhandler_tag wlan_ifllevent; | |||||
static void | static void | ||||
bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach) | bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach) | ||||
Context not available. | |||||
} | } | ||||
} | } | ||||
static void | |||||
wlan_iflladdr(void *arg __unused, struct ifnet *ifp) | |||||
{ | |||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ieee80211vap *vap, *next; | |||||
if (ifp->if_type != IFT_IEEE80211 || ic == NULL) | |||||
return; | |||||
IEEE80211_LOCK(ic); | |||||
TAILQ_FOREACH_SAFE(vap, &ic->ic_vaps, iv_next, next) { | |||||
/* | |||||
* If the MAC address has changed on the parent and it was | |||||
* copied to the vap on creation then re-sync. | |||||
*/ | |||||
if (vap->iv_ic == ic && | |||||
(vap->iv_flags_ext & IEEE80211_FEXT_UNIQMAC) == 0) { | |||||
IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp)); | |||||
IEEE80211_UNLOCK(ic); | |||||
if_setlladdr(vap->iv_ifp, IF_LLADDR(ifp), | |||||
IEEE80211_ADDR_LEN); | |||||
IEEE80211_LOCK(ic); | |||||
} | |||||
} | |||||
IEEE80211_UNLOCK(ic); | |||||
} | |||||
/* | /* | ||||
* Module glue. | * Module glue. | ||||
* | * | ||||
Context not available. | |||||
printf("wlan: <802.11 Link Layer>\n"); | printf("wlan: <802.11 Link Layer>\n"); | ||||
wlan_bpfevent = EVENTHANDLER_REGISTER(bpf_track, | wlan_bpfevent = EVENTHANDLER_REGISTER(bpf_track, | ||||
bpf_track, 0, EVENTHANDLER_PRI_ANY); | bpf_track, 0, EVENTHANDLER_PRI_ANY); | ||||
wlan_ifllevent = EVENTHANDLER_REGISTER(iflladdr_event, | |||||
wlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY); | |||||
wlan_cloner = if_clone_simple(wlanname, wlan_clone_create, | wlan_cloner = if_clone_simple(wlanname, wlan_clone_create, | ||||
wlan_clone_destroy, 0); | wlan_clone_destroy, 0); | ||||
if_register_com_alloc(IFT_IEEE80211, wlan_alloc, wlan_free); | |||||
return 0; | return 0; | ||||
case MOD_UNLOAD: | case MOD_UNLOAD: | ||||
if_deregister_com_alloc(IFT_IEEE80211); | |||||
if_clone_detach(wlan_cloner); | if_clone_detach(wlan_cloner); | ||||
EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent); | EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent); | ||||
EVENTHANDLER_DEREGISTER(iflladdr_event, wlan_ifllevent); | |||||
return 0; | return 0; | ||||
} | } | ||||
return EINVAL; | return EINVAL; | ||||
Context not available. |