Import FreeBSD's net80211(9) of 1-nov-2005
This commit is contained in:
parent
02d3eacb6e
commit
a0f92c66a0
|
@ -29,7 +29,7 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/net80211/_ieee80211.h,v 1.2 2004/12/31 22:42:38 sam Exp $
|
||||
* $FreeBSD: src/sys/net80211/_ieee80211.h,v 1.3 2005/08/10 17:42:13 sam Exp $
|
||||
*/
|
||||
#ifndef _NET80211__IEEE80211_H_
|
||||
#define _NET80211__IEEE80211_H_
|
||||
|
@ -152,6 +152,8 @@ struct ieee80211_channel {
|
|||
(((_c)->ic_flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG)
|
||||
#define IEEE80211_IS_CHAN_G(_c) \
|
||||
(((_c)->ic_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)
|
||||
#define IEEE80211_IS_CHAN_ANYG(_c) \
|
||||
(IEEE80211_IS_CHAN_PUREG(_c) || IEEE80211_IS_CHAN_G(_c))
|
||||
#define IEEE80211_IS_CHAN_T(_c) \
|
||||
(((_c)->ic_flags & IEEE80211_CHAN_T) == IEEE80211_CHAN_T)
|
||||
#define IEEE80211_IS_CHAN_108G(_c) \
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211.c,v 1.19 2005/01/27 17:39:17 sam Exp $");
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211.c,v 1.22 2005/08/10 16:22:29 sam Exp $");
|
||||
|
||||
/*
|
||||
* IEEE 802.11 generic handler
|
||||
|
@ -167,6 +167,10 @@ ieee80211_ifattach(struct ieee80211com *ic)
|
|||
ic->ic_modecaps |= 1<<IEEE80211_MODE_TURBO_A;
|
||||
if (IEEE80211_IS_CHAN_108G(c))
|
||||
ic->ic_modecaps |= 1<<IEEE80211_MODE_TURBO_G;
|
||||
if (ic->ic_curchan == NULL) {
|
||||
/* arbitrarily pick the first channel */
|
||||
ic->ic_curchan = &ic->ic_channels[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* validate ic->ic_curmode */
|
||||
|
@ -182,12 +186,14 @@ ieee80211_ifattach(struct ieee80211com *ic)
|
|||
#endif
|
||||
(void) ieee80211_setmode(ic, ic->ic_curmode);
|
||||
|
||||
if (ic->ic_lintval == 0)
|
||||
ic->ic_lintval = IEEE80211_BINTVAL_DEFAULT;
|
||||
ic->ic_bmisstimeout = 7*ic->ic_lintval; /* default 7 beacons */
|
||||
if (ic->ic_bintval == 0)
|
||||
ic->ic_bintval = IEEE80211_BINTVAL_DEFAULT;
|
||||
ic->ic_bmisstimeout = 7*ic->ic_bintval; /* default 7 beacons */
|
||||
ic->ic_dtim_period = IEEE80211_DTIM_DEFAULT;
|
||||
IEEE80211_BEACON_LOCK_INIT(ic, "beacon");
|
||||
|
||||
if (ic->ic_lintval == 0)
|
||||
ic->ic_lintval = ic->ic_bintval;
|
||||
ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX;
|
||||
|
||||
ieee80211_node_attach(ic);
|
||||
|
@ -665,7 +671,7 @@ ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
|
|||
/*
|
||||
* Calculate a current rate if possible.
|
||||
*/
|
||||
if (ic->ic_fixed_rate != -1) {
|
||||
if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
|
||||
/*
|
||||
* A fixed rate is set, report that.
|
||||
*/
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/net80211/ieee80211.h,v 1.9 2005/06/10 04:42:34 sam Exp $
|
||||
* $FreeBSD: src/sys/net80211/ieee80211.h,v 1.10 2005/07/22 16:55:27 sam Exp $
|
||||
*/
|
||||
#ifndef _NET80211_IEEE80211_H_
|
||||
#define _NET80211_IEEE80211_H_
|
||||
|
@ -622,10 +622,18 @@ enum {
|
|||
|
||||
/*
|
||||
* RTS frame length parameters. The default is specified in
|
||||
* the 802.11 spec. The max may be wrong for jumbo frames.
|
||||
* the 802.11 spec as 512; we treat it as implementation-dependent
|
||||
* so it's defined in ieee80211_var.h. The max may be wrong
|
||||
* for jumbo frames.
|
||||
*/
|
||||
#define IEEE80211_RTS_DEFAULT 512
|
||||
#define IEEE80211_RTS_MIN 1
|
||||
#define IEEE80211_RTS_MAX IEEE80211_MAX_LEN
|
||||
#define IEEE80211_RTS_MAX 2346
|
||||
|
||||
/*
|
||||
* TX fragmentation parameters. As above for RTS, we treat
|
||||
* default as implementation-dependent so define it elsewhere.
|
||||
*/
|
||||
#define IEEE80211_FRAG_MIN 256
|
||||
#define IEEE80211_FRAG_MAX 2346
|
||||
|
||||
#endif /* _NET80211_IEEE80211_H_ */
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_acl.c,v 1.3 2004/12/31 22:42:38 sam Exp $");
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_acl.c,v 1.4 2005/08/13 17:31:48 sam Exp $");
|
||||
|
||||
/*
|
||||
* IEEE 802.11 MAC ACL support.
|
||||
|
@ -75,6 +75,7 @@ struct acl {
|
|||
struct aclstate {
|
||||
acl_lock_t as_lock;
|
||||
int as_policy;
|
||||
int as_nacls;
|
||||
TAILQ_HEAD(, acl) as_list; /* list of all ACL's */
|
||||
LIST_HEAD(, acl) as_hash[ACL_HASHSIZE];
|
||||
struct ieee80211com *as_ic;
|
||||
|
@ -94,7 +95,7 @@ acl_attach(struct ieee80211com *ic)
|
|||
struct aclstate *as;
|
||||
|
||||
MALLOC(as, struct aclstate *, sizeof(struct aclstate),
|
||||
M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
M_80211_ACL, M_NOWAIT | M_ZERO);
|
||||
if (as == NULL)
|
||||
return 0;
|
||||
ACL_LOCK_INIT(as, "acl");
|
||||
|
@ -138,6 +139,7 @@ _acl_free(struct aclstate *as, struct acl *acl)
|
|||
TAILQ_REMOVE(&as->as_list, acl, acl_list);
|
||||
LIST_REMOVE(acl, acl_hash);
|
||||
FREE(acl, M_80211_ACL);
|
||||
as->as_nacls--;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -186,6 +188,7 @@ acl_add(struct ieee80211com *ic, const u_int8_t mac[IEEE80211_ADDR_LEN])
|
|||
IEEE80211_ADDR_COPY(new->acl_macaddr, mac);
|
||||
TAILQ_INSERT_TAIL(&as->as_list, new, acl_list);
|
||||
LIST_INSERT_HEAD(&as->as_hash[hash], new, acl_hash);
|
||||
as->as_nacls++;
|
||||
ACL_UNLOCK(as);
|
||||
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_ACL,
|
||||
|
@ -260,6 +263,53 @@ acl_getpolicy(struct ieee80211com *ic)
|
|||
return as->as_policy;
|
||||
}
|
||||
|
||||
static int
|
||||
acl_setioctl(struct ieee80211com *ic, struct ieee80211req *ireq)
|
||||
{
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
acl_getioctl(struct ieee80211com *ic, struct ieee80211req *ireq)
|
||||
{
|
||||
struct aclstate *as = ic->ic_as;
|
||||
struct acl *acl;
|
||||
struct ieee80211req_maclist *ap;
|
||||
int error, space, i;
|
||||
|
||||
switch (ireq->i_val) {
|
||||
case IEEE80211_MACCMD_POLICY:
|
||||
ireq->i_val = as->as_policy;
|
||||
return 0;
|
||||
case IEEE80211_MACCMD_LIST:
|
||||
space = as->as_nacls * IEEE80211_ADDR_LEN;
|
||||
if (ireq->i_len == 0) {
|
||||
ireq->i_len = space; /* return required space */
|
||||
return 0; /* NB: must not error */
|
||||
}
|
||||
MALLOC(ap, struct ieee80211req_maclist *, space,
|
||||
M_TEMP, M_NOWAIT);
|
||||
if (ap == NULL)
|
||||
return ENOMEM;
|
||||
i = 0;
|
||||
ACL_LOCK(as);
|
||||
TAILQ_FOREACH(acl, &as->as_list, acl_list) {
|
||||
IEEE80211_ADDR_COPY(ap[i].ml_macaddr, acl->acl_macaddr);
|
||||
i++;
|
||||
}
|
||||
ACL_UNLOCK(as);
|
||||
if (ireq->i_len >= space) {
|
||||
error = copyout(ap, ireq->i_data, space);
|
||||
ireq->i_len = space;
|
||||
} else
|
||||
error = copyout(ap, ireq->i_data, ireq->i_len);
|
||||
FREE(ap, M_TEMP);
|
||||
return error;
|
||||
}
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
static const struct ieee80211_aclator mac = {
|
||||
.iac_name = "mac",
|
||||
.iac_attach = acl_attach,
|
||||
|
@ -270,6 +320,8 @@ static const struct ieee80211_aclator mac = {
|
|||
.iac_flush = acl_free_all,
|
||||
.iac_setpolicy = acl_setpolicy,
|
||||
.iac_getpolicy = acl_getpolicy,
|
||||
.iac_setioctl = acl_setioctl,
|
||||
.iac_getioctl = acl_getioctl,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_crypto.c,v 1.10 2005/07/09 23:15:30 sam Exp $");
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_crypto.c,v 1.12 2005/08/08 18:46:35 sam Exp $");
|
||||
|
||||
/*
|
||||
* IEEE 802.11 generic crypto support.
|
||||
|
@ -59,7 +59,8 @@ static int _ieee80211_crypto_delkey(struct ieee80211com *,
|
|||
* Default "null" key management routines.
|
||||
*/
|
||||
static int
|
||||
null_key_alloc(struct ieee80211com *ic, const struct ieee80211_key *k)
|
||||
null_key_alloc(struct ieee80211com *ic, const struct ieee80211_key *k,
|
||||
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
|
||||
{
|
||||
if (!(&ic->ic_nw_keys[0] <= k &&
|
||||
k < &ic->ic_nw_keys[IEEE80211_WEP_NKID])) {
|
||||
|
@ -73,12 +74,14 @@ null_key_alloc(struct ieee80211com *ic, const struct ieee80211_key *k)
|
|||
* packets through untouched when marked with the WEP bit
|
||||
* and key index 0.
|
||||
*/
|
||||
if ((k->wk_flags & IEEE80211_KEY_GROUP) == 0)
|
||||
return 0; /* NB: use key index 0 for ucast key */
|
||||
else
|
||||
return IEEE80211_KEYIX_NONE;
|
||||
if (k->wk_flags & IEEE80211_KEY_GROUP)
|
||||
return 0;
|
||||
*keyix = 0; /* NB: use key index 0 for ucast key */
|
||||
} else {
|
||||
*keyix = k - ic->ic_nw_keys;
|
||||
}
|
||||
return k - ic->ic_nw_keys;
|
||||
*rxkeyix = IEEE80211_KEYIX_NONE; /* XXX maybe *keyix? */
|
||||
return 1;
|
||||
}
|
||||
static int
|
||||
null_key_delete(struct ieee80211com *ic, const struct ieee80211_key *k)
|
||||
|
@ -113,9 +116,10 @@ cipher_attach(struct ieee80211com *ic, struct ieee80211_key *key)
|
|||
*/
|
||||
static __inline int
|
||||
dev_key_alloc(struct ieee80211com *ic,
|
||||
const struct ieee80211_key *key)
|
||||
const struct ieee80211_key *key,
|
||||
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
|
||||
{
|
||||
return ic->ic_crypto.cs_key_alloc(ic, key);
|
||||
return ic->ic_crypto.cs_key_alloc(ic, key, keyix, rxkeyix);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
|
@ -143,6 +147,7 @@ ieee80211_crypto_attach(struct ieee80211com *ic)
|
|||
|
||||
/* NB: we assume everything is pre-zero'd */
|
||||
cs->cs_def_txkey = IEEE80211_KEYIX_NONE;
|
||||
cs->cs_max_keyix = IEEE80211_WEP_NKID;
|
||||
ciphers[IEEE80211_CIPHER_NONE] = &ieee80211_cipher_none;
|
||||
for (i = 0; i < IEEE80211_WEP_NKID; i++)
|
||||
ieee80211_crypto_resetkey(ic, &cs->cs_nw_keys[i],
|
||||
|
@ -241,6 +246,7 @@ ieee80211_crypto_newkey(struct ieee80211com *ic,
|
|||
{
|
||||
#define N(a) (sizeof(a) / sizeof(a[0]))
|
||||
const struct ieee80211_cipher *cip;
|
||||
ieee80211_keyix keyix, rxkeyix;
|
||||
void *keyctx;
|
||||
int oflags;
|
||||
|
||||
|
@ -354,8 +360,7 @@ again:
|
|||
* crypto we also call the driver to give us a key index.
|
||||
*/
|
||||
if (key->wk_keyix == IEEE80211_KEYIX_NONE) {
|
||||
key->wk_keyix = dev_key_alloc(ic, key);
|
||||
if (key->wk_keyix == IEEE80211_KEYIX_NONE) {
|
||||
if (!dev_key_alloc(ic, key, &keyix, &rxkeyix)) {
|
||||
/*
|
||||
* Driver has no room; fallback to doing crypto
|
||||
* in the host. We change the flags and start the
|
||||
|
@ -382,6 +387,8 @@ again:
|
|||
__func__, cip->ic_name);
|
||||
return 0;
|
||||
}
|
||||
key->wk_keyix = keyix;
|
||||
key->wk_rxkeyix = rxkeyix;
|
||||
}
|
||||
return 1;
|
||||
#undef N
|
||||
|
@ -393,7 +400,7 @@ again:
|
|||
static int
|
||||
_ieee80211_crypto_delkey(struct ieee80211com *ic, struct ieee80211_key *key)
|
||||
{
|
||||
u_int16_t keyix;
|
||||
ieee80211_keyix keyix;
|
||||
|
||||
KASSERT(key->wk_cipher != NULL, ("No cipher!"));
|
||||
|
||||
|
@ -543,7 +550,7 @@ ieee80211_crypto_decap(struct ieee80211com *ic,
|
|||
{
|
||||
#define IEEE80211_WEP_HDRLEN (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)
|
||||
#define IEEE80211_WEP_MINLEN \
|
||||
(sizeof(struct ieee80211_frame) + ETHER_HDR_LEN + \
|
||||
(sizeof(struct ieee80211_frame) + \
|
||||
IEEE80211_WEP_HDRLEN + IEEE80211_WEP_CRCLEN)
|
||||
struct ieee80211_key *k;
|
||||
struct ieee80211_frame *wh;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/net80211/ieee80211_crypto.h,v 1.9 2005/06/10 16:11:24 sam Exp $
|
||||
* $FreeBSD: src/sys/net80211/ieee80211_crypto.h,v 1.10 2005/08/08 18:46:35 sam Exp $
|
||||
*/
|
||||
#ifndef _NET80211_IEEE80211_CRYPTO_H_
|
||||
#define _NET80211_IEEE80211_CRYPTO_H_
|
||||
|
@ -66,18 +66,19 @@ struct ieee80211_cipher;
|
|||
* Ciphers such as TKIP may also support mixed hardware/software
|
||||
* encrypt/decrypt and MIC processing.
|
||||
*/
|
||||
/* XXX need key index typedef */
|
||||
/* XXX pack better? */
|
||||
/* XXX 48-bit rsc/tsc */
|
||||
typedef u_int16_t ieee80211_keyix; /* h/w key index */
|
||||
|
||||
struct ieee80211_key {
|
||||
u_int8_t wk_keylen; /* key length in bytes */
|
||||
u_int8_t wk_flags;
|
||||
u_int8_t wk_pad;
|
||||
u_int16_t wk_flags;
|
||||
#define IEEE80211_KEY_XMIT 0x01 /* key used for xmit */
|
||||
#define IEEE80211_KEY_RECV 0x02 /* key used for recv */
|
||||
#define IEEE80211_KEY_GROUP 0x04 /* key used for WPA group operation */
|
||||
#define IEEE80211_KEY_SWCRYPT 0x10 /* host-based encrypt/decrypt */
|
||||
#define IEEE80211_KEY_SWMIC 0x20 /* host-based enmic/demic */
|
||||
u_int16_t wk_keyix; /* key index */
|
||||
ieee80211_keyix wk_keyix; /* h/w key index */
|
||||
ieee80211_keyix wk_rxkeyix; /* optional h/w rx key index */
|
||||
u_int8_t wk_key[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
|
||||
#define wk_txmic wk_key+IEEE80211_KEYBUF_SIZE+0 /* XXX can't () right */
|
||||
#define wk_rxmic wk_key+IEEE80211_KEYBUF_SIZE+8 /* XXX can't () right */
|
||||
|
@ -103,7 +104,7 @@ struct ieee80211_key {
|
|||
|
||||
#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_NONE+1)
|
||||
|
||||
#define IEEE80211_KEYIX_NONE ((u_int16_t) -1)
|
||||
#define IEEE80211_KEYIX_NONE ((ieee80211_keyix) -1)
|
||||
|
||||
#if defined(__KERNEL__) || defined(_KERNEL)
|
||||
|
||||
|
@ -120,10 +121,12 @@ struct mbuf;
|
|||
*/
|
||||
struct ieee80211_crypto_state {
|
||||
struct ieee80211_key cs_nw_keys[IEEE80211_WEP_NKID];
|
||||
u_int16_t cs_def_txkey; /* default/group tx key index */
|
||||
ieee80211_keyix cs_def_txkey; /* default/group tx key index */
|
||||
u_int16_t cs_max_keyix; /* max h/w key index */
|
||||
|
||||
int (*cs_key_alloc)(struct ieee80211com *,
|
||||
const struct ieee80211_key *);
|
||||
const struct ieee80211_key *,
|
||||
ieee80211_keyix *, ieee80211_keyix *);
|
||||
int (*cs_key_delete)(struct ieee80211com *,
|
||||
const struct ieee80211_key *);
|
||||
int (*cs_key_set)(struct ieee80211com *,
|
||||
|
@ -204,11 +207,11 @@ ieee80211_crypto_enmic(struct ieee80211com *ic,
|
|||
*/
|
||||
static __inline void
|
||||
ieee80211_crypto_resetkey(struct ieee80211com *ic,
|
||||
struct ieee80211_key *k, u_int16_t ix)
|
||||
struct ieee80211_key *k, ieee80211_keyix ix)
|
||||
{
|
||||
k->wk_cipher = &ieee80211_cipher_none;;
|
||||
k->wk_private = k->wk_cipher->ic_attach(ic, k);
|
||||
k->wk_keyix = ix;
|
||||
k->wk_keyix = k->wk_rxkeyix = ix;
|
||||
k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_crypto_tkip.c,v 1.9 2005/06/10 16:11:24 sam Exp $");
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_crypto_tkip.c,v 1.10 2005/08/08 18:46:35 sam Exp $");
|
||||
|
||||
/*
|
||||
* IEEE 802.11i TKIP crypto support.
|
||||
|
@ -339,7 +339,9 @@ tkip_demic(struct ieee80211_key *k, struct mbuf *m, int force)
|
|||
tkip.ic_miclen, mic0);
|
||||
if (memcmp(mic, mic0, tkip.ic_miclen)) {
|
||||
/* NB: 802.11 layer handles statistic and debug msg */
|
||||
ieee80211_notify_michael_failure(ic, wh, k->wk_keyix);
|
||||
ieee80211_notify_michael_failure(ic, wh,
|
||||
k->wk_rxkeyix != IEEE80211_KEYIX_NONE ?
|
||||
k->wk_rxkeyix : k->wk_keyix);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_input.c,v 1.62 2005/07/11 03:00:20 sam Exp $");
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_input.c,v 1.81 2005/08/10 16:22:29 sam Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -112,6 +112,8 @@ static struct mbuf *ieee80211_defrag(struct ieee80211com *,
|
|||
static struct mbuf *ieee80211_decap(struct ieee80211com *, struct mbuf *, int);
|
||||
static void ieee80211_send_error(struct ieee80211com *, struct ieee80211_node *,
|
||||
const u_int8_t *mac, int subtype, int arg);
|
||||
static void ieee80211_deliver_data(struct ieee80211com *,
|
||||
struct ieee80211_node *, struct mbuf *);
|
||||
static void ieee80211_node_pwrsave(struct ieee80211_node *, int enable);
|
||||
static void ieee80211_recv_pspoll(struct ieee80211com *,
|
||||
struct ieee80211_node *, struct mbuf *);
|
||||
|
@ -136,7 +138,7 @@ ieee80211_input(struct ieee80211com *ic, struct mbuf *m,
|
|||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_key *key;
|
||||
struct ether_header *eh;
|
||||
int len, hdrspace;
|
||||
int hdrspace;
|
||||
u_int8_t dir, type, subtype;
|
||||
u_int8_t *bssid;
|
||||
u_int16_t rxseq;
|
||||
|
@ -295,6 +297,8 @@ ieee80211_input(struct ieee80211com *ic, struct mbuf *m,
|
|||
switch (ic->ic_opmode) {
|
||||
case IEEE80211_M_STA:
|
||||
if (dir != IEEE80211_FC1_DIR_FROMDS) {
|
||||
IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
|
||||
wh, "data", "%s", "unknown dir 0x%x", dir);
|
||||
ic->ic_stats.is_rx_wrongdir++;
|
||||
goto out;
|
||||
}
|
||||
|
@ -316,6 +320,8 @@ ieee80211_input(struct ieee80211com *ic, struct mbuf *m,
|
|||
case IEEE80211_M_IBSS:
|
||||
case IEEE80211_M_AHDEMO:
|
||||
if (dir != IEEE80211_FC1_DIR_NODS) {
|
||||
IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
|
||||
wh, "data", "%s", "unknown dir 0x%x", dir);
|
||||
ic->ic_stats.is_rx_wrongdir++;
|
||||
goto out;
|
||||
}
|
||||
|
@ -323,6 +329,8 @@ ieee80211_input(struct ieee80211com *ic, struct mbuf *m,
|
|||
break;
|
||||
case IEEE80211_M_HOSTAP:
|
||||
if (dir != IEEE80211_FC1_DIR_TODS) {
|
||||
IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
|
||||
wh, "data", "%s", "unknown dir 0x%x", dir);
|
||||
ic->ic_stats.is_rx_wrongdir++;
|
||||
goto out;
|
||||
}
|
||||
|
@ -469,54 +477,14 @@ ieee80211_input(struct ieee80211com *ic, struct mbuf *m,
|
|||
IEEE80211_NODE_STAT(ni, rx_data);
|
||||
IEEE80211_NODE_STAT_ADD(ni, rx_bytes, m->m_pkthdr.len);
|
||||
|
||||
/* perform as a bridge within the AP */
|
||||
if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
|
||||
(ic->ic_flags & IEEE80211_F_NOBRIDGE) == 0) {
|
||||
struct mbuf *m1 = NULL;
|
||||
|
||||
if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
|
||||
m1 = m_copypacket(m, M_DONTWAIT);
|
||||
if (m1 == NULL)
|
||||
ifp->if_oerrors++;
|
||||
else
|
||||
m1->m_flags |= M_MCAST;
|
||||
} else {
|
||||
/* XXX this dups work done in ieee80211_encap */
|
||||
/* check if destination is associated */
|
||||
struct ieee80211_node *ni1 =
|
||||
ieee80211_find_node(&ic->ic_sta,
|
||||
eh->ether_dhost);
|
||||
if (ni1 != NULL) {
|
||||
/* XXX check if authorized */
|
||||
if (ni1->ni_associd != 0) {
|
||||
m1 = m;
|
||||
m = NULL;
|
||||
}
|
||||
/* XXX statistic? */
|
||||
ieee80211_free_node(ni1);
|
||||
}
|
||||
}
|
||||
if (m1 != NULL) {
|
||||
len = m1->m_pkthdr.len;
|
||||
IF_ENQUEUE(&ifp->if_snd, m1);
|
||||
if (m != NULL)
|
||||
ifp->if_omcasts++;
|
||||
ifp->if_obytes += len;
|
||||
}
|
||||
}
|
||||
if (m != NULL) {
|
||||
if (ni->ni_vlan != 0) {
|
||||
/* attach vlan tag */
|
||||
/* XXX goto err? */
|
||||
VLAN_INPUT_TAG(ifp, m, ni->ni_vlan, goto out);
|
||||
}
|
||||
(*ifp->if_input)(ifp, m);
|
||||
}
|
||||
ieee80211_deliver_data(ic, ni, m);
|
||||
return IEEE80211_FC0_TYPE_DATA;
|
||||
|
||||
case IEEE80211_FC0_TYPE_MGT:
|
||||
IEEE80211_NODE_STAT(ni, rx_mgmt);
|
||||
if (dir != IEEE80211_FC1_DIR_NODS) {
|
||||
IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
|
||||
wh, "data", "%s", "unknown dir 0x%x", dir);
|
||||
ic->ic_stats.is_rx_wrongdir++;
|
||||
goto err;
|
||||
}
|
||||
|
@ -692,6 +660,69 @@ ieee80211_defrag(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
return mfrag;
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211_deliver_data(struct ieee80211com *ic,
|
||||
struct ieee80211_node *ni, struct mbuf *m)
|
||||
{
|
||||
struct ether_header *eh = mtod(m, struct ether_header *);
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
|
||||
/* perform as a bridge within the AP */
|
||||
if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
|
||||
(ic->ic_flags & IEEE80211_F_NOBRIDGE) == 0) {
|
||||
struct mbuf *m1 = NULL;
|
||||
|
||||
if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
|
||||
m1 = m_copypacket(m, M_DONTWAIT);
|
||||
if (m1 == NULL)
|
||||
ifp->if_oerrors++;
|
||||
else
|
||||
m1->m_flags |= M_MCAST;
|
||||
} else {
|
||||
/*
|
||||
* Check if the destination is known; if so
|
||||
* and the port is authorized dispatch directly.
|
||||
*/
|
||||
struct ieee80211_node *sta =
|
||||
ieee80211_find_node(&ic->ic_sta, eh->ether_dhost);
|
||||
if (sta != NULL) {
|
||||
if (ieee80211_node_is_authorized(sta)) {
|
||||
/*
|
||||
* Beware of sending to ourself; this
|
||||
* needs to happen via the normal
|
||||
* input path.
|
||||
*/
|
||||
if (sta != ic->ic_bss) {
|
||||
m1 = m;
|
||||
m = NULL;
|
||||
}
|
||||
} else {
|
||||
ic->ic_stats.is_rx_unauth++;
|
||||
IEEE80211_NODE_STAT(sta, rx_unauth);
|
||||
}
|
||||
ieee80211_free_node(sta);
|
||||
}
|
||||
}
|
||||
if (m1 != NULL)
|
||||
IF_HANDOFF(&ifp->if_snd, m1, ifp);
|
||||
}
|
||||
if (m != NULL) {
|
||||
if (ni->ni_vlan != 0) {
|
||||
/* attach vlan tag */
|
||||
/* XXX goto err? */
|
||||
VLAN_INPUT_TAG(ifp, m, ni->ni_vlan, goto out);
|
||||
}
|
||||
(*ifp->if_input)(ifp, m);
|
||||
}
|
||||
return;
|
||||
out:
|
||||
if (m != NULL) {
|
||||
if (ic->ic_rawbpf)
|
||||
bpf_mtap(ic->ic_rawbpf, m);
|
||||
m_freem(m);
|
||||
}
|
||||
}
|
||||
|
||||
static struct mbuf *
|
||||
ieee80211_decap(struct ieee80211com *ic, struct mbuf *m, int hdrlen)
|
||||
{
|
||||
|
@ -794,10 +825,11 @@ ieee80211_decap(struct ieee80211com *ic, struct mbuf *m, int hdrlen)
|
|||
/*
|
||||
* Install received rate set information in the node's state block.
|
||||
*/
|
||||
static int
|
||||
ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
u_int8_t *rates, u_int8_t *xrates, int flags)
|
||||
int
|
||||
ieee80211_setup_rates(struct ieee80211_node *ni,
|
||||
const u_int8_t *rates, const u_int8_t *xrates, int flags)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct ieee80211_rateset *rs = &ni->ni_rates;
|
||||
|
||||
memset(rs, 0, sizeof(*rs));
|
||||
|
@ -820,7 +852,7 @@ ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates);
|
||||
rs->rs_nrates += nxrates;
|
||||
}
|
||||
return ieee80211_fix_rate(ic, ni, flags);
|
||||
return ieee80211_fix_rate(ni, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -882,7 +914,7 @@ ieee80211_auth_open(struct ieee80211com *ic, struct ieee80211_frame *wh,
|
|||
* authorized at this point so traffic can flow.
|
||||
*/
|
||||
if (ni->ni_authmode != IEEE80211_AUTH_8021X)
|
||||
ieee80211_node_authorize(ic, ni);
|
||||
ieee80211_node_authorize(ni);
|
||||
break;
|
||||
|
||||
case IEEE80211_M_STA:
|
||||
|
@ -922,7 +954,7 @@ ieee80211_send_error(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
int istmp;
|
||||
|
||||
if (ni == ic->ic_bss) {
|
||||
ni = ieee80211_dup_bss(&ic->ic_sta, mac);
|
||||
ni = ieee80211_tmp_node(ic, mac);
|
||||
if (ni == NULL) {
|
||||
/* XXX msg */
|
||||
return;
|
||||
|
@ -1105,7 +1137,7 @@ ieee80211_auth_shared(struct ieee80211com *ic, struct ieee80211_frame *wh,
|
|||
IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
|
||||
"[%s] station authenticated (shared key)\n",
|
||||
ether_sprintf(ni->ni_macaddr));
|
||||
ieee80211_node_authorize(ic, ni);
|
||||
ieee80211_node_authorize(ni);
|
||||
break;
|
||||
default:
|
||||
IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
|
||||
|
@ -1361,8 +1393,12 @@ ieee80211_parse_wpa(struct ieee80211com *ic, u_int8_t *frm,
|
|||
* version, mcast cipher, and 2 selector counts.
|
||||
* Other, variable-length data, must be checked separately.
|
||||
*/
|
||||
KASSERT(ic->ic_flags & IEEE80211_F_WPA1,
|
||||
("not WPA, flags 0x%x", ic->ic_flags));
|
||||
if ((ic->ic_flags & IEEE80211_F_WPA1) == 0) {
|
||||
IEEE80211_DISCARD_IE(ic,
|
||||
IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
|
||||
wh, "WPA", "not WPA, flags 0x%x", ic->ic_flags);
|
||||
return IEEE80211_REASON_IE_INVALID;
|
||||
}
|
||||
if (len < 14) {
|
||||
IEEE80211_DISCARD_IE(ic,
|
||||
IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
|
||||
|
@ -1524,8 +1560,12 @@ ieee80211_parse_rsn(struct ieee80211com *ic, u_int8_t *frm,
|
|||
* version, mcast cipher, and 2 selector counts.
|
||||
* Other, variable-length data, must be checked separately.
|
||||
*/
|
||||
KASSERT(ic->ic_flags & IEEE80211_F_WPA2,
|
||||
("not RSN, flags 0x%x", ic->ic_flags));
|
||||
if ((ic->ic_flags & IEEE80211_F_WPA2) == 0) {
|
||||
IEEE80211_DISCARD_IE(ic,
|
||||
IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
|
||||
wh, "WPA", "not RSN, flags 0x%x", ic->ic_flags);
|
||||
return IEEE80211_REASON_IE_INVALID;
|
||||
}
|
||||
if (len < 10) {
|
||||
IEEE80211_DISCARD_IE(ic,
|
||||
IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
|
||||
|
@ -1652,7 +1692,7 @@ ieee80211_parse_wmeparams(struct ieee80211com *ic, u_int8_t *frm,
|
|||
#undef MS
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
ieee80211_saveie(u_int8_t **iep, const u_int8_t *ie)
|
||||
{
|
||||
u_int ielen = ie[1]+2;
|
||||
|
@ -1669,38 +1709,6 @@ ieee80211_saveie(u_int8_t **iep, const u_int8_t *ie)
|
|||
/* XXX note failure */
|
||||
}
|
||||
|
||||
#ifdef IEEE80211_DEBUG
|
||||
static void
|
||||
dump_probe_beacon(u_int8_t subtype, int isnew,
|
||||
const u_int8_t mac[IEEE80211_ADDR_LEN],
|
||||
u_int8_t chan, u_int8_t bchan, u_int16_t capinfo, u_int16_t bintval,
|
||||
u_int8_t erp, u_int8_t *ssid, u_int8_t *country)
|
||||
{
|
||||
printf("[%s] %s%s on chan %u (bss chan %u) ",
|
||||
ether_sprintf(mac), isnew ? "new " : "",
|
||||
ieee80211_mgt_subtype_name[subtype >> IEEE80211_FC0_SUBTYPE_SHIFT],
|
||||
chan, bchan);
|
||||
ieee80211_print_essid(ssid + 2, ssid[1]);
|
||||
printf("\n");
|
||||
|
||||
if (isnew) {
|
||||
printf("[%s] caps 0x%x bintval %u erp 0x%x",
|
||||
ether_sprintf(mac), capinfo, bintval, erp);
|
||||
if (country) {
|
||||
#ifdef __FreeBSD__
|
||||
printf(" country info %*D", country[1], country+2, " ");
|
||||
#else
|
||||
int i;
|
||||
printf(" country info");
|
||||
for (i = 0; i < country[1]; i++)
|
||||
printf(" %02x", country[i+2]);
|
||||
#endif
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
#endif /* IEEE80211_DEBUG */
|
||||
|
||||
void
|
||||
ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
struct ieee80211_node *ni,
|
||||
|
@ -1720,10 +1728,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
switch (subtype) {
|
||||
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
|
||||
case IEEE80211_FC0_SUBTYPE_BEACON: {
|
||||
u_int8_t *tstamp, *country, *tim;
|
||||
u_int8_t chan, bchan, fhindex, erp;
|
||||
u_int16_t capinfo, bintval, timoff;
|
||||
u_int16_t fhdwell;
|
||||
struct ieee80211_scanparams scan;
|
||||
|
||||
/*
|
||||
* We process beacon/probe response frames:
|
||||
|
@ -1754,32 +1759,29 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
* [tlv] WPA or RSN
|
||||
*/
|
||||
IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
|
||||
tstamp = frm; frm += 8;
|
||||
bintval = le16toh(*(u_int16_t *)frm); frm += 2;
|
||||
capinfo = le16toh(*(u_int16_t *)frm); frm += 2;
|
||||
ssid = rates = xrates = country = wpa = wme = tim = NULL;
|
||||
bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
|
||||
chan = bchan;
|
||||
fhdwell = 0;
|
||||
fhindex = 0;
|
||||
erp = 0;
|
||||
timoff = 0;
|
||||
memset(&scan, 0, sizeof(scan));
|
||||
scan.tstamp = frm; frm += 8;
|
||||
scan.bintval = le16toh(*(u_int16_t *)frm); frm += 2;
|
||||
scan.capinfo = le16toh(*(u_int16_t *)frm); frm += 2;
|
||||
scan.bchan = ieee80211_chan2ieee(ic, ic->ic_curchan);
|
||||
scan.chan = scan.bchan;
|
||||
|
||||
while (frm < efrm) {
|
||||
switch (*frm) {
|
||||
case IEEE80211_ELEMID_SSID:
|
||||
ssid = frm;
|
||||
scan.ssid = frm;
|
||||
break;
|
||||
case IEEE80211_ELEMID_RATES:
|
||||
rates = frm;
|
||||
scan.rates = frm;
|
||||
break;
|
||||
case IEEE80211_ELEMID_COUNTRY:
|
||||
country = frm;
|
||||
scan.country = frm;
|
||||
break;
|
||||
case IEEE80211_ELEMID_FHPARMS:
|
||||
if (ic->ic_phytype == IEEE80211_T_FH) {
|
||||
fhdwell = LE_READ_2(&frm[2]);
|
||||
chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
|
||||
fhindex = frm[6];
|
||||
scan.fhdwell = LE_READ_2(&frm[2]);
|
||||
scan.chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
|
||||
scan.fhindex = frm[6];
|
||||
}
|
||||
break;
|
||||
case IEEE80211_ELEMID_DSPARMS:
|
||||
|
@ -1788,17 +1790,17 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
* is problematic for multi-mode devices.
|
||||
*/
|
||||
if (ic->ic_phytype != IEEE80211_T_FH)
|
||||
chan = frm[2];
|
||||
scan.chan = frm[2];
|
||||
break;
|
||||
case IEEE80211_ELEMID_TIM:
|
||||
/* XXX ATIM? */
|
||||
tim = frm;
|
||||
timoff = frm - mtod(m0, u_int8_t *);
|
||||
scan.tim = frm;
|
||||
scan.timoff = frm - mtod(m0, u_int8_t *);
|
||||
break;
|
||||
case IEEE80211_ELEMID_IBSSPARMS:
|
||||
break;
|
||||
case IEEE80211_ELEMID_XRATES:
|
||||
xrates = frm;
|
||||
scan.xrates = frm;
|
||||
break;
|
||||
case IEEE80211_ELEMID_ERP:
|
||||
if (frm[1] != 1) {
|
||||
|
@ -1808,16 +1810,16 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
ic->ic_stats.is_rx_elem_toobig++;
|
||||
break;
|
||||
}
|
||||
erp = frm[2];
|
||||
scan.erp = frm[2];
|
||||
break;
|
||||
case IEEE80211_ELEMID_RSN:
|
||||
wpa = frm;
|
||||
scan.wpa = frm;
|
||||
break;
|
||||
case IEEE80211_ELEMID_VENDOR:
|
||||
if (iswpaoui(frm))
|
||||
wpa = frm;
|
||||
scan.wpa = frm;
|
||||
else if (iswmeparam(frm) || iswmeinfo(frm))
|
||||
wme = frm;
|
||||
scan.wme = frm;
|
||||
/* XXX Atheros OUI support */
|
||||
break;
|
||||
default:
|
||||
|
@ -1829,21 +1831,23 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
}
|
||||
frm += frm[1] + 2;
|
||||
}
|
||||
IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
|
||||
IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
|
||||
IEEE80211_VERIFY_ELEMENT(scan.rates, IEEE80211_RATE_MAXSIZE);
|
||||
IEEE80211_VERIFY_ELEMENT(scan.ssid, IEEE80211_NWID_LEN);
|
||||
if (
|
||||
#if IEEE80211_CHAN_MAX < 255
|
||||
chan > IEEE80211_CHAN_MAX ||
|
||||
scan.chan > IEEE80211_CHAN_MAX ||
|
||||
#endif
|
||||
isclr(ic->ic_chan_active, chan)) {
|
||||
IEEE80211_DISCARD(ic, IEEE80211_MSG_ELEMID,
|
||||
isclr(ic->ic_chan_active, scan.chan)) {
|
||||
IEEE80211_DISCARD(ic,
|
||||
IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
|
||||
wh, ieee80211_mgt_subtype_name[subtype >>
|
||||
IEEE80211_FC0_SUBTYPE_SHIFT],
|
||||
"invalid channel %u", chan);
|
||||
"invalid channel %u", scan.chan);
|
||||
ic->ic_stats.is_rx_badchan++;
|
||||
return;
|
||||
}
|
||||
if (chan != bchan && ic->ic_phytype != IEEE80211_T_FH) {
|
||||
if (scan.chan != scan.bchan &&
|
||||
ic->ic_phytype != IEEE80211_T_FH) {
|
||||
/*
|
||||
* Frame was received on a channel different from the
|
||||
* one indicated in the DS params element id;
|
||||
|
@ -1854,13 +1858,24 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
* the rssi value should be correct even for
|
||||
* different hop pattern in FH.
|
||||
*/
|
||||
IEEE80211_DISCARD(ic, IEEE80211_MSG_ELEMID,
|
||||
IEEE80211_DISCARD(ic,
|
||||
IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
|
||||
wh, ieee80211_mgt_subtype_name[subtype >>
|
||||
IEEE80211_FC0_SUBTYPE_SHIFT],
|
||||
"for off-channel %u", chan);
|
||||
"for off-channel %u", scan.chan);
|
||||
ic->ic_stats.is_rx_chanmismatch++;
|
||||
return;
|
||||
}
|
||||
if (!(IEEE80211_BINTVAL_MIN <= scan.bintval &&
|
||||
scan.bintval <= IEEE80211_BINTVAL_MAX)) {
|
||||
IEEE80211_DISCARD(ic,
|
||||
IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
|
||||
wh, ieee80211_mgt_subtype_name[subtype >>
|
||||
IEEE80211_FC0_SUBTYPE_SHIFT],
|
||||
"bogus beacon interval", scan.bintval);
|
||||
ic->ic_stats.is_rx_badbintval++;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Count frame now that we know it's to be processed.
|
||||
|
@ -1881,27 +1896,27 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
((ic->ic_flags & IEEE80211_F_SCAN) == 0 ||
|
||||
IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid))) {
|
||||
/* record tsf of last beacon */
|
||||
memcpy(ni->ni_tstamp.data, tstamp,
|
||||
memcpy(ni->ni_tstamp.data, scan.tstamp,
|
||||
sizeof(ni->ni_tstamp));
|
||||
if (ni->ni_erp != erp) {
|
||||
if (ni->ni_erp != scan.erp) {
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
|
||||
"[%s] erp change: was 0x%x, now 0x%x\n",
|
||||
ether_sprintf(wh->i_addr2),
|
||||
ni->ni_erp, erp);
|
||||
ni->ni_erp, scan.erp);
|
||||
if (ic->ic_curmode == IEEE80211_MODE_11G &&
|
||||
(ni->ni_erp & IEEE80211_ERP_USE_PROTECTION))
|
||||
ic->ic_flags |= IEEE80211_F_USEPROT;
|
||||
else
|
||||
ic->ic_flags &= ~IEEE80211_F_USEPROT;
|
||||
ni->ni_erp = erp;
|
||||
ni->ni_erp = scan.erp;
|
||||
/* XXX statistic */
|
||||
}
|
||||
if ((ni->ni_capinfo ^ capinfo) & IEEE80211_CAPINFO_SHORT_SLOTTIME) {
|
||||
if ((ni->ni_capinfo ^ scan.capinfo) & IEEE80211_CAPINFO_SHORT_SLOTTIME) {
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
|
||||
"[%s] capabilities change: before 0x%x,"
|
||||
" now 0x%x\n",
|
||||
ether_sprintf(wh->i_addr2),
|
||||
ni->ni_capinfo, capinfo);
|
||||
ni->ni_capinfo, scan.capinfo);
|
||||
/*
|
||||
* NB: we assume short preamble doesn't
|
||||
* change dynamically
|
||||
|
@ -1909,105 +1924,51 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
ieee80211_set_shortslottime(ic,
|
||||
ic->ic_curmode == IEEE80211_MODE_11A ||
|
||||
(ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME));
|
||||
ni->ni_capinfo = capinfo;
|
||||
ni->ni_capinfo = scan.capinfo;
|
||||
/* XXX statistic */
|
||||
}
|
||||
if (wme != NULL &&
|
||||
if (scan.wme != NULL &&
|
||||
(ni->ni_flags & IEEE80211_NODE_QOS) &&
|
||||
ieee80211_parse_wmeparams(ic, wme, wh) > 0)
|
||||
ieee80211_parse_wmeparams(ic, scan.wme, wh) > 0)
|
||||
ieee80211_wme_updateparams(ic);
|
||||
if (tim != NULL) {
|
||||
if (scan.tim != NULL) {
|
||||
struct ieee80211_tim_ie *ie =
|
||||
(struct ieee80211_tim_ie *) tim;
|
||||
(struct ieee80211_tim_ie *) scan.tim;
|
||||
|
||||
ni->ni_dtim_count = ie->tim_count;
|
||||
ni->ni_dtim_period = ie->tim_period;
|
||||
}
|
||||
/* NB: don't need the rest of this */
|
||||
if ((ic->ic_flags & IEEE80211_F_SCAN) == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ni == ic->ic_bss &&
|
||||
!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
|
||||
#ifdef IEEE80211_DEBUG
|
||||
if (ieee80211_msg_scan(ic))
|
||||
dump_probe_beacon(subtype, 1,
|
||||
wh->i_addr2, chan, bchan, capinfo,
|
||||
bintval, erp, ssid, country);
|
||||
#endif
|
||||
/*
|
||||
* Create a new entry. If scanning the entry goes
|
||||
* in the scan cache. Otherwise, be particular when
|
||||
* operating in adhoc mode--only take nodes marked
|
||||
* as ibss participants so we don't populate our
|
||||
* neighbor table with unintersting sta's.
|
||||
*/
|
||||
if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
|
||||
if ((capinfo & IEEE80211_CAPINFO_IBSS) == 0)
|
||||
return;
|
||||
ni = ieee80211_fakeup_adhoc_node(&ic->ic_sta,
|
||||
wh->i_addr2);
|
||||
} else
|
||||
ni = ieee80211_dup_bss(&ic->ic_scan, wh->i_addr2);
|
||||
if (ni == NULL)
|
||||
return;
|
||||
ni->ni_esslen = ssid[1];
|
||||
memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
|
||||
memcpy(ni->ni_essid, ssid + 2, ssid[1]);
|
||||
} else if (ssid[1] != 0 &&
|
||||
(ISPROBE(subtype) || ni->ni_esslen == 0)) {
|
||||
/*
|
||||
* Update ESSID at probe response to adopt
|
||||
* hidden AP by Lucent/Cisco, which announces
|
||||
* null ESSID in beacon.
|
||||
*/
|
||||
#ifdef IEEE80211_DEBUG
|
||||
if (ieee80211_msg_scan(ic) ||
|
||||
ieee80211_msg_debug(ic))
|
||||
dump_probe_beacon(subtype, 0,
|
||||
wh->i_addr2, chan, bchan, capinfo,
|
||||
bintval, erp, ssid, country);
|
||||
#endif
|
||||
ni->ni_esslen = ssid[1];
|
||||
memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
|
||||
memcpy(ni->ni_essid, ssid + 2, ssid[1]);
|
||||
}
|
||||
ni->ni_scangen = ic->ic_scan.nt_scangen;
|
||||
IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
|
||||
ni->ni_rssi = rssi;
|
||||
ni->ni_rstamp = rstamp;
|
||||
memcpy(ni->ni_tstamp.data, tstamp, sizeof(ni->ni_tstamp));
|
||||
ni->ni_intval = bintval;
|
||||
ni->ni_capinfo = capinfo;
|
||||
ni->ni_chan = &ic->ic_channels[chan];
|
||||
ni->ni_fhdwell = fhdwell;
|
||||
ni->ni_fhindex = fhindex;
|
||||
ni->ni_erp = erp;
|
||||
if (tim != NULL) {
|
||||
struct ieee80211_tim_ie *ie =
|
||||
(struct ieee80211_tim_ie *) tim;
|
||||
|
||||
ni->ni_dtim_count = ie->tim_count;
|
||||
ni->ni_dtim_period = ie->tim_period;
|
||||
if (ic->ic_flags & IEEE80211_F_SCAN)
|
||||
ieee80211_add_scan(ic, &scan, wh,
|
||||
subtype, rssi, rstamp);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Record the byte offset from the mac header to
|
||||
* the start of the TIM information element for
|
||||
* use by hardware and/or to speedup software
|
||||
* processing of beacon frames.
|
||||
* If scanning, just pass information to the scan module.
|
||||
*/
|
||||
ni->ni_timoff = timoff;
|
||||
/*
|
||||
* Record optional information elements that might be
|
||||
* used by applications or drivers.
|
||||
*/
|
||||
if (wme != NULL)
|
||||
ieee80211_saveie(&ni->ni_wme_ie, wme);
|
||||
if (wpa != NULL)
|
||||
ieee80211_saveie(&ni->ni_wpa_ie, wpa);
|
||||
/* NB: must be after ni_chan is setup */
|
||||
ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT);
|
||||
if (ic->ic_flags & IEEE80211_F_SCAN) {
|
||||
ieee80211_add_scan(ic, &scan, wh,
|
||||
subtype, rssi, rstamp);
|
||||
return;
|
||||
}
|
||||
if (scan.capinfo & IEEE80211_CAPINFO_IBSS) {
|
||||
if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
|
||||
/*
|
||||
* Create a new entry in the neighbor table.
|
||||
*/
|
||||
ni = ieee80211_add_neighbor(ic, wh, &scan);
|
||||
} else {
|
||||
/*
|
||||
* Record tsf for potential resync.
|
||||
*/
|
||||
memcpy(ni->ni_tstamp.data, scan.tstamp,
|
||||
sizeof(ni->ni_tstamp));
|
||||
}
|
||||
if (ni != NULL) {
|
||||
ni->ni_rssi = rssi;
|
||||
ni->ni_rstamp = rstamp;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2067,7 +2028,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
ni = ieee80211_fakeup_adhoc_node(&ic->ic_sta,
|
||||
wh->i_addr2);
|
||||
} else
|
||||
ni = ieee80211_dup_bss(&ic->ic_sta, wh->i_addr2);
|
||||
ni = ieee80211_tmp_node(ic, wh->i_addr2);
|
||||
if (ni == NULL)
|
||||
return;
|
||||
allocbs = 1;
|
||||
|
@ -2077,7 +2038,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
"[%s] recv probe req\n", ether_sprintf(wh->i_addr2));
|
||||
ni->ni_rssi = rssi;
|
||||
ni->ni_rstamp = rstamp;
|
||||
rate = ieee80211_setup_rates(ic, ni, rates, xrates,
|
||||
rate = ieee80211_setup_rates(ni, rates, xrates,
|
||||
IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE
|
||||
| IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
|
||||
if (rate & IEEE80211_RATE_BASIC) {
|
||||
|
@ -2119,6 +2080,11 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
IEEE80211_DISCARD(ic, IEEE80211_MSG_ACL,
|
||||
wh, "auth", "%s", "disallowed by ACL");
|
||||
ic->ic_stats.is_rx_acl++;
|
||||
if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
|
||||
IEEE80211_SEND_MGMT(ic, ni,
|
||||
IEEE80211_FC0_SUBTYPE_AUTH,
|
||||
(seq+1) | (IEEE80211_STATUS_UNSPECIFIED<<16));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ic->ic_flags & IEEE80211_F_COUNTERM) {
|
||||
|
@ -2156,7 +2122,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
|
||||
case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
|
||||
case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: {
|
||||
u_int16_t capinfo, bintval;
|
||||
u_int16_t capinfo, lintval;
|
||||
struct ieee80211_rsnparms rsn;
|
||||
u_int8_t reason;
|
||||
|
||||
|
@ -2193,7 +2159,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
return;
|
||||
}
|
||||
capinfo = le16toh(*(u_int16_t *)frm); frm += 2;
|
||||
bintval = le16toh(*(u_int16_t *)frm); frm += 2;
|
||||
lintval = le16toh(*(u_int16_t *)frm); frm += 2;
|
||||
if (reassoc)
|
||||
frm += 6; /* ignore current AP info */
|
||||
ssid = rates = xrates = wpa = wme = NULL;
|
||||
|
@ -2213,10 +2179,9 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
wpa = frm;
|
||||
break;
|
||||
case IEEE80211_ELEMID_VENDOR:
|
||||
if (iswpaoui(frm)) {
|
||||
if (ic->ic_flags & IEEE80211_F_WPA1)
|
||||
wpa = frm;
|
||||
} else if (iswmeinfo(frm))
|
||||
if (iswpaoui(frm))
|
||||
wpa = frm;
|
||||
else if (iswmeinfo(frm))
|
||||
wme = frm;
|
||||
/* XXX Atheros OUI support */
|
||||
break;
|
||||
|
@ -2299,7 +2264,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
ic->ic_stats.is_rx_assoc_capmismatch++;
|
||||
return;
|
||||
}
|
||||
rate = ieee80211_setup_rates(ic, ni, rates, xrates,
|
||||
rate = ieee80211_setup_rates(ni, rates, xrates,
|
||||
IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
|
||||
IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
|
||||
/*
|
||||
|
@ -2322,7 +2287,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
}
|
||||
ni->ni_rssi = rssi;
|
||||
ni->ni_rstamp = rstamp;
|
||||
ni->ni_intval = bintval;
|
||||
ni->ni_intval = lintval;
|
||||
ni->ni_capinfo = capinfo;
|
||||
ni->ni_chan = ic->ic_bss->ni_chan;
|
||||
ni->ni_fhdwell = ic->ic_bss->ni_fhdwell;
|
||||
|
@ -2420,7 +2385,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
}
|
||||
|
||||
IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
|
||||
rate = ieee80211_setup_rates(ic, ni, rates, xrates,
|
||||
rate = ieee80211_setup_rates(ni, rates, xrates,
|
||||
IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
|
||||
IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
|
||||
if (rate & IEEE80211_RATE_BASIC) {
|
||||
|
@ -2537,7 +2502,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
|||
IEEE80211_NODE_STAT(ni, rx_disassoc);
|
||||
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
|
||||
"[%s] recv disassociated (reason %d)\n",
|
||||
"[%s] recv disassociate (reason %d)\n",
|
||||
ether_sprintf(ni->ni_macaddr), reason);
|
||||
switch (ic->ic_opmode) {
|
||||
case IEEE80211_M_STA:
|
||||
|
@ -2598,7 +2563,7 @@ ieee80211_node_pwrsave(struct ieee80211_node *ni, int enable)
|
|||
*/
|
||||
if (IEEE80211_NODE_SAVEQ_QLEN(ni) == 0) {
|
||||
if (ic->ic_set_tim != NULL)
|
||||
ic->ic_set_tim(ic, ni, 0); /* just in case */
|
||||
ic->ic_set_tim(ni, 0); /* just in case */
|
||||
return;
|
||||
}
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
|
||||
|
@ -2623,7 +2588,7 @@ ieee80211_node_pwrsave(struct ieee80211_node *ni, int enable)
|
|||
IF_ENQUEUE(&ic->ic_ifp->if_snd, m);
|
||||
}
|
||||
if (ic->ic_set_tim != NULL)
|
||||
ic->ic_set_tim(ic, ni, 0);
|
||||
ic->ic_set_tim(ni, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2667,10 +2632,10 @@ ieee80211_recv_pspoll(struct ieee80211com *ic,
|
|||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
|
||||
"[%s] recv ps-poll, but queue empty\n",
|
||||
ether_sprintf(wh->i_addr2));
|
||||
ieee80211_send_nulldata(ic, ni);
|
||||
ieee80211_send_nulldata(ieee80211_ref_node(ni));
|
||||
ic->ic_stats.is_ps_qempty++; /* XXX node stat */
|
||||
if (ic->ic_set_tim != NULL)
|
||||
ic->ic_set_tim(ic, ni, 0); /* just in case */
|
||||
ic->ic_set_tim(ni, 0); /* just in case */
|
||||
return;
|
||||
}
|
||||
/*
|
||||
|
@ -2688,7 +2653,7 @@ ieee80211_recv_pspoll(struct ieee80211com *ic,
|
|||
"[%s] recv ps-poll, send packet, queue empty\n",
|
||||
ether_sprintf(ni->ni_macaddr));
|
||||
if (ic->ic_set_tim != NULL)
|
||||
ic->ic_set_tim(ic, ni, 0);
|
||||
ic->ic_set_tim(ni, 0);
|
||||
}
|
||||
m->m_flags |= M_PWR_SAV; /* bypass PS handling */
|
||||
IF_ENQUEUE(&ic->ic_ifp->if_snd, m);
|
||||
|
@ -2714,6 +2679,48 @@ ieee80211_getbssid(struct ieee80211com *ic, const struct ieee80211_frame *wh)
|
|||
return wh->i_addr3;
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_note(struct ieee80211com *ic, const char *fmt, ...)
|
||||
{
|
||||
char buf[128]; /* XXX */
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if_printf(ic->ic_ifp, "%s", buf); /* NB: no \n */
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_note_frame(struct ieee80211com *ic,
|
||||
const struct ieee80211_frame *wh,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
char buf[128]; /* XXX */
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
if_printf(ic->ic_ifp, "[%s] %s\n",
|
||||
ether_sprintf(ieee80211_getbssid(ic, wh)), buf);
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_note_mac(struct ieee80211com *ic,
|
||||
const u_int8_t mac[IEEE80211_ADDR_LEN],
|
||||
const char *fmt, ...)
|
||||
{
|
||||
char buf[128]; /* XXX */
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
if_printf(ic->ic_ifp, "[%s] %s\n", ether_sprintf(mac), buf);
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211_discard_frame(struct ieee80211com *ic,
|
||||
const struct ieee80211_frame *wh,
|
||||
|
@ -2721,11 +2728,12 @@ ieee80211_discard_frame(struct ieee80211com *ic,
|
|||
{
|
||||
va_list ap;
|
||||
|
||||
printf("[%s] discard ", ether_sprintf(ieee80211_getbssid(ic, wh)));
|
||||
printf("[%s:%s] discard ", ic->ic_ifp->if_xname,
|
||||
ether_sprintf(ieee80211_getbssid(ic, wh)));
|
||||
if (type != NULL)
|
||||
printf(" %s frame, ", type);
|
||||
printf("%s frame, ", type);
|
||||
else
|
||||
printf(" frame, ");
|
||||
printf("frame, ");
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
@ -2739,11 +2747,12 @@ ieee80211_discard_ie(struct ieee80211com *ic,
|
|||
{
|
||||
va_list ap;
|
||||
|
||||
printf("[%s] discard ", ether_sprintf(ieee80211_getbssid(ic, wh)));
|
||||
printf("[%s:%s] discard ", ic->ic_ifp->if_xname,
|
||||
ether_sprintf(ieee80211_getbssid(ic, wh)));
|
||||
if (type != NULL)
|
||||
printf(" %s information element, ", type);
|
||||
printf("%s information element, ", type);
|
||||
else
|
||||
printf(" information element, ");
|
||||
printf("information element, ");
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
@ -2757,11 +2766,11 @@ ieee80211_discard_mac(struct ieee80211com *ic,
|
|||
{
|
||||
va_list ap;
|
||||
|
||||
printf("[%s] discard ", ether_sprintf(mac));
|
||||
printf("[%s:%s] discard ", ic->ic_ifp->if_xname, ether_sprintf(mac));
|
||||
if (type != NULL)
|
||||
printf(" %s frame, ", type);
|
||||
printf("%s frame, ", type);
|
||||
else
|
||||
printf(" frame, ");
|
||||
printf("frame, ");
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_ioctl.c,v 1.25 2005/07/06 15:38:27 sam Exp $");
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_ioctl.c,v 1.35 2005/08/30 14:27:47 avatar Exp $");
|
||||
|
||||
/*
|
||||
* IEEE 802.11 ioctl support (FreeBSD-specific)
|
||||
|
@ -68,7 +68,8 @@ __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_ioctl.c,v 1.25 2005/07/06 15:38:2
|
|||
#include <dev/wi/if_wavelan_ieee.h>
|
||||
|
||||
#define IS_UP(_ic) \
|
||||
(((_ic)->ic_ifp->if_flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
|
||||
(((_ic)->ic_ifp->if_flags & IFF_UP) && \
|
||||
((_ic)->ic_ifp->if_drv_flags & IFF_DRV_RUNNING))
|
||||
#define IS_UP_AUTO(_ic) \
|
||||
(IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO)
|
||||
|
||||
|
@ -251,7 +252,7 @@ ieee80211_cfgget(struct ieee80211com *ic, u_long cmd, caddr_t data)
|
|||
break;
|
||||
case WI_RID_CURRENT_CHAN:
|
||||
wreq.wi_val[0] = htole16(
|
||||
ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan));
|
||||
ieee80211_chan2ieee(ic, ic->ic_curchan));
|
||||
wreq.wi_len = 1;
|
||||
break;
|
||||
case WI_RID_COMMS_QUALITY:
|
||||
|
@ -273,7 +274,7 @@ ieee80211_cfgget(struct ieee80211com *ic, u_long cmd, caddr_t data)
|
|||
wreq.wi_len = IEEE80211_ADDR_LEN / 2;
|
||||
break;
|
||||
case WI_RID_TX_RATE:
|
||||
if (ic->ic_fixed_rate == -1)
|
||||
if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)
|
||||
wreq.wi_val[0] = 0; /* auto */
|
||||
else
|
||||
wreq.wi_val[0] = htole16(
|
||||
|
@ -447,7 +448,6 @@ findrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate)
|
|||
static int
|
||||
ieee80211_setupscan(struct ieee80211com *ic, const u_int8_t chanlist[])
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* XXX don't permit a scan to be started unless we
|
||||
|
@ -459,20 +459,6 @@ ieee80211_setupscan(struct ieee80211com *ic, const u_int8_t chanlist[])
|
|||
*/
|
||||
if (!IS_UP(ic))
|
||||
return EINVAL;
|
||||
if (ic->ic_ibss_chan == NULL ||
|
||||
isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) {
|
||||
for (i = 0; i <= IEEE80211_CHAN_MAX; i++)
|
||||
if (isset(chanlist, i)) {
|
||||
ic->ic_ibss_chan = &ic->ic_channels[i];
|
||||
goto found;
|
||||
}
|
||||
return EINVAL; /* no active channels */
|
||||
found:
|
||||
;
|
||||
}
|
||||
if (ic->ic_bss->ni_chan == IEEE80211_CHAN_ANYC ||
|
||||
isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan)))
|
||||
ic->ic_bss->ni_chan = ic->ic_ibss_chan;
|
||||
memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
|
||||
/*
|
||||
* We force the state to INIT before calling ieee80211_new_state
|
||||
|
@ -592,7 +578,7 @@ ieee80211_cfgset(struct ieee80211com *ic, u_long cmd, caddr_t data)
|
|||
return EINVAL;
|
||||
if (wreq.wi_val[0] == 0) {
|
||||
/* auto */
|
||||
ic->ic_fixed_rate = -1;
|
||||
ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE;
|
||||
break;
|
||||
}
|
||||
rate = 2 * le16toh(wreq.wi_val[0]);
|
||||
|
@ -826,18 +812,6 @@ ieee80211_cfgset(struct ieee80211com *ic, u_long cmd, caddr_t data)
|
|||
return error;
|
||||
}
|
||||
|
||||
static struct ieee80211_channel *
|
||||
getcurchan(struct ieee80211com *ic)
|
||||
{
|
||||
switch (ic->ic_state) {
|
||||
case IEEE80211_S_INIT:
|
||||
case IEEE80211_S_SCAN:
|
||||
return ic->ic_des_chan;
|
||||
default:
|
||||
return ic->ic_ibss_chan;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
cap2cipher(int flag)
|
||||
{
|
||||
|
@ -1074,18 +1048,57 @@ ieee80211_ioctl_getscanresults(struct ieee80211com *ic, struct ieee80211req *ire
|
|||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
get_sta_info(struct ieee80211req_sta_info *si, const struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct stainforeq {
|
||||
struct ieee80211com *ic;
|
||||
struct ieee80211req_sta_info *si;
|
||||
size_t space;
|
||||
};
|
||||
|
||||
si->isi_ie_len = 0;
|
||||
static size_t
|
||||
sta_space(const struct ieee80211_node *ni, size_t *ielen)
|
||||
{
|
||||
*ielen = 0;
|
||||
if (ni->ni_wpa_ie != NULL)
|
||||
si->isi_ie_len += 2+ni->ni_wpa_ie[1];
|
||||
*ielen += 2+ni->ni_wpa_ie[1];
|
||||
if (ni->ni_wme_ie != NULL)
|
||||
si->isi_ie_len += 2+ni->ni_wme_ie[1];
|
||||
si->isi_len = sizeof(*si) + si->isi_ie_len, sizeof(u_int32_t);
|
||||
si->isi_len = roundup(si->isi_len, sizeof(u_int32_t));
|
||||
*ielen += 2+ni->ni_wme_ie[1];
|
||||
return roundup(sizeof(struct ieee80211req_sta_info) + *ielen,
|
||||
sizeof(u_int32_t));
|
||||
}
|
||||
|
||||
static void
|
||||
get_sta_space(void *arg, struct ieee80211_node *ni)
|
||||
{
|
||||
struct stainforeq *req = arg;
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
size_t ielen;
|
||||
|
||||
if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
|
||||
ni->ni_associd == 0) /* only associated stations */
|
||||
return;
|
||||
req->space += sta_space(ni, &ielen);
|
||||
}
|
||||
|
||||
static void
|
||||
get_sta_info(void *arg, struct ieee80211_node *ni)
|
||||
{
|
||||
struct stainforeq *req = arg;
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct ieee80211req_sta_info *si;
|
||||
size_t ielen, len;
|
||||
u_int8_t *cp;
|
||||
|
||||
if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
|
||||
ni->ni_associd == 0) /* only associated stations */
|
||||
return;
|
||||
if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */
|
||||
return;
|
||||
len = sta_space(ni, &ielen);
|
||||
if (len > req->space)
|
||||
return;
|
||||
si = req->si;
|
||||
si->isi_len = len;
|
||||
si->isi_ie_len = ielen;
|
||||
si->isi_freq = ni->ni_chan->ic_freq;
|
||||
si->isi_flags = ni->ni_chan->ic_flags;
|
||||
si->isi_state = ni->ni_flags;
|
||||
|
@ -1109,55 +1122,60 @@ get_sta_info(struct ieee80211req_sta_info *si, const struct ieee80211_node *ni)
|
|||
si->isi_txseqs[0] = ni->ni_txseqs[0];
|
||||
si->isi_rxseqs[0] = ni->ni_rxseqs[0];
|
||||
}
|
||||
if (ic->ic_opmode == IEEE80211_M_IBSS || ni->ni_associd != 0)
|
||||
/* NB: leave all cases in case we relax ni_associd == 0 check */
|
||||
if (ieee80211_node_is_authorized(ni))
|
||||
si->isi_inact = ic->ic_inact_run;
|
||||
else if (ieee80211_node_is_authorized(ni))
|
||||
else if (ni->ni_associd != 0)
|
||||
si->isi_inact = ic->ic_inact_auth;
|
||||
else
|
||||
si->isi_inact = ic->ic_inact_init;
|
||||
si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT;
|
||||
|
||||
cp = (u_int8_t *)(si+1);
|
||||
if (ni->ni_wpa_ie != NULL) {
|
||||
memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]);
|
||||
cp += 2+ni->ni_wpa_ie[1];
|
||||
}
|
||||
if (ni->ni_wme_ie != NULL) {
|
||||
memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]);
|
||||
cp += 2+ni->ni_wme_ie[1];
|
||||
}
|
||||
|
||||
req->si = (struct ieee80211req_sta_info *)(((u_int8_t *)si) + len);
|
||||
req->space -= len;
|
||||
}
|
||||
|
||||
static int
|
||||
ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq)
|
||||
{
|
||||
union {
|
||||
struct ieee80211req_sta_info info;
|
||||
char data[512]; /* XXX shrink? */
|
||||
} u;
|
||||
struct ieee80211req_sta_info *si = &u.info;
|
||||
struct ieee80211_node_table *nt;
|
||||
struct ieee80211_node *ni;
|
||||
int error, space;
|
||||
u_int8_t *p, *cp;
|
||||
struct stainforeq req;
|
||||
int error;
|
||||
|
||||
if (ireq->i_len < sizeof(struct stainforeq))
|
||||
return EFAULT;
|
||||
|
||||
nt = &ic->ic_sta;
|
||||
p = ireq->i_data;
|
||||
space = ireq->i_len;
|
||||
error = 0;
|
||||
/* XXX locking */
|
||||
TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
|
||||
get_sta_info(si, ni);
|
||||
if (si->isi_len > sizeof(u))
|
||||
continue; /* XXX */
|
||||
if (space < si->isi_len)
|
||||
break;
|
||||
cp = (u_int8_t *)(si+1);
|
||||
if (ni->ni_wpa_ie != NULL) {
|
||||
memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]);
|
||||
cp += 2+ni->ni_wpa_ie[1];
|
||||
}
|
||||
if (ni->ni_wme_ie != NULL) {
|
||||
memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]);
|
||||
cp += 2+ni->ni_wme_ie[1];
|
||||
}
|
||||
error = copyout(si, p, si->isi_len);
|
||||
if (error)
|
||||
break;
|
||||
p += si->isi_len;
|
||||
space -= si->isi_len;
|
||||
}
|
||||
ireq->i_len -= space;
|
||||
req.space = 0;
|
||||
ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req);
|
||||
if (req.space > ireq->i_len)
|
||||
req.space = ireq->i_len;
|
||||
if (req.space > 0) {
|
||||
size_t space;
|
||||
void *p;
|
||||
|
||||
space = req.space;
|
||||
/* XXX M_WAITOK after driver lock released */
|
||||
MALLOC(p, void *, space, M_TEMP, M_NOWAIT);
|
||||
if (p == NULL)
|
||||
return ENOMEM;
|
||||
req.si = p;
|
||||
ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req);
|
||||
ireq->i_len = space - req.space;
|
||||
error = copyout(p, ireq->i_data, ireq->i_len);
|
||||
FREE(p, M_TEMP);
|
||||
} else
|
||||
ireq->i_len = 0;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1224,6 +1242,14 @@ ieee80211_ioctl_getwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ieee80211_ioctl_getmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
|
||||
{
|
||||
const struct ieee80211_aclator *acl = ic->ic_acl;
|
||||
|
||||
return (acl == NULL ? EINVAL : acl->iac_getioctl(ic, ireq));
|
||||
}
|
||||
|
||||
/*
|
||||
* When building the kernel with -O2 on the i386 architecture, gcc
|
||||
* seems to want to inline this function into ieee80211_ioctl()
|
||||
|
@ -1306,7 +1332,7 @@ ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re
|
|||
ireq->i_val = ic->ic_bss->ni_authmode;
|
||||
break;
|
||||
case IEEE80211_IOC_CHANNEL:
|
||||
ireq->i_val = ieee80211_chan2ieee(ic, getcurchan(ic));
|
||||
ireq->i_val = ieee80211_chan2ieee(ic, ic->ic_curchan);
|
||||
break;
|
||||
case IEEE80211_IOC_POWERSAVE:
|
||||
if (ic->ic_flags & IEEE80211_F_PMGTON)
|
||||
|
@ -1454,6 +1480,12 @@ ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re
|
|||
case IEEE80211_IOC_PUREG:
|
||||
ireq->i_val = (ic->ic_flags & IEEE80211_F_PUREG) != 0;
|
||||
break;
|
||||
case IEEE80211_IOC_FRAGTHRESHOLD:
|
||||
ireq->i_val = ic->ic_fragthreshold;
|
||||
break;
|
||||
case IEEE80211_IOC_MACCMD:
|
||||
error = ieee80211_ioctl_getmaccmd(ic, ireq);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
|
@ -1583,7 +1615,7 @@ ieee80211_ioctl_delkey(struct ieee80211com *ic, struct ieee80211req *ireq)
|
|||
return ENOENT;
|
||||
}
|
||||
/* XXX error return */
|
||||
ieee80211_crypto_delkey(ic, &ni->ni_ucastkey);
|
||||
ieee80211_node_delucastkey(ni);
|
||||
ieee80211_free_node(ni);
|
||||
} else {
|
||||
if (kid >= IEEE80211_WEP_NKID)
|
||||
|
@ -1682,9 +1714,9 @@ ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq)
|
|||
if (ni == NULL)
|
||||
return EINVAL;
|
||||
if (mlme.im_op == IEEE80211_MLME_AUTHORIZE)
|
||||
ieee80211_node_authorize(ic, ni);
|
||||
ieee80211_node_authorize(ni);
|
||||
else
|
||||
ieee80211_node_unauthorize(ic, ni);
|
||||
ieee80211_node_unauthorize(ni);
|
||||
ieee80211_free_node(ni);
|
||||
break;
|
||||
default:
|
||||
|
@ -1719,7 +1751,7 @@ ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq)
|
|||
}
|
||||
|
||||
static int
|
||||
ieee80211_ioctl_maccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
|
||||
ieee80211_ioctl_setmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
|
||||
{
|
||||
const struct ieee80211_aclator *acl = ic->ic_acl;
|
||||
|
||||
|
@ -1747,7 +1779,10 @@ ieee80211_ioctl_maccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
if (acl == NULL)
|
||||
return EINVAL;
|
||||
else
|
||||
return acl->iac_setioctl(ic, ireq);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1793,9 +1828,6 @@ found:
|
|||
;
|
||||
}
|
||||
memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
|
||||
if (ic->ic_bss->ni_chan == IEEE80211_CHAN_ANYC ||
|
||||
isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan)))
|
||||
ic->ic_bss->ni_chan = ic->ic_ibss_chan;
|
||||
return IS_UP_AUTO(ic) ? ENETRESET : 0;
|
||||
}
|
||||
|
||||
|
@ -2058,8 +2090,18 @@ ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re
|
|||
error = ENETRESET;
|
||||
break;
|
||||
}
|
||||
if (error == ENETRESET && ic->ic_opmode == IEEE80211_M_MONITOR)
|
||||
error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
|
||||
if (error == ENETRESET &&
|
||||
ic->ic_opmode == IEEE80211_M_MONITOR) {
|
||||
if (IS_UP(ic)) {
|
||||
/*
|
||||
* Monitor mode can switch directly.
|
||||
*/
|
||||
if (ic->ic_des_chan != IEEE80211_CHAN_ANYC)
|
||||
ic->ic_curchan = ic->ic_des_chan;
|
||||
error = ic->ic_reset(ic->ic_ifp);
|
||||
} else
|
||||
error = 0;
|
||||
}
|
||||
break;
|
||||
case IEEE80211_IOC_POWERSAVE:
|
||||
switch (ireq->i_val) {
|
||||
|
@ -2089,8 +2131,8 @@ ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re
|
|||
error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
|
||||
break;
|
||||
case IEEE80211_IOC_RTSTHRESHOLD:
|
||||
if (!(IEEE80211_RTS_MIN < ireq->i_val &&
|
||||
ireq->i_val < IEEE80211_RTS_MAX))
|
||||
if (!(IEEE80211_RTS_MIN <= ireq->i_val &&
|
||||
ireq->i_val <= IEEE80211_RTS_MAX))
|
||||
return EINVAL;
|
||||
ic->ic_rtsthreshold = ireq->i_val;
|
||||
error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
|
||||
|
@ -2284,7 +2326,7 @@ ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re
|
|||
error = ieee80211_ioctl_macmac(ic, ireq);
|
||||
break;
|
||||
case IEEE80211_IOC_MACCMD:
|
||||
error = ieee80211_ioctl_maccmd(ic, ireq);
|
||||
error = ieee80211_ioctl_setmaccmd(ic, ireq);
|
||||
break;
|
||||
case IEEE80211_IOC_STA_TXPOW:
|
||||
error = ieee80211_ioctl_setstatxpow(ic, ireq);
|
||||
|
@ -2314,7 +2356,7 @@ ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re
|
|||
return EINVAL;
|
||||
if (IEEE80211_BINTVAL_MIN <= ireq->i_val &&
|
||||
ireq->i_val <= IEEE80211_BINTVAL_MAX) {
|
||||
ic->ic_lintval = ireq->i_val;
|
||||
ic->ic_bintval = ireq->i_val;
|
||||
error = ENETRESET; /* requires restart */
|
||||
} else
|
||||
error = EINVAL;
|
||||
|
@ -2328,6 +2370,16 @@ ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re
|
|||
if (ic->ic_curmode == IEEE80211_MODE_11G)
|
||||
error = ENETRESET;
|
||||
break;
|
||||
case IEEE80211_IOC_FRAGTHRESHOLD:
|
||||
if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 &&
|
||||
ireq->i_val != IEEE80211_FRAG_MAX)
|
||||
return EINVAL;
|
||||
if (!(IEEE80211_FRAG_MIN <= ireq->i_val &&
|
||||
ireq->i_val <= IEEE80211_FRAG_MAX))
|
||||
return EINVAL;
|
||||
ic->ic_fragthreshold = ireq->i_val;
|
||||
error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/net80211/ieee80211_ioctl.h,v 1.10 2005/07/06 15:38:27 sam Exp $
|
||||
* $FreeBSD: src/sys/net80211/ieee80211_ioctl.h,v 1.14 2005/08/13 17:31:48 sam Exp $
|
||||
*/
|
||||
#ifndef _NET80211_IEEE80211_IOCTL_H_
|
||||
#define _NET80211_IEEE80211_IOCTL_H_
|
||||
|
@ -149,6 +149,8 @@ struct ieee80211_stats {
|
|||
u_int32_t is_tx_badcipher; /* tx failed 'cuz key type */
|
||||
u_int32_t is_tx_nodefkey; /* tx failed 'cuz no defkey */
|
||||
u_int32_t is_tx_noheadroom; /* tx failed 'cuz no space */
|
||||
u_int32_t is_tx_fragframes; /* tx frames fragmented */
|
||||
u_int32_t is_tx_frags; /* tx fragments created */
|
||||
u_int32_t is_scan_active; /* active scans started */
|
||||
u_int32_t is_scan_passive; /* passive scans started */
|
||||
u_int32_t is_node_timeout; /* nodes timed out inactivity */
|
||||
|
@ -173,6 +175,13 @@ struct ieee80211_stats {
|
|||
u_int32_t is_ps_unassoc; /* ps-poll for unassoc. sta */
|
||||
u_int32_t is_ps_badaid; /* ps-poll w/ incorrect aid */
|
||||
u_int32_t is_ps_qempty; /* ps-poll w/ nothing to send */
|
||||
u_int32_t is_ff_badhdr; /* fast frame rx'd w/ bad hdr */
|
||||
u_int32_t is_ff_tooshort; /* fast frame rx decap error */
|
||||
u_int32_t is_ff_split; /* fast frame rx split error */
|
||||
u_int32_t is_ff_decap; /* fast frames decap'd */
|
||||
u_int32_t is_ff_encap; /* fast frames encap'd for tx */
|
||||
u_int32_t is_rx_badbintval; /* rx frame w/ bogus bintval */
|
||||
u_int32_t is_spare[9];
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -243,6 +252,12 @@ enum {
|
|||
IEEE80211_MACCMD_POLICY_DENY = 2, /* set policy: deny traffic */
|
||||
IEEE80211_MACCMD_FLUSH = 3, /* flush ACL database */
|
||||
IEEE80211_MACCMD_DETACH = 4, /* detach ACL policy */
|
||||
IEEE80211_MACCMD_POLICY = 5, /* get ACL policy */
|
||||
IEEE80211_MACCMD_LIST = 6, /* get ACL database */
|
||||
};
|
||||
|
||||
struct ieee80211req_maclist {
|
||||
u_int8_t ml_macaddr[IEEE80211_ADDR_LEN];
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -427,6 +442,7 @@ struct ieee80211req {
|
|||
#define IEEE80211_IOC_ADDMAC 54 /* add sta to MAC ACL table */
|
||||
#define IEEE80211_IOC_DELMAC 55 /* del sta from MAC ACL table */
|
||||
#define IEEE80211_IOC_PUREG 56 /* pure 11g (no 11b stations) */
|
||||
#define IEEE80211_IOC_FRAGTHRESHOLD 73 /* tx fragmentation threshold */
|
||||
|
||||
/*
|
||||
* Scan result data returned for IEEE80211_IOC_SCAN_RESULTS.
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_freebsd.c,v 1.7 2005/03/29 19:36:42 sam Exp $");
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_freebsd.c,v 1.8 2005/08/08 18:46:35 sam Exp $");
|
||||
|
||||
/*
|
||||
* IEEE 802.11 support (FreeBSD-specific code)
|
||||
|
@ -261,9 +261,10 @@ ieee80211_notify_replay_failure(struct ieee80211com *ic,
|
|||
struct ifnet *ifp = ic->ic_ifp;
|
||||
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
|
||||
"[%s] %s replay detected <rsc %ju, csc %ju, keyix %u>\n",
|
||||
ether_sprintf(wh->i_addr2), k->wk_cipher->ic_name,
|
||||
(intmax_t) rsc, (intmax_t) k->wk_keyrsc, k->wk_keyix);
|
||||
"[%s] %s replay detected <rsc %ju, csc %ju, keyix %u rxkeyix %u>\n",
|
||||
ether_sprintf(wh->i_addr2), k->wk_cipher->ic_name,
|
||||
(intmax_t) rsc, (intmax_t) k->wk_keyrsc,
|
||||
k->wk_keyix, k->wk_rxkeyix);
|
||||
|
||||
if (ifp != NULL) { /* NB: for cipher test modules */
|
||||
struct ieee80211_replay_event iev;
|
||||
|
@ -271,7 +272,10 @@ ieee80211_notify_replay_failure(struct ieee80211com *ic,
|
|||
IEEE80211_ADDR_COPY(iev.iev_dst, wh->i_addr1);
|
||||
IEEE80211_ADDR_COPY(iev.iev_src, wh->i_addr2);
|
||||
iev.iev_cipher = k->wk_cipher->ic_cipher;
|
||||
iev.iev_keyix = k->wk_keyix;
|
||||
if (k->wk_rxkeyix != IEEE80211_KEYIX_NONE)
|
||||
iev.iev_keyix = k->wk_rxkeyix;
|
||||
else
|
||||
iev.iev_keyix = k->wk_keyix;
|
||||
iev.iev_keyrsc = k->wk_keyrsc;
|
||||
iev.iev_rsc = rsc;
|
||||
rt_ieee80211msg(ifp, RTM_IEEE80211_REPLAY, &iev, sizeof(iev));
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/net80211/ieee80211_freebsd.h,v 1.5 2005/07/06 01:55:17 sam Exp $
|
||||
* $FreeBSD: src/sys/net80211/ieee80211_freebsd.h,v 1.6 2005/08/08 18:46:36 sam Exp $
|
||||
*/
|
||||
#ifndef _NET80211_IEEE80211_FREEBSD_H_
|
||||
#define _NET80211_IEEE80211_FREEBSD_H_
|
||||
|
@ -43,12 +43,15 @@ typedef struct mtx ieee80211_beacon_lock_t;
|
|||
|
||||
/*
|
||||
* Node locking definitions.
|
||||
* NB: MTX_DUPOK is because we don't generate per-interface strings.
|
||||
*/
|
||||
typedef struct mtx ieee80211_node_lock_t;
|
||||
#define IEEE80211_NODE_LOCK_INIT(_nt, _name) \
|
||||
mtx_init(&(_nt)->nt_nodelock, _name, "802.11 node table", MTX_DEF)
|
||||
mtx_init(&(_nt)->nt_nodelock, _name, "802.11 node table", \
|
||||
MTX_DEF | MTX_DUPOK)
|
||||
#define IEEE80211_NODE_LOCK_DESTROY(_nt) mtx_destroy(&(_nt)->nt_nodelock)
|
||||
#define IEEE80211_NODE_LOCK(_nt) mtx_lock(&(_nt)->nt_nodelock)
|
||||
#define IEEE80211_NODE_IS_LOCKED(_nt) mtx_owned(&(_nt)->nt_nodelock)
|
||||
#define IEEE80211_NODE_UNLOCK(_nt) mtx_unlock(&(_nt)->nt_nodelock)
|
||||
#define IEEE80211_NODE_LOCK_ASSERT(_nt) \
|
||||
mtx_assert(&(_nt)->nt_nodelock, MA_OWNED)
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_node.c,v 1.48 2005/07/06 01:51:44 sam Exp $");
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_node.c,v 1.65 2005/08/13 17:50:21 sam Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -72,11 +72,11 @@ static void ieee80211_free_allnodes(struct ieee80211_node_table *);
|
|||
static void ieee80211_timeout_scan_candidates(struct ieee80211_node_table *);
|
||||
static void ieee80211_timeout_stations(struct ieee80211_node_table *);
|
||||
|
||||
static void ieee80211_set_tim(struct ieee80211com *,
|
||||
struct ieee80211_node *, int set);
|
||||
static void ieee80211_set_tim(struct ieee80211_node *, int set);
|
||||
|
||||
static void ieee80211_node_table_init(struct ieee80211com *ic,
|
||||
struct ieee80211_node_table *nt, const char *name, int inact,
|
||||
struct ieee80211_node_table *nt, const char *name,
|
||||
int inact, int keyixmax,
|
||||
void (*timeout)(struct ieee80211_node_table *));
|
||||
static void ieee80211_node_table_cleanup(struct ieee80211_node_table *nt);
|
||||
|
||||
|
@ -86,11 +86,6 @@ void
|
|||
ieee80211_node_attach(struct ieee80211com *ic)
|
||||
{
|
||||
|
||||
ieee80211_node_table_init(ic, &ic->ic_sta, "station",
|
||||
IEEE80211_INACT_INIT, ieee80211_timeout_stations);
|
||||
ieee80211_node_table_init(ic, &ic->ic_scan, "scan",
|
||||
IEEE80211_INACT_SCAN, ieee80211_timeout_scan_candidates);
|
||||
|
||||
ic->ic_node_alloc = node_alloc;
|
||||
ic->ic_node_free = node_free;
|
||||
ic->ic_node_cleanup = node_cleanup;
|
||||
|
@ -102,10 +97,17 @@ ieee80211_node_attach(struct ieee80211com *ic)
|
|||
ic->ic_inact_run = IEEE80211_INACT_RUN;
|
||||
ic->ic_inact_probe = IEEE80211_INACT_PROBE;
|
||||
|
||||
/* XXX defer */
|
||||
if (ic->ic_max_aid == 0)
|
||||
ic->ic_max_aid = IEEE80211_AID_DEF;
|
||||
else if (ic->ic_max_aid > IEEE80211_AID_MAX)
|
||||
/* NB: driver should override */
|
||||
ic->ic_max_aid = IEEE80211_AID_DEF;
|
||||
ic->ic_set_tim = ieee80211_set_tim;
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_node_lateattach(struct ieee80211com *ic)
|
||||
{
|
||||
struct ieee80211_rsnparms *rsn;
|
||||
|
||||
if (ic->ic_max_aid > IEEE80211_AID_MAX)
|
||||
ic->ic_max_aid = IEEE80211_AID_MAX;
|
||||
MALLOC(ic->ic_aid_bitmap, u_int32_t *,
|
||||
howmany(ic->ic_max_aid, 32) * sizeof(u_int32_t),
|
||||
|
@ -124,22 +126,20 @@ ieee80211_node_attach(struct ieee80211com *ic)
|
|||
/* XXX no way to recover */
|
||||
printf("%s: no memory for TIM bitmap!\n", __func__);
|
||||
}
|
||||
ic->ic_set_tim = ieee80211_set_tim; /* NB: driver should override */
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_node_lateattach(struct ieee80211com *ic)
|
||||
{
|
||||
struct ieee80211_node *ni;
|
||||
struct ieee80211_rsnparms *rsn;
|
||||
ieee80211_node_table_init(ic, &ic->ic_sta, "station",
|
||||
IEEE80211_INACT_INIT, ic->ic_crypto.cs_max_keyix,
|
||||
ieee80211_timeout_stations);
|
||||
ieee80211_node_table_init(ic, &ic->ic_scan, "scan",
|
||||
IEEE80211_INACT_SCAN, 0,
|
||||
ieee80211_timeout_scan_candidates);
|
||||
|
||||
ni = ieee80211_alloc_node(&ic->ic_scan, ic->ic_myaddr);
|
||||
KASSERT(ni != NULL, ("unable to setup inital BSS node"));
|
||||
ieee80211_reset_bss(ic);
|
||||
/*
|
||||
* Setup "global settings" in the bss node so that
|
||||
* each new station automatically inherits them.
|
||||
*/
|
||||
rsn = &ni->ni_rsn;
|
||||
rsn = &ic->ic_bss->ni_rsn;
|
||||
/* WEP, TKIP, and AES-CCM are always supported */
|
||||
rsn->rsn_ucastcipherset |= 1<<IEEE80211_CIPHER_WEP;
|
||||
rsn->rsn_ucastcipherset |= 1<<IEEE80211_CIPHER_TKIP;
|
||||
|
@ -171,8 +171,7 @@ ieee80211_node_lateattach(struct ieee80211com *ic)
|
|||
rsn->rsn_keymgmtset = WPA_ASE_8021X_UNSPEC | WPA_ASE_8021X_PSK;
|
||||
rsn->rsn_keymgmt = WPA_ASE_8021X_PSK;
|
||||
|
||||
ic->ic_bss = ieee80211_ref_node(ni); /* hold reference */
|
||||
ic->ic_auth = ieee80211_authenticator_get(ni->ni_authmode);
|
||||
ic->ic_auth = ieee80211_authenticator_get(ic->ic_bss->ni_authmode);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -200,14 +199,16 @@ ieee80211_node_detach(struct ieee80211com *ic)
|
|||
*/
|
||||
|
||||
void
|
||||
ieee80211_node_authorize(struct ieee80211com *ic, struct ieee80211_node *ni)
|
||||
ieee80211_node_authorize(struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
|
||||
ni->ni_flags |= IEEE80211_NODE_AUTH;
|
||||
ni->ni_inact_reload = ic->ic_inact_run;
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_node_unauthorize(struct ieee80211com *ic, struct ieee80211_node *ni)
|
||||
ieee80211_node_unauthorize(struct ieee80211_node *ni)
|
||||
{
|
||||
ni->ni_flags &= ~IEEE80211_NODE_AUTH;
|
||||
}
|
||||
|
@ -260,16 +261,12 @@ ieee80211_reset_scan(struct ieee80211com *ic)
|
|||
} else
|
||||
memcpy(ic->ic_chan_scan, ic->ic_chan_active,
|
||||
sizeof(ic->ic_chan_active));
|
||||
/* NB: hack, setup so next_scan starts with the first channel */
|
||||
if (ic->ic_bss->ni_chan == IEEE80211_CHAN_ANYC)
|
||||
ieee80211_set_chan(ic, ic->ic_bss,
|
||||
&ic->ic_channels[IEEE80211_CHAN_MAX]);
|
||||
#ifdef IEEE80211_DEBUG
|
||||
if (ieee80211_msg_scan(ic)) {
|
||||
printf("%s: scan set:", __func__);
|
||||
dump_chanlist(ic->ic_chan_scan);
|
||||
printf(" start chan %u\n",
|
||||
ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan));
|
||||
ieee80211_chan2ieee(ic, ic->ic_curchan));
|
||||
}
|
||||
#endif /* IEEE80211_DEBUG */
|
||||
}
|
||||
|
@ -323,7 +320,7 @@ ieee80211_next_scan(struct ieee80211com *ic)
|
|||
*/
|
||||
ic->ic_mgt_timer = 0;
|
||||
|
||||
chan = ic->ic_bss->ni_chan;
|
||||
chan = ic->ic_curchan;
|
||||
do {
|
||||
if (++chan > &ic->ic_channels[IEEE80211_CHAN_MAX])
|
||||
chan = &ic->ic_channels[0];
|
||||
|
@ -331,28 +328,19 @@ ieee80211_next_scan(struct ieee80211com *ic)
|
|||
clrbit(ic->ic_chan_scan, ieee80211_chan2ieee(ic, chan));
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN,
|
||||
"%s: chan %d->%d\n", __func__,
|
||||
ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),
|
||||
ieee80211_chan2ieee(ic, ic->ic_curchan),
|
||||
ieee80211_chan2ieee(ic, chan));
|
||||
ieee80211_set_chan(ic, ic->ic_bss, chan);
|
||||
#ifdef notyet
|
||||
/* XXX driver state change */
|
||||
ic->ic_curchan = chan;
|
||||
/*
|
||||
* Scan next channel. If doing an active scan
|
||||
* and the channel is not marked passive-only
|
||||
* then send a probe request. Otherwise just
|
||||
* listen for beacons on the channel.
|
||||
* XXX drivers should do this as needed,
|
||||
* XXX for now maintain compatibility
|
||||
*/
|
||||
if ((ic->ic_flags & IEEE80211_F_ASCAN) &&
|
||||
(ni->ni_chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0) {
|
||||
IEEE80211_SEND_MGMT(ic, ni,
|
||||
IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
|
||||
}
|
||||
#else
|
||||
ic->ic_bss->ni_rates =
|
||||
ic->ic_sup_rates[ieee80211_chan2mode(ic, chan)];
|
||||
ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
} while (chan != ic->ic_bss->ni_chan);
|
||||
} while (chan != ic->ic_curchan);
|
||||
ieee80211_end_scan(ic);
|
||||
return 0;
|
||||
}
|
||||
|
@ -394,7 +382,7 @@ ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
|
|||
}
|
||||
IEEE80211_NODE_UNLOCK(nt);
|
||||
|
||||
ni = ieee80211_alloc_node(nt, ic->ic_myaddr);
|
||||
ni = ieee80211_alloc_node(&ic->ic_sta, ic->ic_myaddr);
|
||||
if (ni == NULL) {
|
||||
/* XXX recovery? */
|
||||
return;
|
||||
|
@ -403,7 +391,7 @@ ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
|
|||
ni->ni_esslen = ic->ic_des_esslen;
|
||||
memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
|
||||
copy_bss(ni, ic->ic_bss);
|
||||
ni->ni_intval = ic->ic_lintval;
|
||||
ni->ni_intval = ic->ic_bintval;
|
||||
if (ic->ic_flags & IEEE80211_F_PRIVACY)
|
||||
ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
|
||||
if (ic->ic_phytype == IEEE80211_T_FH) {
|
||||
|
@ -422,6 +410,7 @@ ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
|
|||
* Fix the channel and related attributes.
|
||||
*/
|
||||
ieee80211_set_chan(ic, ni, chan);
|
||||
ic->ic_curchan = chan;
|
||||
ic->ic_curmode = ieee80211_chan2mode(ic, chan);
|
||||
/*
|
||||
* Do mode-specific rate setup.
|
||||
|
@ -455,11 +444,14 @@ ieee80211_reset_bss(struct ieee80211com *ic)
|
|||
ic->ic_bss = ieee80211_ref_node(ni);
|
||||
if (obss != NULL) {
|
||||
copy_bss(ni, obss);
|
||||
ni->ni_intval = ic->ic_lintval;
|
||||
ni->ni_intval = ic->ic_bintval;
|
||||
ieee80211_free_node(obss);
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX tunable */
|
||||
#define STA_FAILS_MAX 2 /* assoc failures before ignored */
|
||||
|
||||
static int
|
||||
ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
|
||||
{
|
||||
|
@ -487,8 +479,7 @@ ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
|
|||
if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
|
||||
fail |= 0x04;
|
||||
}
|
||||
rate = ieee80211_fix_rate(ic, ni,
|
||||
IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);
|
||||
rate = ieee80211_fix_rate(ni, IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);
|
||||
if (rate & IEEE80211_RATE_BASIC)
|
||||
fail |= 0x08;
|
||||
if (ic->ic_des_esslen != 0 &&
|
||||
|
@ -498,9 +489,12 @@ ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
|
|||
if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
|
||||
!IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
|
||||
fail |= 0x20;
|
||||
if (ni->ni_fails >= STA_FAILS_MAX)
|
||||
fail |= 0x40;
|
||||
#ifdef IEEE80211_DEBUG
|
||||
if (ieee80211_msg_scan(ic)) {
|
||||
printf(" %c %s", fail ? '-' : '+',
|
||||
printf(" %c %s",
|
||||
fail & 0x40 ? '=' : fail & 0x80 ? '^' : fail ? '-' : '+',
|
||||
ether_sprintf(ni->ni_macaddr));
|
||||
printf(" %s%c", ether_sprintf(ni->ni_bssid),
|
||||
fail & 0x20 ? '!' : ' ');
|
||||
|
@ -547,6 +541,7 @@ ieee80211_node_compare(struct ieee80211com *ic,
|
|||
{
|
||||
u_int8_t maxa, maxb;
|
||||
u_int8_t rssia, rssib;
|
||||
int weight;
|
||||
|
||||
/* privacy support preferred */
|
||||
if ((a->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) &&
|
||||
|
@ -556,6 +551,11 @@ ieee80211_node_compare(struct ieee80211com *ic,
|
|||
(b->ni_capinfo & IEEE80211_CAPINFO_PRIVACY))
|
||||
return -1;
|
||||
|
||||
/* compare count of previous failures */
|
||||
weight = b->ni_fails - a->ni_fails;
|
||||
if (abs(weight) > 1)
|
||||
return weight;
|
||||
|
||||
rssia = ic->ic_node_getrssi(a);
|
||||
rssib = ic->ic_node_getrssi(b);
|
||||
if (abs(rssib - rssia) < 5) {
|
||||
|
@ -672,6 +672,17 @@ ieee80211_end_scan(struct ieee80211com *ic)
|
|||
ieee80211_create_ibss(ic, ic->ic_ibss_chan);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Decrement the failure counts so entries will be
|
||||
* reconsidered the next time around. We really want
|
||||
* to do this only for sta's where we've previously
|
||||
had some success.
|
||||
*/
|
||||
IEEE80211_NODE_LOCK(nt);
|
||||
TAILQ_FOREACH(ni, &nt->nt_node, ni_list)
|
||||
if (ni->ni_fails)
|
||||
ni->ni_fails--;
|
||||
IEEE80211_NODE_UNLOCK(nt);
|
||||
/*
|
||||
* Reset the list of channels to scan and start again.
|
||||
*/
|
||||
|
@ -685,23 +696,6 @@ ieee80211_end_scan(struct ieee80211com *ic)
|
|||
"macaddr bssid chan rssi rate flag wep essid");
|
||||
IEEE80211_NODE_LOCK(nt);
|
||||
TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
|
||||
if (ni->ni_fails) {
|
||||
/*
|
||||
* The configuration of the access points may change
|
||||
* during my scan. So delete the entry for the AP
|
||||
* and retry to associate if there is another beacon.
|
||||
*/
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN,
|
||||
"%s: skip scan candidate %s, fails %u\n",
|
||||
__func__, ether_sprintf(ni->ni_macaddr),
|
||||
ni->ni_fails);
|
||||
ni->ni_fails++;
|
||||
#if 0
|
||||
if (ni->ni_fails++ > 2)
|
||||
ieee80211_free_node(ni);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
if (ieee80211_match_bss(ic, ni) == 0) {
|
||||
if (selbs == NULL)
|
||||
selbs = ni;
|
||||
|
@ -733,8 +727,9 @@ ieee80211_end_scan(struct ieee80211com *ic)
|
|||
* Return !0 if the BSSID changed, 0 otherwise.
|
||||
*/
|
||||
int
|
||||
ieee80211_ibss_merge(struct ieee80211com *ic, struct ieee80211_node *ni)
|
||||
ieee80211_ibss_merge(struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
|
||||
if (ni == ic->ic_bss ||
|
||||
IEEE80211_ADDR_EQ(ni->ni_bssid, ic->ic_bss->ni_bssid)) {
|
||||
|
@ -772,7 +767,7 @@ ieee80211_sta_join(struct ieee80211com *ic, struct ieee80211_node *selbs)
|
|||
* Delete unusable rates; we've already checked
|
||||
* that the negotiated rate set is acceptable.
|
||||
*/
|
||||
ieee80211_fix_rate(ic, selbs, IEEE80211_F_DODEL);
|
||||
ieee80211_fix_rate(selbs, IEEE80211_F_DODEL);
|
||||
/*
|
||||
* Fillin the neighbor table; it will already
|
||||
* exist if we are simply switching mastership.
|
||||
|
@ -798,6 +793,7 @@ ieee80211_sta_join(struct ieee80211com *ic, struct ieee80211_node *selbs)
|
|||
* mode is locked.
|
||||
*/
|
||||
ic->ic_curmode = ieee80211_chan2mode(ic, selbs->ni_chan);
|
||||
ic->ic_curchan = selbs->ni_chan;
|
||||
ieee80211_reset_erp(ic);
|
||||
ieee80211_wme_initparams(ic);
|
||||
|
||||
|
@ -863,7 +859,7 @@ node_cleanup(struct ieee80211_node *ni)
|
|||
*/
|
||||
IEEE80211_NODE_SAVEQ_DRAIN(ni, qlen);
|
||||
if (qlen != 0 && ic->ic_set_tim != NULL)
|
||||
ic->ic_set_tim(ic, ni, 0);
|
||||
ic->ic_set_tim(ni, 0);
|
||||
|
||||
ni->ni_associd = 0;
|
||||
if (ni->ni_challenge != NULL) {
|
||||
|
@ -887,7 +883,10 @@ node_cleanup(struct ieee80211_node *ni)
|
|||
m_freem(ni->ni_rxfrag[i]);
|
||||
ni->ni_rxfrag[i] = NULL;
|
||||
}
|
||||
ieee80211_crypto_delkey(ic, &ni->ni_ucastkey);
|
||||
/*
|
||||
* Must be careful here to remove any key map entry w/o a LOR.
|
||||
*/
|
||||
ieee80211_node_delucastkey(ni);
|
||||
#undef N
|
||||
}
|
||||
|
||||
|
@ -955,6 +954,42 @@ ieee80211_alloc_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
|
|||
return ni;
|
||||
}
|
||||
|
||||
/*
|
||||
* Craft a temporary node suitable for sending a management frame
|
||||
* to the specified station. We craft only as much state as we
|
||||
* need to do the work since the node will be immediately reclaimed
|
||||
* once the send completes.
|
||||
*/
|
||||
struct ieee80211_node *
|
||||
ieee80211_tmp_node(struct ieee80211com *ic, const u_int8_t *macaddr)
|
||||
{
|
||||
struct ieee80211_node *ni;
|
||||
|
||||
ni = ic->ic_node_alloc(&ic->ic_sta);
|
||||
if (ni != NULL) {
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
|
||||
"%s %p<%s>\n", __func__, ni, ether_sprintf(macaddr));
|
||||
|
||||
IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
|
||||
IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
|
||||
ieee80211_node_initref(ni); /* mark referenced */
|
||||
ni->ni_txpower = ic->ic_bss->ni_txpower;
|
||||
/* NB: required by ieee80211_fix_rate */
|
||||
ieee80211_set_chan(ic, ni, ic->ic_bss->ni_chan);
|
||||
ieee80211_crypto_resetkey(ic, &ni->ni_ucastkey,
|
||||
IEEE80211_KEYIX_NONE);
|
||||
/* XXX optimize away */
|
||||
IEEE80211_NODE_SAVEQ_INIT(ni, "unknown");
|
||||
|
||||
ni->ni_table = NULL; /* NB: pedantic */
|
||||
ni->ni_ic = ic;
|
||||
} else {
|
||||
/* XXX msg */
|
||||
ic->ic_stats.is_rx_nodealloc++;
|
||||
}
|
||||
return ni;
|
||||
}
|
||||
|
||||
struct ieee80211_node *
|
||||
ieee80211_dup_bss(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
|
||||
{
|
||||
|
@ -1047,13 +1082,188 @@ ieee80211_fakeup_adhoc_node(struct ieee80211_node_table *nt,
|
|||
/* XXX no rate negotiation; just dup */
|
||||
ni->ni_rates = ic->ic_bss->ni_rates;
|
||||
if (ic->ic_newassoc != NULL)
|
||||
ic->ic_newassoc(ic, ni, 1);
|
||||
ic->ic_newassoc(ni, 1);
|
||||
/* XXX not right for 802.1x/WPA */
|
||||
ieee80211_node_authorize(ic, ni);
|
||||
ieee80211_node_authorize(ni);
|
||||
}
|
||||
return ni;
|
||||
}
|
||||
|
||||
#ifdef IEEE80211_DEBUG
|
||||
static void
|
||||
dump_probe_beacon(u_int8_t subtype, int isnew,
|
||||
const u_int8_t mac[IEEE80211_ADDR_LEN],
|
||||
const struct ieee80211_scanparams *sp)
|
||||
{
|
||||
|
||||
printf("[%s] %s%s on chan %u (bss chan %u) ",
|
||||
ether_sprintf(mac), isnew ? "new " : "",
|
||||
ieee80211_mgt_subtype_name[subtype >> IEEE80211_FC0_SUBTYPE_SHIFT],
|
||||
sp->chan, sp->bchan);
|
||||
ieee80211_print_essid(sp->ssid + 2, sp->ssid[1]);
|
||||
printf("\n");
|
||||
|
||||
if (isnew) {
|
||||
printf("[%s] caps 0x%x bintval %u erp 0x%x",
|
||||
ether_sprintf(mac), sp->capinfo, sp->bintval, sp->erp);
|
||||
if (sp->country != NULL) {
|
||||
#ifdef __FreeBSD__
|
||||
printf(" country info %*D",
|
||||
sp->country[1], sp->country+2, " ");
|
||||
#else
|
||||
int i;
|
||||
printf(" country info");
|
||||
for (i = 0; i < sp->country[1]; i++)
|
||||
printf(" %02x", sp->country[i+2]);
|
||||
#endif
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
#endif /* IEEE80211_DEBUG */
|
||||
|
||||
static void
|
||||
saveie(u_int8_t **iep, const u_int8_t *ie)
|
||||
{
|
||||
|
||||
if (ie == NULL)
|
||||
*iep = NULL;
|
||||
else
|
||||
ieee80211_saveie(iep, ie);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a beacon or probe response frame.
|
||||
*/
|
||||
void
|
||||
ieee80211_add_scan(struct ieee80211com *ic,
|
||||
const struct ieee80211_scanparams *sp,
|
||||
const struct ieee80211_frame *wh,
|
||||
int subtype, int rssi, int rstamp)
|
||||
{
|
||||
#define ISPROBE(_st) ((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
|
||||
struct ieee80211_node_table *nt = &ic->ic_scan;
|
||||
struct ieee80211_node *ni;
|
||||
int newnode = 0;
|
||||
|
||||
ni = ieee80211_find_node(nt, wh->i_addr2);
|
||||
if (ni == NULL) {
|
||||
/*
|
||||
* Create a new entry.
|
||||
*/
|
||||
ni = ic->ic_node_alloc(nt);
|
||||
if (ni == NULL) {
|
||||
ic->ic_stats.is_rx_nodealloc++;
|
||||
return;
|
||||
}
|
||||
ieee80211_setup_node(nt, ni, wh->i_addr2);
|
||||
/*
|
||||
* XXX inherit from ic_bss.
|
||||
*/
|
||||
ni->ni_authmode = ic->ic_bss->ni_authmode;
|
||||
ni->ni_txpower = ic->ic_bss->ni_txpower;
|
||||
ni->ni_vlan = ic->ic_bss->ni_vlan; /* XXX?? */
|
||||
ieee80211_set_chan(ic, ni, ic->ic_curchan);
|
||||
ni->ni_rsn = ic->ic_bss->ni_rsn;
|
||||
newnode = 1;
|
||||
}
|
||||
#ifdef IEEE80211_DEBUG
|
||||
if (ieee80211_msg_scan(ic) && (ic->ic_flags & IEEE80211_F_SCAN))
|
||||
dump_probe_beacon(subtype, newnode, wh->i_addr2, sp);
|
||||
#endif
|
||||
/* XXX ap beaconing multiple ssid w/ same bssid */
|
||||
if (sp->ssid[1] != 0 &&
|
||||
(ISPROBE(subtype) || ni->ni_esslen == 0)) {
|
||||
ni->ni_esslen = sp->ssid[1];
|
||||
memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
|
||||
memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
|
||||
}
|
||||
ni->ni_scangen = ic->ic_scan.nt_scangen;
|
||||
IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
|
||||
ni->ni_rssi = rssi;
|
||||
ni->ni_rstamp = rstamp;
|
||||
memcpy(ni->ni_tstamp.data, sp->tstamp, sizeof(ni->ni_tstamp));
|
||||
ni->ni_intval = sp->bintval;
|
||||
ni->ni_capinfo = sp->capinfo;
|
||||
ni->ni_chan = &ic->ic_channels[sp->chan];
|
||||
ni->ni_fhdwell = sp->fhdwell;
|
||||
ni->ni_fhindex = sp->fhindex;
|
||||
ni->ni_erp = sp->erp;
|
||||
if (sp->tim != NULL) {
|
||||
struct ieee80211_tim_ie *ie =
|
||||
(struct ieee80211_tim_ie *) sp->tim;
|
||||
|
||||
ni->ni_dtim_count = ie->tim_count;
|
||||
ni->ni_dtim_period = ie->tim_period;
|
||||
}
|
||||
/*
|
||||
* Record the byte offset from the mac header to
|
||||
* the start of the TIM information element for
|
||||
* use by hardware and/or to speedup software
|
||||
* processing of beacon frames.
|
||||
*/
|
||||
ni->ni_timoff = sp->timoff;
|
||||
/*
|
||||
* Record optional information elements that might be
|
||||
* used by applications or drivers.
|
||||
*/
|
||||
saveie(&ni->ni_wme_ie, sp->wme);
|
||||
saveie(&ni->ni_wpa_ie, sp->wpa);
|
||||
|
||||
/* NB: must be after ni_chan is setup */
|
||||
ieee80211_setup_rates(ni, sp->rates, sp->xrates, IEEE80211_F_DOSORT);
|
||||
|
||||
if (!newnode)
|
||||
ieee80211_free_node(ni);
|
||||
#undef ISPROBE
|
||||
}
|
||||
|
||||
/*
|
||||
* Do node discovery in adhoc mode on receipt of a beacon
|
||||
* or probe response frame. Note that for the driver's
|
||||
* benefit we we treat this like an association so the
|
||||
* driver has an opportunity to setup it's private state.
|
||||
*/
|
||||
struct ieee80211_node *
|
||||
ieee80211_add_neighbor(struct ieee80211com *ic,
|
||||
const struct ieee80211_frame *wh,
|
||||
const struct ieee80211_scanparams *sp)
|
||||
{
|
||||
struct ieee80211_node *ni;
|
||||
|
||||
ni = ieee80211_dup_bss(&ic->ic_sta, wh->i_addr2);/* XXX alloc_node? */
|
||||
if (ni != NULL) {
|
||||
ni->ni_esslen = sp->ssid[1];
|
||||
memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
|
||||
IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
|
||||
memcpy(ni->ni_tstamp.data, sp->tstamp, sizeof(ni->ni_tstamp));
|
||||
ni->ni_intval = sp->bintval;
|
||||
ni->ni_capinfo = sp->capinfo;
|
||||
ni->ni_chan = ic->ic_bss->ni_chan;
|
||||
ni->ni_fhdwell = sp->fhdwell;
|
||||
ni->ni_fhindex = sp->fhindex;
|
||||
ni->ni_erp = sp->erp;
|
||||
ni->ni_timoff = sp->timoff;
|
||||
if (sp->wme != NULL)
|
||||
ieee80211_saveie(&ni->ni_wme_ie, sp->wme);
|
||||
if (sp->wpa != NULL)
|
||||
ieee80211_saveie(&ni->ni_wpa_ie, sp->wpa);
|
||||
|
||||
/* NB: must be after ni_chan is setup */
|
||||
ieee80211_setup_rates(ni, sp->rates, sp->xrates, IEEE80211_F_DOSORT);
|
||||
|
||||
if (ic->ic_newassoc != NULL)
|
||||
ic->ic_newassoc(ni, 1);
|
||||
/* XXX not right for 802.1x/WPA */
|
||||
ieee80211_node_authorize(ni);
|
||||
}
|
||||
return ni;
|
||||
}
|
||||
|
||||
#define IS_CTL(wh) \
|
||||
((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
|
||||
#define IS_PSPOLL(wh) \
|
||||
((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
|
||||
/*
|
||||
* Locate the node for sender, track state, and then pass the
|
||||
* (referenced) node up to the 802.11 layer for its use. We
|
||||
|
@ -1071,10 +1281,6 @@ ieee80211_find_rxnode(struct ieee80211com *ic,
|
|||
const struct ieee80211_frame_min *wh)
|
||||
#endif
|
||||
{
|
||||
#define IS_CTL(wh) \
|
||||
((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
|
||||
#define IS_PSPOLL(wh) \
|
||||
((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
|
||||
struct ieee80211_node_table *nt;
|
||||
struct ieee80211_node *ni;
|
||||
|
||||
|
@ -1092,12 +1298,77 @@ ieee80211_find_rxnode(struct ieee80211com *ic,
|
|||
ni = _ieee80211_find_node(nt, wh->i_addr1);
|
||||
else
|
||||
ni = _ieee80211_find_node(nt, wh->i_addr2);
|
||||
if (ni == NULL)
|
||||
ni = ieee80211_ref_node(ic->ic_bss);
|
||||
IEEE80211_NODE_UNLOCK(nt);
|
||||
|
||||
return (ni != NULL ? ni : ieee80211_ref_node(ic->ic_bss));
|
||||
return ni;
|
||||
}
|
||||
|
||||
/*
|
||||
* Like ieee80211_find_rxnode but use the supplied h/w
|
||||
* key index as a hint to locate the node in the key
|
||||
* mapping table. If an entry is present at the key
|
||||
* index we return it; otherwise do a normal lookup and
|
||||
* update the mapping table if the station has a unicast
|
||||
* key assigned to it.
|
||||
*/
|
||||
struct ieee80211_node *
|
||||
#ifdef IEEE80211_DEBUG_REFCNT
|
||||
ieee80211_find_rxnode_withkey_debug(struct ieee80211com *ic,
|
||||
const struct ieee80211_frame_min *wh, ieee80211_keyix keyix,
|
||||
const char *func, int line)
|
||||
#else
|
||||
ieee80211_find_rxnode_withkey(struct ieee80211com *ic,
|
||||
const struct ieee80211_frame_min *wh, ieee80211_keyix keyix)
|
||||
#endif
|
||||
{
|
||||
struct ieee80211_node_table *nt;
|
||||
struct ieee80211_node *ni;
|
||||
|
||||
if (ic->ic_opmode == IEEE80211_M_STA ||
|
||||
ic->ic_opmode == IEEE80211_M_MONITOR ||
|
||||
(ic->ic_flags & IEEE80211_F_SCAN))
|
||||
nt = &ic->ic_scan;
|
||||
else
|
||||
nt = &ic->ic_sta;
|
||||
IEEE80211_NODE_LOCK(nt);
|
||||
if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax)
|
||||
ni = nt->nt_keyixmap[keyix];
|
||||
else
|
||||
ni = NULL;
|
||||
if (ni == NULL) {
|
||||
if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/)
|
||||
ni = _ieee80211_find_node(nt, wh->i_addr1);
|
||||
else
|
||||
ni = _ieee80211_find_node(nt, wh->i_addr2);
|
||||
if (ni == NULL)
|
||||
ni = ieee80211_ref_node(ic->ic_bss);
|
||||
if (nt->nt_keyixmap != NULL) {
|
||||
/*
|
||||
* If the station has a unicast key cache slot
|
||||
* assigned update the key->node mapping table.
|
||||
*/
|
||||
keyix = ni->ni_ucastkey.wk_rxkeyix;
|
||||
/* XXX can keyixmap[keyix] != NULL? */
|
||||
if (keyix < nt->nt_keyixmax &&
|
||||
nt->nt_keyixmap[keyix] == NULL) {
|
||||
IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
|
||||
"%s: add key map entry %p<%s> refcnt %d\n",
|
||||
__func__, ni, ether_sprintf(ni->ni_macaddr),
|
||||
ieee80211_node_refcnt(ni)+1);
|
||||
nt->nt_keyixmap[keyix] = ieee80211_ref_node(ni);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ieee80211_ref_node(ni);
|
||||
}
|
||||
IEEE80211_NODE_UNLOCK(nt);
|
||||
|
||||
return ni;
|
||||
}
|
||||
#undef IS_PSPOLL
|
||||
#undef IS_CTL
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a reference to the appropriate node for sending
|
||||
|
@ -1116,15 +1387,16 @@ ieee80211_find_txnode(struct ieee80211com *ic, const u_int8_t *macaddr)
|
|||
|
||||
/*
|
||||
* The destination address should be in the node table
|
||||
* unless we are operating in station mode or this is a
|
||||
* multicast/broadcast frame.
|
||||
* unless this is a multicast/broadcast frame. We can
|
||||
* also optimize station mode operation, all frames go
|
||||
* to the bss node.
|
||||
*/
|
||||
if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(macaddr))
|
||||
return ieee80211_ref_node(ic->ic_bss);
|
||||
|
||||
/* XXX can't hold lock across dup_bss 'cuz of recursive locking */
|
||||
IEEE80211_NODE_LOCK(nt);
|
||||
ni = _ieee80211_find_node(nt, macaddr);
|
||||
if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(macaddr))
|
||||
ni = ieee80211_ref_node(ic->ic_bss);
|
||||
else
|
||||
ni = _ieee80211_find_node(nt, macaddr);
|
||||
IEEE80211_NODE_UNLOCK(nt);
|
||||
|
||||
if (ni == NULL) {
|
||||
|
@ -1274,22 +1546,86 @@ ieee80211_free_node(struct ieee80211_node *ni)
|
|||
"%s (%s:%u) %p<%s> refcnt %d\n", __func__, func, line, ni,
|
||||
ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)-1);
|
||||
#endif
|
||||
if (ieee80211_node_dectestref(ni)) {
|
||||
/*
|
||||
* Beware; if the node is marked gone then it's already
|
||||
* been removed from the table and we cannot assume the
|
||||
* table still exists. Regardless, there's no need to lock
|
||||
* the table.
|
||||
*/
|
||||
if (ni->ni_table != NULL) {
|
||||
IEEE80211_NODE_LOCK(nt);
|
||||
if (nt != NULL) {
|
||||
IEEE80211_NODE_LOCK(nt);
|
||||
if (ieee80211_node_dectestref(ni)) {
|
||||
/*
|
||||
* Last reference, reclaim state.
|
||||
*/
|
||||
_ieee80211_free_node(ni);
|
||||
IEEE80211_NODE_UNLOCK(nt);
|
||||
} else
|
||||
} else if (ieee80211_node_refcnt(ni) == 1 &&
|
||||
nt->nt_keyixmap != NULL) {
|
||||
ieee80211_keyix keyix;
|
||||
/*
|
||||
* Check for a last reference in the key mapping table.
|
||||
*/
|
||||
keyix = ni->ni_ucastkey.wk_rxkeyix;
|
||||
if (keyix < nt->nt_keyixmax &&
|
||||
nt->nt_keyixmap[keyix] == ni) {
|
||||
IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
|
||||
"%s: %p<%s> clear key map entry", __func__,
|
||||
ni, ether_sprintf(ni->ni_macaddr));
|
||||
nt->nt_keyixmap[keyix] = NULL;
|
||||
ieee80211_node_decref(ni); /* XXX needed? */
|
||||
_ieee80211_free_node(ni);
|
||||
}
|
||||
}
|
||||
IEEE80211_NODE_UNLOCK(nt);
|
||||
} else {
|
||||
if (ieee80211_node_dectestref(ni))
|
||||
_ieee80211_free_node(ni);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reclaim a unicast key and clear any key cache state.
|
||||
*/
|
||||
int
|
||||
ieee80211_node_delucastkey(struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct ieee80211_node_table *nt = &ic->ic_sta;
|
||||
struct ieee80211_node *nikey;
|
||||
ieee80211_keyix keyix;
|
||||
int isowned, status;
|
||||
|
||||
/*
|
||||
* NB: We must beware of LOR here; deleting the key
|
||||
* can cause the crypto layer to block traffic updates
|
||||
* which can generate a LOR against the node table lock;
|
||||
* grab it here and stash the key index for our use below.
|
||||
*
|
||||
* Must also beware of recursion on the node table lock.
|
||||
* When called from node_cleanup we may already have
|
||||
* the node table lock held. Unfortunately there's no
|
||||
* way to separate out this path so we must do this
|
||||
* conditionally.
|
||||
*/
|
||||
isowned = IEEE80211_NODE_IS_LOCKED(nt);
|
||||
if (!isowned)
|
||||
IEEE80211_NODE_LOCK(nt);
|
||||
keyix = ni->ni_ucastkey.wk_rxkeyix;
|
||||
status = ieee80211_crypto_delkey(ic, &ni->ni_ucastkey);
|
||||
if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax) {
|
||||
nikey = nt->nt_keyixmap[keyix];
|
||||
nt->nt_keyixmap[keyix] = NULL;;
|
||||
} else
|
||||
nikey = NULL;
|
||||
if (!isowned)
|
||||
IEEE80211_NODE_UNLOCK(&ic->ic_sta);
|
||||
|
||||
if (nikey != NULL) {
|
||||
KASSERT(nikey == ni,
|
||||
("key map out of sync, ni %p nikey %p", ni, nikey));
|
||||
IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
|
||||
"%s: delete key map entry %p<%s> refcnt %d\n",
|
||||
__func__, ni, ether_sprintf(ni->ni_macaddr),
|
||||
ieee80211_node_refcnt(ni)-1);
|
||||
ieee80211_free_node(ni);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reclaim a node. If this is the last reference count then
|
||||
* do the normal free work. Otherwise remove it from the node
|
||||
|
@ -1298,11 +1634,30 @@ ieee80211_free_node(struct ieee80211_node *ni)
|
|||
static void
|
||||
node_reclaim(struct ieee80211_node_table *nt, struct ieee80211_node *ni)
|
||||
{
|
||||
ieee80211_keyix keyix;
|
||||
|
||||
IEEE80211_NODE_LOCK_ASSERT(nt);
|
||||
|
||||
IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
|
||||
"%s: remove %p<%s> from %s table, refcnt %d\n",
|
||||
__func__, ni, ether_sprintf(ni->ni_macaddr),
|
||||
nt->nt_name, ieee80211_node_refcnt(ni)-1);
|
||||
/*
|
||||
* Clear any entry in the unicast key mapping table.
|
||||
* We need to do it here so rx lookups don't find it
|
||||
* in the mapping table even if it's not in the hash
|
||||
* table. We cannot depend on the mapping table entry
|
||||
* being cleared because the node may not be free'd.
|
||||
*/
|
||||
keyix = ni->ni_ucastkey.wk_rxkeyix;
|
||||
if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax &&
|
||||
nt->nt_keyixmap[keyix] == ni) {
|
||||
IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
|
||||
"%s: %p<%s> clear key map entry\n",
|
||||
__func__, ni, ether_sprintf(ni->ni_macaddr));
|
||||
nt->nt_keyixmap[keyix] = NULL;
|
||||
ieee80211_node_decref(ni); /* NB: don't need free */
|
||||
}
|
||||
if (!ieee80211_node_dectestref(ni)) {
|
||||
/*
|
||||
* Other references are present, just remove the
|
||||
|
@ -1392,7 +1747,10 @@ ieee80211_timeout_stations(struct ieee80211_node_table *nt)
|
|||
struct ieee80211com *ic = nt->nt_ic;
|
||||
struct ieee80211_node *ni;
|
||||
u_int gen;
|
||||
int isadhoc;
|
||||
|
||||
isadhoc = (ic->ic_opmode == IEEE80211_M_IBSS ||
|
||||
ic->ic_opmode == IEEE80211_M_AHDEMO);
|
||||
IEEE80211_SCAN_LOCK(nt);
|
||||
gen = nt->nt_scangen++;
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
|
||||
|
@ -1409,7 +1767,8 @@ restart:
|
|||
* will be reclaimed when the last reference to them
|
||||
* goes away (when frame xmits complete).
|
||||
*/
|
||||
if ((ni->ni_flags & IEEE80211_NODE_AREF) == 0)
|
||||
if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
|
||||
(ni->ni_flags & IEEE80211_NODE_AREF) == 0)
|
||||
continue;
|
||||
/*
|
||||
* Free fragment if not needed anymore
|
||||
|
@ -1428,7 +1787,7 @@ restart:
|
|||
if (ni == ic->ic_bss)
|
||||
continue;
|
||||
ni->ni_inact--;
|
||||
if (ni->ni_associd != 0) {
|
||||
if (ni->ni_associd != 0 || isadhoc) {
|
||||
/*
|
||||
* Age frames on the power save queue. The
|
||||
* aging interval is 4 times the listen
|
||||
|
@ -1463,7 +1822,7 @@ IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER, "[%s] discard frame, age %u\n", ether
|
|||
IEEE80211_NODE_STAT_ADD(ni,
|
||||
ps_discard, discard);
|
||||
if (IEEE80211_NODE_SAVEQ_QLEN(ni) == 0)
|
||||
ic->ic_set_tim(ic, ni, 0);
|
||||
ic->ic_set_tim(ni, 0);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
@ -1474,20 +1833,29 @@ IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER, "[%s] discard frame, age %u\n", ether
|
|||
*/
|
||||
if (0 < ni->ni_inact &&
|
||||
ni->ni_inact <= ic->ic_inact_probe) {
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
|
||||
"[%s] probe station due to inactivity\n",
|
||||
ether_sprintf(ni->ni_macaddr));
|
||||
IEEE80211_NOTE(ic,
|
||||
IEEE80211_MSG_INACT | IEEE80211_MSG_NODE,
|
||||
ni, "%s",
|
||||
"probe station due to inactivity");
|
||||
/*
|
||||
* Grab a reference before unlocking the table
|
||||
* so the node cannot be reclaimed before we
|
||||
* send the frame. ieee80211_send_nulldata
|
||||
* understands we've done this and reclaims the
|
||||
* ref for us as needed.
|
||||
*/
|
||||
ieee80211_ref_node(ni);
|
||||
IEEE80211_NODE_UNLOCK(nt);
|
||||
ieee80211_send_nulldata(ic, ni);
|
||||
ieee80211_send_nulldata(ni);
|
||||
/* XXX stat? */
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
if (ni->ni_inact <= 0) {
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
|
||||
"[%s] station timed out due to inactivity "
|
||||
"(refcnt %u)\n", ether_sprintf(ni->ni_macaddr),
|
||||
ieee80211_node_refcnt(ni));
|
||||
IEEE80211_NOTE(ic,
|
||||
IEEE80211_MSG_INACT | IEEE80211_MSG_NODE, ni,
|
||||
"station timed out due to inactivity "
|
||||
"(refcnt %u)", ieee80211_node_refcnt(ni));
|
||||
/*
|
||||
* Send a deauthenticate frame and drop the station.
|
||||
* This is somewhat complicated due to reference counts
|
||||
|
@ -1659,8 +2027,7 @@ ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp
|
|||
IEEE80211_AID_SET(ni->ni_associd, ic->ic_aid_bitmap);
|
||||
ic->ic_sta_assoc++;
|
||||
newassoc = 1;
|
||||
if (ic->ic_curmode == IEEE80211_MODE_11G ||
|
||||
ic->ic_curmode == IEEE80211_MODE_TURBO_G)
|
||||
if (ic->ic_curmode == IEEE80211_MODE_11G)
|
||||
ieee80211_node_join_11g(ic, ni);
|
||||
} else
|
||||
newassoc = 0;
|
||||
|
@ -1677,7 +2044,7 @@ ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp
|
|||
|
||||
/* give driver a chance to setup state like ni_txrate */
|
||||
if (ic->ic_newassoc != NULL)
|
||||
ic->ic_newassoc(ic, ni, newassoc);
|
||||
ic->ic_newassoc(ni, newassoc);
|
||||
ni->ni_inact_reload = ic->ic_inact_auth;
|
||||
ni->ni_inact = ni->ni_inact_reload;
|
||||
IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
|
||||
|
@ -1694,9 +2061,9 @@ static void
|
|||
ieee80211_node_leave_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
|
||||
{
|
||||
|
||||
KASSERT(ic->ic_curmode == IEEE80211_MODE_11G ||
|
||||
ic->ic_curmode == IEEE80211_MODE_TURBO_G,
|
||||
("not in 11g, curmode %x", ic->ic_curmode));
|
||||
KASSERT(ic->ic_curmode == IEEE80211_MODE_11G,
|
||||
("not in 11g, bss %u:0x%x, curmode %u", ni->ni_chan->ic_freq,
|
||||
ni->ni_chan->ic_flags, ic->ic_curmode));
|
||||
|
||||
/*
|
||||
* If a long slot station do the slot time bookkeeping.
|
||||
|
@ -1784,8 +2151,7 @@ ieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
|
|||
ni->ni_associd = 0;
|
||||
ic->ic_sta_assoc--;
|
||||
|
||||
if (ic->ic_curmode == IEEE80211_MODE_11G ||
|
||||
ic->ic_curmode == IEEE80211_MODE_TURBO_G)
|
||||
if (ic->ic_curmode == IEEE80211_MODE_11G)
|
||||
ieee80211_node_leave_11g(ic, ni);
|
||||
/*
|
||||
* Cleanup station state. In particular clear various
|
||||
|
@ -1859,8 +2225,9 @@ ieee80211_getrssi(struct ieee80211com *ic)
|
|||
* Indicate whether there are frames queued for a station in power-save mode.
|
||||
*/
|
||||
static void
|
||||
ieee80211_set_tim(struct ieee80211com *ic, struct ieee80211_node *ni, int set)
|
||||
ieee80211_set_tim(struct ieee80211_node *ni, int set)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
u_int16_t aid;
|
||||
|
||||
KASSERT(ic->ic_opmode == IEEE80211_M_HOSTAP ||
|
||||
|
@ -1892,7 +2259,7 @@ ieee80211_set_tim(struct ieee80211com *ic, struct ieee80211_node *ni, int set)
|
|||
static void
|
||||
ieee80211_node_table_init(struct ieee80211com *ic,
|
||||
struct ieee80211_node_table *nt,
|
||||
const char *name, int inact,
|
||||
const char *name, int inact, int keyixmax,
|
||||
void (*timeout)(struct ieee80211_node_table *))
|
||||
{
|
||||
|
||||
|
@ -1908,6 +2275,17 @@ ieee80211_node_table_init(struct ieee80211com *ic,
|
|||
nt->nt_scangen = 1;
|
||||
nt->nt_inact_init = inact;
|
||||
nt->nt_timeout = timeout;
|
||||
nt->nt_keyixmax = keyixmax;
|
||||
if (nt->nt_keyixmax > 0) {
|
||||
MALLOC(nt->nt_keyixmap, struct ieee80211_node **,
|
||||
keyixmax * sizeof(struct ieee80211_node *),
|
||||
M_80211_NODE, M_NOWAIT | M_ZERO);
|
||||
if (nt->nt_keyixmap == NULL)
|
||||
if_printf(ic->ic_ifp,
|
||||
"Cannot allocate key index map with %u entries\n",
|
||||
keyixmax);
|
||||
} else
|
||||
nt->nt_keyixmap = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1930,7 +2308,18 @@ ieee80211_node_table_cleanup(struct ieee80211_node_table *nt)
|
|||
IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
|
||||
"%s %s table\n", __func__, nt->nt_name);
|
||||
|
||||
IEEE80211_NODE_LOCK(nt);
|
||||
ieee80211_free_allnodes_locked(nt);
|
||||
if (nt->nt_keyixmap != NULL) {
|
||||
/* XXX verify all entries are NULL */
|
||||
int i;
|
||||
for (i = 0; i < nt->nt_keyixmax; i++)
|
||||
if (nt->nt_keyixmap[i] != NULL)
|
||||
printf("%s: %s[%u] still active\n", __func__,
|
||||
nt->nt_name, i);
|
||||
FREE(nt->nt_keyixmap, M_80211_NODE);
|
||||
nt->nt_keyixmap = NULL;
|
||||
}
|
||||
IEEE80211_SCAN_LOCK_DESTROY(nt);
|
||||
IEEE80211_NODE_LOCK_DESTROY(nt);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/net80211/ieee80211_node.h,v 1.17 2005/07/06 01:51:44 sam Exp $
|
||||
* $FreeBSD: src/sys/net80211/ieee80211_node.h,v 1.22 2005/08/10 16:22:29 sam Exp $
|
||||
*/
|
||||
#ifndef _NET80211_IEEE80211_NODE_H_
|
||||
#define _NET80211_IEEE80211_NODE_H_
|
||||
|
@ -132,7 +132,7 @@ struct ieee80211_node {
|
|||
u_int8_t ni_esslen;
|
||||
u_int8_t ni_essid[IEEE80211_NWID_LEN];
|
||||
struct ieee80211_rateset ni_rates; /* negotiated rate set */
|
||||
struct ieee80211_channel *ni_chan;
|
||||
struct ieee80211_channel *ni_chan; /* XXX multiple uses */
|
||||
u_int16_t ni_fhdwell; /* FH only */
|
||||
u_int8_t ni_fhindex; /* FH only */
|
||||
u_int8_t ni_erp; /* ERP from beacon/probe resp */
|
||||
|
@ -182,10 +182,8 @@ ieee80211_node_is_authorized(const struct ieee80211_node *ni)
|
|||
return (ni->ni_flags & IEEE80211_NODE_AUTH);
|
||||
}
|
||||
|
||||
void ieee80211_node_authorize(struct ieee80211com *,
|
||||
struct ieee80211_node *);
|
||||
void ieee80211_node_unauthorize(struct ieee80211com *,
|
||||
struct ieee80211_node *);
|
||||
void ieee80211_node_authorize(struct ieee80211_node *);
|
||||
void ieee80211_node_unauthorize(struct ieee80211_node *);
|
||||
|
||||
void ieee80211_begin_scan(struct ieee80211com *, int);
|
||||
int ieee80211_next_scan(struct ieee80211com *);
|
||||
|
@ -193,7 +191,7 @@ void ieee80211_create_ibss(struct ieee80211com*, struct ieee80211_channel *);
|
|||
void ieee80211_reset_bss(struct ieee80211com *);
|
||||
void ieee80211_cancel_scan(struct ieee80211com *);
|
||||
void ieee80211_end_scan(struct ieee80211com *);
|
||||
int ieee80211_ibss_merge(struct ieee80211com *, struct ieee80211_node *);
|
||||
int ieee80211_ibss_merge(struct ieee80211_node *);
|
||||
int ieee80211_sta_join(struct ieee80211com *, struct ieee80211_node *);
|
||||
void ieee80211_sta_leave(struct ieee80211com *, struct ieee80211_node *);
|
||||
|
||||
|
@ -213,6 +211,8 @@ struct ieee80211_node_table {
|
|||
u_int nt_scangen; /* gen# for timeout scan */
|
||||
int nt_inact_timer; /* inactivity timer */
|
||||
int nt_inact_init; /* initial node inact setting */
|
||||
struct ieee80211_node **nt_keyixmap; /* key ix -> node map */
|
||||
int nt_keyixmax; /* keyixmap size */
|
||||
|
||||
void (*nt_timeout)(struct ieee80211_node_table *);
|
||||
};
|
||||
|
@ -220,6 +220,8 @@ void ieee80211_node_table_reset(struct ieee80211_node_table *);
|
|||
|
||||
struct ieee80211_node *ieee80211_alloc_node(
|
||||
struct ieee80211_node_table *, const u_int8_t *);
|
||||
struct ieee80211_node *ieee80211_tmp_node(struct ieee80211com *,
|
||||
const u_int8_t *macaddr);
|
||||
struct ieee80211_node *ieee80211_dup_bss(struct ieee80211_node_table *,
|
||||
const u_int8_t *);
|
||||
#ifdef IEEE80211_DEBUG_REFCNT
|
||||
|
@ -231,6 +233,10 @@ struct ieee80211_node *ieee80211_find_node_debug(
|
|||
struct ieee80211_node * ieee80211_find_rxnode_debug(
|
||||
struct ieee80211com *, const struct ieee80211_frame_min *,
|
||||
const char *func, int line);
|
||||
struct ieee80211_node * ieee80211_find_rxnode_withkey_debug(
|
||||
struct ieee80211com *,
|
||||
const struct ieee80211_frame_min *, u_int16_t keyix,
|
||||
const char *func, int line);
|
||||
struct ieee80211_node *ieee80211_find_txnode_debug(
|
||||
struct ieee80211com *, const u_int8_t *,
|
||||
const char *func, int line);
|
||||
|
@ -247,6 +253,8 @@ struct ieee80211_node *ieee80211_find_node_with_ssid_debug(
|
|||
ieee80211_find_node_debug(nt, mac, __func__, __LINE__)
|
||||
#define ieee80211_find_rxnode(nt, wh) \
|
||||
ieee80211_find_rxnode_debug(nt, wh, __func__, __LINE__)
|
||||
#define ieee80211_find_rxnode_withkey(nt, wh, keyix) \
|
||||
ieee80211_find_rxnode_withkey_debug(nt, wh, keyix, __func__, __LINE__)
|
||||
#define ieee80211_find_txnode(nt, mac) \
|
||||
ieee80211_find_txnode_debug(nt, mac, __func__, __LINE__)
|
||||
#define ieee80211_find_node_with_channel(nt, mac, c) \
|
||||
|
@ -259,6 +267,8 @@ struct ieee80211_node *ieee80211_find_node(
|
|||
struct ieee80211_node_table *, const u_int8_t *);
|
||||
struct ieee80211_node * ieee80211_find_rxnode(
|
||||
struct ieee80211com *, const struct ieee80211_frame_min *);
|
||||
struct ieee80211_node * ieee80211_find_rxnode_withkey(struct ieee80211com *,
|
||||
const struct ieee80211_frame_min *, u_int16_t keyix);
|
||||
struct ieee80211_node *ieee80211_find_txnode(
|
||||
struct ieee80211com *, const u_int8_t *);
|
||||
struct ieee80211_node *ieee80211_find_node_with_channel(
|
||||
|
@ -268,6 +278,7 @@ struct ieee80211_node *ieee80211_find_node_with_ssid(
|
|||
struct ieee80211_node_table *, const u_int8_t *macaddr,
|
||||
u_int ssidlen, const u_int8_t *ssid);
|
||||
#endif
|
||||
int ieee80211_node_delucastkey(struct ieee80211_node *);
|
||||
|
||||
typedef void ieee80211_iter_func(void *, struct ieee80211_node *);
|
||||
void ieee80211_iterate_nodes(struct ieee80211_node_table *,
|
||||
|
@ -282,4 +293,38 @@ struct ieee80211_node *ieee80211_fakeup_adhoc_node(
|
|||
void ieee80211_node_join(struct ieee80211com *, struct ieee80211_node *,int);
|
||||
void ieee80211_node_leave(struct ieee80211com *, struct ieee80211_node *);
|
||||
u_int8_t ieee80211_getrssi(struct ieee80211com *ic);
|
||||
|
||||
/*
|
||||
* Parameters supplied when adding/updating an entry in a
|
||||
* scan cache. Pointer variables should be set to NULL
|
||||
* if no data is available. Pointer references can be to
|
||||
* local data; any information that is saved will be copied.
|
||||
* All multi-byte values must be in host byte order.
|
||||
*/
|
||||
struct ieee80211_scanparams {
|
||||
u_int16_t capinfo; /* 802.11 capabilities */
|
||||
u_int16_t fhdwell; /* FHSS dwell interval */
|
||||
u_int8_t chan; /* */
|
||||
u_int8_t bchan;
|
||||
u_int8_t fhindex;
|
||||
u_int8_t erp;
|
||||
u_int16_t bintval;
|
||||
u_int8_t timoff;
|
||||
u_int8_t *tim;
|
||||
u_int8_t *tstamp;
|
||||
u_int8_t *country;
|
||||
u_int8_t *ssid;
|
||||
u_int8_t *rates;
|
||||
u_int8_t *xrates;
|
||||
u_int8_t *wpa;
|
||||
u_int8_t *wme;
|
||||
};
|
||||
|
||||
void ieee80211_add_scan(struct ieee80211com *,
|
||||
const struct ieee80211_scanparams *,
|
||||
const struct ieee80211_frame *,
|
||||
int subtype, int rssi, int rstamp);
|
||||
struct ieee80211_node *ieee80211_add_neighbor(struct ieee80211com *,
|
||||
const struct ieee80211_frame *,
|
||||
const struct ieee80211_scanparams *);
|
||||
#endif /* _NET80211_IEEE80211_NODE_H_ */
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_output.c,v 1.26 2005/07/06 01:55:17 sam Exp $");
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_output.c,v 1.34 2005/08/10 16:22:29 sam Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
|
@ -77,6 +77,62 @@ doprint(struct ieee80211com *ic, int subtype)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the direction field and address fields of an outgoing
|
||||
* non-QoS frame. Note this should be called early on in
|
||||
* constructing a frame as it sets i_fc[1]; other bits can
|
||||
* then be or'd in.
|
||||
*/
|
||||
static void
|
||||
ieee80211_send_setup(struct ieee80211com *ic,
|
||||
struct ieee80211_node *ni,
|
||||
struct ieee80211_frame *wh,
|
||||
int type,
|
||||
const u_int8_t sa[IEEE80211_ADDR_LEN],
|
||||
const u_int8_t da[IEEE80211_ADDR_LEN],
|
||||
const u_int8_t bssid[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
#define WH4(wh) ((struct ieee80211_frame_addr4 *)wh)
|
||||
|
||||
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | type;
|
||||
if ((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) {
|
||||
switch (ic->ic_opmode) {
|
||||
case IEEE80211_M_STA:
|
||||
wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
|
||||
IEEE80211_ADDR_COPY(wh->i_addr1, bssid);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr2, sa);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr3, da);
|
||||
break;
|
||||
case IEEE80211_M_IBSS:
|
||||
case IEEE80211_M_AHDEMO:
|
||||
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
|
||||
IEEE80211_ADDR_COPY(wh->i_addr1, da);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr2, sa);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr3, bssid);
|
||||
break;
|
||||
case IEEE80211_M_HOSTAP:
|
||||
wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
|
||||
IEEE80211_ADDR_COPY(wh->i_addr1, da);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr2, bssid);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr3, sa);
|
||||
break;
|
||||
case IEEE80211_M_MONITOR: /* NB: to quiet compiler */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
|
||||
IEEE80211_ADDR_COPY(wh->i_addr1, da);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr2, sa);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr3, bssid);
|
||||
}
|
||||
*(u_int16_t *)&wh->i_dur[0] = 0;
|
||||
/* NB: use non-QoS tid */
|
||||
*(u_int16_t *)&wh->i_seq[0] =
|
||||
htole16(ni->ni_txseqs[0] << IEEE80211_SEQ_SEQ_SHIFT);
|
||||
ni->ni_txseqs[0]++;
|
||||
#undef WH4
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a management frame to the specified node. The node pointer
|
||||
* must have a reference as the pointer will be passed to the driver
|
||||
|
@ -112,30 +168,9 @@ ieee80211_mgmt_output(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
m->m_pkthdr.rcvif = (void *)ni;
|
||||
|
||||
wh = mtod(m, struct ieee80211_frame *);
|
||||
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type;
|
||||
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
|
||||
*(u_int16_t *)wh->i_dur = 0;
|
||||
*(u_int16_t *)wh->i_seq =
|
||||
htole16(ni->ni_txseqs[0] << IEEE80211_SEQ_SEQ_SHIFT);
|
||||
ni->ni_txseqs[0]++;
|
||||
/*
|
||||
* Hack. When sending PROBE_REQ frames while scanning we
|
||||
* explicitly force a broadcast rather than (as before) clobber
|
||||
* ni_macaddr and ni_bssid. This is stopgap, we need a way
|
||||
* to communicate this directly rather than do something
|
||||
* implicit based on surrounding state.
|
||||
*/
|
||||
if (type == IEEE80211_FC0_SUBTYPE_PROBE_REQ &&
|
||||
(ic->ic_flags & IEEE80211_F_SCAN)) {
|
||||
IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr);
|
||||
} else {
|
||||
IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
|
||||
}
|
||||
|
||||
ieee80211_send_setup(ic, ni, wh,
|
||||
IEEE80211_FC0_TYPE_MGT | type,
|
||||
ic->ic_myaddr, ni->ni_macaddr, ni->ni_bssid);
|
||||
if ((m->m_flags & M_LINK0) != 0 && ni->ni_challenge != NULL) {
|
||||
m->m_flags &= ~M_LINK0;
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
|
||||
|
@ -152,7 +187,7 @@ ieee80211_mgmt_output(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
ieee80211_mgt_subtype_name[
|
||||
(type & IEEE80211_FC0_SUBTYPE_MASK) >>
|
||||
IEEE80211_FC0_SUBTYPE_SHIFT],
|
||||
ieee80211_chan2ieee(ic, ni->ni_chan));
|
||||
ieee80211_chan2ieee(ic, ic->ic_curchan));
|
||||
}
|
||||
#endif
|
||||
IEEE80211_NODE_STAT(ni, tx_mgmt);
|
||||
|
@ -164,10 +199,15 @@ ieee80211_mgmt_output(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
|
||||
/*
|
||||
* Send a null data frame to the specified node.
|
||||
*
|
||||
* NB: the caller is assumed to have setup a node reference
|
||||
* for use; this is necessary to deal with a race condition
|
||||
* when probing for inactive stations.
|
||||
*/
|
||||
int
|
||||
ieee80211_send_nulldata(struct ieee80211com *ic, struct ieee80211_node *ni)
|
||||
ieee80211_send_nulldata(struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct mbuf *m;
|
||||
struct ieee80211_frame *wh;
|
||||
|
@ -176,27 +216,29 @@ ieee80211_send_nulldata(struct ieee80211com *ic, struct ieee80211_node *ni)
|
|||
if (m == NULL) {
|
||||
/* XXX debug msg */
|
||||
ic->ic_stats.is_tx_nobuf++;
|
||||
ieee80211_unref_node(&ni);
|
||||
return ENOMEM;
|
||||
}
|
||||
m->m_pkthdr.rcvif = (void *) ieee80211_ref_node(ni);
|
||||
m->m_pkthdr.rcvif = (void *) ni;
|
||||
|
||||
wh = mtod(m, struct ieee80211_frame *);
|
||||
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA |
|
||||
IEEE80211_FC0_SUBTYPE_NODATA;
|
||||
*(u_int16_t *)wh->i_dur = 0;
|
||||
*(u_int16_t *)wh->i_seq =
|
||||
htole16(ni->ni_txseqs[0] << IEEE80211_SEQ_SEQ_SHIFT);
|
||||
ni->ni_txseqs[0]++;
|
||||
|
||||
/* XXX WDS */
|
||||
wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
|
||||
IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr3, ic->ic_myaddr);
|
||||
ieee80211_send_setup(ic, ni, wh,
|
||||
IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_NODATA,
|
||||
ic->ic_myaddr, ni->ni_macaddr, ni->ni_bssid);
|
||||
/* NB: power management bit is never sent by an AP */
|
||||
if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) &&
|
||||
ic->ic_opmode != IEEE80211_M_HOSTAP)
|
||||
wh->i_fc[1] |= IEEE80211_FC1_PWR_MGT;
|
||||
m->m_len = m->m_pkthdr.len = sizeof(struct ieee80211_frame);
|
||||
|
||||
IEEE80211_NODE_STAT(ni, tx_data);
|
||||
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS,
|
||||
"[%s] send null data frame on channel %u, pwr mgt %s\n",
|
||||
ether_sprintf(ni->ni_macaddr),
|
||||
ieee80211_chan2ieee(ic, ic->ic_curchan),
|
||||
wh->i_fc[1] & IEEE80211_FC1_PWR_MGT ? "ena" : "dis");
|
||||
|
||||
IF_ENQUEUE(&ic->ic_mgtq, m); /* cheat */
|
||||
if_start(ifp);
|
||||
|
||||
|
@ -907,6 +949,91 @@ ieee80211_add_wme_param(u_int8_t *frm, struct ieee80211_wme_state *wme)
|
|||
}
|
||||
#undef WME_OUI_BYTES
|
||||
|
||||
/*
|
||||
* Send a probe request frame with the specified ssid
|
||||
* and any optional information element data.
|
||||
*/
|
||||
int
|
||||
ieee80211_send_probereq(struct ieee80211_node *ni,
|
||||
const u_int8_t sa[IEEE80211_ADDR_LEN],
|
||||
const u_int8_t da[IEEE80211_ADDR_LEN],
|
||||
const u_int8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const u_int8_t *ssid, size_t ssidlen,
|
||||
const void *optie, size_t optielen)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
enum ieee80211_phymode mode;
|
||||
struct ieee80211_frame *wh;
|
||||
struct mbuf *m;
|
||||
u_int8_t *frm;
|
||||
|
||||
/*
|
||||
* Hold a reference on the node so it doesn't go away until after
|
||||
* the xmit is complete all the way in the driver. On error we
|
||||
* will remove our reference.
|
||||
*/
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
|
||||
"ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n",
|
||||
__func__, __LINE__,
|
||||
ni, ether_sprintf(ni->ni_macaddr),
|
||||
ieee80211_node_refcnt(ni)+1);
|
||||
ieee80211_ref_node(ni);
|
||||
|
||||
/*
|
||||
* prreq frame format
|
||||
* [tlv] ssid
|
||||
* [tlv] supported rates
|
||||
* [tlv] extended supported rates
|
||||
* [tlv] user-specified ie's
|
||||
*/
|
||||
m = ieee80211_getmgtframe(&frm,
|
||||
2 + IEEE80211_NWID_LEN
|
||||
+ 2 + IEEE80211_RATE_SIZE
|
||||
+ 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
|
||||
+ (optie != NULL ? optielen : 0)
|
||||
);
|
||||
if (m == NULL) {
|
||||
ic->ic_stats.is_tx_nobuf++;
|
||||
ieee80211_free_node(ni);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
frm = ieee80211_add_ssid(frm, ssid, ssidlen);
|
||||
mode = ieee80211_chan2mode(ic, ic->ic_curchan);
|
||||
frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[mode]);
|
||||
frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[mode]);
|
||||
|
||||
if (optie != NULL) {
|
||||
memcpy(frm, optie, optielen);
|
||||
frm += optielen;
|
||||
}
|
||||
m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
|
||||
|
||||
M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
|
||||
if (m == NULL)
|
||||
return ENOMEM;
|
||||
KASSERT(m->m_pkthdr.rcvif == NULL, ("rcvif not null"));
|
||||
m->m_pkthdr.rcvif = (void *)ni;
|
||||
|
||||
wh = mtod(m, struct ieee80211_frame *);
|
||||
ieee80211_send_setup(ic, ni, wh,
|
||||
IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ,
|
||||
sa, da, bssid);
|
||||
/* XXX power management? */
|
||||
|
||||
IEEE80211_NODE_STAT(ni, tx_probereq);
|
||||
IEEE80211_NODE_STAT(ni, tx_mgmt);
|
||||
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS,
|
||||
"[%s] send probe req on channel %u\n",
|
||||
ether_sprintf(wh->i_addr1),
|
||||
ieee80211_chan2ieee(ic, ic->ic_curchan));
|
||||
|
||||
IF_ENQUEUE(&ic->ic_mgtq, m);
|
||||
if_start(ic->ic_ifp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a management frame. The node is for the destination (or ic_bss
|
||||
* when in station mode). Nodes other than ic_bss have their reference
|
||||
|
@ -919,7 +1046,6 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
#define senderr(_x, _v) do { ic->ic_stats._v++; ret = _x; goto bad; } while (0)
|
||||
struct mbuf *m;
|
||||
u_int8_t *frm;
|
||||
enum ieee80211_phymode mode;
|
||||
u_int16_t capinfo;
|
||||
int has_challenge, is_shared_key, ret, timer, status;
|
||||
|
||||
|
@ -939,38 +1065,6 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
|
||||
timer = 0;
|
||||
switch (type) {
|
||||
case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
|
||||
/*
|
||||
* prreq frame format
|
||||
* [tlv] ssid
|
||||
* [tlv] supported rates
|
||||
* [tlv] extended supported rates
|
||||
* [tlv] user-specified ie's
|
||||
*/
|
||||
m = ieee80211_getmgtframe(&frm,
|
||||
2 + IEEE80211_NWID_LEN
|
||||
+ 2 + IEEE80211_RATE_SIZE
|
||||
+ 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
|
||||
+ (ic->ic_opt_ie != NULL ? ic->ic_opt_ie_len : 0)
|
||||
);
|
||||
if (m == NULL)
|
||||
senderr(ENOMEM, is_tx_nobuf);
|
||||
|
||||
frm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen);
|
||||
mode = ieee80211_chan2mode(ic, ni->ni_chan);
|
||||
frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[mode]);
|
||||
frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[mode]);
|
||||
if (ic->ic_opt_ie != NULL) {
|
||||
memcpy(frm, ic->ic_opt_ie, ic->ic_opt_ie_len);
|
||||
frm += ic->ic_opt_ie_len;
|
||||
}
|
||||
m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
|
||||
|
||||
IEEE80211_NODE_STAT(ni, tx_probereq);
|
||||
if (ic->ic_opmode == IEEE80211_M_STA)
|
||||
timer = IEEE80211_TRANS_WAIT;
|
||||
break;
|
||||
|
||||
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
|
||||
/*
|
||||
* probe response frame format
|
||||
|
@ -1015,7 +1109,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
if (ic->ic_flags & IEEE80211_F_PRIVACY)
|
||||
capinfo |= IEEE80211_CAPINFO_PRIVACY;
|
||||
if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
|
||||
IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
|
||||
IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
|
||||
capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
|
||||
if (ic->ic_flags & IEEE80211_F_SHSLOT)
|
||||
capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
|
||||
|
@ -1032,14 +1126,14 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
*frm++ = ni->ni_fhdwell & 0x00ff;
|
||||
*frm++ = (ni->ni_fhdwell >> 8) & 0x00ff;
|
||||
*frm++ = IEEE80211_FH_CHANSET(
|
||||
ieee80211_chan2ieee(ic, ni->ni_chan));
|
||||
ieee80211_chan2ieee(ic, ic->ic_curchan));
|
||||
*frm++ = IEEE80211_FH_CHANPAT(
|
||||
ieee80211_chan2ieee(ic, ni->ni_chan));
|
||||
ieee80211_chan2ieee(ic, ic->ic_curchan));
|
||||
*frm++ = ni->ni_fhindex;
|
||||
} else {
|
||||
*frm++ = IEEE80211_ELEMID_DSPARMS;
|
||||
*frm++ = 1;
|
||||
*frm++ = ieee80211_chan2ieee(ic, ni->ni_chan);
|
||||
*frm++ = ieee80211_chan2ieee(ic, ic->ic_curchan);
|
||||
}
|
||||
|
||||
if (ic->ic_opmode == IEEE80211_M_IBSS) {
|
||||
|
@ -1130,7 +1224,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
IEEE80211_NODE_STAT(ni, tx_deauth);
|
||||
IEEE80211_NODE_STAT_SET(ni, tx_deauth_code, arg);
|
||||
|
||||
ieee80211_node_unauthorize(ic, ni); /* port closed */
|
||||
ieee80211_node_unauthorize(ni); /* port closed */
|
||||
break;
|
||||
|
||||
case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
|
||||
|
@ -1171,7 +1265,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
* short premable is set.
|
||||
*/
|
||||
if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
|
||||
IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
|
||||
IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
|
||||
capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
|
||||
if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) &&
|
||||
(ic->ic_caps & IEEE80211_C_SHSLOT))
|
||||
|
@ -1227,7 +1321,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
if (ic->ic_flags & IEEE80211_F_PRIVACY)
|
||||
capinfo |= IEEE80211_CAPINFO_PRIVACY;
|
||||
if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
|
||||
IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
|
||||
IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
|
||||
capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
|
||||
if (ic->ic_flags & IEEE80211_F_SHSLOT)
|
||||
capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
|
||||
|
@ -1592,14 +1686,14 @@ ieee80211_pwrsave(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|||
* using this information.
|
||||
*/
|
||||
/* XXX handle overflow? */
|
||||
age = ((ni->ni_intval * ic->ic_lintval) << 2) / 1024; /* TU -> secs */
|
||||
age = ((ni->ni_intval * ic->ic_bintval) << 2) / 1024; /* TU -> secs */
|
||||
_IEEE80211_NODE_SAVEQ_ENQUEUE(ni, m, qlen, age);
|
||||
IEEE80211_NODE_SAVEQ_UNLOCK(ni);
|
||||
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
|
||||
"[%s] save frame, %u now queued\n",
|
||||
ether_sprintf(ni->ni_macaddr), qlen);
|
||||
"[%s] save frame with age %d, %u now queued\n",
|
||||
ether_sprintf(ni->ni_macaddr), age, qlen);
|
||||
|
||||
if (qlen == 1)
|
||||
ic->ic_set_tim(ic, ni, 1);
|
||||
ic->ic_set_tim(ni, 1);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_proto.c,v 1.17 2005/07/04 01:29:41 sam Exp $");
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_proto.c,v 1.23 2005/08/10 16:22:29 sam Exp $");
|
||||
|
||||
/*
|
||||
* IEEE 802.11 protocol support.
|
||||
|
@ -94,13 +94,9 @@ ieee80211_proto_attach(struct ieee80211com *ic)
|
|||
/* XXX room for crypto */
|
||||
ifp->if_hdrlen = sizeof(struct ieee80211_qosframe_addr4);
|
||||
|
||||
#ifdef notdef
|
||||
ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
|
||||
#else
|
||||
ic->ic_rtsthreshold = IEEE80211_RTS_MAX;
|
||||
#endif
|
||||
ic->ic_fragthreshold = 2346; /* XXX not used yet */
|
||||
ic->ic_fixed_rate = -1; /* no fixed rate */
|
||||
ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT;
|
||||
ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE;
|
||||
ic->ic_protmode = IEEE80211_PROT_CTSONLY;
|
||||
ic->ic_roaming = IEEE80211_ROAMING_AUTO;
|
||||
|
||||
|
@ -323,9 +319,10 @@ ieee80211_dump_pkt(const u_int8_t *buf, int len, int rate, int rssi)
|
|||
}
|
||||
|
||||
int
|
||||
ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni, int flags)
|
||||
ieee80211_fix_rate(struct ieee80211_node *ni, int flags)
|
||||
{
|
||||
#define RV(v) ((v) & IEEE80211_RATE_VAL)
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
int i, j, ignore, error;
|
||||
int okrate, badrate, fixedrate;
|
||||
struct ieee80211_rateset *srs, *nrs;
|
||||
|
@ -335,7 +332,8 @@ ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni, int flags
|
|||
* If the fixed rate check was requested but no
|
||||
* fixed has been defined then just remove it.
|
||||
*/
|
||||
if ((flags & IEEE80211_F_DOFRATE) && ic->ic_fixed_rate < 0)
|
||||
if ((flags & IEEE80211_F_DOFRATE) &&
|
||||
ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)
|
||||
flags &= ~IEEE80211_F_DOFRATE;
|
||||
error = 0;
|
||||
okrate = badrate = fixedrate = 0;
|
||||
|
@ -924,9 +922,12 @@ ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg
|
|||
* beacons on the channel.
|
||||
*/
|
||||
if ((ic->ic_flags & IEEE80211_F_ASCAN) &&
|
||||
(ni->ni_chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0) {
|
||||
IEEE80211_SEND_MGMT(ic, ni,
|
||||
IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
|
||||
(ic->ic_curchan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0) {
|
||||
ieee80211_send_probereq(ni,
|
||||
ic->ic_myaddr, ifp->if_broadcastaddr,
|
||||
ifp->if_broadcastaddr,
|
||||
ic->ic_des_essid, ic->ic_des_esslen,
|
||||
ic->ic_opt_ie, ic->ic_opt_ie_len);
|
||||
}
|
||||
break;
|
||||
case IEEE80211_S_RUN:
|
||||
|
@ -1042,7 +1043,7 @@ ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg
|
|||
ieee80211_print_essid(ic->ic_bss->ni_essid,
|
||||
ni->ni_esslen);
|
||||
printf(" channel %d start %uMb\n",
|
||||
ieee80211_chan2ieee(ic, ni->ni_chan),
|
||||
ieee80211_chan2ieee(ic, ic->ic_curchan),
|
||||
IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate]));
|
||||
}
|
||||
#endif
|
||||
|
@ -1070,7 +1071,7 @@ ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg
|
|||
* at this point so traffic can flow.
|
||||
*/
|
||||
if (ni->ni_authmode != IEEE80211_AUTH_8021X)
|
||||
ieee80211_node_authorize(ic, ni);
|
||||
ieee80211_node_authorize(ni);
|
||||
/*
|
||||
* Enable inactivity processing.
|
||||
* XXX
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/net80211/ieee80211_proto.h,v 1.11 2005/04/04 04:27:20 sam Exp $
|
||||
* $FreeBSD: src/sys/net80211/ieee80211_proto.h,v 1.16 2005/08/13 17:31:48 sam Exp $
|
||||
*/
|
||||
#ifndef _NET80211_IEEE80211_PROTO_H_
|
||||
#define _NET80211_IEEE80211_PROTO_H_
|
||||
|
@ -59,9 +59,18 @@ void ieee80211_proto_detach(struct ieee80211com *);
|
|||
struct ieee80211_node;
|
||||
int ieee80211_input(struct ieee80211com *, struct mbuf *,
|
||||
struct ieee80211_node *, int, u_int32_t);
|
||||
int ieee80211_setup_rates(struct ieee80211_node *ni,
|
||||
const u_int8_t *rates, const u_int8_t *xrates, int flags);
|
||||
void ieee80211_saveie(u_int8_t **, const u_int8_t *);
|
||||
void ieee80211_recv_mgmt(struct ieee80211com *, struct mbuf *,
|
||||
struct ieee80211_node *, int, int, u_int32_t);
|
||||
int ieee80211_send_nulldata(struct ieee80211com *, struct ieee80211_node *);
|
||||
int ieee80211_send_nulldata(struct ieee80211_node *);
|
||||
int ieee80211_send_probereq(struct ieee80211_node *ni,
|
||||
const u_int8_t sa[IEEE80211_ADDR_LEN],
|
||||
const u_int8_t da[IEEE80211_ADDR_LEN],
|
||||
const u_int8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const u_int8_t *ssid, size_t ssidlen,
|
||||
const void *optie, size_t optielen);
|
||||
int ieee80211_send_mgmt(struct ieee80211com *, struct ieee80211_node *,
|
||||
int, int);
|
||||
int ieee80211_classify(struct ieee80211com *, struct mbuf *,
|
||||
|
@ -135,6 +144,7 @@ void ieee80211_authenticator_register(int type,
|
|||
void ieee80211_authenticator_unregister(int type);
|
||||
const struct ieee80211_authenticator *ieee80211_authenticator_get(int auth);
|
||||
|
||||
struct ieee80211req;
|
||||
/*
|
||||
* Template for an MAC ACL policy module. Such modules
|
||||
* register with the protocol code and are passed the sender's
|
||||
|
@ -153,6 +163,8 @@ struct ieee80211_aclator {
|
|||
int (*iac_flush)(struct ieee80211com *);
|
||||
int (*iac_setpolicy)(struct ieee80211com *, int);
|
||||
int (*iac_getpolicy)(struct ieee80211com *);
|
||||
int (*iac_setioctl)(struct ieee80211com *, struct ieee80211req *);
|
||||
int (*iac_getioctl)(struct ieee80211com *, struct ieee80211req *);
|
||||
};
|
||||
void ieee80211_aclator_register(const struct ieee80211_aclator *);
|
||||
void ieee80211_aclator_unregister(const struct ieee80211_aclator *);
|
||||
|
@ -163,7 +175,7 @@ const struct ieee80211_aclator *ieee80211_aclator_get(const char *name);
|
|||
#define IEEE80211_F_DOFRATE 0x00000002 /* use fixed rate */
|
||||
#define IEEE80211_F_DONEGO 0x00000004 /* calc negotiated rate */
|
||||
#define IEEE80211_F_DODEL 0x00000008 /* delete ignore rate */
|
||||
int ieee80211_fix_rate(struct ieee80211com *, struct ieee80211_node *, int);
|
||||
int ieee80211_fix_rate(struct ieee80211_node *, int);
|
||||
|
||||
/*
|
||||
* WME/WMM support.
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/net80211/ieee80211_var.h,v 1.22 2005/07/06 15:38:27 sam Exp $
|
||||
* $FreeBSD: src/sys/net80211/ieee80211_var.h,v 1.30 2005/08/10 16:22:29 sam Exp $
|
||||
*/
|
||||
#ifndef _NET80211_IEEE80211_VAR_H_
|
||||
#define _NET80211_IEEE80211_VAR_H_
|
||||
|
@ -65,13 +65,19 @@
|
|||
#define IEEE80211_DTIM_MIN 1 /* min DTIM period */
|
||||
#define IEEE80211_DTIM_DEFAULT 1 /* default DTIM period */
|
||||
|
||||
#define IEEE80211_BINTVAL_MAX 500 /* max beacon interval (TU's) */
|
||||
/* NB: min+max come from WiFi requirements */
|
||||
#define IEEE80211_BINTVAL_MAX 1000 /* max beacon interval (TU's) */
|
||||
#define IEEE80211_BINTVAL_MIN 25 /* min beacon interval (TU's) */
|
||||
#define IEEE80211_BINTVAL_DEFAULT 100 /* default beacon interval (TU's) */
|
||||
|
||||
#define IEEE80211_PS_SLEEP 0x1 /* STA is in power saving mode */
|
||||
#define IEEE80211_PS_MAX_QUEUE 50 /* maximum saved packets */
|
||||
|
||||
#define IEEE80211_FIXED_RATE_NONE -1
|
||||
|
||||
#define IEEE80211_RTS_DEFAULT IEEE80211_RTS_MAX
|
||||
#define IEEE80211_FRAG_DEFAULT IEEE80211_FRAG_MAX
|
||||
|
||||
#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024)
|
||||
#define IEEE80211_TU_TO_MS(x) (((x) * 1024) / 1000)
|
||||
|
||||
|
@ -95,11 +101,9 @@ struct ieee80211com {
|
|||
struct ieee80211_node *, int, int);
|
||||
int (*ic_newstate)(struct ieee80211com *,
|
||||
enum ieee80211_state, int);
|
||||
void (*ic_newassoc)(struct ieee80211com *,
|
||||
struct ieee80211_node *, int);
|
||||
void (*ic_newassoc)(struct ieee80211_node *, int);
|
||||
void (*ic_updateslot)(struct ifnet *);
|
||||
void (*ic_set_tim)(struct ieee80211com *,
|
||||
struct ieee80211_node *, int);
|
||||
void (*ic_set_tim)(struct ieee80211_node *, int);
|
||||
u_int8_t ic_myaddr[IEEE80211_ADDR_LEN];
|
||||
struct ieee80211_rateset ic_sup_rates[IEEE80211_MODE_MAX];
|
||||
struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX+1];
|
||||
|
@ -109,6 +113,7 @@ struct ieee80211com {
|
|||
struct ieee80211_node_table ic_scan; /* scan candidates */
|
||||
struct ifqueue ic_mgtq;
|
||||
u_int32_t ic_flags; /* state flags */
|
||||
u_int32_t ic_flags_ext; /* extended state flags */
|
||||
u_int32_t ic_caps; /* capabilities */
|
||||
u_int16_t ic_modecaps; /* set of mode capabilities */
|
||||
u_int16_t ic_curmode; /* current mode */
|
||||
|
@ -131,6 +136,7 @@ struct ieee80211com {
|
|||
struct bpf_if *ic_rawbpf; /* packet filter structure */
|
||||
struct ieee80211_node *ic_bss; /* information for this node */
|
||||
struct ieee80211_channel *ic_ibss_chan;
|
||||
struct ieee80211_channel *ic_curchan; /* current channel */
|
||||
int ic_fixed_rate; /* index to ic_sup_rates[] */
|
||||
u_int16_t ic_rtsthreshold;
|
||||
u_int16_t ic_fragthreshold;
|
||||
|
@ -139,6 +145,7 @@ struct ieee80211com {
|
|||
void (*ic_node_cleanup)(struct ieee80211_node *);
|
||||
u_int8_t (*ic_node_getrssi)(const struct ieee80211_node*);
|
||||
u_int16_t ic_lintval; /* listen interval */
|
||||
u_int16_t ic_bintval; /* beacon interval */
|
||||
u_int16_t ic_holdover; /* PM hold over duration */
|
||||
u_int16_t ic_txmin; /* min tx retry count */
|
||||
u_int16_t ic_txmax; /* max tx retry count */
|
||||
|
@ -196,7 +203,9 @@ struct ieee80211com {
|
|||
#define IEEE80211_ADDR_COPY(dst,src) memcpy(dst,src,IEEE80211_ADDR_LEN)
|
||||
|
||||
/* ic_flags */
|
||||
/* NB: bits 0x4f available */
|
||||
/* NB: bits 0x4c available */
|
||||
#define IEEE80211_F_FF 0x00000001 /* CONF: ATH FF enabled */
|
||||
#define IEEE80211_F_TURBOP 0x00000002 /* CONF: ATH Turbo enabled*/
|
||||
/* NB: this is intentionally setup to be IEEE80211_CAPINFO_PRIVACY */
|
||||
#define IEEE80211_F_PRIVACY 0x00000010 /* CONF: privacy enabled */
|
||||
#define IEEE80211_F_PUREG 0x00000020 /* CONF: 11g w/o 11b sta's */
|
||||
|
@ -208,7 +217,7 @@ struct ieee80211com {
|
|||
#define IEEE80211_F_PMGTON 0x00000800 /* CONF: Power mgmt enable */
|
||||
#define IEEE80211_F_DESBSSID 0x00001000 /* CONF: des_bssid is set */
|
||||
#define IEEE80211_F_WME 0x00002000 /* CONF: enable WME use */
|
||||
#define IEEE80211_F_ROAMING 0x00004000 /* CONF: roaming enabled (???)*/
|
||||
#define IEEE80211_F_BGSCAN 0x00004000 /* CONF: bg scan enabled (???)*/
|
||||
#define IEEE80211_F_SWRETRY 0x00008000 /* CONF: sw tx retry enabled */
|
||||
#define IEEE80211_F_TXPOW_FIXED 0x00010000 /* TX Power: fixed rate */
|
||||
#define IEEE80211_F_IBSSON 0x00020000 /* CONF: IBSS creation enable */
|
||||
|
@ -226,12 +235,19 @@ struct ieee80211com {
|
|||
#define IEEE80211_F_NOBRIDGE 0x10000000 /* CONF: dis. internal bridge */
|
||||
#define IEEE80211_F_WMEUPDATE 0x20000000 /* STATUS: update beacon wme */
|
||||
|
||||
/* ic_flags_ext */
|
||||
#define IEEE80211_FEXT_WDS 0x00000001 /* CONF: 4 addr allowed */
|
||||
/* 0x00000006 reserved */
|
||||
#define IEEE80211_FEXT_BGSCAN 0x00000008 /* STATUS: enable full bgscan completion */
|
||||
|
||||
/* ic_caps */
|
||||
#define IEEE80211_C_WEP 0x00000001 /* CAPABILITY: WEP available */
|
||||
#define IEEE80211_C_TKIP 0x00000002 /* CAPABILITY: TKIP available */
|
||||
#define IEEE80211_C_AES 0x00000004 /* CAPABILITY: AES OCB avail */
|
||||
#define IEEE80211_C_AES_CCM 0x00000008 /* CAPABILITY: AES CCM avail */
|
||||
#define IEEE80211_C_CKIP 0x00000020 /* CAPABILITY: CKIP available */
|
||||
#define IEEE80211_C_FF 0x00000040 /* CAPABILITY: ATH FF avail */
|
||||
#define IEEE80211_C_TURBOP 0x00000080 /* CAPABILITY: ATH Turbo avail*/
|
||||
#define IEEE80211_C_IBSS 0x00000100 /* CAPABILITY: IBSS available */
|
||||
#define IEEE80211_C_PMGT 0x00000200 /* CAPABILITY: Power mgmt */
|
||||
#define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */
|
||||
|
@ -247,6 +263,10 @@ struct ieee80211com {
|
|||
#define IEEE80211_C_WPA 0x01800000 /* CAPABILITY: WPA1+WPA2 avail*/
|
||||
#define IEEE80211_C_BURST 0x02000000 /* CAPABILITY: frame bursting */
|
||||
#define IEEE80211_C_WME 0x04000000 /* CAPABILITY: WME avail */
|
||||
#define IEEE80211_C_WDS 0x08000000 /* CAPABILITY: 4-addr support */
|
||||
/* 0x10000000 reserved */
|
||||
#define IEEE80211_C_BGSCAN 0x20000000 /* CAPABILITY: bg scanning */
|
||||
#define IEEE80211_C_TXFRAG 0x40000000 /* CAPABILITY: tx fragments */
|
||||
/* XXX protection/barker? */
|
||||
|
||||
#define IEEE80211_C_CRYPTO 0x0000002f /* CAPABILITY: crypto alg's */
|
||||
|
@ -338,14 +358,36 @@ ieee80211_anyhdrspace(struct ieee80211com *ic, const void *data)
|
|||
#define IEEE80211_MSG_WPA 0x00001000 /* WPA/RSN protocol */
|
||||
#define IEEE80211_MSG_ACL 0x00000800 /* ACL handling */
|
||||
#define IEEE80211_MSG_WME 0x00000400 /* WME protocol */
|
||||
#define IEEE80211_MSG_SUPERG 0x00000200 /* Atheros SuperG protocol */
|
||||
#define IEEE80211_MSG_DOTH 0x00000100 /* 802.11h support */
|
||||
#define IEEE80211_MSG_INACT 0x00000080 /* inactivity handling */
|
||||
#define IEEE80211_MSG_ROAM 0x00000040 /* sta-mode roaming */
|
||||
|
||||
#define IEEE80211_MSG_ANY 0xffffffff /* anything */
|
||||
|
||||
#ifdef IEEE80211_DEBUG
|
||||
#define IEEE80211_DPRINTF(_ic, _m, _fmt, ...) do { \
|
||||
if (_ic->ic_debug & (_m)) \
|
||||
printf(_fmt, __VA_ARGS__); \
|
||||
#define ieee80211_msg(_ic, _m) ((_ic)->ic_debug & (_m))
|
||||
#define IEEE80211_DPRINTF(_ic, _m, _fmt, ...) do { \
|
||||
if (ieee80211_msg(_ic, _m)) \
|
||||
ieee80211_note(_ic, _fmt, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#define IEEE80211_NOTE(_ic, _m, _ni, _fmt, ...) do { \
|
||||
if (ieee80211_msg(_ic, _m)) \
|
||||
ieee80211_note_mac(_ic, (_ni)->ni_macaddr, _fmt, __VA_ARGS__);\
|
||||
} while (0)
|
||||
#define IEEE80211_NOTE_MAC(_ic, _m, _mac, _fmt, ...) do { \
|
||||
if (ieee80211_msg(_ic, _m)) \
|
||||
ieee80211_note_mac(_ic, _mac, _fmt, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#define IEEE80211_NOTE_FRAME(_ic, _m, _wh, _fmt, ...) do { \
|
||||
if (ieee80211_msg(_ic, _m)) \
|
||||
ieee80211_note_frame(_ic, _wh, _fmt, __VA_ARGS__); \
|
||||
} while (0)
|
||||
void ieee80211_note(struct ieee80211com *ic, const char *fmt, ...);
|
||||
void ieee80211_note_mac(struct ieee80211com *ic,
|
||||
const u_int8_t mac[IEEE80211_ADDR_LEN], const char *fmt, ...);
|
||||
void ieee80211_note_frame(struct ieee80211com *ic,
|
||||
const struct ieee80211_frame *wh, const char *fmt, ...);
|
||||
#define ieee80211_msg_debug(_ic) \
|
||||
((_ic)->ic_debug & IEEE80211_MSG_DEBUG)
|
||||
#define ieee80211_msg_dumppkts(_ic) \
|
||||
|
@ -360,8 +402,14 @@ ieee80211_anyhdrspace(struct ieee80211com *ic, const void *data)
|
|||
((_ic)->ic_debug & IEEE80211_MSG_RADKEYS)
|
||||
#define ieee80211_msg_scan(_ic) \
|
||||
((_ic)->ic_debug & IEEE80211_MSG_SCAN)
|
||||
#define ieee80211_msg_assoc(_ic) \
|
||||
((_ic)->ic_debug & IEEE80211_MSG_ASSOC)
|
||||
#else
|
||||
#define IEEE80211_DPRINTF(_ic, _m, _fmt, ...)
|
||||
#define IEEE80211_NOTE_FRAME(_ic, _m, _wh, _fmt, ...)
|
||||
#define IEEE80211_NOTE_MAC(_ic, _m, _mac, _fmt, ...)
|
||||
#define ieee80211_msg_dumppkts(_ic) 0
|
||||
#define ieee80211_msg(_ic, _m) 0
|
||||
#endif
|
||||
|
||||
#endif /* _NET80211_IEEE80211_VAR_H_ */
|
||||
|
|
Loading…
Reference in New Issue