diff options
author | adrian <adrian@FreeBSD.org> | 2015-08-08 01:10:17 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2015-08-08 01:10:17 +0000 |
commit | bad6d5c89b6ffd35818850d95cb88e218dee73b3 (patch) | |
tree | 5973a9059f73ed5abf84d6d98e44f1953e764064 /sys/net80211 | |
parent | 33a3844dbf69152b9d47f6fa1ac1c2d5b1d502e4 (diff) | |
download | FreeBSD-src-bad6d5c89b6ffd35818850d95cb88e218dee73b3.zip FreeBSD-src-bad6d5c89b6ffd35818850d95cb88e218dee73b3.tar.gz |
Revert the wifi ifnet changes until things are more baked and tested.
* 286410
* 286413
* 286416
The initial commit broke a variety of debug and features that aren't
in the GENERIC kernels but are enabled in other platforms.
Diffstat (limited to 'sys/net80211')
-rw-r--r-- | sys/net80211/ieee80211.c | 282 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ddb.c | 3 | ||||
-rw-r--r-- | sys/net80211/ieee80211_freebsd.c | 90 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ioctl.c | 71 | ||||
-rw-r--r-- | sys/net80211/ieee80211_output.c | 30 | ||||
-rw-r--r-- | sys/net80211/ieee80211_power.c | 55 | ||||
-rw-r--r-- | sys/net80211/ieee80211_proto.c | 36 | ||||
-rw-r--r-- | sys/net80211/ieee80211_proto.h | 3 | ||||
-rw-r--r-- | sys/net80211/ieee80211_regdomain.c | 3 | ||||
-rw-r--r-- | sys/net80211/ieee80211_scan_sta.c | 26 | ||||
-rw-r--r-- | sys/net80211/ieee80211_var.h | 27 |
11 files changed, 409 insertions, 217 deletions
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index 39e03ea..3902227 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/kernel.h> #include <sys/socket.h> -#include <sys/sbuf.h> #include <machine/stdarg.h> @@ -92,6 +91,8 @@ static void ieee80211_syncflag_ext_locked(struct ieee80211com *ic, int flag); static int ieee80211_media_setup(struct ieee80211com *ic, struct ifmedia *media, int caps, int addsta, ifm_change_cb_t media_change, ifm_stat_cb_t media_stat); +static void ieee80211com_media_status(struct ifnet *, struct ifmediareq *); +static int ieee80211com_media_change(struct ifnet *); static int media_status(enum ieee80211_opmode, const struct ieee80211_channel *); static uint64_t ieee80211_get_counter(struct ifnet *, ift_counter); @@ -120,7 +121,7 @@ static const struct ieee80211_rateset ieee80211_rateset_11g = * all available channels as active, and pick * a default channel if not already specified. */ -void +static void ieee80211_chan_init(struct ieee80211com *ic) { #define DEFAULTRATES(m, def) do { \ @@ -237,6 +238,29 @@ null_update_promisc(struct ieee80211com *ic) ic_printf(ic, "need promiscuous mode update callback\n"); } +static int +null_transmit(struct ifnet *ifp, struct mbuf *m) +{ + m_freem(m); + if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + return EACCES; /* XXX EIO/EPERM? */ +} + +static int +null_output(struct ifnet *ifp, struct mbuf *m, + const struct sockaddr *dst, struct route *ro) +{ + if_printf(ifp, "discard raw packet\n"); + return null_transmit(ifp, m); +} + +static void +null_input(struct ifnet *ifp, struct mbuf *m) +{ + if_printf(ifp, "if_input should not be called\n"); + m_freem(m); +} + static void null_update_chw(struct ieee80211com *ic) { @@ -257,43 +281,19 @@ ic_printf(struct ieee80211com *ic, const char * fmt, ...) return (retval); } -static LIST_HEAD(, ieee80211com) ic_head = LIST_HEAD_INITIALIZER(ic_head); -static struct mtx ic_list_mtx; -MTX_SYSINIT(ic_list, &ic_list_mtx, "ieee80211com list", MTX_DEF); - -static int -sysctl_ieee80211coms(SYSCTL_HANDLER_ARGS) -{ - struct ieee80211com *ic; - struct sbuf *sb; - char *sp; - int error; - - sb = sbuf_new_auto(); - sp = ""; - mtx_lock(&ic_list_mtx); - LIST_FOREACH(ic, &ic_head, ic_next) { - sbuf_printf(sb, "%s%s", sp, ic->ic_name); - sp = " "; - } - mtx_unlock(&ic_list_mtx); - sbuf_finish(sb); - error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); - sbuf_delete(sb); - return (error); -} - -SYSCTL_PROC(_net_wlan, OID_AUTO, devices, - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, - sysctl_ieee80211coms, "A", "names of available 802.11 devices"); - /* * Attach/setup the common net80211 state. Called by * the driver on attach to prior to creating any vap's. */ void -ieee80211_ifattach(struct ieee80211com *ic) +ieee80211_ifattach(struct ieee80211com *ic, + const uint8_t macaddr[IEEE80211_ADDR_LEN]) { + struct ifnet *ifp = ic->ic_ifp; + struct sockaddr_dl *sdl; + struct ifaddr *ifa; + + KASSERT(ifp->if_type == IFT_IEEE80211, ("if_type %d", ifp->if_type)); IEEE80211_LOCK_INIT(ic, ic->ic_name); IEEE80211_TX_LOCK_INIT(ic, ic->ic_name); @@ -311,7 +311,7 @@ ieee80211_ifattach(struct ieee80211com *ic) * available channels as active, and pick a default * channel if not already specified. */ - ieee80211_chan_init(ic); + ieee80211_media_init(ic); ic->ic_update_mcast = null_update_mcast; ic->ic_update_promisc = null_update_promisc; @@ -336,9 +336,28 @@ ieee80211_ifattach(struct ieee80211com *ic) ieee80211_sysctl_attach(ic); - mtx_lock(&ic_list_mtx); - LIST_INSERT_HEAD(&ic_head, ic, ic_next); - mtx_unlock(&ic_list_mtx); + ifp->if_addrlen = IEEE80211_ADDR_LEN; + ifp->if_hdrlen = 0; + + CURVNET_SET(vnet0); + + if_attach(ifp); + + ifp->if_mtu = IEEE80211_MTU_MAX; + ifp->if_broadcastaddr = ieee80211broadcastaddr; + ifp->if_output = null_output; + ifp->if_input = null_input; /* just in case */ + ifp->if_resolvemulti = NULL; /* NB: callers check */ + + ifa = ifaddr_byindex(ifp->if_index); + KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__)); + sdl = (struct sockaddr_dl *)ifa->ifa_addr; + sdl->sdl_type = IFT_ETHER; /* XXX IFT_IEEE80211? */ + sdl->sdl_alen = IEEE80211_ADDR_LEN; + IEEE80211_ADDR_COPY(LLADDR(sdl), macaddr); + ifa_free(ifa); + + CURVNET_RESTORE(); } /* @@ -350,11 +369,16 @@ ieee80211_ifattach(struct ieee80211com *ic) void ieee80211_ifdetach(struct ieee80211com *ic) { + struct ifnet *ifp = ic->ic_ifp; struct ieee80211vap *vap; - mtx_lock(&ic_list_mtx); - LIST_REMOVE(ic, ic_next); - mtx_unlock(&ic_list_mtx); + /* + * This detaches the main interface, but not the vaps. + * Each VAP may be in a separate VIMAGE. + */ + CURVNET_SET(ifp->if_vnet); + if_detach(ifp); + CURVNET_RESTORE(); /* * The VAP is responsible for setting and clearing @@ -378,6 +402,8 @@ ieee80211_ifdetach(struct ieee80211com *ic) ieee80211_power_detach(ic); ieee80211_node_detach(ic); + /* XXX VNET needed? */ + ifmedia_removeall(&ic->ic_media); counter_u64_free(ic->ic_ierrors); counter_u64_free(ic->ic_oerrors); @@ -386,20 +412,6 @@ ieee80211_ifdetach(struct ieee80211com *ic) IEEE80211_LOCK_DESTROY(ic); } -struct ieee80211com * -ieee80211_find_com(const char *name) -{ - struct ieee80211com *ic; - - mtx_lock(&ic_list_mtx); - LIST_FOREACH(ic, &ic_head, ic_next) - if (strcmp(ic->ic_name, name) == 0) - break; - mtx_unlock(&ic_list_mtx); - - return (ic); -} - /* * Default reset method for use with the ioctl support. This * method is invoked after any state change in the 802.11 @@ -448,7 +460,8 @@ ieee80211_get_counter(struct ifnet *ifp, ift_counter cnt) int ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode, - int flags, const uint8_t bssid[IEEE80211_ADDR_LEN]) + int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], + const uint8_t macaddr[IEEE80211_ADDR_LEN]) { struct ifnet *ifp; @@ -477,7 +490,6 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, vap->iv_htextcaps = ic->ic_htextcaps; vap->iv_opmode = opmode; vap->iv_caps |= ieee80211_opcap[opmode]; - vap->iv_myaddr = ic->ic_macaddr; switch (opmode) { case IEEE80211_M_WDS: /* @@ -544,6 +556,8 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, */ vap->iv_reset = default_reset; + IEEE80211_ADDR_COPY(vap->iv_myaddr, macaddr); + ieee80211_sysctl_vattach(vap); ieee80211_crypto_vattach(vap); ieee80211_node_vattach(vap); @@ -567,8 +581,8 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, * from this call the vap is ready for use. */ int -ieee80211_vap_attach(struct ieee80211vap *vap, ifm_change_cb_t media_change, - ifm_stat_cb_t media_stat, const uint8_t macaddr[IEEE80211_ADDR_LEN]) +ieee80211_vap_attach(struct ieee80211vap *vap, + ifm_change_cb_t media_change, ifm_stat_cb_t media_stat) { struct ifnet *ifp = vap->iv_ifp; struct ieee80211com *ic = vap->iv_ic; @@ -596,8 +610,7 @@ ieee80211_vap_attach(struct ieee80211vap *vap, ifm_change_cb_t media_change, if (maxrate) ifp->if_baudrate = IF_Mbps(maxrate); - ether_ifattach(ifp, macaddr); - vap->iv_myaddr = IF_LLADDR(ifp); + ether_ifattach(ifp, vap->iv_myaddr); /* hook output method setup by ether_ifattach */ vap->iv_output = ifp->if_output; ifp->if_output = ieee80211_output; @@ -613,6 +626,8 @@ ieee80211_vap_attach(struct ieee80211vap *vap, ifm_change_cb_t media_change, ieee80211_syncflag_locked(ic, IEEE80211_F_BURST); ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_HT); ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40); + ieee80211_syncifflag_locked(ic, IFF_PROMISC); + ieee80211_syncifflag_locked(ic, IFF_ALLMULTI); IEEE80211_UNLOCK(ic); return 1; @@ -662,10 +677,8 @@ ieee80211_vap_detach(struct ieee80211vap *vap) ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40); /* NB: this handles the bpfdetach done below */ ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_BPF); - if (vap->iv_ifflags & IFF_PROMISC) - ieee80211_promisc(vap, false); - if (vap->iv_ifflags & IFF_ALLMULTI) - ieee80211_allmulti(vap, false); + ieee80211_syncifflag_locked(ic, IFF_PROMISC); + ieee80211_syncifflag_locked(ic, IFF_ALLMULTI); IEEE80211_UNLOCK(ic); ifmedia_removeall(&vap->iv_media); @@ -690,57 +703,49 @@ ieee80211_vap_detach(struct ieee80211vap *vap) } /* - * Count number of vaps in promisc, and issue promisc on - * parent respectively. + * Synchronize flag bit state in the parent ifnet structure + * according to the state of all vap ifnet's. This is used, + * for example, to handle IFF_PROMISC and IFF_ALLMULTI. */ void -ieee80211_promisc(struct ieee80211vap *vap, bool on) +ieee80211_syncifflag_locked(struct ieee80211com *ic, int flag) { - struct ieee80211com *ic = vap->iv_ic; - - /* - * XXX the bridge sets PROMISC but we don't want to - * enable it on the device, discard here so all the - * drivers don't need to special-case it - */ - if (!(vap->iv_opmode == IEEE80211_M_MONITOR || - (vap->iv_opmode == IEEE80211_M_AHDEMO && - (vap->iv_caps & IEEE80211_C_TDMA) == 0))) - return; - - IEEE80211_LOCK(ic); - if (on) { - if (++ic->ic_promisc == 1) - ieee80211_runtask(ic, &ic->ic_promisc_task); - } else { - KASSERT(ic->ic_promisc > 0, ("%s: ic %p not promisc", - __func__, ic)); - if (--ic->ic_promisc == 0) - ieee80211_runtask(ic, &ic->ic_promisc_task); - } - IEEE80211_UNLOCK(ic); -} + struct ifnet *ifp = ic->ic_ifp; + struct ieee80211vap *vap; + int bit, oflags; -/* - * Count number of vaps in allmulti, and issue allmulti on - * parent respectively. - */ -void -ieee80211_allmulti(struct ieee80211vap *vap, bool on) -{ - struct ieee80211com *ic = vap->iv_ic; + IEEE80211_LOCK_ASSERT(ic); - IEEE80211_LOCK(ic); - if (on) { - if (++ic->ic_allmulti == 1) - ieee80211_runtask(ic, &ic->ic_mcast_task); - } else { - KASSERT(ic->ic_allmulti > 0, ("%s: ic %p not allmulti", - __func__, ic)); - if (--ic->ic_allmulti == 0) - ieee80211_runtask(ic, &ic->ic_mcast_task); + bit = 0; + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) + if (vap->iv_ifp->if_flags & flag) { + /* + * XXX the bridge sets PROMISC but we don't want to + * enable it on the device, discard here so all the + * drivers don't need to special-case it + */ + if (flag == IFF_PROMISC && + !(vap->iv_opmode == IEEE80211_M_MONITOR || + (vap->iv_opmode == IEEE80211_M_AHDEMO && + (vap->iv_caps & IEEE80211_C_TDMA) == 0))) + continue; + bit = 1; + break; + } + oflags = ifp->if_flags; + if (bit) + ifp->if_flags |= flag; + else + ifp->if_flags &= ~flag; + if ((ifp->if_flags ^ oflags) & flag) { + /* XXX should we return 1/0 and let caller do this? */ + if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + if (flag == IFF_PROMISC) + ieee80211_runtask(ic, &ic->ic_promisc_task); + else if (flag == IFF_ALLMULTI) + ieee80211_runtask(ic, &ic->ic_mcast_task); + } } - IEEE80211_UNLOCK(ic); } /* @@ -1229,6 +1234,39 @@ ieee80211_media_setup(struct ieee80211com *ic, return maxrate; } +void +ieee80211_media_init(struct ieee80211com *ic) +{ + struct ifnet *ifp = ic->ic_ifp; + int maxrate; + + /* NB: this works because the structure is initialized to zero */ + if (!LIST_EMPTY(&ic->ic_media.ifm_list)) { + /* + * We are re-initializing the channel list; clear + * the existing media state as the media routines + * don't suppress duplicates. + */ + ifmedia_removeall(&ic->ic_media); + } + ieee80211_chan_init(ic); + + /* + * Recalculate media settings in case new channel list changes + * the set of available modes. + */ + maxrate = ieee80211_media_setup(ic, &ic->ic_media, ic->ic_caps, 1, + ieee80211com_media_change, ieee80211com_media_status); + /* NB: strip explicit mode; we're actually in autoselect */ + ifmedia_set(&ic->ic_media, + media_status(ic->ic_opmode, ic->ic_curchan) &~ + (IFM_MMASK | IFM_IEEE80211_TURBO)); + if (maxrate) + ifp->if_baudrate = IF_Mbps(maxrate); + + /* XXX need to propagate new media settings to vap's */ +} + /* XXX inline or eliminate? */ const struct ieee80211_rateset * ieee80211_get_suprates(struct ieee80211com *ic, const struct ieee80211_channel *c) @@ -1357,6 +1395,15 @@ media2mode(const struct ifmedia_entry *ime, uint32_t flags, uint16_t *mode) } /* + * Handle a media change request on the underlying interface. + */ +int +ieee80211com_media_change(struct ifnet *ifp) +{ + return EINVAL; +} + +/* * Handle a media change request on the vap interface. */ int @@ -1433,6 +1480,23 @@ media_status(enum ieee80211_opmode opmode, const struct ieee80211_channel *chan) return status; } +static void +ieee80211com_media_status(struct ifnet *ifp, struct ifmediareq *imr) +{ + struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211vap *vap; + + imr->ifm_status = IFM_AVALID; + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) + if (vap->iv_ifp->if_flags & IFF_UP) { + imr->ifm_status |= IFM_ACTIVE; + break; + } + imr->ifm_active = media_status(ic->ic_opmode, ic->ic_curchan); + if (imr->ifm_status & IFM_ACTIVE) + imr->ifm_current = imr->ifm_active; +} + void ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr) { diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c index ae4910c..e646cf2 100644 --- a/sys/net80211/ieee80211_ddb.c +++ b/sys/net80211/ieee80211_ddb.c @@ -520,7 +520,7 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta, TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) db_printf(" %s(%p)", vap->iv_ifp->if_xname, vap); db_printf("\n"); - db_printf("\tsoftc %p", ic->ic_softc); + db_printf("\tifp %p(%s)", ic->ic_ifp, ic->ic_ifp->if_xname); db_printf("\tname %s", ic->ic_name); db_printf(" comlock %p", &ic->ic_comlock); db_printf("\n"); @@ -528,6 +528,7 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta, db_printf(" phytype %d", ic->ic_phytype); db_printf(" opmode %s", ieee80211_opmode_name[ic->ic_opmode]); db_printf("\n"); + db_printf("\tmedia %p", &ic->ic_media); db_printf(" inact %p", &ic->ic_inact); db_printf("\n"); diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c index 9a8e941..3af75df 100644 --- a/sys/net80211/ieee80211_freebsd.c +++ b/sys/net80211/ieee80211_freebsd.c @@ -69,27 +69,58 @@ static MALLOC_DEFINE(M_80211_COM, "80211com", "802.11 com state"); static const char wlanname[] = "wlan"; 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 wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params) { struct ieee80211_clone_params cp; struct ieee80211vap *vap; struct ieee80211com *ic; + struct ifnet *ifp; int error; error = copyin(params, &cp, sizeof(cp)); if (error) return error; - ic = ieee80211_find_com(cp.icp_parent); - if (ic == NULL) + ifp = ifunit(cp.icp_parent); + if (ifp == NULL) 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) { - ic_printf(ic, "%s: invalid opmode %d\n", __func__, - cp.icp_opmode); + if_printf(ifp, "%s: invalid opmode %d\n", + __func__, cp.icp_opmode); return EINVAL; } + ic = ifp->if_l2com; if ((ic->ic_caps & ieee80211_opcap[cp.icp_opmode]) == 0) { - ic_printf(ic, "%s mode not supported\n", + if_printf(ifp, "%s mode not supported\n", ieee80211_opmode_name[cp.icp_opmode]); return EOPNOTSUPP; } @@ -100,13 +131,13 @@ wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params) (1) #endif ) { - ic_printf(ic, "TDMA not supported\n"); + if_printf(ifp, "TDMA not supported\n"); return EOPNOTSUPP; } vap = ic->ic_vap_create(ic, wlanname, unit, cp.icp_opmode, cp.icp_flags, cp.icp_bssid, cp.icp_flags & IEEE80211_CLONE_MACADDR ? - cp.icp_macaddr : ic->ic_macaddr); + cp.icp_macaddr : (const uint8_t *)IF_LLADDR(ifp)); return (vap == NULL ? EIO : 0); } @@ -497,19 +528,17 @@ ieee80211_process_callback(struct ieee80211_node *ni, * (the callers will first need modifying.) */ int -ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m) +ieee80211_parent_xmitpkt(struct ieee80211com *ic, + struct mbuf *m) { - int error; - + struct ifnet *parent = ic->ic_ifp; /* * Assert the IC TX lock is held - this enforces the * processing -> queuing order is maintained */ IEEE80211_TX_LOCK_ASSERT(ic); - error = ic->ic_transmit(ic, m); - if (error) - m_freem(m); - return (error); + + return (parent->if_transmit(parent, m)); } /* @@ -807,6 +836,7 @@ ieee80211_load_module(const char *modname) } static eventhandler_tag wlan_bpfevent; +static eventhandler_tag wlan_ifllevent; static void bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach) @@ -834,6 +864,33 @@ bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach) } } +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. * @@ -848,12 +905,17 @@ wlan_modevent(module_t mod, int type, void *unused) printf("wlan: <802.11 Link Layer>\n"); wlan_bpfevent = EVENTHANDLER_REGISTER(bpf_track, 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_clone_destroy, 0); + if_register_com_alloc(IFT_IEEE80211, wlan_alloc, wlan_free); return 0; case MOD_UNLOAD: + if_deregister_com_alloc(IFT_IEEE80211); if_clone_detach(wlan_cloner); EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent); + EVENTHANDLER_DEREGISTER(iflladdr_event, wlan_ifllevent); return 0; } return EINVAL; diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index 1c7ddb9..54ab390 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -1329,12 +1329,13 @@ static int setmlme_dropsta(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop) { - struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta; + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_node_table *nt = &ic->ic_sta; struct ieee80211_node *ni; int error = 0; /* NB: the broadcast address means do 'em all */ - if (!IEEE80211_ADDR_EQ(mac, vap->iv_ifp->if_broadcastaddr)) { + if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) { IEEE80211_NODE_LOCK(nt); ni = ieee80211_find_node_locked(nt, mac); IEEE80211_NODE_UNLOCK(nt); @@ -2528,9 +2529,14 @@ ieee80211_scanreq(struct ieee80211vap *vap, struct ieee80211_scan_req *sr) static __noinline int ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq) { + struct ieee80211com *ic = vap->iv_ic; struct ieee80211_scan_req sr; /* XXX off stack? */ int error; + /* NB: parent must be running */ + if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + return ENXIO; + if (ireq->i_len != sizeof(sr)) return EINVAL; error = copyin(ireq->i_data, &sr, sizeof(sr)); @@ -3294,6 +3300,41 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r 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 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { @@ -3306,11 +3347,8 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) switch (cmd) { case SIOCSIFFLAGS: IEEE80211_LOCK(ic); - if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_PROMISC) - 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; + ieee80211_syncifflag_locked(ic, IFF_PROMISC); + ieee80211_syncifflag_locked(ic, IFF_ALLMULTI); if (ifp->if_flags & IFF_UP) { /* * Bring ourself up unless we're already operational. @@ -3333,7 +3371,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCADDMULTI: case SIOCDELMULTI: - ieee80211_runtask(ic, &ic->ic_mcast_task); + ieee80211_ioctl_updatemulti(ic); break; case SIOCSIFMEDIA: case SIOCGIFMEDIA: @@ -3389,16 +3427,17 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 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: - /* - * 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); break; } - return (error); + return error; } diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index eb333da1..d11628d 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -254,6 +254,10 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, /* NB: IFQ_HANDOFF reclaims mbuf */ ieee80211_free_node(ni); if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + } else { + if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast); + if_inc_counter(ifp, IFCOUNTER_OBYTES, len); } ic->ic_lastdata = ticks; @@ -426,6 +430,17 @@ ieee80211_vap_transmit(struct ifnet *ifp, struct mbuf *m) { struct ieee80211vap *vap = ifp->if_softc; struct ieee80211com *ic = vap->iv_ic; + struct ifnet *parent = ic->ic_ifp; + + /* NB: parent must be up and running */ + if (!IFNET_IS_UP_RUNNING(parent)) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT, + "%s: ignore queue, parent %s not up+running\n", + __func__, parent->if_xname); + m_freem(m); + if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + return (ENETDOWN); + } /* * No data frames go out unless we're running. @@ -492,7 +507,6 @@ ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni, struct mbuf *m, const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = vap->iv_ic; - int error; /* * Set node - the caller has taken a reference, so ensure @@ -514,10 +528,7 @@ ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni, if (params) (void) ieee80211_add_xmit_params(m, params); - error = ic->ic_raw_xmit(ni, m, params); - if (error) - if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, 1); - return (error); + return (ic->ic_raw_xmit(ni, m, params)); } /* @@ -3446,15 +3457,6 @@ ieee80211_tx_complete(struct ieee80211_node *ni, struct mbuf *m, int status) { if (ni != NULL) { - struct ifnet *ifp = ni->ni_vap->iv_ifp; - - if (status == 0) { - if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - if (m->m_flags & M_MCAST) - if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1); - } else - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); if (m->m_flags & M_TXCB) ieee80211_process_callback(ni, m, status); ieee80211_free_node(ni); diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c index 2d216c2..91668cc 100644 --- a/sys/net80211/ieee80211_power.c +++ b/sys/net80211/ieee80211_power.c @@ -418,6 +418,7 @@ pwrsave_flushq(struct ieee80211_node *ni) struct ieee80211com *ic = ni->ni_ic; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_psq_head *qhead; + struct ifnet *parent, *ifp; struct mbuf *parent_q = NULL, *ifp_q = NULL; struct mbuf *m; @@ -428,51 +429,59 @@ pwrsave_flushq(struct ieee80211_node *ni) qhead = &psq->psq_head[0]; /* 802.11 frames */ if (qhead->head != NULL) { /* XXX could dispatch through vap and check M_ENCAP */ + parent = vap->iv_ic->ic_ifp; /* XXX need different driver interface */ /* XXX bypasses q max and OACTIVE */ parent_q = qhead->head; qhead->head = qhead->tail = NULL; qhead->len = 0; - } + } else + parent = NULL; qhead = &psq->psq_head[1]; /* 802.3 frames */ if (qhead->head != NULL) { + ifp = vap->iv_ifp; /* XXX need different driver interface */ /* XXX bypasses q max and OACTIVE */ ifp_q = qhead->head; qhead->head = qhead->tail = NULL; qhead->len = 0; - } + } else + ifp = NULL; psq->psq_len = 0; IEEE80211_PSQ_UNLOCK(psq); /* NB: do this outside the psq lock */ /* XXX packets might get reordered if parent is OACTIVE */ /* parent frames, should be encapsulated */ - while (parent_q != NULL) { - m = parent_q; - parent_q = m->m_nextpkt; - m->m_nextpkt = NULL; - /* must be encapsulated */ - KASSERT((m->m_flags & M_ENCAP), - ("%s: parentq with non-M_ENCAP frame!\n", - __func__)); - /* - * For encaped frames, we need to free the node - * reference upon failure. - */ - if (ieee80211_parent_xmitpkt(ic, m) != 0) - ieee80211_free_node(ni); + if (parent != NULL) { + while (parent_q != NULL) { + m = parent_q; + parent_q = m->m_nextpkt; + m->m_nextpkt = NULL; + /* must be encapsulated */ + KASSERT((m->m_flags & M_ENCAP), + ("%s: parentq with non-M_ENCAP frame!\n", + __func__)); + /* + * For encaped frames, we need to free the node + * reference upon failure. + */ + if (ieee80211_parent_xmitpkt(ic, m) != 0) + ieee80211_free_node(ni); + } } /* VAP frames, aren't encapsulated */ - while (ifp_q != NULL) { - m = ifp_q; - ifp_q = m->m_nextpkt; - m->m_nextpkt = NULL; - KASSERT((!(m->m_flags & M_ENCAP)), - ("%s: vapq with M_ENCAP frame!\n", __func__)); - (void) ieee80211_vap_xmitpkt(vap, m); + if (ifp != NULL) { + while (ifp_q != NULL) { + m = ifp_q; + ifp_q = m->m_nextpkt; + m->m_nextpkt = NULL; + KASSERT((!(m->m_flags & M_ENCAP)), + ("%s: vapq with M_ENCAP frame!\n", __func__)); + (void) ieee80211_vap_xmitpkt(vap, m); + } } } diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c index 7adf044..01c60e1 100644 --- a/sys/net80211/ieee80211_proto.c +++ b/sys/net80211/ieee80211_proto.c @@ -122,23 +122,23 @@ null_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, void ieee80211_proto_attach(struct ieee80211com *ic) { - uint8_t hdrlen; + struct ifnet *ifp = ic->ic_ifp; /* override the 802.3 setting */ - hdrlen = ic->ic_headroom + ifp->if_hdrlen = ic->ic_headroom + sizeof(struct ieee80211_qosframe_addr4) + IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_EXTIVLEN; /* XXX no way to recalculate on ifdetach */ - if (ALIGN(hdrlen) > max_linkhdr) { + if (ALIGN(ifp->if_hdrlen) > max_linkhdr) { /* XXX sanity check... */ - max_linkhdr = ALIGN(hdrlen); + max_linkhdr = ALIGN(ifp->if_hdrlen); max_hdr = max_linkhdr + max_protohdr; max_datalen = MHLEN - max_hdr; } ic->ic_protmode = IEEE80211_PROT_CTSONLY; - TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ic); + TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ifp); TASK_INIT(&ic->ic_mcast_task, 0, update_mcast, ic); TASK_INIT(&ic->ic_promisc_task, 0, update_promisc, ic); TASK_INIT(&ic->ic_chan_task, 0, update_channel, ic); @@ -188,10 +188,7 @@ ieee80211_proto_vattach(struct ieee80211vap *vap) int i; /* override the 802.3 setting */ - ifp->if_hdrlen = ic->ic_headroom - + sizeof(struct ieee80211_qosframe_addr4) - + IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN - + IEEE80211_WEP_EXTIVLEN; + ifp->if_hdrlen = ic->ic_ifp->if_hdrlen; vap->iv_rtsthreshold = IEEE80211_RTS_DEFAULT; vap->iv_fragthreshold = IEEE80211_FRAG_DEFAULT; @@ -1158,9 +1155,9 @@ ieee80211_wme_updateparams(struct ieee80211vap *vap) static void parent_updown(void *arg, int npending) { - struct ieee80211com *ic = arg; + struct ifnet *parent = arg; - ic->ic_parent(ic); + parent->if_ioctl(parent, SIOCSIFFLAGS, NULL); } static void @@ -1227,6 +1224,7 @@ ieee80211_start_locked(struct ieee80211vap *vap) { struct ifnet *ifp = vap->iv_ifp; struct ieee80211com *ic = vap->iv_ic; + struct ifnet *parent = ic->ic_ifp; IEEE80211_LOCK_ASSERT(ic); @@ -1248,10 +1246,12 @@ ieee80211_start_locked(struct ieee80211vap *vap) * We are not running; if this we are the first vap * to be brought up auto-up the parent if necessary. */ - if (ic->ic_nrunning++ == 0) { + if (ic->ic_nrunning++ == 0 && + (parent->if_drv_flags & IFF_DRV_RUNNING) == 0) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, - "%s: up parent %s\n", __func__, ic->ic_name); + "%s: up parent %s\n", __func__, parent->if_xname); + parent->if_flags |= IFF_UP; ieee80211_runtask(ic, &ic->ic_parent_task); return; } @@ -1260,7 +1260,8 @@ ieee80211_start_locked(struct ieee80211vap *vap) * If the parent is up and running, then kick the * 802.11 state machine as appropriate. */ - if (vap->iv_roaming != IEEE80211_ROAMING_MANUAL) { + if ((parent->if_drv_flags & IFF_DRV_RUNNING) && + vap->iv_roaming != IEEE80211_ROAMING_MANUAL) { if (vap->iv_opmode == IEEE80211_M_STA) { #if 0 /* XXX bypasses scan too easily; disable for now */ @@ -1343,6 +1344,7 @@ ieee80211_stop_locked(struct ieee80211vap *vap) { struct ieee80211com *ic = vap->iv_ic; struct ifnet *ifp = vap->iv_ifp; + struct ifnet *parent = ic->ic_ifp; IEEE80211_LOCK_ASSERT(ic); @@ -1352,10 +1354,12 @@ ieee80211_stop_locked(struct ieee80211vap *vap) ieee80211_new_state_locked(vap, IEEE80211_S_INIT, -1); if (ifp->if_drv_flags & IFF_DRV_RUNNING) { ifp->if_drv_flags &= ~IFF_DRV_RUNNING; /* mark us stopped */ - if (--ic->ic_nrunning == 0) { + if (--ic->ic_nrunning == 0 && + (parent->if_drv_flags & IFF_DRV_RUNNING)) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, - "down parent %s\n", ic->ic_name); + "down parent %s\n", parent->if_xname); + parent->if_flags &= ~IFF_UP; ieee80211_runtask(ic, &ic->ic_parent_task); } } diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h index b5918b4..a812393 100644 --- a/sys/net80211/ieee80211_proto.h +++ b/sys/net80211/ieee80211_proto.h @@ -56,8 +56,7 @@ void ieee80211_proto_detach(struct ieee80211com *); void ieee80211_proto_vattach(struct ieee80211vap *); void ieee80211_proto_vdetach(struct ieee80211vap *); -void ieee80211_promisc(struct ieee80211vap *, bool); -void ieee80211_allmulti(struct ieee80211vap *, bool); +void ieee80211_syncifflag_locked(struct ieee80211com *, int flag); void ieee80211_syncflag(struct ieee80211vap *, int flag); void ieee80211_syncflag_ht(struct ieee80211vap *, int flag); void ieee80211_syncflag_ext(struct ieee80211vap *, int flag); diff --git a/sys/net80211/ieee80211_regdomain.c b/sys/net80211/ieee80211_regdomain.c index efbe1a8..9dfef2c 100644 --- a/sys/net80211/ieee80211_regdomain.c +++ b/sys/net80211/ieee80211_regdomain.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> + #include <sys/socket.h> #include <net/if.h> @@ -486,7 +487,7 @@ ieee80211_setregdomain(struct ieee80211vap *vap, memset(&ic->ic_channels[ic->ic_nchans], 0, (IEEE80211_CHAN_MAX - ic->ic_nchans) * sizeof(struct ieee80211_channel)); - ieee80211_chan_init(ic); + ieee80211_media_init(ic); /* * Invalidate channel-related state. diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c index 709710c..c0cbb7d 100644 --- a/sys/net80211/ieee80211_scan_sta.c +++ b/sys/net80211/ieee80211_scan_sta.c @@ -1706,6 +1706,26 @@ static const struct ieee80211_scanner adhoc_default = { IEEE80211_SCANNER_ALG(ibss, IEEE80211_M_IBSS, adhoc_default); IEEE80211_SCANNER_ALG(ahdemo, IEEE80211_M_AHDEMO, adhoc_default); +static void +ap_force_promisc(struct ieee80211com *ic) +{ + struct ifnet *ifp = ic->ic_ifp; + + IEEE80211_LOCK(ic); + /* set interface into promiscuous mode */ + ifp->if_flags |= IFF_PROMISC; + ieee80211_runtask(ic, &ic->ic_promisc_task); + IEEE80211_UNLOCK(ic); +} + +static void +ap_reset_promisc(struct ieee80211com *ic) +{ + IEEE80211_LOCK(ic); + ieee80211_syncifflag_locked(ic, IFF_PROMISC); + IEEE80211_UNLOCK(ic); +} + static int ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) { @@ -1721,7 +1741,7 @@ ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) st->st_scangen++; st->st_newscan = 1; - ieee80211_promisc(vap, true); + ap_force_promisc(vap->iv_ic); return 0; } @@ -1731,7 +1751,7 @@ ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) static int ap_cancel(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) { - ieee80211_promisc(vap, false); + ap_reset_promisc(vap->iv_ic); return 0; } @@ -1805,7 +1825,7 @@ ap_end(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) return 0; } } - ieee80211_promisc(vap, false); + ap_reset_promisc(ic); if (ss->ss_flags & (IEEE80211_SCAN_NOPICK | IEEE80211_SCAN_NOJOIN)) { /* * Manual/background scan, don't select+join the diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index a450701..26238b8 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -116,15 +116,16 @@ struct ieee80211_superg; struct ieee80211_frame; struct ieee80211com { + struct ifnet *ic_ifp; /* associated device */ void *ic_softc; /* driver softc */ const char *ic_name; /* usually device name */ ieee80211_com_lock_t ic_comlock; /* state update lock */ ieee80211_tx_lock_t ic_txlock; /* ic/vap TX lock */ - LIST_ENTRY(ieee80211com) ic_next; /* on global list */ TAILQ_HEAD(, ieee80211vap) ic_vaps; /* list of vap instances */ int ic_headroom; /* driver tx headroom needs */ enum ieee80211_phytype ic_phytype; /* XXX wrong for multi-mode */ enum ieee80211_opmode ic_opmode; /* operation mode */ + struct ifmedia ic_media; /* interface media config */ struct callout ic_inact; /* inactivity processing */ struct taskqueue *ic_tq; /* deferred state thread */ struct task ic_parent_task; /* deferred parent processing */ @@ -150,7 +151,6 @@ struct ieee80211com { uint8_t ic_allmulti; /* vap's needing all multicast*/ uint8_t ic_nrunning; /* vap's marked running */ uint8_t ic_curmode; /* current mode */ - uint8_t ic_macaddr[IEEE80211_ADDR_LEN]; uint16_t ic_bintval; /* beacon interval */ uint16_t ic_lintval; /* listen interval */ uint16_t ic_holdover; /* PM hold over duration */ @@ -241,11 +241,6 @@ struct ieee80211com { const uint8_t [IEEE80211_ADDR_LEN], const uint8_t [IEEE80211_ADDR_LEN]); void (*ic_vap_delete)(struct ieee80211vap *); - /* device specific ioctls */ - int (*ic_ioctl)(struct ieee80211com *, - u_long, void *); - /* start/stop device */ - void (*ic_parent)(struct ieee80211com *); /* operating mode attachment */ ieee80211vap_attach ic_vattach[IEEE80211_OPMODE_MAX]; /* return hardware/radio capabilities */ @@ -259,9 +254,6 @@ struct ieee80211com { int (*ic_set_quiet)(struct ieee80211_node *, u_int8_t *quiet_elm); - /* regular transmit */ - int (*ic_transmit)(struct ieee80211com *, - struct mbuf *); /* send/recv 802.11 management frame */ int (*ic_send_mgmt)(struct ieee80211_node *, int, int); @@ -359,15 +351,14 @@ struct ieee80211vap { TAILQ_ENTRY(ieee80211vap) iv_next; /* list of vap instances */ struct ieee80211com *iv_ic; /* back ptr to common state */ - const uint8_t *iv_myaddr; /* MAC address: ifp or ic */ uint32_t iv_debug; /* debug msg flags */ struct ieee80211_stats iv_stats; /* statistics */ + uint8_t iv_myaddr[IEEE80211_ADDR_LEN]; uint32_t iv_flags; /* state flags */ uint32_t iv_flags_ext; /* extended state flags */ uint32_t iv_flags_ht; /* HT state flags */ uint32_t iv_flags_ven; /* vendor state flags */ - uint32_t iv_ifflags; /* ifnet flags */ uint32_t iv_caps; /* capabilities */ uint32_t iv_htcaps; /* HT capabilities */ uint32_t iv_htextcaps; /* HT extended capabilities */ @@ -690,24 +681,24 @@ MALLOC_DECLARE(M_80211_VAP); "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS" int ic_printf(struct ieee80211com *, const char *, ...) __printflike(2, 3); -void ieee80211_ifattach(struct ieee80211com *); +void ieee80211_ifattach(struct ieee80211com *, + const uint8_t macaddr[IEEE80211_ADDR_LEN]); void ieee80211_ifdetach(struct ieee80211com *); int ieee80211_vap_setup(struct ieee80211com *, struct ieee80211vap *, const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN]); -int ieee80211_vap_attach(struct ieee80211vap *, - ifm_change_cb_t, ifm_stat_cb_t, + const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t macaddr[IEEE80211_ADDR_LEN]); +int ieee80211_vap_attach(struct ieee80211vap *, + ifm_change_cb_t, ifm_stat_cb_t); void ieee80211_vap_detach(struct ieee80211vap *); const struct ieee80211_rateset *ieee80211_get_suprates(struct ieee80211com *ic, const struct ieee80211_channel *); void ieee80211_announce(struct ieee80211com *); void ieee80211_announce_channels(struct ieee80211com *); void ieee80211_drain(struct ieee80211com *); -void ieee80211_chan_init(struct ieee80211com *); +void ieee80211_media_init(struct ieee80211com *); struct ieee80211com *ieee80211_find_vap(const uint8_t mac[IEEE80211_ADDR_LEN]); -struct ieee80211com *ieee80211_find_com(const char *name); int ieee80211_media_change(struct ifnet *); void ieee80211_media_status(struct ifnet *, struct ifmediareq *); int ieee80211_ioctl(struct ifnet *, u_long, caddr_t); |