summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2015-08-08 01:10:17 +0000
committeradrian <adrian@FreeBSD.org>2015-08-08 01:10:17 +0000
commitbad6d5c89b6ffd35818850d95cb88e218dee73b3 (patch)
tree5973a9059f73ed5abf84d6d98e44f1953e764064 /sys/net80211
parent33a3844dbf69152b9d47f6fa1ac1c2d5b1d502e4 (diff)
downloadFreeBSD-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.c282
-rw-r--r--sys/net80211/ieee80211_ddb.c3
-rw-r--r--sys/net80211/ieee80211_freebsd.c90
-rw-r--r--sys/net80211/ieee80211_ioctl.c71
-rw-r--r--sys/net80211/ieee80211_output.c30
-rw-r--r--sys/net80211/ieee80211_power.c55
-rw-r--r--sys/net80211/ieee80211_proto.c36
-rw-r--r--sys/net80211/ieee80211_proto.h3
-rw-r--r--sys/net80211/ieee80211_regdomain.c3
-rw-r--r--sys/net80211/ieee80211_scan_sta.c26
-rw-r--r--sys/net80211/ieee80211_var.h27
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);
OpenPOWER on IntegriCloud