Resolve conflicts and adapt to NetBSD.
Thanks to dyoung@, scw@, and perry@ for help testing. 2005-08-30 15:27 avatar Properly set ic_curchan before calling back to device driver to do channel switching(ifconfig devX channel Y). This fix should make channel changing works again in monitor mode. Submitted by: sam X-MFC-With: other ic_curchan changes 2005-08-13 18:50 sam revert 1.64: we cannot use the channel characteristics to decide when to do 11g erp sta accounting because b/g channels show up as false positives when operating in 11b. Noticed by: Michal Mertl 2005-08-13 18:31 sam Extend acl support to pass ioctl requests through and use this to add support for getting the current policy setting and collecting the list of mac addresses in the acl table. Submitted by: Michal Mertl (original version) MFC after: 2 weeks 2005-08-10 18:42 sam Don't use ic_curmode to decide when to do 11g station accounting, use the station channel properties. Fixes assert failure/bogus operation when an ap is operating in 11a and has associated stations then switches to 11g. Noticed by: Michal Mertl Reviewed by: avatar MFC after: 2 weeks 2005-08-10 17:22 sam Clarify/fix handling of the current channel: o add ic_curchan and use it uniformly for specifying the current channel instead of overloading ic->ic_bss->ni_chan (or in some drivers ic_ibss_chan) o add ieee80211_scanparams structure to encapsulate scanning-related state captured for rx frames o move rx beacon+probe response frame handling into separate routines o change beacon+probe response handling to treat the scan table more like a scan cache--look for an existing entry before adding a new one; this combined with ic_curchan use corrects handling of stations that were previously found at a different channel o move adhoc neighbor discovery by beacon+probe response frames to a new ieee80211_add_neighbor routine Reviewed by: avatar Tested by: avatar, Michal Mertl MFC after: 2 weeks 2005-08-09 11:19 rwatson Propagate rename of IFF_OACTIVE and IFF_RUNNING to IFF_DRV_OACTIVE and IFF_DRV_RUNNING, as well as the move from ifnet.if_flags to ifnet.if_drv_flags. Device drivers are now responsible for synchronizing access to these flags, as they are in if_drv_flags. This helps prevent races between the network stack and device driver in maintaining the interface flags field. Many __FreeBSD__ and __FreeBSD_version checks maintained and continued; some less so. Reviewed by: pjd, bz MFC after: 7 days 2005-08-08 19:46 sam Split crypto tx+rx key indices and add a key index -> node mapping table: Crypto changes: o change driver/net80211 key_alloc api to return tx+rx key indices; a driver can leave the rx key index set to IEEE80211_KEYIX_NONE or set it to be the same as the tx key index (the former disables use of the key index in building the keyix->node mapping table and is the default setup for naive drivers by null_key_alloc) o add cs_max_keyid to crypto state to specify the max h/w key index a driver will return; this is used to allocate the key index mapping table and to bounds check table loookups o while here introduce ieee80211_keyix (finally) for the type of a h/w key index o change crypto notifiers for rx failures to pass the rx key index up as appropriate (michael failure, replay, etc.) Node table changes: o optionally allocate a h/w key index to node mapping table for the station table using the max key index setting supplied by drivers (note the scan table does not get a map) o defer node table allocation to lateattach so the driver has a chance to set the max key id to size the key index map o while here also defer the aid bitmap allocation o add new ieee80211_find_rxnode_withkey api to find a sta/node entry on frame receive with an optional h/w key index to use in checking mapping table; also updates the map if it does a hash lookup and the found node has a rx key index set in the unicast key; note this work is separated from the old ieee80211_find_rxnode call so drivers do not need to be aware of the new mechanism o move some node table manipulation under the node table lock to close a race on node delete o add ieee80211_node_delucastkey to do the dirty work of deleting unicast key state for a node (deletes any key and handles key map references) Ath driver: o nuke private sc_keyixmap mechansim in favor of net80211 support o update key alloc api These changes close several race conditions for the ath driver operating in ap mode. Other drivers should see no change. Station mode operation for ath no longer uses the key index map but performance tests show no noticeable change and this will be fixed when the scan table is eliminated with the new scanning support. Tested by: Michal Mertl, avatar, others Reviewed by: avatar, others MFC after: 2 weeks 2005-08-08 06:49 sam use ieee80211_iterate_nodes to retrieve station data; the previous code walked the list w/o locking MFC after: 1 week 2005-08-08 04:30 sam Cleanup beacon/listen interval handling: o separate configured beacon interval from listen interval; this avoids potential use of one value for the other (e.g. setting powersavesleep to 0 clobbers the beacon interval used in hostap or ibss mode) o bounds check the beacon interval received in probe response and beacon frames and drop frames with bogus settings; not clear if we should instead clamp the value as any alteration would result in mismatched sta+ap configuration and probably be more confusing (don't want to log to the console but perhaps ok with rate limiting) o while here up max beacon interval to reflect WiFi standard Noticed by: Martin <nakal@nurfuerspam.de> MFC after: 1 week 2005-08-06 05:57 sam fix debug msg typo MFC after: 3 days 2005-08-06 05:56 sam Fix handling of frames sent prior to a station being authorized when operating in ap mode. Previously we allocated a node from the station table, sent the frame (using the node), then released the reference that "held the frame in the table". But while the frame was in flight the node might be reclaimed which could lead to problems. The solution is to add an ieee80211_tmp_node routine that crafts a node that does exist in a table and so isn't ever reclaimed; it exists only so long as the associated frame is in flight. MFC after: 5 days 2005-07-31 07:12 sam close a race between reclaiming a node when a station is inactive and sending the null data frame used to probe inactive stations MFC after: 5 days 2005-07-27 05:41 sam when bridging internally bypass the bss node as traffic to it must follow the normal input path Submitted by: Michal Mertl MFC after: 5 days 2005-07-27 03:53 sam bandaid ni_fails handling so ap's with association failures are reconsidered after a bit; a proper fix involves more changes to the scanning infrastructure Reviewed by: avatar, David Young MFC after: 5 days 2005-07-23 01:16 sam the AREF flag is only meaningful in ap mode; adhoc neighbors now are timed out of the sta/neighbor table 2005-07-23 00:25 sam o move inactivity-related debug msgs under IEEE80211_MSG_INACT o probe inactive neighbors in adhoc mode (they don't have an association id so previously were being timed out) MFC after: 3 days 2005-07-22 22:11 sam split xmit of probe request frame out into a separate routine that takes explicit parameters; this will be needed when scanning is decoupled from the state machine to do bg scanning MFC after: 3 days 2005-07-22 21:48 sam split 802.11 frame xmit setup code into ieee80211_send_setup MFC after: 3 days 2005-07-22 18:57 sam simplify ic_newassoc callback MFC after: 3 days 2005-07-22 18:54 sam simplify ieee80211_ibss_merge api MFC after: 3 days 2005-07-22 18:50 sam add stats we know we'll need soon and some spare fields for future expansion MFC after: 3 days 2005-07-22 18:45 sam simplify tim callback api MFC after: 3 days 2005-07-22 18:42 sam don't include 802.3 header in min frame length calculation as it may not be present for a frag; fixes problem with small (fragmented) frames being dropped Obtained from: Atheros MFC after: 3 days 2005-07-22 18:36 sam simplify ieee80211_node_authorize and ieee80211_node_unauthorize api's MFC after: 3 days 2005-07-22 18:31 sam simplifiy ieee80211_send_nulldata api MFC after: 3 days 2005-07-22 18:29 sam simplify rate set api's by removing ic parameter (implicit in node reference) MFC after: 3 days 2005-07-22 18:21 sam reject association requests with a wpa/rsn ie when wpa/rsn is not configured on the ap; previously we either ignored the ie or (possibly) failed an assertion Obtained from: Atheros MFC after: 3 days 2005-07-22 18:16 sam missed one in last commit; add device name to discard msgs 2005-07-22 18:13 sam include device name in discard msgs 2005-07-22 18:12 sam add diag msgs for frames discarded because the direction field is wrong 2005-07-22 18:08 sam split data frame delivery out to a new function ieee80211_deliver_data 2005-07-22 18:00 sam o add IEEE80211_IOC_FRAGTHRESHOLD for getting+setting the tx fragmentation threshold o fix bounds checking on IEEE80211_IOC_RTSTHRESHOLD MFC after: 3 days 2005-07-22 17:55 sam o add IEEE80211_FRAG_DEFAULT o move default settings for RTS and frag thresholds to ieee80211_var.h 2005-07-22 17:50 sam diff reduction against p4: define IEEE80211_FIXED_RATE_NONE and use it instead of -1 2005-07-22 17:37 sam add flags missed in last merge 2005-07-22 17:36 sam Diff reduction against p4: o add ic_flags_ext for eventual extention of ic_flags o define/reserve flag+capabilities bits for superg, bg scan, and roaming support o refactor debug msg macros MFC after: 3 days 2005-07-22 06:17 sam send a response when an auth request is denied due to an acl; might be better to silently ignore the frame but this way we give stations a chance of figuring out what's wrong 2005-07-22 06:15 sam remove excess whitespace 2005-07-22 05:55 sam use IF_HANDOFF when bridging frames internally so if_start gets called; fixes communication between associated sta's MFC after: 3 days 2005-07-11 04:06 sam Handle encrypt of arbitarily fragmented mbuf chains: previously we bailed if we couldn't collect the 16-bytes of data required for an aes block cipher in 2 mbufs; now we deal with it. While here make space accounting signed so a sanity check does the right thing for malformed mbuf chains. Approved by: re (scottl) 2005-07-11 04:00 sam nuke assert that duplicates real check Reviewed by: avatar Approved by: re (scottl)
This commit is contained in:
parent
931fb40431
commit
87515e34ff
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: init_main.c,v 1.251 2005/08/05 11:03:18 junyoung Exp $ */
|
||||
/* $NetBSD: init_main.c,v 1.252 2005/11/18 16:40:08 skrll Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
|
||||
@ -71,7 +71,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.251 2005/08/05 11:03:18 junyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.252 2005/11/18 16:40:08 skrll Exp $");
|
||||
|
||||
#include "fs_nfs.h"
|
||||
#include "opt_nfsserver.h"
|
||||
@ -153,6 +153,7 @@ __KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.251 2005/08/05 11:03:18 junyoung Exp
|
||||
#ifdef VERIFIED_EXEC
|
||||
#include <sys/verified_exec.h>
|
||||
#endif
|
||||
#include <net80211/ieee80211_netbsd.h>
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sa.h>
|
||||
@ -284,6 +285,9 @@ main(void)
|
||||
/* Initialize signal-related data structures. */
|
||||
signal_init();
|
||||
|
||||
/* Initialize the net80211 layer */
|
||||
ieee80211_init();
|
||||
|
||||
/* Create process 0 (the swapper). */
|
||||
proc0_init();
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211.c,v 1.40 2005/07/26 22:52:48 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211.c,v 1.41 2005/11/18 16:40:08 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001 Atsushi Onoe
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
@ -33,10 +33,10 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifdef __FreeBSD__
|
||||
__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 $");
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211.c,v 1.40 2005/07/26 22:52:48 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211.c,v 1.41 2005/11/18 16:40:08 skrll Exp $");
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -196,6 +196,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 */
|
||||
@ -211,12 +215,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;
|
||||
|
||||
LIST_INSERT_HEAD(&ieee80211com_head, ic, ic_list);
|
||||
@ -708,7 +714,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.
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211.h,v 1.14 2005/07/26 22:52:48 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211.h,v 1.15 2005/11/18 16:40:08 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001 Atsushi Onoe
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
@ -30,7 +30,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_
|
||||
@ -626,11 +626,19 @@ 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
|
||||
|
||||
/*
|
||||
* 802.11 frame duration definitions.
|
||||
|
@ -31,10 +31,10 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifdef __FreeBSD__
|
||||
__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 $");
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_acl.c,v 1.3 2005/07/26 22:52:48 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_acl.c,v 1.4 2005/11/18 16:40:08 skrll Exp $");
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -79,6 +79,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;
|
||||
@ -98,7 +99,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");
|
||||
@ -142,6 +143,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
|
||||
@ -190,6 +192,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,
|
||||
@ -264,6 +267,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,
|
||||
@ -274,4 +324,6 @@ 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,
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211_crypto.c,v 1.9 2005/07/26 22:52:48 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211_crypto.c,v 1.10 2005/11/18 16:40:08 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001 Atsushi Onoe
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
@ -33,10 +33,10 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifdef __FreeBSD__
|
||||
__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 $");
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_crypto.c,v 1.9 2005/07/26 22:52:48 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_crypto.c,v 1.10 2005/11/18 16:40:08 skrll Exp $");
|
||||
#endif
|
||||
|
||||
#include "opt_inet.h"
|
||||
@ -81,7 +81,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])) {
|
||||
@ -95,12 +96,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)
|
||||
@ -135,9 +138,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
|
||||
@ -165,11 +169,8 @@ ieee80211_crypto_attach(struct ieee80211com *ic)
|
||||
|
||||
/* NB: we assume everything is pre-zero'd */
|
||||
cs->cs_def_txkey = IEEE80211_KEYIX_NONE;
|
||||
ciphers[IEEE80211_CIPHER_AES_CCM] = &ieee80211_cipher_ccmp;
|
||||
ciphers[IEEE80211_CIPHER_TKIP] = &ieee80211_cipher_tkip;
|
||||
ciphers[IEEE80211_CIPHER_WEP] = &ieee80211_cipher_wep;
|
||||
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],
|
||||
IEEE80211_KEYIX_NONE);
|
||||
@ -267,6 +268,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;
|
||||
|
||||
@ -380,8 +382,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
|
||||
@ -408,6 +409,8 @@ again:
|
||||
__func__, cip->ic_name);
|
||||
return 0;
|
||||
}
|
||||
key->wk_keyix = keyix;
|
||||
key->wk_rxkeyix = rxkeyix;
|
||||
}
|
||||
return 1;
|
||||
#undef N
|
||||
@ -419,7 +422,7 @@ again:
|
||||
static int
|
||||
_ieee80211_crypto_delkey(struct ieee80211com *ic, struct ieee80211_key *key)
|
||||
{
|
||||
u_int16_t keyix;
|
||||
ieee80211_keyix keyix;
|
||||
|
||||
IASSERT(key->wk_cipher != NULL, ("No cipher!"));
|
||||
|
||||
@ -547,7 +550,7 @@ ieee80211_crypto_encap(struct ieee80211com *ic,
|
||||
ether_sprintf(wh->i_addr1), __func__,
|
||||
ic->ic_def_txkey);
|
||||
ic->ic_stats.is_tx_nodefkey++;
|
||||
goto bad;
|
||||
return NULL;
|
||||
}
|
||||
keyid = ic->ic_def_txkey;
|
||||
k = &ic->ic_nw_keys[ic->ic_def_txkey];
|
||||
@ -556,10 +559,7 @@ ieee80211_crypto_encap(struct ieee80211com *ic,
|
||||
k = &ni->ni_ucastkey;
|
||||
}
|
||||
cip = k->wk_cipher;
|
||||
if (cip->ic_encap(k, m, keyid<<6))
|
||||
return k;
|
||||
bad:
|
||||
return NULL;
|
||||
return (cip->ic_encap(k, m, keyid<<6) ? k : NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -572,7 +572,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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211_crypto.h,v 1.6 2005/07/26 22:57:26 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211_crypto.h,v 1.7 2005/11/18 16:40:08 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001 Atsushi Onoe
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
@ -30,7 +30,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_
|
||||
@ -67,18 +67,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 */
|
||||
@ -104,7 +105,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)
|
||||
#define IEEE80211_KEY_UNDEFINED(k) ((k).wk_cipher == &ieee80211_cipher_none)
|
||||
|
||||
#if defined(__KERNEL__) || defined(_KERNEL)
|
||||
@ -122,10 +123,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 *,
|
||||
@ -209,11 +212,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;
|
||||
}
|
||||
|
||||
|
@ -31,10 +31,10 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifdef __FreeBSD__
|
||||
__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 $");
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_crypto_tkip.c,v 1.3 2005/07/26 22:52:48 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_crypto_tkip.c,v 1.4 2005/11/18 16:40:08 skrll Exp $");
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -343,7 +343,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;
|
||||
}
|
||||
}
|
||||
@ -968,3 +970,8 @@ tkip_decrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
IEEE80211_CRYPTO_SETUP(tkip_register)
|
||||
{
|
||||
ieee80211_crypto_register(&tkip);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211_input.c,v 1.46 2005/09/24 23:04:51 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211_input.c,v 1.47 2005/11/18 16:40:08 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001 Atsushi Onoe
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
@ -33,10 +33,10 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifdef __FreeBSD__
|
||||
__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 $");
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_input.c,v 1.46 2005/09/24 23:04:51 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_input.c,v 1.47 2005/11/18 16:40:08 skrll Exp $");
|
||||
#endif
|
||||
|
||||
#include "opt_inet.h"
|
||||
@ -140,6 +140,8 @@ 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);
|
||||
#ifndef IEEE80211_NO_HOSTAP
|
||||
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 *);
|
||||
@ -325,6 +327,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;
|
||||
}
|
||||
@ -346,6 +350,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;
|
||||
}
|
||||
@ -354,6 +360,8 @@ ieee80211_input(struct ieee80211com *ic, struct mbuf *m,
|
||||
case IEEE80211_M_HOSTAP:
|
||||
#ifndef IEEE80211_NO_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;
|
||||
}
|
||||
@ -503,71 +511,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);
|
||||
|
||||
#ifndef IEEE80211_NO_HOSTAP
|
||||
/* 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) {
|
||||
int len;
|
||||
#ifdef ALTQ
|
||||
if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
|
||||
altq_etherclassify(&ifp->if_snd, m1,
|
||||
&pktattr);
|
||||
}
|
||||
#endif
|
||||
len = m1->m_pkthdr.len;
|
||||
IF_ENQUEUE(&ifp->if_snd, m1);
|
||||
if (m != NULL)
|
||||
ifp->if_omcasts++;
|
||||
ifp->if_obytes += len;
|
||||
}
|
||||
}
|
||||
#endif /* !IEEE80211_NO_HOSTAP */
|
||||
if (m != NULL) {
|
||||
#if NBPFILTER > 0
|
||||
/*
|
||||
* XXX If we forward packet into transmitter of the AP,
|
||||
* we don't need to duplicate for DLT_EN10MB.
|
||||
*/
|
||||
if (ifp->if_bpf)
|
||||
bpf_mtap(ifp->if_bpf, m);
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
@ -749,6 +700,90 @@ 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) {
|
||||
int len;
|
||||
#ifdef ALTQ
|
||||
if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
|
||||
altq_etherclassify(&ifp->if_snd, m1,
|
||||
&pktattr);
|
||||
}
|
||||
#endif
|
||||
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 NBPFILTER > 0
|
||||
/*
|
||||
* XXX If we forward packet into transmitter of the AP,
|
||||
* we don't need to duplicate for DLT_EN10MB.
|
||||
*/
|
||||
if (ifp->if_bpf)
|
||||
bpf_mtap(ifp->if_bpf, m);
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
@ -851,10 +886,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));
|
||||
@ -877,7 +913,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
|
||||
@ -940,7 +976,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);
|
||||
#endif /* !IEEE80211_NO_HOSTAP */
|
||||
break;
|
||||
|
||||
@ -981,7 +1017,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;
|
||||
@ -1167,7 +1203,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,
|
||||
@ -1429,8 +1465,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.
|
||||
*/
|
||||
IASSERT(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,
|
||||
@ -1592,8 +1632,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.
|
||||
*/
|
||||
IASSERT(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,
|
||||
@ -1720,7 +1764,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;
|
||||
@ -1737,38 +1781,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,
|
||||
@ -1788,10 +1800,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:
|
||||
@ -1822,32 +1831,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:
|
||||
@ -1856,17 +1862,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) {
|
||||
@ -1876,16 +1882,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:
|
||||
@ -1897,21 +1903,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;
|
||||
@ -1922,17 +1930,28 @@ 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;
|
||||
}
|
||||
|
||||
if (ni != ic->ic_bss) {
|
||||
ni = ieee80211_refine_node_for_beacon(ic, ni,
|
||||
&ic->ic_channels[chan], ssid);
|
||||
&ic->ic_channels[scan.chan], scan.ssid);
|
||||
}
|
||||
/*
|
||||
* Count frame now that we know it's to be processed.
|
||||
@ -1953,27 +1972,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
|
||||
@ -1981,105 +2000,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;
|
||||
}
|
||||
|
||||
@ -2139,7 +2104,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;
|
||||
@ -2149,7 +2114,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) {
|
||||
@ -2191,6 +2156,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) {
|
||||
@ -2232,7 +2202,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;
|
||||
|
||||
@ -2269,7 +2239,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;
|
||||
@ -2289,10 +2259,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;
|
||||
@ -2375,7 +2344,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);
|
||||
/*
|
||||
@ -2398,7 +2367,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;
|
||||
@ -2496,7 +2465,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) {
|
||||
@ -2615,7 +2584,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:
|
||||
@ -2679,7 +2648,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,
|
||||
@ -2704,7 +2673,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2748,10 +2717,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;
|
||||
}
|
||||
/*
|
||||
@ -2769,7 +2738,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);
|
||||
@ -2796,6 +2765,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,
|
||||
@ -2803,11 +2814,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);
|
||||
@ -2821,11 +2833,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);
|
||||
@ -2839,11 +2852,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);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211_ioctl.c,v 1.25 2005/07/27 20:31:24 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211_ioctl.c,v 1.26 2005/11/18 16:40:08 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001 Atsushi Onoe
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
@ -33,10 +33,10 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifdef __FreeBSD__
|
||||
__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 $");
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_ioctl.c,v 1.25 2005/07/27 20:31:24 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_ioctl.c,v 1.26 2005/11/18 16:40:08 skrll Exp $");
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -68,8 +68,16 @@ __KERNEL_RCSID(0, "$NetBSD: ieee80211_ioctl.c,v 1.25 2005/07/27 20:31:24 dyoung
|
||||
|
||||
#include <dev/ic/wi_ieee.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#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))
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
#define IS_UP(_ic) \
|
||||
(((_ic)->ic_ifp->if_flags & IFF_UP) && \
|
||||
((_ic)->ic_ifp->if_flags & IFF_RUNNING))
|
||||
#endif
|
||||
#define IS_UP_AUTO(_ic) \
|
||||
(IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO)
|
||||
|
||||
@ -256,7 +264,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:
|
||||
@ -278,7 +286,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(
|
||||
@ -456,7 +464,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
|
||||
@ -468,20 +475,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
|
||||
@ -601,7 +594,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]);
|
||||
@ -841,20 +834,6 @@ ieee80211_cfgset(struct ieee80211com *ic, u_long cmd, caddr_t data)
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
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;
|
||||
}
|
||||
}
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
static int
|
||||
cap2cipher(int flag)
|
||||
{
|
||||
@ -1091,18 +1070,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;
|
||||
@ -1126,55 +1144,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;
|
||||
}
|
||||
|
||||
@ -1241,6 +1264,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()
|
||||
@ -1329,7 +1360,7 @@ ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re
|
||||
break;
|
||||
#ifdef __FreeBSD__
|
||||
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)
|
||||
@ -1480,6 +1511,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;
|
||||
@ -1609,7 +1646,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)
|
||||
@ -1712,9 +1749,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:
|
||||
@ -1749,7 +1786,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;
|
||||
|
||||
@ -1777,7 +1814,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;
|
||||
}
|
||||
@ -1823,9 +1863,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;
|
||||
}
|
||||
|
||||
@ -2095,8 +2132,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) {
|
||||
@ -2127,8 +2174,8 @@ ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re
|
||||
break;
|
||||
#endif /* __FreeBSD__ */
|
||||
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;
|
||||
@ -2324,7 +2371,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);
|
||||
@ -2354,7 +2401,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;
|
||||
@ -2368,6 +2415,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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211_ioctl.h,v 1.14 2005/07/27 20:31:25 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211_ioctl.h,v 1.15 2005/11/18 16:40:08 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001 Atsushi Onoe
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
@ -30,7 +30,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_
|
||||
@ -196,6 +196,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 */
|
||||
@ -220,6 +222,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];
|
||||
};
|
||||
|
||||
/*
|
||||
@ -290,6 +299,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];
|
||||
};
|
||||
|
||||
/*
|
||||
@ -487,6 +502,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.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211_netbsd.c,v 1.7 2005/09/24 23:57:12 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211_netbsd.c,v 1.8 2005/11/18 16:40:09 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2003-2005 Sam Leffler, Errno Consulting
|
||||
* All rights reserved.
|
||||
@ -28,9 +28,9 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifdef __FreeBSD__
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_freebsd.c,v 1.6 2005/01/22 20:29:23 sam Exp $");
|
||||
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_freebsd.c,v 1.8 2005/08/08 18:46:35 sam Exp $");
|
||||
#else
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_netbsd.c,v 1.7 2005/09/24 23:57:12 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_netbsd.c,v 1.8 2005/11/18 16:40:09 skrll Exp $");
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -70,6 +70,21 @@ static int ieee80211_sysctl_node(SYSCTLFN_ARGS);
|
||||
int ieee80211_debug = 0;
|
||||
#endif
|
||||
|
||||
typedef void (*ieee80211_setup_func)(void);
|
||||
|
||||
__link_set_decl(ieee80211_funcs, ieee80211_setup_func);
|
||||
|
||||
void
|
||||
ieee80211_init(void)
|
||||
{
|
||||
ieee80211_setup_func * const *ieee80211_setup, f;
|
||||
|
||||
__link_set_foreach(ieee80211_setup, ieee80211_funcs) {
|
||||
f = (void*)*ieee80211_setup;
|
||||
(*f)();
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ieee80211_sysctl_inact(SYSCTLFN_ARGS)
|
||||
{
|
||||
@ -661,9 +676,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;
|
||||
@ -671,7 +687,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));
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211_netbsd.h,v 1.6 2005/08/18 06:07:30 skrll Exp $ */
|
||||
/* $NetBSD: ieee80211_netbsd.h,v 1.7 2005/11/18 16:40:09 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2003-2005 Sam Leffler, Errno Consulting
|
||||
* All rights reserved.
|
||||
@ -25,7 +25,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_NETBSD_H_
|
||||
#define _NET80211_IEEE80211_NETBSD_H_
|
||||
@ -53,6 +53,8 @@ struct ieee80211_lock {
|
||||
if ((_ic)->_member.count++ == 0) \
|
||||
(_ic)->_member.ipl = __s; \
|
||||
} while (0)
|
||||
#define IEEE80211_IS_LOCKED_IMPL(_ic, _member) \
|
||||
((_ic)->_member.count != 0)
|
||||
#define IEEE80211_UNLOCK_IMPL(_ic, _member) \
|
||||
do { \
|
||||
if (--(_ic)->_member.count == 0) \
|
||||
@ -78,6 +80,7 @@ typedef struct ieee80211_lock ieee80211_beacon_lock_t;
|
||||
|
||||
/*
|
||||
* Node locking definitions.
|
||||
* NB: MTX_DUPOK is because we don't generate per-interface strings.
|
||||
*/
|
||||
typedef struct ieee80211_lock ieee80211_node_lock_t;
|
||||
#define IEEE80211_NODE_LOCK_INIT(_nt, _name) \
|
||||
@ -85,6 +88,8 @@ typedef struct ieee80211_lock ieee80211_node_lock_t;
|
||||
#define IEEE80211_NODE_LOCK_DESTROY(_nt)
|
||||
#define IEEE80211_NODE_LOCK(_nt) \
|
||||
IEEE80211_LOCK_IMPL(_nt, nt_nodelock)
|
||||
#define IEEE80211_NODE_IS_LOCKED(_nt) \
|
||||
IEEE80211_IS_LOCKED_IMPL(_nt, nt_nodelock)
|
||||
#define IEEE80211_NODE_UNLOCK(_nt) \
|
||||
IEEE80211_UNLOCK_IMPL(_nt, nt_nodelock)
|
||||
#define IEEE80211_NODE_LOCK_ASSERT(_nt) \
|
||||
@ -262,4 +267,10 @@ void ieee80211_sysctl_attach(struct ieee80211com *);
|
||||
void ieee80211_sysctl_detach(struct ieee80211com *);
|
||||
void ieee80211_load_module(const char *);
|
||||
|
||||
void ieee80211_init(void);
|
||||
#define IEEE80211_CRYPTO_SETUP(name) \
|
||||
static void name(void); \
|
||||
__link_set_add_text(ieee80211_funcs, name); \
|
||||
static void name(void)
|
||||
|
||||
#endif /* _NET80211_IEEE80211_NETBSD_H_ */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211_node.c,v 1.44 2005/09/25 00:03:06 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211_node.c,v 1.45 2005/11/18 16:40:09 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001 Atsushi Onoe
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
@ -33,10 +33,10 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifdef __FreeBSD__
|
||||
__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 $");
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_node.c,v 1.44 2005/09/25 00:03:06 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_node.c,v 1.45 2005/11/18 16:40:09 skrll Exp $");
|
||||
#endif
|
||||
|
||||
#include "opt_inet.h"
|
||||
@ -93,11 +93,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);
|
||||
|
||||
@ -107,11 +107,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;
|
||||
@ -123,10 +118,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),
|
||||
@ -145,22 +147,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);
|
||||
IASSERT(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;
|
||||
@ -192,8 +192,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
|
||||
@ -221,14 +220,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;
|
||||
}
|
||||
@ -281,16 +282,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 */
|
||||
}
|
||||
@ -344,7 +341,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];
|
||||
@ -352,28 +349,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;
|
||||
}
|
||||
@ -415,7 +403,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;
|
||||
@ -424,7 +412,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) {
|
||||
@ -443,6 +431,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.
|
||||
@ -476,11 +465,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)
|
||||
{
|
||||
@ -508,8 +500,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 &&
|
||||
@ -519,9 +510,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 ? '!' : ' ');
|
||||
@ -568,6 +562,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) &&
|
||||
@ -577,6 +572,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) {
|
||||
@ -695,6 +695,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.
|
||||
*/
|
||||
@ -708,23 +719,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;
|
||||
@ -756,8 +750,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)) {
|
||||
@ -795,7 +790,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.
|
||||
@ -821,6 +816,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);
|
||||
|
||||
@ -904,7 +900,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) {
|
||||
@ -928,7 +924,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
|
||||
}
|
||||
|
||||
@ -996,6 +995,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)
|
||||
{
|
||||
@ -1088,13 +1123,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
|
||||
@ -1112,10 +1322,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;
|
||||
|
||||
@ -1133,12 +1339,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
|
||||
@ -1157,15 +1428,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) {
|
||||
@ -1360,22 +1632,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) {
|
||||
IASSERT(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
|
||||
@ -1384,11 +1720,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
|
||||
@ -1478,7 +1833,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,
|
||||
@ -1495,7 +1853,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
|
||||
@ -1514,7 +1873,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
|
||||
@ -1549,7 +1908,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);
|
||||
}
|
||||
}
|
||||
/*
|
||||
@ -1560,20 +1919,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
|
||||
@ -1745,8 +2113,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;
|
||||
@ -1763,7 +2130,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);
|
||||
@ -1780,9 +2147,9 @@ static void
|
||||
ieee80211_node_leave_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
|
||||
{
|
||||
|
||||
IASSERT(ic->ic_curmode == IEEE80211_MODE_11G ||
|
||||
ic->ic_curmode == IEEE80211_MODE_TURBO_G,
|
||||
("not in 11g, curmode %x", ic->ic_curmode));
|
||||
IASSERT(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.
|
||||
@ -1870,8 +2237,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
|
||||
@ -1947,8 +2313,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;
|
||||
|
||||
IASSERT(ic->ic_opmode == IEEE80211_M_HOSTAP ||
|
||||
@ -1980,7 +2347,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 *))
|
||||
{
|
||||
|
||||
@ -1996,6 +2363,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
|
||||
@ -2018,7 +2396,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);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211_node.h,v 1.18 2005/07/26 22:52:48 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211_node.h,v 1.19 2005/11/18 16:40:09 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001 Atsushi Onoe
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
@ -30,7 +30,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_
|
||||
@ -134,7 +134,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 */
|
||||
@ -186,10 +186,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 *);
|
||||
@ -197,7 +195,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 *);
|
||||
|
||||
@ -217,6 +215,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 *);
|
||||
};
|
||||
@ -224,6 +224,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
|
||||
@ -235,6 +237,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);
|
||||
@ -251,6 +257,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) \
|
||||
@ -263,6 +271,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(
|
||||
@ -272,6 +282,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 *);
|
||||
|
||||
struct ieee80211_node *ieee80211_refine_node_for_beacon(
|
||||
struct ieee80211com *, struct ieee80211_node *,
|
||||
@ -289,4 +300,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_ */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211_output.c,v 1.38 2005/09/25 00:04:01 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211_output.c,v 1.39 2005/11/18 16:40:09 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001 Atsushi Onoe
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
@ -33,10 +33,10 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifdef __FreeBSD__
|
||||
__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 $");
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_output.c,v 1.38 2005/09/25 00:04:01 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_output.c,v 1.39 2005/11/18 16:40:09 skrll Exp $");
|
||||
#endif
|
||||
|
||||
#include "opt_inet.h"
|
||||
@ -95,6 +95,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
|
||||
@ -132,30 +188,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,
|
||||
@ -172,7 +207,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);
|
||||
@ -184,10 +219,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;
|
||||
@ -196,27 +236,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 */
|
||||
(*ifp->if_start)(ifp);
|
||||
|
||||
@ -1116,6 +1158,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;
|
||||
IASSERT(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);
|
||||
(*ic->ic_ifp->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
|
||||
@ -1128,7 +1255,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;
|
||||
|
||||
@ -1148,38 +1274,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
|
||||
@ -1224,7 +1318,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;
|
||||
@ -1241,14 +1335,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) {
|
||||
@ -1339,7 +1433,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:
|
||||
@ -1380,7 +1474,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))
|
||||
@ -1436,7 +1530,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;
|
||||
@ -1803,14 +1897,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);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211_proto.c,v 1.22 2005/08/15 23:37:10 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211_proto.c,v 1.23 2005/11/18 16:40:09 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001 Atsushi Onoe
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
@ -33,10 +33,10 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifdef __FreeBSD__
|
||||
__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 $");
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_proto.c,v 1.22 2005/08/15 23:37:10 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ieee80211_proto.c,v 1.23 2005/11/18 16:40:09 skrll Exp $");
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -116,13 +116,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;
|
||||
|
||||
@ -345,9 +341,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;
|
||||
@ -357,7 +354,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;
|
||||
@ -958,9 +956,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:
|
||||
@ -1076,7 +1077,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
|
||||
@ -1104,7 +1105,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
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211_proto.h,v 1.12 2005/07/26 22:52:48 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211_proto.h,v 1.13 2005/11/18 16:40:09 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001 Atsushi Onoe
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
@ -30,7 +30,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.9 2005/01/24 20:38:26 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_
|
||||
@ -60,9 +60,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 *,
|
||||
@ -136,6 +145,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
|
||||
@ -154,6 +164,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 *);
|
||||
@ -164,7 +176,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.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieee80211_var.h,v 1.20 2005/07/26 22:52:48 dyoung Exp $ */
|
||||
/* $NetBSD: ieee80211_var.h,v 1.21 2005/11/18 16:40:09 skrll Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2001 Atsushi Onoe
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
@ -30,7 +30,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_
|
||||
@ -68,13 +68,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)
|
||||
|
||||
@ -102,11 +108,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];
|
||||
@ -116,6 +120,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 */
|
||||
@ -138,6 +143,7 @@ struct ieee80211com {
|
||||
caddr_t 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;
|
||||
@ -146,6 +152,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 */
|
||||
@ -207,7 +214,9 @@ extern struct ieee80211com_head ieee80211com_head;
|
||||
#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 */
|
||||
@ -219,7 +228,7 @@ extern struct ieee80211com_head ieee80211com_head;
|
||||
#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 */
|
||||
@ -237,12 +246,19 @@ extern struct ieee80211com_head ieee80211com_head;
|
||||
#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 */
|
||||
@ -258,6 +274,10 @@ extern struct ieee80211com_head ieee80211com_head;
|
||||
#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 */
|
||||
@ -350,14 +370,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) \
|
||||
@ -372,8 +414,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
Block a user