add updated mac80211 - this no longer relies on patching includes in the kernel trees...
authorFelix Fietkau <nbd@openwrt.org>
Sat, 13 Oct 2007 22:41:08 +0000 (22:41 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 13 Oct 2007 22:41:08 +0000 (22:41 +0000)
SVN-Revision: 9290

52 files changed:
package/mac80211/Makefile
package/mac80211/src/include/linux/ieee80211.h [new file with mode: 0644]
package/mac80211/src/include/linux/nl80211.h [new file with mode: 0644]
package/mac80211/src/include/net/cfg80211.h [new file with mode: 0644]
package/mac80211/src/include/net/ieee80211_radiotap.h [new file with mode: 0644]
package/mac80211/src/include/net/mac80211.h [new file with mode: 0644]
package/mac80211/src/mac80211/Kconfig
package/mac80211/src/mac80211/Makefile
package/mac80211/src/mac80211/cfg.c [new file with mode: 0644]
package/mac80211/src/mac80211/cfg.h [new file with mode: 0644]
package/mac80211/src/mac80211/debugfs.c
package/mac80211/src/mac80211/debugfs_key.c
package/mac80211/src/mac80211/debugfs_netdev.c
package/mac80211/src/mac80211/debugfs_sta.c
package/mac80211/src/mac80211/event.c [new file with mode: 0644]
package/mac80211/src/mac80211/hostapd_ioctl.h [deleted file]
package/mac80211/src/mac80211/ieee80211.c
package/mac80211/src/mac80211/ieee80211_cfg.c [deleted file]
package/mac80211/src/mac80211/ieee80211_cfg.h [deleted file]
package/mac80211/src/mac80211/ieee80211_common.h
package/mac80211/src/mac80211/ieee80211_i.h
package/mac80211/src/mac80211/ieee80211_iface.c
package/mac80211/src/mac80211/ieee80211_ioctl.c
package/mac80211/src/mac80211/ieee80211_key.h
package/mac80211/src/mac80211/ieee80211_led.c
package/mac80211/src/mac80211/ieee80211_led.h
package/mac80211/src/mac80211/ieee80211_rate.c
package/mac80211/src/mac80211/ieee80211_rate.h
package/mac80211/src/mac80211/ieee80211_sta.c
package/mac80211/src/mac80211/key.c [new file with mode: 0644]
package/mac80211/src/mac80211/rc80211_lowest.c [deleted file]
package/mac80211/src/mac80211/rc80211_simple.c
package/mac80211/src/mac80211/regdomain.c
package/mac80211/src/mac80211/rx.c [new file with mode: 0644]
package/mac80211/src/mac80211/sta_info.c
package/mac80211/src/mac80211/sta_info.h
package/mac80211/src/mac80211/tkip.c
package/mac80211/src/mac80211/tkip.h
package/mac80211/src/mac80211/tx.c [new file with mode: 0644]
package/mac80211/src/mac80211/util.c [new file with mode: 0644]
package/mac80211/src/mac80211/wep.c
package/mac80211/src/mac80211/wep.h
package/mac80211/src/mac80211/wme.c
package/mac80211/src/mac80211/wme.h
package/mac80211/src/mac80211/wpa.c
package/mac80211/src/mac80211/wpa.h
package/mac80211/src/wireless/Makefile
package/mac80211/src/wireless/core.c
package/mac80211/src/wireless/nl80211.c
package/mac80211/src/wireless/radiotap.c [new file with mode: 0644]
package/mac80211/src/wireless/sysfs.c
package/mac80211/src/wireless/wext.c [deleted file]

index 416507f..1898998 100644 (file)
@@ -21,58 +21,59 @@ define KernelPackage/mac80211
   SUBMENU:=Wireless Drivers
   TITLE:=Linux 802.11 Wireless Networking Stack
   DEPENDS:=@LINUX_2_6 +kmod-crypto-arc4 +kmod-crypto-aes
-  KCONFIG:=CONFIG_MAC80211
   FILES:= \
        $(PKG_BUILD_DIR)/mac80211/mac80211.$(LINUX_KMOD_SUFFIX) \
-       $(PKG_BUILD_DIR)/mac80211/rc80211_lowest.$(LINUX_KMOD_SUFFIX) \
        $(PKG_BUILD_DIR)/mac80211/rc80211_simple.$(LINUX_KMOD_SUFFIX) \
        $(PKG_BUILD_DIR)/wireless/cfg80211.$(LINUX_KMOD_SUFFIX)
   AUTOLOAD:=$(call AutoLoad,20,cfg80211 mac80211 rc80211_simple)
 endef
 
 define KernelPackage/mac80211/description
- This package contains the DeviceScape 80211 wireless stack.
+Linux 802.11 Wireless Networking Stack
 endef
 
-define Build/Prepare
-       mkdir -p $(PKG_BUILD_DIR)/mac80211
-       $(CP) ./src/mac80211/* $(PKG_BUILD_DIR)/mac80211/
-       mkdir -p $(PKG_BUILD_DIR)/wireless
-       $(CP) ./src/wireless/* $(PKG_BUILD_DIR)/wireless/
-endef
+CONFOPTS:=MAC80211 CFG80211 NL80211
 
-ifneq ($(CONFIG_MAC80211),)
+BUILDFLAGS:= \
+       $(foreach opt,$(CONFOPTS),-DCONFIG_$(opt) ) \
+       $(if $(CONFIG_LEDS_TRIGGERS), -DCONFIG_MAC80211_LEDS -DCONFIG_LEDS_TRIGGERS)
 
-  MAKE_OPTS:= \
+MAKE_OPTS:= \
        CROSS_COMPILE="$(TARGET_CROSS)" \
        ARCH="$(LINUX_KARCH)" \
-       EXTRA_CFLAGS="$(BUILDFLAGS) -DCONFIG_MAC80211_LEDS -DCONFIG_LEDS_TRIGGERS" \
-       CONFIG_MAC80211=m \
+       EXTRA_CFLAGS="$(BUILDFLAGS)" \
+       $(foreach opt,$(CONFOPTS),CONFIG_$(opt)=m) \
        CONFIG_MAC80211_LEDS=$(CONFIG_LEDS_TRIGGERS) \
+       LINUXINCLUDE="-I${CURDIR}/src/include -I$(LINUX_DIR)/include -include linux/autoconf.h" \
+       V=1
+
+
+ifneq ($(findstring 2.6.23,$(LINUX_VERSION)),)
+  define Build/Prepare
+       mkdir -p $(PKG_BUILD_DIR)/mac80211
+       $(CP) ./src/mac80211/* $(PKG_BUILD_DIR)/mac80211/
+       mkdir -p $(PKG_BUILD_DIR)/wireless
+       $(CP) ./src/wireless/* $(PKG_BUILD_DIR)/wireless/
+  endef
 
-  define Build/Compile/it
+  define Build/Compile
        $(MAKE) -C "$(LINUX_DIR)" $(MAKE_OPTS) SUBDIRS="$(PKG_BUILD_DIR)/wireless" modules
        $(MAKE) -C "$(LINUX_DIR)" $(MAKE_OPTS) SUBDIRS="$(PKG_BUILD_DIR)/mac80211" modules
   endef
 
-endif
-
-define Build/Compile
-       $(call Build/Compile/it)
-endef
-
-define Build/InstallDev
+  define Build/InstallDev
        mkdir -p $(1)/usr/include/mac80211
-       $(CP) $(PKG_BUILD_DIR)/mac80211/{hostapd_ioctl,ieee80211_common}.h $(1)/usr/include/mac80211/
-endef
+       $(CP) ./src/include $(1)/usr/include/mac80211/
+  endef
 
-define Build/UninstallDev
+  define Build/UninstallDev
        rm -rf  $(1)/usr/include/mac80211
-endef
+  endef
 
-define KernelPackage/mac80211/install
+  define KernelPackage/mac80211/install
        $(INSTALL_DIR) $(1)/lib/wifi
        $(INSTALL_DATA) ./files/lib/wifi/mac80211.sh $(1)/lib/wifi
-endef
+  endef
+endif
 
 $(eval $(call KernelPackage,mac80211))
diff --git a/package/mac80211/src/include/linux/ieee80211.h b/package/mac80211/src/include/linux/ieee80211.h
new file mode 100644 (file)
index 0000000..30621c2
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * IEEE 802.11 defines
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2005, Devicescape Software, Inc.
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef IEEE80211_H
+#define IEEE80211_H
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+#define FCS_LEN 4
+
+#define IEEE80211_FCTL_VERS            0x0003
+#define IEEE80211_FCTL_FTYPE           0x000c
+#define IEEE80211_FCTL_STYPE           0x00f0
+#define IEEE80211_FCTL_TODS            0x0100
+#define IEEE80211_FCTL_FROMDS          0x0200
+#define IEEE80211_FCTL_MOREFRAGS       0x0400
+#define IEEE80211_FCTL_RETRY           0x0800
+#define IEEE80211_FCTL_PM              0x1000
+#define IEEE80211_FCTL_MOREDATA                0x2000
+#define IEEE80211_FCTL_PROTECTED       0x4000
+#define IEEE80211_FCTL_ORDER           0x8000
+
+#define IEEE80211_SCTL_FRAG            0x000F
+#define IEEE80211_SCTL_SEQ             0xFFF0
+
+#define IEEE80211_FTYPE_MGMT           0x0000
+#define IEEE80211_FTYPE_CTL            0x0004
+#define IEEE80211_FTYPE_DATA           0x0008
+
+/* management */
+#define IEEE80211_STYPE_ASSOC_REQ      0x0000
+#define IEEE80211_STYPE_ASSOC_RESP     0x0010
+#define IEEE80211_STYPE_REASSOC_REQ    0x0020
+#define IEEE80211_STYPE_REASSOC_RESP   0x0030
+#define IEEE80211_STYPE_PROBE_REQ      0x0040
+#define IEEE80211_STYPE_PROBE_RESP     0x0050
+#define IEEE80211_STYPE_BEACON         0x0080
+#define IEEE80211_STYPE_ATIM           0x0090
+#define IEEE80211_STYPE_DISASSOC       0x00A0
+#define IEEE80211_STYPE_AUTH           0x00B0
+#define IEEE80211_STYPE_DEAUTH         0x00C0
+#define IEEE80211_STYPE_ACTION         0x00D0
+
+/* control */
+#define IEEE80211_STYPE_PSPOLL         0x00A0
+#define IEEE80211_STYPE_RTS            0x00B0
+#define IEEE80211_STYPE_CTS            0x00C0
+#define IEEE80211_STYPE_ACK            0x00D0
+#define IEEE80211_STYPE_CFEND          0x00E0
+#define IEEE80211_STYPE_CFENDACK       0x00F0
+
+/* data */
+#define IEEE80211_STYPE_DATA                   0x0000
+#define IEEE80211_STYPE_DATA_CFACK             0x0010
+#define IEEE80211_STYPE_DATA_CFPOLL            0x0020
+#define IEEE80211_STYPE_DATA_CFACKPOLL         0x0030
+#define IEEE80211_STYPE_NULLFUNC               0x0040
+#define IEEE80211_STYPE_CFACK                  0x0050
+#define IEEE80211_STYPE_CFPOLL                 0x0060
+#define IEEE80211_STYPE_CFACKPOLL              0x0070
+#define IEEE80211_STYPE_QOS_DATA               0x0080
+#define IEEE80211_STYPE_QOS_DATA_CFACK         0x0090
+#define IEEE80211_STYPE_QOS_DATA_CFPOLL                0x00A0
+#define IEEE80211_STYPE_QOS_DATA_CFACKPOLL     0x00B0
+#define IEEE80211_STYPE_QOS_NULLFUNC           0x00C0
+#define IEEE80211_STYPE_QOS_CFACK              0x00D0
+#define IEEE80211_STYPE_QOS_CFPOLL             0x00E0
+#define IEEE80211_STYPE_QOS_CFACKPOLL          0x00F0
+
+
+/* miscellaneous IEEE 802.11 constants */
+#define IEEE80211_MAX_FRAG_THRESHOLD   2346
+#define IEEE80211_MAX_RTS_THRESHOLD    2347
+#define IEEE80211_MAX_AID              2007
+#define IEEE80211_MAX_TIM_LEN          251
+#define IEEE80211_MAX_DATA_LEN         2304
+/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
+   6.2.1.1.2.
+
+   The figure in section 7.1.2 suggests a body size of up to 2312
+   bytes is allowed, which is a bit confusing, I suspect this
+   represents the 2304 bytes of real data, plus a possible 8 bytes of
+   WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
+
+#define IEEE80211_MAX_SSID_LEN         32
+
+struct ieee80211_hdr {
+       __le16 frame_control;
+       __le16 duration_id;
+       u8 addr1[6];
+       u8 addr2[6];
+       u8 addr3[6];
+       __le16 seq_ctrl;
+       u8 addr4[6];
+} __attribute__ ((packed));
+
+
+struct ieee80211_mgmt {
+       __le16 frame_control;
+       __le16 duration;
+       u8 da[6];
+       u8 sa[6];
+       u8 bssid[6];
+       __le16 seq_ctrl;
+       union {
+               struct {
+                       __le16 auth_alg;
+                       __le16 auth_transaction;
+                       __le16 status_code;
+                       /* possibly followed by Challenge text */
+                       u8 variable[0];
+               } __attribute__ ((packed)) auth;
+               struct {
+                       __le16 reason_code;
+               } __attribute__ ((packed)) deauth;
+               struct {
+                       __le16 capab_info;
+                       __le16 listen_interval;
+                       /* followed by SSID and Supported rates */
+                       u8 variable[0];
+               } __attribute__ ((packed)) assoc_req;
+               struct {
+                       __le16 capab_info;
+                       __le16 status_code;
+                       __le16 aid;
+                       /* followed by Supported rates */
+                       u8 variable[0];
+               } __attribute__ ((packed)) assoc_resp, reassoc_resp;
+               struct {
+                       __le16 capab_info;
+                       __le16 listen_interval;
+                       u8 current_ap[6];
+                       /* followed by SSID and Supported rates */
+                       u8 variable[0];
+               } __attribute__ ((packed)) reassoc_req;
+               struct {
+                       __le16 reason_code;
+               } __attribute__ ((packed)) disassoc;
+               struct {
+                       __le64 timestamp;
+                       __le16 beacon_int;
+                       __le16 capab_info;
+                       /* followed by some of SSID, Supported rates,
+                        * FH Params, DS Params, CF Params, IBSS Params, TIM */
+                       u8 variable[0];
+               } __attribute__ ((packed)) beacon;
+               struct {
+                       /* only variable items: SSID, Supported rates */
+                       u8 variable[0];
+               } __attribute__ ((packed)) probe_req;
+               struct {
+                       __le64 timestamp;
+                       __le16 beacon_int;
+                       __le16 capab_info;
+                       /* followed by some of SSID, Supported rates,
+                        * FH Params, DS Params, CF Params, IBSS Params */
+                       u8 variable[0];
+               } __attribute__ ((packed)) probe_resp;
+               struct {
+                       u8 category;
+                       union {
+                               struct {
+                                       u8 action_code;
+                                       u8 dialog_token;
+                                       u8 status_code;
+                                       u8 variable[0];
+                               } __attribute__ ((packed)) wme_action;
+                               struct{
+                                       u8 action_code;
+                                       u8 element_id;
+                                       u8 length;
+                                       u8 switch_mode;
+                                       u8 new_chan;
+                                       u8 switch_count;
+                               } __attribute__((packed)) chan_switch;
+                       } u;
+               } __attribute__ ((packed)) action;
+       } u;
+} __attribute__ ((packed));
+
+
+/* Control frames */
+struct ieee80211_rts {
+       __le16 frame_control;
+       __le16 duration;
+       u8 ra[6];
+       u8 ta[6];
+} __attribute__ ((packed));
+
+struct ieee80211_cts {
+       __le16 frame_control;
+       __le16 duration;
+       u8 ra[6];
+} __attribute__ ((packed));
+
+
+/* Authentication algorithms */
+#define WLAN_AUTH_OPEN 0
+#define WLAN_AUTH_SHARED_KEY 1
+#define WLAN_AUTH_FAST_BSS_TRANSITION 2
+#define WLAN_AUTH_LEAP 128
+
+#define WLAN_AUTH_CHALLENGE_LEN 128
+
+#define WLAN_CAPABILITY_ESS            (1<<0)
+#define WLAN_CAPABILITY_IBSS           (1<<1)
+#define WLAN_CAPABILITY_CF_POLLABLE    (1<<2)
+#define WLAN_CAPABILITY_CF_POLL_REQUEST        (1<<3)
+#define WLAN_CAPABILITY_PRIVACY                (1<<4)
+#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
+#define WLAN_CAPABILITY_PBCC           (1<<6)
+#define WLAN_CAPABILITY_CHANNEL_AGILITY        (1<<7)
+/* 802.11h */
+#define WLAN_CAPABILITY_SPECTRUM_MGMT  (1<<8)
+#define WLAN_CAPABILITY_QOS            (1<<9)
+#define WLAN_CAPABILITY_SHORT_SLOT_TIME        (1<<10)
+#define WLAN_CAPABILITY_DSSS_OFDM      (1<<13)
+
+/* 802.11g ERP information element */
+#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
+#define WLAN_ERP_USE_PROTECTION (1<<1)
+#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
+
+/* WLAN_ERP_BARKER_PREAMBLE values */
+enum {
+       WLAN_ERP_PREAMBLE_SHORT = 0,
+       WLAN_ERP_PREAMBLE_LONG = 1,
+};
+
+/* Status codes */
+enum ieee80211_statuscode {
+       WLAN_STATUS_SUCCESS = 0,
+       WLAN_STATUS_UNSPECIFIED_FAILURE = 1,
+       WLAN_STATUS_CAPS_UNSUPPORTED = 10,
+       WLAN_STATUS_REASSOC_NO_ASSOC = 11,
+       WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12,
+       WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13,
+       WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14,
+       WLAN_STATUS_CHALLENGE_FAIL = 15,
+       WLAN_STATUS_AUTH_TIMEOUT = 16,
+       WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17,
+       WLAN_STATUS_ASSOC_DENIED_RATES = 18,
+       /* 802.11b */
+       WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19,
+       WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20,
+       WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21,
+       /* 802.11h */
+       WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22,
+       WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23,
+       WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24,
+       /* 802.11g */
+       WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
+       WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
+       /* 802.11i */
+       WLAN_STATUS_INVALID_IE = 40,
+       WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
+       WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42,
+       WLAN_STATUS_INVALID_AKMP = 43,
+       WLAN_STATUS_UNSUPP_RSN_VERSION = 44,
+       WLAN_STATUS_INVALID_RSN_IE_CAP = 45,
+       WLAN_STATUS_CIPHER_SUITE_REJECTED = 46,
+};
+
+
+/* Reason codes */
+enum ieee80211_reasoncode {
+       WLAN_REASON_UNSPECIFIED = 1,
+       WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
+       WLAN_REASON_DEAUTH_LEAVING = 3,
+       WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4,
+       WLAN_REASON_DISASSOC_AP_BUSY = 5,
+       WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6,
+       WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7,
+       WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8,
+       WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9,
+       /* 802.11h */
+       WLAN_REASON_DISASSOC_BAD_POWER = 10,
+       WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11,
+       /* 802.11i */
+       WLAN_REASON_INVALID_IE = 13,
+       WLAN_REASON_MIC_FAILURE = 14,
+       WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
+       WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16,
+       WLAN_REASON_IE_DIFFERENT = 17,
+       WLAN_REASON_INVALID_GROUP_CIPHER = 18,
+       WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19,
+       WLAN_REASON_INVALID_AKMP = 20,
+       WLAN_REASON_UNSUPP_RSN_VERSION = 21,
+       WLAN_REASON_INVALID_RSN_IE_CAP = 22,
+       WLAN_REASON_IEEE8021X_FAILED = 23,
+       WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
+};
+
+
+/* Information Element IDs */
+enum ieee80211_eid {
+       WLAN_EID_SSID = 0,
+       WLAN_EID_SUPP_RATES = 1,
+       WLAN_EID_FH_PARAMS = 2,
+       WLAN_EID_DS_PARAMS = 3,
+       WLAN_EID_CF_PARAMS = 4,
+       WLAN_EID_TIM = 5,
+       WLAN_EID_IBSS_PARAMS = 6,
+       WLAN_EID_CHALLENGE = 16,
+       /* 802.11d */
+       WLAN_EID_COUNTRY = 7,
+       WLAN_EID_HP_PARAMS = 8,
+       WLAN_EID_HP_TABLE = 9,
+       WLAN_EID_REQUEST = 10,
+       /* 802.11h */
+       WLAN_EID_PWR_CONSTRAINT = 32,
+       WLAN_EID_PWR_CAPABILITY = 33,
+       WLAN_EID_TPC_REQUEST = 34,
+       WLAN_EID_TPC_REPORT = 35,
+       WLAN_EID_SUPPORTED_CHANNELS = 36,
+       WLAN_EID_CHANNEL_SWITCH = 37,
+       WLAN_EID_MEASURE_REQUEST = 38,
+       WLAN_EID_MEASURE_REPORT = 39,
+       WLAN_EID_QUIET = 40,
+       WLAN_EID_IBSS_DFS = 41,
+       /* 802.11g */
+       WLAN_EID_ERP_INFO = 42,
+       WLAN_EID_EXT_SUPP_RATES = 50,
+       /* 802.11i */
+       WLAN_EID_RSN = 48,
+       WLAN_EID_WPA = 221,
+       WLAN_EID_GENERIC = 221,
+       WLAN_EID_VENDOR_SPECIFIC = 221,
+       WLAN_EID_QOS_PARAMETER = 222
+};
+
+/* cipher suite selectors */
+#define WLAN_CIPHER_SUITE_USE_GROUP    0x000FAC00
+#define WLAN_CIPHER_SUITE_WEP40                0x000FAC01
+#define WLAN_CIPHER_SUITE_TKIP         0x000FAC02
+/* reserved:                           0x000FAC03 */
+#define WLAN_CIPHER_SUITE_CCMP         0x000FAC04
+#define WLAN_CIPHER_SUITE_WEP104       0x000FAC05
+
+#define WLAN_MAX_KEY_LEN               32
+
+/**
+ * ieee80211_get_SA - get pointer to SA
+ *
+ * Given an 802.11 frame, this function returns the offset
+ * to the source address (SA). It does not verify that the
+ * header is long enough to contain the address, and the
+ * header must be long enough to contain the frame control
+ * field.
+ *
+ * @hdr: the frame
+ */
+static inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr)
+{
+       u8 *raw = (u8 *) hdr;
+       u8 tofrom = (*(raw+1)) & 3; /* get the TODS and FROMDS bits */
+
+       switch (tofrom) {
+               case 2:
+                       return hdr->addr3;
+               case 3:
+                       return hdr->addr4;
+       }
+       return hdr->addr2;
+}
+
+/**
+ * ieee80211_get_DA - get pointer to DA
+ *
+ * Given an 802.11 frame, this function returns the offset
+ * to the destination address (DA). It does not verify that
+ * the header is long enough to contain the address, and the
+ * header must be long enough to contain the frame control
+ * field.
+ *
+ * @hdr: the frame
+ */
+static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr)
+{
+       u8 *raw = (u8 *) hdr;
+       u8 to_ds = (*(raw+1)) & 1; /* get the TODS bit */
+
+       if (to_ds)
+               return hdr->addr3;
+       return hdr->addr1;
+}
+
+/**
+ * ieee80211_get_morefrag - determine whether the MOREFRAGS bit is set
+ *
+ * This function determines whether the "more fragments" bit is set
+ * in the frame.
+ *
+ * @hdr: the frame
+ */
+static inline int ieee80211_get_morefrag(struct ieee80211_hdr *hdr)
+{
+       return (le16_to_cpu(hdr->frame_control) &
+               IEEE80211_FCTL_MOREFRAGS) != 0;
+}
+
+#endif /* IEEE80211_H */
diff --git a/package/mac80211/src/include/linux/nl80211.h b/package/mac80211/src/include/linux/nl80211.h
new file mode 100644 (file)
index 0000000..a5dd030
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef __LINUX_NL80211_H
+#define __LINUX_NL80211_H
+/*
+ * 802.11 netlink interface public header
+ *
+ * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
+ */
+
+/**
+ * enum nl80211_commands - supported nl80211 commands
+ *
+ * @NL80211_CMD_UNSPEC: unspecified command to catch errors
+ *
+ * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request
+ *     to get a list of all present wiphys.
+ * @NL80211_CMD_SET_WIPHY: set wiphy name, needs %NL80211_ATTR_WIPHY and
+ *     %NL80211_ATTR_WIPHY_NAME.
+ * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
+ *     or rename notification. Has attributes %NL80211_ATTR_WIPHY and
+ *     %NL80211_ATTR_WIPHY_NAME.
+ * @NL80211_CMD_DEL_WIPHY: Wiphy deleted. Has attributes
+ *     %NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME.
+ *
+ * @NL80211_CMD_GET_INTERFACE: Request an interface's configuration;
+ *     either a dump request on a %NL80211_ATTR_WIPHY or a specific get
+ *     on an %NL80211_ATTR_IFINDEX is supported.
+ * @NL80211_CMD_SET_INTERFACE: Set type of a virtual interface, requires
+       %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE.
+ * @NL80211_CMD_NEW_INTERFACE: Newly created virtual interface or response
+ *     to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX,
+ *     %NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also
+ *     be sent from userspace to request creation of a new virtual interface,
+ *     then requires attributes %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFTYPE and
+ *     %NL80211_ATTR_IFNAME.
+ * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes
+ *     %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from
+ *     userspace to request deletion of a virtual interface, then requires
+ *     attribute %NL80211_ATTR_IFINDEX.
+ *
+ * @NL80211_CMD_MAX: highest used command number
+ * @__NL80211_CMD_AFTER_LAST: internal use
+ */
+enum nl80211_commands {
+/* don't change the order or add anything inbetween, this is ABI! */
+       NL80211_CMD_UNSPEC,
+
+       NL80211_CMD_GET_WIPHY,          /* can dump */
+       NL80211_CMD_SET_WIPHY,
+       NL80211_CMD_NEW_WIPHY,
+       NL80211_CMD_DEL_WIPHY,
+
+       NL80211_CMD_GET_INTERFACE,      /* can dump */
+       NL80211_CMD_SET_INTERFACE,
+       NL80211_CMD_NEW_INTERFACE,
+       NL80211_CMD_DEL_INTERFACE,
+
+       /* add commands here */
+
+       /* used to define NL80211_CMD_MAX below */
+       __NL80211_CMD_AFTER_LAST,
+       NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
+};
+
+
+/**
+ * enum nl80211_attrs - nl80211 netlink attributes
+ *
+ * @NL80211_ATTR_UNSPEC: unspecified attribute to catch errors
+ *
+ * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf.
+ *     /sys/class/ieee80211/<phyname>/index
+ * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming)
+ *
+ * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on
+ * @NL80211_ATTR_IFNAME: network interface name
+ * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype
+ *
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
+ * @__NL80211_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_attrs {
+/* don't change the order or add anything inbetween, this is ABI! */
+       NL80211_ATTR_UNSPEC,
+
+       NL80211_ATTR_WIPHY,
+       NL80211_ATTR_WIPHY_NAME,
+
+       NL80211_ATTR_IFINDEX,
+       NL80211_ATTR_IFNAME,
+       NL80211_ATTR_IFTYPE,
+
+       /* add attributes here, update the policy in nl80211.c */
+
+       __NL80211_ATTR_AFTER_LAST,
+       NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_iftype - (virtual) interface types
+ *
+ * @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides
+ * @NL80211_IFTYPE_ADHOC: independent BSS member
+ * @NL80211_IFTYPE_STATION: managed BSS member
+ * @NL80211_IFTYPE_AP: access point
+ * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points
+ * @NL80211_IFTYPE_WDS: wireless distribution interface
+ * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
+ * @NL80211_IFTYPE_MAX: highest interface type number currently defined
+ * @__NL80211_IFTYPE_AFTER_LAST: internal use
+ *
+ * These values are used with the %NL80211_ATTR_IFTYPE
+ * to set the type of an interface.
+ *
+ */
+enum nl80211_iftype {
+       NL80211_IFTYPE_UNSPECIFIED,
+       NL80211_IFTYPE_ADHOC,
+       NL80211_IFTYPE_STATION,
+       NL80211_IFTYPE_AP,
+       NL80211_IFTYPE_AP_VLAN,
+       NL80211_IFTYPE_WDS,
+       NL80211_IFTYPE_MONITOR,
+
+       /* keep last */
+       __NL80211_IFTYPE_AFTER_LAST,
+       NL80211_IFTYPE_MAX = __NL80211_IFTYPE_AFTER_LAST - 1
+};
+
+#endif /* __LINUX_NL80211_H */
diff --git a/package/mac80211/src/include/net/cfg80211.h b/package/mac80211/src/include/net/cfg80211.h
new file mode 100644 (file)
index 0000000..d30960e
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __NET_CFG80211_H
+#define __NET_CFG80211_H
+
+#include <linux/netlink.h>
+#include <linux/skbuff.h>
+#include <linux/nl80211.h>
+#include <net/genetlink.h>
+
+/*
+ * 802.11 configuration in-kernel interface
+ *
+ * Copyright 2006, 2007        Johannes Berg <johannes@sipsolutions.net>
+ */
+
+/* Radiotap header iteration
+ *   implemented in net/wireless/radiotap.c
+ *   docs in Documentation/networking/radiotap-headers.txt
+ */
+/**
+ * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args
+ * @rtheader: pointer to the radiotap header we are walking through
+ * @max_length: length of radiotap header in cpu byte ordering
+ * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg
+ * @this_arg: pointer to current radiotap arg
+ * @arg_index: internal next argument index
+ * @arg: internal next argument pointer
+ * @next_bitmap: internal pointer to next present u32
+ * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present
+ */
+
+struct ieee80211_radiotap_iterator {
+       struct ieee80211_radiotap_header *rtheader;
+       int max_length;
+       int this_arg_index;
+       u8 *this_arg;
+
+       int arg_index;
+       u8 *arg;
+       __le32 *next_bitmap;
+       u32 bitmap_shifter;
+};
+
+extern int ieee80211_radiotap_iterator_init(
+   struct ieee80211_radiotap_iterator *iterator,
+   struct ieee80211_radiotap_header *radiotap_header,
+   int max_length);
+
+extern int ieee80211_radiotap_iterator_next(
+   struct ieee80211_radiotap_iterator *iterator);
+
+
+/* from net/wireless.h */
+struct wiphy;
+
+/**
+ * struct cfg80211_ops - backend description for wireless configuration
+ *
+ * This struct is registered by fullmac card drivers and/or wireless stacks
+ * in order to handle configuration requests on their interfaces.
+ *
+ * All callbacks except where otherwise noted should return 0
+ * on success or a negative error code.
+ *
+ * All operations are currently invoked under rtnl for consistency with the
+ * wireless extensions but this is subject to reevaluation as soon as this
+ * code is used more widely and we have a first user without wext.
+ *
+ * @add_virtual_intf: create a new virtual interface with the given name
+ *
+ * @del_virtual_intf: remove the virtual interface determined by ifindex.
+ *
+ * @change_virtual_intf: change type of virtual interface
+ *
+ */
+struct cfg80211_ops {
+       int     (*add_virtual_intf)(struct wiphy *wiphy, char *name,
+                                   enum nl80211_iftype type);
+       int     (*del_virtual_intf)(struct wiphy *wiphy, int ifindex);
+       int     (*change_virtual_intf)(struct wiphy *wiphy, int ifindex,
+                                      enum nl80211_iftype type);
+};
+
+#endif /* __NET_CFG80211_H */
diff --git a/package/mac80211/src/include/net/ieee80211_radiotap.h b/package/mac80211/src/include/net/ieee80211_radiotap.h
new file mode 100644 (file)
index 0000000..dfd8bf6
--- /dev/null
@@ -0,0 +1,268 @@
+/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
+/* $NetBSD: ieee80211_radiotap.h,v 1.11 2005/06/22 06:16:02 dyoung Exp $ */
+
+/*-
+ * Copyright (c) 2003, 2004 David Young.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of David Young may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DAVID
+ * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+/*
+ * Modifications to fit into the linux IEEE 802.11 stack,
+ * Mike Kershaw (dragorn@kismetwireless.net)
+ */
+
+#ifndef IEEE80211RADIOTAP_H
+#define IEEE80211RADIOTAP_H
+
+#include <linux/if_ether.h>
+#include <linux/kernel.h>
+#include <asm/unaligned.h>
+
+/* Radiotap header version (from official NetBSD feed) */
+#define IEEE80211RADIOTAP_VERSION      "1.5"
+/* Base version of the radiotap packet header data */
+#define PKTHDR_RADIOTAP_VERSION                0
+
+/* A generic radio capture format is desirable. There is one for
+ * Linux, but it is neither rigidly defined (there were not even
+ * units given for some fields) nor easily extensible.
+ *
+ * I suggest the following extensible radio capture format. It is
+ * based on a bitmap indicating which fields are present.
+ *
+ * I am trying to describe precisely what the application programmer
+ * should expect in the following, and for that reason I tell the
+ * units and origin of each measurement (where it applies), or else I
+ * use sufficiently weaselly language ("is a monotonically nondecreasing
+ * function of...") that I cannot set false expectations for lawyerly
+ * readers.
+ */
+
+/* XXX tcpdump/libpcap do not tolerate variable-length headers,
+ * yet, so we pad every radiotap header to 64 bytes. Ugh.
+ */
+#define IEEE80211_RADIOTAP_HDRLEN      64
+
+/* The radio capture header precedes the 802.11 header.
+ * All data in the header is little endian on all platforms.
+ */
+struct ieee80211_radiotap_header {
+       u8 it_version;          /* Version 0. Only increases
+                                * for drastic changes,
+                                * introduction of compatible
+                                * new fields does not count.
+                                */
+       u8 it_pad;
+       __le16 it_len;          /* length of the whole
+                                * header in bytes, including
+                                * it_version, it_pad,
+                                * it_len, and data fields.
+                                */
+       __le32 it_present;      /* A bitmap telling which
+                                * fields are present. Set bit 31
+                                * (0x80000000) to extend the
+                                * bitmap by another 32 bits.
+                                * Additional extensions are made
+                                * by setting bit 31.
+                                */
+};
+
+/* Name                                 Data type    Units
+ * ----                                 ---------    -----
+ *
+ * IEEE80211_RADIOTAP_TSFT              __le64       microseconds
+ *
+ *      Value in microseconds of the MAC's 64-bit 802.11 Time
+ *      Synchronization Function timer when the first bit of the
+ *      MPDU arrived at the MAC. For received frames, only.
+ *
+ * IEEE80211_RADIOTAP_CHANNEL           2 x __le16   MHz, bitmap
+ *
+ *      Tx/Rx frequency in MHz, followed by flags (see below).
+ *
+ * IEEE80211_RADIOTAP_FHSS              __le16       see below
+ *
+ *      For frequency-hopping radios, the hop set (first byte)
+ *      and pattern (second byte).
+ *
+ * IEEE80211_RADIOTAP_RATE              u8           500kb/s
+ *
+ *      Tx/Rx data rate
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTSIGNAL     s8           decibels from
+ *                                                   one milliwatt (dBm)
+ *
+ *      RF signal power at the antenna, decibel difference from
+ *      one milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTNOISE      s8           decibels from
+ *                                                   one milliwatt (dBm)
+ *
+ *      RF noise power at the antenna, decibel difference from one
+ *      milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTSIGNAL      u8           decibel (dB)
+ *
+ *      RF signal power at the antenna, decibel difference from an
+ *      arbitrary, fixed reference.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTNOISE       u8           decibel (dB)
+ *
+ *      RF noise power at the antenna, decibel difference from an
+ *      arbitrary, fixed reference point.
+ *
+ * IEEE80211_RADIOTAP_LOCK_QUALITY      __le16       unitless
+ *
+ *      Quality of Barker code lock. Unitless. Monotonically
+ *      nondecreasing with "better" lock strength. Called "Signal
+ *      Quality" in datasheets.  (Is there a standard way to measure
+ *      this?)
+ *
+ * IEEE80211_RADIOTAP_TX_ATTENUATION    __le16       unitless
+ *
+ *      Transmit power expressed as unitless distance from max
+ *      power set at factory calibration.  0 is max power.
+ *      Monotonically nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16       decibels (dB)
+ *
+ *      Transmit power expressed as decibel distance from max power
+ *      set at factory calibration.  0 is max power.  Monotonically
+ *      nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DBM_TX_POWER      s8           decibels from
+ *                                                   one milliwatt (dBm)
+ *
+ *      Transmit power expressed as dBm (decibels from a 1 milliwatt
+ *      reference). This is the absolute power level measured at
+ *      the antenna port.
+ *
+ * IEEE80211_RADIOTAP_FLAGS             u8           bitmap
+ *
+ *      Properties of transmitted and received frames. See flags
+ *      defined below.
+ *
+ * IEEE80211_RADIOTAP_ANTENNA           u8           antenna index
+ *
+ *      Unitless indication of the Rx/Tx antenna for this packet.
+ *      The first antenna is antenna 0.
+ *
+ * IEEE80211_RADIOTAP_RX_FLAGS          __le16       bitmap
+ *
+ *     Properties of received frames. See flags defined below.
+ *
+ * IEEE80211_RADIOTAP_TX_FLAGS          __le16       bitmap
+ *
+ *     Properties of transmitted frames. See flags defined below.
+ *
+ * IEEE80211_RADIOTAP_RTS_RETRIES       u8           data
+ *
+ *     Number of rts retries a transmitted frame used.
+ *
+ * IEEE80211_RADIOTAP_DATA_RETRIES      u8           data
+ *
+ *     Number of unicast retries a transmitted frame used.
+ *
+ */
+enum ieee80211_radiotap_type {
+       IEEE80211_RADIOTAP_TSFT = 0,
+       IEEE80211_RADIOTAP_FLAGS = 1,
+       IEEE80211_RADIOTAP_RATE = 2,
+       IEEE80211_RADIOTAP_CHANNEL = 3,
+       IEEE80211_RADIOTAP_FHSS = 4,
+       IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+       IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+       IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+       IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+       IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+       IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+       IEEE80211_RADIOTAP_ANTENNA = 11,
+       IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+       IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+       IEEE80211_RADIOTAP_RX_FLAGS = 14,
+       IEEE80211_RADIOTAP_TX_FLAGS = 15,
+       IEEE80211_RADIOTAP_RTS_RETRIES = 16,
+       IEEE80211_RADIOTAP_DATA_RETRIES = 17,
+       IEEE80211_RADIOTAP_EXT = 31
+};
+
+/* Channel flags. */
+#define        IEEE80211_CHAN_TURBO    0x0010  /* Turbo channel */
+#define        IEEE80211_CHAN_CCK      0x0020  /* CCK channel */
+#define        IEEE80211_CHAN_OFDM     0x0040  /* OFDM channel */
+#define        IEEE80211_CHAN_2GHZ     0x0080  /* 2 GHz spectrum channel. */
+#define        IEEE80211_CHAN_5GHZ     0x0100  /* 5 GHz spectrum channel */
+#define        IEEE80211_CHAN_PASSIVE  0x0200  /* Only passive scan allowed */
+#define        IEEE80211_CHAN_DYN      0x0400  /* Dynamic CCK-OFDM channel */
+#define        IEEE80211_CHAN_GFSK     0x0800  /* GFSK channel (FHSS PHY) */
+
+/* For IEEE80211_RADIOTAP_FLAGS */
+#define        IEEE80211_RADIOTAP_F_CFP        0x01    /* sent/received
+                                                * during CFP
+                                                */
+#define        IEEE80211_RADIOTAP_F_SHORTPRE   0x02    /* sent/received
+                                                * with short
+                                                * preamble
+                                                */
+#define        IEEE80211_RADIOTAP_F_WEP        0x04    /* sent/received
+                                                * with WEP encryption
+                                                */
+#define        IEEE80211_RADIOTAP_F_FRAG       0x08    /* sent/received
+                                                * with fragmentation
+                                                */
+#define        IEEE80211_RADIOTAP_F_FCS        0x10    /* frame includes FCS */
+#define        IEEE80211_RADIOTAP_F_DATAPAD    0x20    /* frame has padding between
+                                                * 802.11 header and payload
+                                                * (to 32-bit boundary)
+                                                */
+/* For IEEE80211_RADIOTAP_RX_FLAGS */
+#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001  /* frame failed crc check */
+
+/* For IEEE80211_RADIOTAP_TX_FLAGS */
+#define IEEE80211_RADIOTAP_F_TX_FAIL   0x0001  /* failed due to excessive
+                                                * retries */
+#define IEEE80211_RADIOTAP_F_TX_CTS    0x0002  /* used cts 'protection' */
+#define IEEE80211_RADIOTAP_F_TX_RTS    0x0004  /* used rts/cts handshake */
+
+/* Ugly macro to convert literal channel numbers into their mhz equivalents
+ * There are certianly some conditions that will break this (like feeding it '30')
+ * but they shouldn't arise since nothing talks on channel 30. */
+#define ieee80211chan2mhz(x) \
+       (((x) <= 14) ? \
+       (((x) == 14) ? 2484 : ((x) * 5) + 2407) : \
+       ((x) + 1000) * 5)
+
+/* helpers */
+static inline int ieee80211_get_radiotap_len(unsigned char *data)
+{
+       struct ieee80211_radiotap_header *hdr =
+               (struct ieee80211_radiotap_header *)data;
+
+       return le16_to_cpu(get_unaligned(&hdr->it_len));
+}
+
+#endif                         /* IEEE80211_RADIOTAP_H */
diff --git a/package/mac80211/src/include/net/mac80211.h b/package/mac80211/src/include/net/mac80211.h
new file mode 100644 (file)
index 0000000..2b1bffb
--- /dev/null
@@ -0,0 +1,1429 @@
+/*
+ * mac80211 <-> driver interface
+ *
+ * Copyright 2002-2005, Devicescape Software, Inc.
+ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
+ * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MAC80211_H
+#define MAC80211_H
+
+#include <linux/kernel.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/wireless.h>
+#include <linux/device.h>
+#include <linux/ieee80211.h>
+#include <net/wireless.h>
+#include <net/cfg80211.h>
+
+/**
+ * DOC: Introduction
+ *
+ * mac80211 is the Linux stack for 802.11 hardware that implements
+ * only partial functionality in hard- or firmware. This document
+ * defines the interface between mac80211 and low-level hardware
+ * drivers.
+ */
+
+/**
+ * DOC: Calling mac80211 from interrupts
+ *
+ * Only ieee80211_tx_status_irqsafe() and ieee80211_rx_irqsafe() can be
+ * called in hardware interrupt context. The low-level driver must not call any
+ * other functions in hardware interrupt context. If there is a need for such
+ * call, the low-level driver should first ACK the interrupt and perform the
+ * IEEE 802.11 code call after this, e.g. from a scheduled workqueue function.
+ */
+
+/**
+ * DOC: Warning
+ *
+ * If you're reading this document and not the header file itself, it will
+ * be incomplete because not all documentation has been converted yet.
+ */
+
+/**
+ * DOC: Frame format
+ *
+ * As a general rule, when frames are passed between mac80211 and the driver,
+ * they start with the IEEE 802.11 header and include the same octets that are
+ * sent over the air except for the FCS which should be calculated by the
+ * hardware.
+ *
+ * There are, however, various exceptions to this rule for advanced features:
+ *
+ * The first exception is for hardware encryption and decryption offload
+ * where the IV/ICV may or may not be generated in hardware.
+ *
+ * Secondly, when the hardware handles fragmentation, the frame handed to
+ * the driver from mac80211 is the MSDU, not the MPDU.
+ *
+ * Finally, for received frames, the driver is able to indicate that it has
+ * filled a radiotap header and put that in front of the frame; if it does
+ * not do so then mac80211 may add this under certain circumstances.
+ */
+
+#define IEEE80211_CHAN_W_SCAN 0x00000001
+#define IEEE80211_CHAN_W_ACTIVE_SCAN 0x00000002
+#define IEEE80211_CHAN_W_IBSS 0x00000004
+
+/* Channel information structure. Low-level driver is expected to fill in chan,
+ * freq, and val fields. Other fields will be filled in by 80211.o based on
+ * hostapd information and low-level driver does not need to use them. The
+ * limits for each channel will be provided in 'struct ieee80211_conf' when
+ * configuring the low-level driver with hw->config callback. If a device has
+ * a default regulatory domain, IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED
+ * can be set to let the driver configure all fields */
+struct ieee80211_channel {
+       short chan; /* channel number (IEEE 802.11) */
+       short freq; /* frequency in MHz */
+       int val; /* hw specific value for the channel */
+       int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */
+       unsigned char power_level;
+       unsigned char antenna_max;
+};
+
+#define IEEE80211_RATE_ERP 0x00000001
+#define IEEE80211_RATE_BASIC 0x00000002
+#define IEEE80211_RATE_PREAMBLE2 0x00000004
+#define IEEE80211_RATE_SUPPORTED 0x00000010
+#define IEEE80211_RATE_OFDM 0x00000020
+#define IEEE80211_RATE_CCK 0x00000040
+#define IEEE80211_RATE_MANDATORY 0x00000100
+
+#define IEEE80211_RATE_CCK_2 (IEEE80211_RATE_CCK | IEEE80211_RATE_PREAMBLE2)
+#define IEEE80211_RATE_MODULATION(f) \
+       (f & (IEEE80211_RATE_CCK | IEEE80211_RATE_OFDM))
+
+/* Low-level driver should set PREAMBLE2, OFDM and CCK flags.
+ * BASIC, SUPPORTED, ERP, and MANDATORY flags are set in 80211.o based on the
+ * configuration. */
+struct ieee80211_rate {
+       int rate; /* rate in 100 kbps */
+       int val; /* hw specific value for the rate */
+       int flags; /* IEEE80211_RATE_ flags */
+       int val2; /* hw specific value for the rate when using short preamble
+                  * (only when IEEE80211_RATE_PREAMBLE2 flag is set, i.e., for
+                  * 2, 5.5, and 11 Mbps) */
+       signed char min_rssi_ack;
+       unsigned char min_rssi_ack_delta;
+
+       /* following fields are set by 80211.o and need not be filled by the
+        * low-level driver */
+       int rate_inv; /* inverse of the rate (LCM(all rates) / rate) for
+                      * optimizing channel utilization estimates */
+};
+
+/**
+ * enum ieee80211_phymode - PHY modes
+ *
+ * @MODE_IEEE80211A: 5GHz as defined by 802.11a/802.11h
+ * @MODE_IEEE80211B: 2.4 GHz as defined by 802.11b
+ * @MODE_IEEE80211G: 2.4 GHz as defined by 802.11g (with OFDM),
+ *     backwards compatible with 11b mode
+ * @NUM_IEEE80211_MODES: internal
+ */
+enum ieee80211_phymode {
+       MODE_IEEE80211A,
+       MODE_IEEE80211B,
+       MODE_IEEE80211G,
+
+       /* keep last */
+       NUM_IEEE80211_MODES
+};
+
+/**
+ * struct ieee80211_hw_mode - PHY mode definition
+ *
+ * This structure describes the capabilities supported by the device
+ * in a single PHY mode.
+ *
+ * @mode: the PHY mode for this definition
+ * @num_channels: number of supported channels
+ * @channels: pointer to array of supported channels
+ * @num_rates: number of supported bitrates
+ * @rates: pointer to array of supported bitrates
+ * @list: internal
+ */
+struct ieee80211_hw_mode {
+       struct list_head list;
+       struct ieee80211_channel *channels;
+       struct ieee80211_rate *rates;
+       enum ieee80211_phymode mode;
+       int num_channels;
+       int num_rates;
+};
+
+/**
+ * struct ieee80211_tx_queue_params - transmit queue configuration
+ *
+ * The information provided in this structure is required for QoS
+ * transmit queue configuration.
+ *
+ * @aifs: arbitration interface space [0..255, -1: use default]
+ * @cw_min: minimum contention window [will be a value of the form
+ *     2^n-1 in the range 1..1023; 0: use default]
+ * @cw_max: maximum contention window [like @cw_min]
+ * @burst_time: maximum burst time in units of 0.1ms, 0 meaning disabled
+ */
+struct ieee80211_tx_queue_params {
+       int aifs;
+       int cw_min;
+       int cw_max;
+       int burst_time;
+};
+
+/**
+ * struct ieee80211_tx_queue_stats_data - transmit queue statistics
+ *
+ * @len: number of packets in queue
+ * @limit: queue length limit
+ * @count: number of frames sent
+ */
+struct ieee80211_tx_queue_stats_data {
+       unsigned int len;
+       unsigned int limit;
+       unsigned int count;
+};
+
+/**
+ * enum ieee80211_tx_queue - transmit queue number
+ *
+ * These constants are used with some callbacks that take a
+ * queue number to set parameters for a queue.
+ *
+ * @IEEE80211_TX_QUEUE_DATA0: data queue 0
+ * @IEEE80211_TX_QUEUE_DATA1: data queue 1
+ * @IEEE80211_TX_QUEUE_DATA2: data queue 2
+ * @IEEE80211_TX_QUEUE_DATA3: data queue 3
+ * @IEEE80211_TX_QUEUE_DATA4: data queue 4
+ * @IEEE80211_TX_QUEUE_SVP: ??
+ * @NUM_TX_DATA_QUEUES: number of data queues
+ * @IEEE80211_TX_QUEUE_AFTER_BEACON: transmit queue for frames to be
+ *     sent after a beacon
+ * @IEEE80211_TX_QUEUE_BEACON: transmit queue for beacon frames
+ */
+enum ieee80211_tx_queue {
+       IEEE80211_TX_QUEUE_DATA0,
+       IEEE80211_TX_QUEUE_DATA1,
+       IEEE80211_TX_QUEUE_DATA2,
+       IEEE80211_TX_QUEUE_DATA3,
+       IEEE80211_TX_QUEUE_DATA4,
+       IEEE80211_TX_QUEUE_SVP,
+
+       NUM_TX_DATA_QUEUES,
+
+/* due to stupidity in the sub-ioctl userspace interface, the items in
+ * this struct need to have fixed values. As soon as it is removed, we can
+ * fix these entries. */
+       IEEE80211_TX_QUEUE_AFTER_BEACON = 6,
+       IEEE80211_TX_QUEUE_BEACON = 7
+};
+
+struct ieee80211_tx_queue_stats {
+       struct ieee80211_tx_queue_stats_data data[NUM_TX_DATA_QUEUES];
+};
+
+struct ieee80211_low_level_stats {
+       unsigned int dot11ACKFailureCount;
+       unsigned int dot11RTSFailureCount;
+       unsigned int dot11FCSErrorCount;
+       unsigned int dot11RTSSuccessCount;
+};
+
+/* Transmit control fields. This data structure is passed to low-level driver
+ * with each TX frame. The low-level driver is responsible for configuring
+ * the hardware to use given values (depending on what is supported). */
+
+struct ieee80211_tx_control {
+       int tx_rate; /* Transmit rate, given as the hw specific value for the
+                     * rate (from struct ieee80211_rate) */
+       int rts_cts_rate; /* Transmit rate for RTS/CTS frame, given as the hw
+                          * specific value for the rate (from
+                          * struct ieee80211_rate) */
+
+#define IEEE80211_TXCTL_REQ_TX_STATUS  (1<<0)/* request TX status callback for
+                                               * this frame */
+#define IEEE80211_TXCTL_DO_NOT_ENCRYPT (1<<1) /* send this frame without
+                                               * encryption; e.g., for EAPOL
+                                               * frames */
+#define IEEE80211_TXCTL_USE_RTS_CTS    (1<<2) /* use RTS-CTS before sending
+                                               * frame */
+#define IEEE80211_TXCTL_USE_CTS_PROTECT        (1<<3) /* use CTS protection for the
+                                               * frame (e.g., for combined
+                                               * 802.11g / 802.11b networks) */
+#define IEEE80211_TXCTL_NO_ACK         (1<<4) /* tell the low level not to
+                                               * wait for an ack */
+#define IEEE80211_TXCTL_RATE_CTRL_PROBE        (1<<5)
+#define IEEE80211_TXCTL_CLEAR_DST_MASK (1<<6)
+#define IEEE80211_TXCTL_REQUEUE                (1<<7)
+#define IEEE80211_TXCTL_FIRST_FRAGMENT (1<<8) /* this is a first fragment of
+                                               * the frame */
+#define IEEE80211_TXCTL_LONG_RETRY_LIMIT (1<<10) /* this frame should be send
+                                                 * using the through
+                                                 * set_retry_limit configured
+                                                 * long retry value */
+       u32 flags;                             /* tx control flags defined
+                                               * above */
+       u8 key_idx;             /* keyidx from hw->set_key(), undefined if
+                                * IEEE80211_TXCTL_DO_NOT_ENCRYPT is set */
+       u8 retry_limit;         /* 1 = only first attempt, 2 = one retry, ..
+                                * This could be used when set_retry_limit
+                                * is not implemented by the driver */
+       u8 power_level;         /* per-packet transmit power level, in dBm */
+       u8 antenna_sel_tx;      /* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
+       u8 icv_len;             /* length of the ICV/MIC field in octets */
+       u8 iv_len;              /* length of the IV field in octets */
+       u8 queue;               /* hardware queue to use for this frame;
+                                * 0 = highest, hw->queues-1 = lowest */
+       struct ieee80211_rate *rate;            /* internal 80211.o rate */
+       struct ieee80211_rate *rts_rate;        /* internal 80211.o rate
+                                                * for RTS/CTS */
+       int alt_retry_rate; /* retry rate for the last retries, given as the
+                            * hw specific value for the rate (from
+                            * struct ieee80211_rate). To be used to limit
+                            * packet dropping when probing higher rates, if hw
+                            * supports multiple retry rates. -1 = not used */
+       int type;       /* internal */
+       int ifindex;    /* internal */
+};
+
+
+/**
+ * enum mac80211_rx_flags - receive flags
+ *
+ * These flags are used with the @flag member of &struct ieee80211_rx_status.
+ * @RX_FLAG_MMIC_ERROR: Michael MIC error was reported on this frame.
+ *     Use together with %RX_FLAG_MMIC_STRIPPED.
+ * @RX_FLAG_DECRYPTED: This frame was decrypted in hardware.
+ * @RX_FLAG_RADIOTAP: This frame starts with a radiotap header.
+ * @RX_FLAG_MMIC_STRIPPED: the Michael MIC is stripped off this frame,
+ *     verification has been done by the hardware.
+ * @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame.
+ *     If this flag is set, the stack cannot do any replay detection
+ *     hence the driver or hardware will have to do that.
+ * @RX_FLAG_FAILED_FCS_CRC: Set this flag if the FCS check failed on
+ *     the frame.
+ * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on
+ *     the frame.
+ */
+enum mac80211_rx_flags {
+       RX_FLAG_MMIC_ERROR      = 1<<0,
+       RX_FLAG_DECRYPTED       = 1<<1,
+       RX_FLAG_RADIOTAP        = 1<<2,
+       RX_FLAG_MMIC_STRIPPED   = 1<<3,
+       RX_FLAG_IV_STRIPPED     = 1<<4,
+       RX_FLAG_FAILED_FCS_CRC  = 1<<5,
+       RX_FLAG_FAILED_PLCP_CRC = 1<<6,
+};
+
+/**
+ * struct ieee80211_rx_status - receive status
+ *
+ * The low-level driver should provide this information (the subset
+ * supported by hardware) to the 802.11 code with each received
+ * frame.
+ * @mactime: MAC timestamp as defined by 802.11
+ * @freq: frequency the radio was tuned to when receiving this frame, in MHz
+ * @channel: channel the radio was tuned to
+ * @phymode: active PHY mode
+ * @ssi: signal strength when receiving this frame
+ * @signal: used as 'qual' in statistics reporting
+ * @noise: PHY noise when receiving this frame
+ * @antenna: antenna used
+ * @rate: data rate
+ * @flag: %RX_FLAG_*
+ */
+struct ieee80211_rx_status {
+       u64 mactime;
+       int freq;
+       int channel;
+       enum ieee80211_phymode phymode;
+       int ssi;
+       int signal;
+       int noise;
+       int antenna;
+       int rate;
+       int flag;
+};
+
+/**
+ * enum ieee80211_tx_status_flags - transmit status flags
+ *
+ * Status flags to indicate various transmit conditions.
+ *
+ * @IEEE80211_TX_STATUS_TX_FILTERED: The frame was not transmitted
+ *     because the destination STA was in powersave mode.
+ *
+ * @IEEE80211_TX_STATUS_ACK: Frame was acknowledged
+ */
+enum ieee80211_tx_status_flags {
+       IEEE80211_TX_STATUS_TX_FILTERED = 1<<0,
+       IEEE80211_TX_STATUS_ACK         = 1<<1,
+};
+
+/**
+ * struct ieee80211_tx_status - transmit status
+ *
+ * As much information as possible should be provided for each transmitted
+ * frame with ieee80211_tx_status().
+ *
+ * @control: a copy of the &struct ieee80211_tx_control passed to the driver
+ *     in the tx() callback.
+ *
+ * @flags: transmit status flags, defined above
+ *
+ * @ack_signal: signal strength of the ACK frame
+ *
+ * @excessive_retries: set to 1 if the frame was retried many times
+ *     but not acknowledged
+ *
+ * @retry_count: number of retries
+ *
+ * @queue_length: ?? REMOVE
+ * @queue_number: ?? REMOVE
+ */
+struct ieee80211_tx_status {
+       struct ieee80211_tx_control control;
+       u8 flags;
+       bool excessive_retries;
+       u8 retry_count;
+       int ack_signal;
+       int queue_length;
+       int queue_number;
+};
+
+/**
+ * enum ieee80211_conf_flags - configuration flags
+ *
+ * Flags to define PHY configuration options
+ *
+ * @IEEE80211_CONF_SHORT_SLOT_TIME: use 802.11g short slot time
+ * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported)
+ *
+ */
+enum ieee80211_conf_flags {
+       IEEE80211_CONF_SHORT_SLOT_TIME  = 1<<0,
+       IEEE80211_CONF_RADIOTAP         = 1<<1,
+};
+
+/**
+ * struct ieee80211_conf - configuration of the device
+ *
+ * This struct indicates how the driver shall configure the hardware.
+ *
+ * @radio_enabled: when zero, driver is required to switch off the radio.
+ *     TODO make a flag
+ * @channel: IEEE 802.11 channel number
+ * @freq: frequency in MHz
+ * @channel_val: hardware specific channel value for the channel
+ * @phymode: PHY mode to activate (REMOVE)
+ * @chan: channel to switch to, pointer to the channel information
+ * @mode: pointer to mode definition
+ * @regulatory_domain: ??
+ * @beacon_int: beacon interval (TODO make interface config)
+ * @flags: configuration flags defined above
+ * @power_level: transmit power limit for current regulatory domain in dBm
+ * @antenna_max: maximum antenna gain
+ * @antenna_sel_tx: transmit antenna selection, 0: default/diversity,
+ *     1/2: antenna 0/1
+ * @antenna_sel_rx: receive antenna selection, like @antenna_sel_tx
+ */
+struct ieee80211_conf {
+       int channel;                    /* IEEE 802.11 channel number */
+       int freq;                       /* MHz */
+       int channel_val;                /* hw specific value for the channel */
+
+       enum ieee80211_phymode phymode;
+       struct ieee80211_channel *chan;
+       struct ieee80211_hw_mode *mode;
+       unsigned int regulatory_domain;
+       int radio_enabled;
+
+       int beacon_int;
+       u32 flags;
+       u8 power_level;
+       u8 antenna_max;
+       u8 antenna_sel_tx;
+       u8 antenna_sel_rx;
+};
+
+/**
+ * enum ieee80211_if_types - types of 802.11 network interfaces
+ *
+ * @IEEE80211_IF_TYPE_INVALID: invalid interface type, not used
+ *     by mac80211 itself
+ * @IEEE80211_IF_TYPE_AP: interface in AP mode.
+ * @IEEE80211_IF_TYPE_MGMT: special interface for communication with hostap
+ *     daemon. Drivers should never see this type.
+ * @IEEE80211_IF_TYPE_STA: interface in STA (client) mode.
+ * @IEEE80211_IF_TYPE_IBSS: interface in IBSS (ad-hoc) mode.
+ * @IEEE80211_IF_TYPE_MNTR: interface in monitor (rfmon) mode.
+ * @IEEE80211_IF_TYPE_WDS: interface in WDS mode.
+ * @IEEE80211_IF_TYPE_VLAN: VLAN interface bound to an AP, drivers
+ *     will never see this type.
+ */
+enum ieee80211_if_types {
+       IEEE80211_IF_TYPE_INVALID,
+       IEEE80211_IF_TYPE_AP,
+       IEEE80211_IF_TYPE_STA,
+       IEEE80211_IF_TYPE_IBSS,
+       IEEE80211_IF_TYPE_MNTR,
+       IEEE80211_IF_TYPE_WDS,
+       IEEE80211_IF_TYPE_VLAN,
+};
+
+/**
+ * struct ieee80211_if_init_conf - initial configuration of an interface
+ *
+ * @if_id: internal interface ID. This number has no particular meaning to
+ *     drivers and the only allowed usage is to pass it to
+ *     ieee80211_beacon_get() and ieee80211_get_buffered_bc() functions.
+ *     This field is not valid for monitor interfaces
+ *     (interfaces of %IEEE80211_IF_TYPE_MNTR type).
+ * @type: one of &enum ieee80211_if_types constants. Determines the type of
+ *     added/removed interface.
+ * @mac_addr: pointer to MAC address of the interface. This pointer is valid
+ *     until the interface is removed (i.e. it cannot be used after
+ *     remove_interface() callback was called for this interface).
+ *
+ * This structure is used in add_interface() and remove_interface()
+ * callbacks of &struct ieee80211_hw.
+ *
+ * When you allow multiple interfaces to be added to your PHY, take care
+ * that the hardware can actually handle multiple MAC addresses. However,
+ * also take care that when there's no interface left with mac_addr != %NULL
+ * you remove the MAC address from the device to avoid acknowledging packets
+ * in pure monitor mode.
+ */
+struct ieee80211_if_init_conf {
+       int if_id;
+       enum ieee80211_if_types type;
+       void *mac_addr;
+};
+
+/**
+ * struct ieee80211_if_conf - configuration of an interface
+ *
+ * @type: type of the interface. This is always the same as was specified in
+ *     &struct ieee80211_if_init_conf. The type of an interface never changes
+ *     during the life of the interface; this field is present only for
+ *     convenience.
+ * @bssid: BSSID of the network we are associated to/creating.
+ * @ssid: used (together with @ssid_len) by drivers for hardware that
+ *     generate beacons independently. The pointer is valid only during the
+ *     config_interface() call, so copy the value somewhere if you need
+ *     it.
+ * @ssid_len: length of the @ssid field.
+ * @beacon: beacon template. Valid only if @host_gen_beacon_template in
+ *     &struct ieee80211_hw is set. The driver is responsible of freeing
+ *     the sk_buff.
+ * @beacon_control: tx_control for the beacon template, this field is only
+ *     valid when the @beacon field was set.
+ *
+ * This structure is passed to the config_interface() callback of
+ * &struct ieee80211_hw.
+ */
+struct ieee80211_if_conf {
+       int type;
+       u8 *bssid;
+       u8 *ssid;
+       size_t ssid_len;
+       struct sk_buff *beacon;
+       struct ieee80211_tx_control *beacon_control;
+};
+
+/**
+ * enum ieee80211_key_alg - key algorithm
+ * @ALG_WEP: WEP40 or WEP104
+ * @ALG_TKIP: TKIP
+ * @ALG_CCMP: CCMP (AES)
+ */
+enum ieee80211_key_alg {
+       ALG_WEP,
+       ALG_TKIP,
+       ALG_CCMP,
+};
+
+
+/**
+ * enum ieee80211_key_flags - key flags
+ *
+ * These flags are used for communication about keys between the driver
+ * and mac80211, with the @flags parameter of &struct ieee80211_key_conf.
+ *
+ * @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates
+ *     that the STA this key will be used with could be using QoS.
+ * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the
+ *     driver to indicate that it requires IV generation for this
+ *     particular key.
+ * @IEEE80211_KEY_FLAG_GENERATE_MMIC: This flag should be set by
+ *     the driver for a TKIP key if it requires Michael MIC
+ *     generation in software.
+ */
+enum ieee80211_key_flags {
+       IEEE80211_KEY_FLAG_WMM_STA      = 1<<0,
+       IEEE80211_KEY_FLAG_GENERATE_IV  = 1<<1,
+       IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2,
+};
+
+/**
+ * struct ieee80211_key_conf - key information
+ *
+ * This key information is given by mac80211 to the driver by
+ * the set_key() callback in &struct ieee80211_ops.
+ *
+ * @hw_key_idx: To be set by the driver, this is the key index the driver
+ *     wants to be given when a frame is transmitted and needs to be
+ *     encrypted in hardware.
+ * @alg: The key algorithm.
+ * @flags: key flags, see &enum ieee80211_key_flags.
+ * @keyidx: the key index (0-3)
+ * @keylen: key material length
+ * @key: key material
+ */
+struct ieee80211_key_conf {
+       enum ieee80211_key_alg alg;
+       u8 hw_key_idx;
+       u8 flags;
+       s8 keyidx;
+       u8 keylen;
+       u8 key[0];
+};
+
+#define IEEE80211_SEQ_COUNTER_RX       0
+#define IEEE80211_SEQ_COUNTER_TX       1
+
+/**
+ * enum set_key_cmd - key command
+ *
+ * Used with the set_key() callback in &struct ieee80211_ops, this
+ * indicates whether a key is being removed or added.
+ *
+ * @SET_KEY: a key is set
+ * @DISABLE_KEY: a key must be disabled
+ */
+enum set_key_cmd {
+       SET_KEY, DISABLE_KEY,
+};
+
+/**
+ * enum sta_notify_cmd - sta notify command
+ *
+ * Used with the sta_notify() callback in &struct ieee80211_ops, this
+ * indicates addition and removal of a station to station table
+ *
+ * @STA_NOTIFY_ADD: a station was added to the station table
+ * @STA_NOTIFY_REMOVE: a station being removed from the station table
+ */
+enum sta_notify_cmd {
+       STA_NOTIFY_ADD, STA_NOTIFY_REMOVE
+};
+
+/**
+ * enum ieee80211_hw_flags - hardware flags
+ *
+ * These flags are used to indicate hardware capabilities to
+ * the stack. Generally, flags here should have their meaning
+ * done in a way that the simplest hardware doesn't need setting
+ * any particular flags. There are some exceptions to this rule,
+ * however, so you are advised to review these flags carefully.
+ *
+ * @IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE:
+ *     The device only needs to be supplied with a beacon template.
+ *     If you need the host to generate each beacon then don't use
+ *     this flag and call ieee80211_beacon_get() when you need the
+ *     next beacon frame. Note that if you set this flag, you must
+ *     implement the set_tim() callback for powersave mode to work
+ *     properly.
+ *     This flag is only relevant for access-point mode.
+ *
+ * @IEEE80211_HW_RX_INCLUDES_FCS:
+ *     Indicates that received frames passed to the stack include
+ *     the FCS at the end.
+ *
+ * @IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING:
+ *     Some wireless LAN chipsets buffer broadcast/multicast frames
+ *     for power saving stations in the hardware/firmware and others
+ *     rely on the host system for such buffering. This option is used
+ *     to configure the IEEE 802.11 upper layer to buffer broadcast and
+ *     multicast frames when there are power saving stations so that
+ *     the driver can fetch them with ieee80211_get_buffered_bc(). Note
+ *     that not setting this flag works properly only when the
+ *     %IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE is also not set because
+ *     otherwise the stack will not know when the DTIM beacon was sent.
+ *
+ * @IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED:
+ *     Channels are already configured to the default regulatory domain
+ *     specified in the device's EEPROM
+ */
+enum ieee80211_hw_flags {
+       IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE           = 1<<0,
+       IEEE80211_HW_RX_INCLUDES_FCS                    = 1<<1,
+       IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING        = 1<<2,
+       IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED      = 1<<3,
+};
+
+/**
+ * struct ieee80211_hw - hardware information and state
+ *
+ * This structure contains the configuration and hardware
+ * information for an 802.11 PHY.
+ *
+ * @wiphy: This points to the &struct wiphy allocated for this
+ *     802.11 PHY. You must fill in the @perm_addr and @dev
+ *     members of this structure using SET_IEEE80211_DEV()
+ *     and SET_IEEE80211_PERM_ADDR().
+ *
+ * @conf: &struct ieee80211_conf, device configuration, don't use.
+ *
+ * @workqueue: single threaded workqueue available for driver use,
+ *     allocated by mac80211 on registration and flushed on
+ *     unregistration.
+ *
+ * @priv: pointer to private area that was allocated for driver use
+ *     along with this structure.
+ *
+ * @flags: hardware flags, see &enum ieee80211_hw_flags.
+ *
+ * @extra_tx_headroom: headroom to reserve in each transmit skb
+ *     for use by the driver (e.g. for transmit headers.)
+ *
+ * @channel_change_time: time (in microseconds) it takes to change channels.
+ *
+ * @max_rssi: Maximum value for ssi in RX information, use
+ *     negative numbers for dBm and 0 to indicate no support.
+ *
+ * @max_signal: like @max_rssi, but for the signal value.
+ *
+ * @max_noise: like @max_rssi, but for the noise value.
+ *
+ * @queues: number of available hardware transmit queues for
+ *     data packets. WMM/QoS requires at least four.
+ */
+struct ieee80211_hw {
+       struct ieee80211_conf conf;
+       struct wiphy *wiphy;
+       struct workqueue_struct *workqueue;
+       void *priv;
+       u32 flags;
+       unsigned int extra_tx_headroom;
+       int channel_change_time;
+       u8 queues;
+       s8 max_rssi;
+       s8 max_signal;
+       s8 max_noise;
+};
+
+/**
+ * SET_IEEE80211_DEV - set device for 802.11 hardware
+ *
+ * @hw: the &struct ieee80211_hw to set the device for
+ * @dev: the &struct device of this 802.11 device
+ */
+static inline void SET_IEEE80211_DEV(struct ieee80211_hw *hw, struct device *dev)
+{
+       set_wiphy_dev(hw->wiphy, dev);
+}
+
+/**
+ * SET_IEEE80211_PERM_ADDR - set the permanenet MAC address for 802.11 hardware
+ *
+ * @hw: the &struct ieee80211_hw to set the MAC address for
+ * @addr: the address to set
+ */
+static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr)
+{
+       memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN);
+}
+
+/**
+ * DOC: Hardware crypto acceleration
+ *
+ * mac80211 is capable of taking advantage of many hardware
+ * acceleration designs for encryption and decryption operations.
+ *
+ * The set_key() callback in the &struct ieee80211_ops for a given
+ * device is called to enable hardware acceleration of encryption and
+ * decryption. The callback takes an @address parameter that will be
+ * the broadcast address for default keys, the other station's hardware
+ * address for individual keys or the zero address for keys that will
+ * be used only for transmission.
+ * Multiple transmission keys with the same key index may be used when
+ * VLANs are configured for an access point.
+ *
+ * The @local_address parameter will always be set to our own address,
+ * this is only relevant if you support multiple local addresses.
+ *
+ * When transmitting, the TX control data will use the @hw_key_idx
+ * selected by the driver by modifying the &struct ieee80211_key_conf
+ * pointed to by the @key parameter to the set_key() function.
+ *
+ * The set_key() call for the %SET_KEY command should return 0 if
+ * the key is now in use, -%EOPNOTSUPP or -%ENOSPC if it couldn't be
+ * added; if you return 0 then hw_key_idx must be assigned to the
+ * hardware key index, you are free to use the full u8 range.
+ *
+ * When the cmd is %DISABLE_KEY then it must succeed.
+ *
+ * Note that it is permissible to not decrypt a frame even if a key
+ * for it has been uploaded to hardware, the stack will not make any
+ * decision based on whether a key has been uploaded or not but rather
+ * based on the receive flags.
+ *
+ * The &struct ieee80211_key_conf structure pointed to by the @key
+ * parameter is guaranteed to be valid until another call to set_key()
+ * removes it, but it can only be used as a cookie to differentiate
+ * keys.
+ */
+
+/**
+ * DOC: Frame filtering
+ *
+ * mac80211 requires to see many management frames for proper
+ * operation, and users may want to see many more frames when
+ * in monitor mode. However, for best CPU usage and power consumption,
+ * having as few frames as possible percolate through the stack is
+ * desirable. Hence, the hardware should filter as much as possible.
+ *
+ * To achieve this, mac80211 uses filter flags (see below) to tell
+ * the driver's configure_filter() function which frames should be
+ * passed to mac80211 and which should be filtered out.
+ *
+ * The configure_filter() callback is invoked with the parameters
+ * @mc_count and @mc_list for the combined multicast address list
+ * of all virtual interfaces, @changed_flags telling which flags
+ * were changed and @total_flags with the new flag states.
+ *
+ * If your device has no multicast address filters your driver will
+ * need to check both the %FIF_ALLMULTI flag and the @mc_count
+ * parameter to see whether multicast frames should be accepted
+ * or dropped.
+ *
+ * All unsupported flags in @total_flags must be cleared, i.e. you
+ * should clear all bits except those you honoured.
+ */
+
+/**
+ * enum ieee80211_filter_flags - hardware filter flags
+ *
+ * These flags determine what the filter in hardware should be
+ * programmed to let through and what should not be passed to the
+ * stack. It is always safe to pass more frames than requested,
+ * but this has negative impact on power consumption.
+ *
+ * @FIF_PROMISC_IN_BSS: promiscuous mode within your BSS,
+ *     think of the BSS as your network segment and then this corresponds
+ *     to the regular ethernet device promiscuous mode.
+ *
+ * @FIF_ALLMULTI: pass all multicast frames, this is used if requested
+ *     by the user or if the hardware is not capable of filtering by
+ *     multicast address.
+ *
+ * @FIF_FCSFAIL: pass frames with failed FCS (but you need to set the
+ *     %RX_FLAG_FAILED_FCS_CRC for them)
+ *
+ * @FIF_PLCPFAIL: pass frames with failed PLCP CRC (but you need to set
+ *     the %RX_FLAG_FAILED_PLCP_CRC for them
+ *
+ * @FIF_BCN_PRBRESP_PROMISC: This flag is set during scanning to indicate
+ *     to the hardware that it should not filter beacons or probe responses
+ *     by BSSID. Filtering them can greatly reduce the amount of processing
+ *     mac80211 needs to do and the amount of CPU wakeups, so you should
+ *     honour this flag if possible.
+ *
+ * @FIF_CONTROL: pass control frames, if PROMISC_IN_BSS is not set then
+ *     only those addressed to this station
+ *
+ * @FIF_OTHER_BSS: pass frames destined to other BSSes
+ */
+enum ieee80211_filter_flags {
+       FIF_PROMISC_IN_BSS      = 1<<0,
+       FIF_ALLMULTI            = 1<<1,
+       FIF_FCSFAIL             = 1<<2,
+       FIF_PLCPFAIL            = 1<<3,
+       FIF_BCN_PRBRESP_PROMISC = 1<<4,
+       FIF_CONTROL             = 1<<5,
+       FIF_OTHER_BSS           = 1<<6,
+};
+
+/**
+ * enum ieee80211_erp_change_flags - erp change flags
+ *
+ * These flags are used with the erp_ie_changed() callback in
+ * &struct ieee80211_ops to indicate which parameter(s) changed.
+ * @IEEE80211_ERP_CHANGE_PROTECTION: protection changed
+ * @IEEE80211_ERP_CHANGE_PREAMBLE: barker preamble mode changed
+ */
+enum ieee80211_erp_change_flags {
+       IEEE80211_ERP_CHANGE_PROTECTION = 1<<0,
+       IEEE80211_ERP_CHANGE_PREAMBLE   = 1<<1,
+};
+
+
+/**
+ * struct ieee80211_ops - callbacks from mac80211 to the driver
+ *
+ * This structure contains various callbacks that the driver may
+ * handle or, in some cases, must handle, for example to configure
+ * the hardware to a new channel or to transmit a frame.
+ *
+ * @tx: Handler that 802.11 module calls for each transmitted frame.
+ *     skb contains the buffer starting from the IEEE 802.11 header.
+ *     The low-level driver should send the frame out based on
+ *     configuration in the TX control data. Must be implemented and
+ *     atomic.
+ *
+ * @start: Called before the first netdevice attached to the hardware
+ *     is enabled. This should turn on the hardware and must turn on
+ *     frame reception (for possibly enabled monitor interfaces.)
+ *     Returns negative error codes, these may be seen in userspace,
+ *     or zero.
+ *     When the device is started it should not have a MAC address
+ *     to avoid acknowledging frames before a non-monitor device
+ *     is added.
+ *     Must be implemented.
+ *
+ * @stop: Called after last netdevice attached to the hardware
+ *     is disabled. This should turn off the hardware (at least
+ *     it must turn off frame reception.)
+ *     May be called right after add_interface if that rejects
+ *     an interface.
+ *     Must be implemented.
+ *
+ * @add_interface: Called when a netdevice attached to the hardware is
+ *     enabled. Because it is not called for monitor mode devices, @open
+ *     and @stop must be implemented.
+ *     The driver should perform any initialization it needs before
+ *     the device can be enabled. The initial configuration for the
+ *     interface is given in the conf parameter.
+ *     The callback may refuse to add an interface by returning a
+ *     negative error code (which will be seen in userspace.)
+ *     Must be implemented.
+ *
+ * @remove_interface: Notifies a driver that an interface is going down.
+ *     The @stop callback is called after this if it is the last interface
+ *     and no monitor interfaces are present.
+ *     When all interfaces are removed, the MAC address in the hardware
+ *     must be cleared so the device no longer acknowledges packets,
+ *     the mac_addr member of the conf structure is, however, set to the
+ *     MAC address of the device going away.
+ *     Hence, this callback must be implemented.
+ *
+ * @config: Handler for configuration requests. IEEE 802.11 code calls this
+ *     function to change hardware configuration, e.g., channel.
+ *
+ * @config_interface: Handler for configuration requests related to interfaces
+ *     (e.g. BSSID changes.)
+ *
+ * @configure_filter: Configure the device's RX filter.
+ *     See the section "Frame filtering" for more information.
+ *     This callback must be implemented and atomic.
+ *
+ * @set_tim: Set TIM bit. If the hardware/firmware takes care of beacon
+ *     generation (that is, %IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE is set)
+ *     mac80211 calls this function when a TIM bit must be set or cleared
+ *     for a given AID. Must be atomic.
+ *
+ * @set_key: See the section "Hardware crypto acceleration"
+ *     This callback can sleep, and is only called between add_interface
+ *     and remove_interface calls, i.e. while the interface with the
+ *     given local_address is enabled.
+ *
+ * @set_ieee8021x: Enable/disable IEEE 802.1X. This item requests wlan card
+ *     to pass unencrypted EAPOL-Key frames even when encryption is
+ *     configured. If the wlan card does not require such a configuration,
+ *     this function pointer can be set to NULL.
+ *
+ * @set_port_auth: Set port authorization state (IEEE 802.1X PAE) to be
+ *     authorized (@authorized=1) or unauthorized (=0). This function can be
+ *     used if the wlan hardware or low-level driver implements PAE.
+ *     mac80211 will filter frames based on authorization state in any case,
+ *     so this function pointer can be NULL if low-level driver does not
+ *     require event notification about port state changes.
+ *
+ * @hw_scan: Ask the hardware to service the scan request, no need to start
+ *     the scan state machine in stack.
+ *
+ * @get_stats: return low-level statistics
+ *
+ * @set_privacy_invoked: For devices that generate their own beacons and probe
+ *     response or association responses this updates the state of privacy_invoked
+ *     returns 0 for success or an error number.
+ *
+ * @get_sequence_counter: For devices that have internal sequence counters this
+ *     callback allows mac80211 to access the current value of a counter.
+ *     This callback seems not well-defined, tell us if you need it.
+ *
+ * @set_rts_threshold: Configuration of RTS threshold (if device needs it)
+ *
+ * @set_frag_threshold: Configuration of fragmentation threshold. Assign this if
+ *     the device does fragmentation by itself; if this method is assigned then
+ *     the stack will not do fragmentation.
+ *
+ * @set_retry_limit: Configuration of retry limits (if device needs it)
+ *
+ * @sta_notify: Notifies low level driver about addition or removal
+ *     of assocaited station or AP.
+ *
+ * @erp_ie_changed: Handle ERP IE change notifications. Must be atomic.
+ *
+ * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
+ *     bursting) for a hardware TX queue. The @queue parameter uses the
+ *     %IEEE80211_TX_QUEUE_* constants. Must be atomic.
+ *
+ * @get_tx_stats: Get statistics of the current TX queue status. This is used
+ *     to get number of currently queued packets (queue length), maximum queue
+ *     size (limit), and total number of packets sent using each TX queue
+ *     (count). This information is used for WMM to find out which TX
+ *     queues have room for more packets and by hostapd to provide
+ *     statistics about the current queueing state to external programs.
+ *
+ * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently,
+ *     this is only used for IBSS mode debugging and, as such, is not a
+ *     required function. Must be atomic.
+ *
+ * @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize
+ *     with other STAs in the IBSS. This is only used in IBSS mode. This
+ *     function is optional if the firmware/hardware takes full care of
+ *     TSF synchronization.
+ *
+ * @beacon_update: Setup beacon data for IBSS beacons. Unlike access point,
+ *     IBSS uses a fixed beacon frame which is configured using this
+ *     function.
+ *     If the driver returns success (0) from this callback, it owns
+ *     the skb. That means the driver is responsible to kfree_skb() it.
+ *     The control structure is not dynamically allocated. That means the
+ *     driver does not own the pointer and if it needs it somewhere
+ *     outside of the context of this function, it must copy it
+ *     somewhere else.
+ *     This handler is required only for IBSS mode.
+ *
+ * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us.
+ *     This is needed only for IBSS mode and the result of this function is
+ *     used to determine whether to reply to Probe Requests.
+ */
+struct ieee80211_ops {
+       int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb,
+                 struct ieee80211_tx_control *control);
+       int (*start)(struct ieee80211_hw *hw);
+       void (*stop)(struct ieee80211_hw *hw);
+       int (*add_interface)(struct ieee80211_hw *hw,
+                            struct ieee80211_if_init_conf *conf);
+       void (*remove_interface)(struct ieee80211_hw *hw,
+                                struct ieee80211_if_init_conf *conf);
+       int (*config)(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+       int (*config_interface)(struct ieee80211_hw *hw,
+                               int if_id, struct ieee80211_if_conf *conf);
+       void (*configure_filter)(struct ieee80211_hw *hw,
+                                unsigned int changed_flags,
+                                unsigned int *total_flags,
+                                int mc_count, struct dev_addr_list *mc_list);
+       int (*set_tim)(struct ieee80211_hw *hw, int aid, int set);
+       int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+                      const u8 *local_address, const u8 *address,
+                      struct ieee80211_key_conf *key);
+       int (*set_ieee8021x)(struct ieee80211_hw *hw, int use_ieee8021x);
+       int (*set_port_auth)(struct ieee80211_hw *hw, u8 *addr,
+                            int authorized);
+       int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len);
+       int (*get_stats)(struct ieee80211_hw *hw,
+                        struct ieee80211_low_level_stats *stats);
+       int (*set_privacy_invoked)(struct ieee80211_hw *hw,
+                                  int privacy_invoked);
+       int (*get_sequence_counter)(struct ieee80211_hw *hw,
+                                   u8* addr, u8 keyidx, u8 txrx,
+                                   u32* iv32, u16* iv16);
+       int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value);
+       int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value);
+       int (*set_retry_limit)(struct ieee80211_hw *hw,
+                              u32 short_retry, u32 long_retr);
+       void (*sta_notify)(struct ieee80211_hw *hw, int if_id,
+                       enum sta_notify_cmd, const u8 *addr);
+       void (*erp_ie_changed)(struct ieee80211_hw *hw, u8 changes,
+                              int cts_protection, int preamble);
+       int (*conf_tx)(struct ieee80211_hw *hw, int queue,
+                      const struct ieee80211_tx_queue_params *params);
+       int (*get_tx_stats)(struct ieee80211_hw *hw,
+                           struct ieee80211_tx_queue_stats *stats);
+       u64 (*get_tsf)(struct ieee80211_hw *hw);
+       void (*reset_tsf)(struct ieee80211_hw *hw);
+       int (*beacon_update)(struct ieee80211_hw *hw,
+                            struct sk_buff *skb,
+                            struct ieee80211_tx_control *control);
+       int (*tx_last_beacon)(struct ieee80211_hw *hw);
+};
+
+/**
+ * ieee80211_alloc_hw -  Allocate a new hardware device
+ *
+ * This must be called once for each hardware device. The returned pointer
+ * must be used to refer to this device when calling other functions.
+ * mac80211 allocates a private data area for the driver pointed to by
+ * @priv in &struct ieee80211_hw, the size of this area is given as
+ * @priv_data_len.
+ *
+ * @priv_data_len: length of private data
+ * @ops: callbacks for this device
+ */
+struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
+                                       const struct ieee80211_ops *ops);
+
+/**
+ * ieee80211_register_hw - Register hardware device
+ *
+ * You must call this function before any other functions
+ * except ieee80211_register_hwmode.
+ *
+ * @hw: the device to register as returned by ieee80211_alloc_hw()
+ */
+int ieee80211_register_hw(struct ieee80211_hw *hw);
+
+#ifdef CONFIG_MAC80211_LEDS
+extern char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw);
+extern char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw);
+extern char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw);
+#endif
+/**
+ * ieee80211_get_tx_led_name - get name of TX LED
+ *
+ * mac80211 creates a transmit LED trigger for each wireless hardware
+ * that can be used to drive LEDs if your driver registers a LED device.
+ * This function returns the name (or %NULL if not configured for LEDs)
+ * of the trigger so you can automatically link the LED device.
+ *
+ * @hw: the hardware to get the LED trigger name for
+ */
+static inline char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
+{
+#ifdef CONFIG_MAC80211_LEDS
+       return __ieee80211_get_tx_led_name(hw);
+#else
+       return NULL;
+#endif
+}
+
+/**
+ * ieee80211_get_rx_led_name - get name of RX LED
+ *
+ * mac80211 creates a receive LED trigger for each wireless hardware
+ * that can be used to drive LEDs if your driver registers a LED device.
+ * This function returns the name (or %NULL if not configured for LEDs)
+ * of the trigger so you can automatically link the LED device.
+ *
+ * @hw: the hardware to get the LED trigger name for
+ */
+static inline char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
+{
+#ifdef CONFIG_MAC80211_LEDS
+       return __ieee80211_get_rx_led_name(hw);
+#else
+       return NULL;
+#endif
+}
+
+static inline char *ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
+{
+#ifdef CONFIG_MAC80211_LEDS
+       return __ieee80211_get_assoc_led_name(hw);
+#else
+       return NULL;
+#endif
+}
+
+
+/* Register a new hardware PHYMODE capability to the stack. */
+int ieee80211_register_hwmode(struct ieee80211_hw *hw,
+                             struct ieee80211_hw_mode *mode);
+
+/**
+ * ieee80211_unregister_hw - Unregister a hardware device
+ *
+ * This function instructs mac80211 to free allocated resources
+ * and unregister netdevices from the networking subsystem.
+ *
+ * @hw: the hardware to unregister
+ */
+void ieee80211_unregister_hw(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_free_hw - free hardware descriptor
+ *
+ * This function frees everything that was allocated, including the
+ * private data for the driver. You must call ieee80211_unregister_hw()
+ * before calling this function
+ *
+ * @hw: the hardware to free
+ */
+void ieee80211_free_hw(struct ieee80211_hw *hw);
+
+/* trick to avoid symbol clashes with the ieee80211 subsystem */
+void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+                   struct ieee80211_rx_status *status);
+
+/**
+ * ieee80211_rx - receive frame
+ *
+ * Use this function to hand received frames to mac80211. The receive
+ * buffer in @skb must start with an IEEE 802.11 header or a radiotap
+ * header if %RX_FLAG_RADIOTAP is set in the @status flags.
+ *
+ * This function may not be called in IRQ context.
+ *
+ * @hw: the hardware this frame came in on
+ * @skb: the buffer to receive, owned by mac80211 after this call
+ * @status: status of this frame; the status pointer need not be valid
+ *     after this function returns
+ */
+static inline void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+                               struct ieee80211_rx_status *status)
+{
+       __ieee80211_rx(hw, skb, status);
+}
+
+/**
+ * ieee80211_rx_irqsafe - receive frame
+ *
+ * Like ieee80211_rx() but can be called in IRQ context
+ * (internally defers to a workqueue.)
+ *
+ * @hw: the hardware this frame came in on
+ * @skb: the buffer to receive, owned by mac80211 after this call
+ * @status: status of this frame; the status pointer need not be valid
+ *     after this function returns and is not freed by mac80211,
+ *     it is recommended that it points to a stack area
+ */
+void ieee80211_rx_irqsafe(struct ieee80211_hw *hw,
+                         struct sk_buff *skb,
+                         struct ieee80211_rx_status *status);
+
+/**
+ * ieee80211_tx_status - transmit status callback
+ *
+ * Call this function for all transmitted frames after they have been
+ * transmitted. It is permissible to not call this function for
+ * multicast frames but this can affect statistics.
+ *
+ * @hw: the hardware the frame was transmitted by
+ * @skb: the frame that was transmitted, owned by mac80211 after this call
+ * @status: status information for this frame; the status pointer need not
+ *     be valid after this function returns and is not freed by mac80211,
+ *     it is recommended that it points to a stack area
+ */
+void ieee80211_tx_status(struct ieee80211_hw *hw,
+                        struct sk_buff *skb,
+                        struct ieee80211_tx_status *status);
+void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
+                                struct sk_buff *skb,
+                                struct ieee80211_tx_status *status);
+
+/**
+ * ieee80211_beacon_get - beacon generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @if_id: interface ID from &struct ieee80211_if_init_conf.
+ * @control: will be filled with information needed to send this beacon.
+ *
+ * If the beacon frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next beacon frame from the 802.11 code. The low-level is responsible
+ * for calling this function before beacon data is needed (e.g., based on
+ * hardware interrupt). Returned skb is used only once and low-level driver
+ * is responsible of freeing it.
+ */
+struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
+                                    int if_id,
+                                    struct ieee80211_tx_control *control);
+
+/**
+ * ieee80211_rts_get - RTS frame generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @if_id: interface ID from &struct ieee80211_if_init_conf.
+ * @frame: pointer to the frame that is going to be protected by the RTS.
+ * @frame_len: the frame length (in octets).
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ * @rts: The buffer where to store the RTS frame.
+ *
+ * If the RTS frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next RTS frame from the 802.11 code. The low-level is responsible
+ * for calling this function before and RTS frame is needed.
+ */
+void ieee80211_rts_get(struct ieee80211_hw *hw, int if_id,
+                      const void *frame, size_t frame_len,
+                      const struct ieee80211_tx_control *frame_txctl,
+                      struct ieee80211_rts *rts);
+
+/**
+ * ieee80211_rts_duration - Get the duration field for an RTS frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @if_id: interface ID from &struct ieee80211_if_init_conf.
+ * @frame_len: the length of the frame that is going to be protected by the RTS.
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ *
+ * If the RTS is generated in firmware, but the host system must provide
+ * the duration field, the low-level driver uses this function to receive
+ * the duration field value in little-endian byteorder.
+ */
+__le16 ieee80211_rts_duration(struct ieee80211_hw *hw, int if_id,
+                             size_t frame_len,
+                             const struct ieee80211_tx_control *frame_txctl);
+
+/**
+ * ieee80211_ctstoself_get - CTS-to-self frame generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @if_id: interface ID from &struct ieee80211_if_init_conf.
+ * @frame: pointer to the frame that is going to be protected by the CTS-to-self.
+ * @frame_len: the frame length (in octets).
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ * @cts: The buffer where to store the CTS-to-self frame.
+ *
+ * If the CTS-to-self frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next CTS-to-self frame from the 802.11 code. The low-level is responsible
+ * for calling this function before and CTS-to-self frame is needed.
+ */
+void ieee80211_ctstoself_get(struct ieee80211_hw *hw, int if_id,
+                            const void *frame, size_t frame_len,
+                            const struct ieee80211_tx_control *frame_txctl,
+                            struct ieee80211_cts *cts);
+
+/**
+ * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @if_id: interface ID from &struct ieee80211_if_init_conf.
+ * @frame_len: the length of the frame that is going to be protected by the CTS-to-self.
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ *
+ * If the CTS-to-self is generated in firmware, but the host system must provide
+ * the duration field, the low-level driver uses this function to receive
+ * the duration field value in little-endian byteorder.
+ */
+__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, int if_id,
+                                   size_t frame_len,
+                                   const struct ieee80211_tx_control *frame_txctl);
+
+/**
+ * ieee80211_generic_frame_duration - Calculate the duration field for a frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @if_id: interface ID from &struct ieee80211_if_init_conf.
+ * @frame_len: the length of the frame.
+ * @rate: the rate (in 100kbps) at which the frame is going to be transmitted.
+ *
+ * Calculate the duration field of some generic frame, given its
+ * length and transmission rate (in 100kbps).
+ */
+__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, int if_id,
+                                       size_t frame_len,
+                                       int rate);
+
+/**
+ * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @if_id: interface ID from &struct ieee80211_if_init_conf.
+ * @control: will be filled with information needed to send returned frame.
+ *
+ * Function for accessing buffered broadcast and multicast frames. If
+ * hardware/firmware does not implement buffering of broadcast/multicast
+ * frames when power saving is used, 802.11 code buffers them in the host
+ * memory. The low-level driver uses this function to fetch next buffered
+ * frame. In most cases, this is used when generating beacon frame. This
+ * function returns a pointer to the next buffered skb or NULL if no more
+ * buffered frames are available.
+ *
+ * Note: buffered frames are returned only after DTIM beacon frame was
+ * generated with ieee80211_beacon_get() and the low-level driver must thus
+ * call ieee80211_beacon_get() first. ieee80211_get_buffered_bc() returns
+ * NULL if the previous generated beacon was not DTIM, so the low-level driver
+ * does not need to check for DTIM beacons separately and should be able to
+ * use common code for all beacons.
+ */
+struct sk_buff *
+ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id,
+                         struct ieee80211_tx_control *control);
+
+/**
+ * ieee80211_get_hdrlen_from_skb - get header length from data
+ *
+ * Given an skb with a raw 802.11 header at the data pointer this function
+ * returns the 802.11 header length in bytes (not including encryption
+ * headers). If the data in the sk_buff is too short to contain a valid 802.11
+ * header the function returns 0.
+ *
+ * @skb: the frame
+ */
+int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
+
+/**
+ * ieee80211_get_hdrlen - get header length from frame control
+ *
+ * This function returns the 802.11 header length in bytes (not including
+ * encryption headers.)
+ *
+ * @fc: the frame control field (in CPU endianness)
+ */
+int ieee80211_get_hdrlen(u16 fc);
+
+/**
+ * ieee80211_wake_queue - wake specific queue
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @queue: queue number (counted from zero).
+ *
+ * Drivers should use this function instead of netif_wake_queue.
+ */
+void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue);
+
+/**
+ * ieee80211_stop_queue - stop specific queue
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @queue: queue number (counted from zero).
+ *
+ * Drivers should use this function instead of netif_stop_queue.
+ */
+void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
+
+/**
+ * ieee80211_start_queues - start all queues
+ * @hw: pointer to as obtained from ieee80211_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_start_queue.
+ */
+void ieee80211_start_queues(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_stop_queues - stop all queues
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_stop_queue.
+ */
+void ieee80211_stop_queues(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_wake_queues - wake all queues
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_wake_queue.
+ */
+void ieee80211_wake_queues(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_scan_completed - completed hardware scan
+ *
+ * When hardware scan offload is used (i.e. the hw_scan() callback is
+ * assigned) this function needs to be called by the driver to notify
+ * mac80211 that the scan finished.
+ *
+ * @hw: the hardware that finished the scan
+ */
+void ieee80211_scan_completed(struct ieee80211_hw *hw);
+
+#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_ARG(x) ((u8*)(x))[0], ((u8*)(x))[1], ((u8*)(x))[2], \
+                  ((u8*)(x))[3], ((u8*)(x))[4], ((u8*)(x))[5]
+
+#endif /* MAC80211_H */
index a03c886..6fffb38 100644 (file)
@@ -64,10 +64,6 @@ config MAC80211_DEBUG_COUNTERS
        bool "Extra statistics for TX/RX debugging"
        depends on MAC80211_DEBUG
 
-config HOSTAPD_WPA_TESTING
-       bool "Support for TKIP countermeasures testing"
-       depends on MAC80211_DEBUG
-
 config MAC80211_IBSS_DEBUG
        bool "Support for IBSS testing"
        depends on MAC80211_DEBUG
index 0a88dd3..219cd9f 100644 (file)
@@ -1,7 +1,8 @@
-obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o rc80211_lowest.o
+obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o
 
 mac80211-objs-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
 mac80211-objs-$(CONFIG_MAC80211_DEBUGFS) += debugfs.o debugfs_sta.o debugfs_netdev.o debugfs_key.o
+mac80211-objs-$(CONFIG_NET_SCHED) += wme.o
 
 mac80211-objs := \
        ieee80211.o \
@@ -16,6 +17,10 @@ mac80211-objs := \
        regdomain.o \
        tkip.o \
        aes_ccm.o \
-       wme.o \
-       ieee80211_cfg.o \
+       cfg.o \
+       rx.o \
+       tx.o \
+       key.o \
+       util.o \
+       event.o \
        $(mac80211-objs-y)
diff --git a/package/mac80211/src/mac80211/cfg.c b/package/mac80211/src/mac80211/cfg.c
new file mode 100644 (file)
index 0000000..cd78b3f
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * mac80211 configuration hooks for cfg80211
+ *
+ * Copyright 2006      Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This file is GPLv2 as found in COPYING.
+ */
+
+#include <linux/nl80211.h>
+#include <linux/rtnetlink.h>
+#include <net/cfg80211.h>
+#include "ieee80211_i.h"
+#include "cfg.h"
+
+static enum ieee80211_if_types
+nl80211_type_to_mac80211_type(enum nl80211_iftype type)
+{
+       switch (type) {
+       case NL80211_IFTYPE_UNSPECIFIED:
+               return IEEE80211_IF_TYPE_STA;
+       case NL80211_IFTYPE_ADHOC:
+               return IEEE80211_IF_TYPE_IBSS;
+       case NL80211_IFTYPE_STATION:
+               return IEEE80211_IF_TYPE_STA;
+       case NL80211_IFTYPE_MONITOR:
+               return IEEE80211_IF_TYPE_MNTR;
+       default:
+               return IEEE80211_IF_TYPE_INVALID;
+       }
+}
+
+static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
+                              enum nl80211_iftype type)
+{
+       struct ieee80211_local *local = wiphy_priv(wiphy);
+       enum ieee80211_if_types itype;
+
+       if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
+               return -ENODEV;
+
+       itype = nl80211_type_to_mac80211_type(type);
+       if (itype == IEEE80211_IF_TYPE_INVALID)
+               return -EINVAL;
+
+       return ieee80211_if_add(local->mdev, name, NULL, itype);
+}
+
+static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
+{
+       struct ieee80211_local *local = wiphy_priv(wiphy);
+       struct net_device *dev;
+       char *name;
+
+       if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
+               return -ENODEV;
+
+       /* we're under RTNL */
+       dev = __dev_get_by_index(ifindex);
+       if (!dev)
+               return 0;
+
+       name = dev->name;
+
+       return ieee80211_if_remove(local->mdev, name, -1);
+}
+
+static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
+                                 enum nl80211_iftype type)
+{
+       struct ieee80211_local *local = wiphy_priv(wiphy);
+       struct net_device *dev;
+       enum ieee80211_if_types itype;
+       struct ieee80211_sub_if_data *sdata;
+
+       if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
+               return -ENODEV;
+
+       /* we're under RTNL */
+       dev = __dev_get_by_index(ifindex);
+       if (!dev)
+               return -ENODEV;
+
+       if (netif_running(dev))
+               return -EBUSY;
+
+       itype = nl80211_type_to_mac80211_type(type);
+       if (itype == IEEE80211_IF_TYPE_INVALID)
+               return -EINVAL;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+        if (sdata->type == IEEE80211_IF_TYPE_VLAN)
+               return -EOPNOTSUPP;
+
+       ieee80211_if_reinit(dev);
+       ieee80211_if_set_type(dev, itype);
+
+       return 0;
+}
+
+struct cfg80211_ops mac80211_config_ops = {
+       .add_virtual_intf = ieee80211_add_iface,
+       .del_virtual_intf = ieee80211_del_iface,
+       .change_virtual_intf = ieee80211_change_iface,
+};
diff --git a/package/mac80211/src/mac80211/cfg.h b/package/mac80211/src/mac80211/cfg.h
new file mode 100644 (file)
index 0000000..7d7879f
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * mac80211 configuration hooks for cfg80211
+ */
+#ifndef __CFG_H
+#define __CFG_H
+
+extern struct cfg80211_ops mac80211_config_ops;
+
+#endif /* __CFG_H */
index 07e643a..60514b2 100644 (file)
 #include "ieee80211_rate.h"
 #include "debugfs.h"
 
-static inline int rtnl_lock_local(struct ieee80211_local *local)
-{
-       rtnl_lock();
-       if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) {
-               rtnl_unlock();
-               return -ENODEV;
-       }
-       return 0;
-}
-
 int mac80211_open_file_generic(struct inode *inode, struct file *file)
 {
        file->private_data = inode->i_private;
@@ -38,8 +28,6 @@ static const char *ieee80211_mode_str(int mode)
                return "IEEE 802.11b";
        case MODE_IEEE80211G:
                return "IEEE 802.11g";
-       case MODE_ATHEROS_TURBO:
-               return "Atheros Turbo (5 GHz)";
        default:
                return "UNKNOWN";
        }
@@ -66,7 +54,7 @@ static const struct file_operations modes_ops = {
        .open = mac80211_open_file_generic,
 };
 
-#define DEBUGFS_READ(name, buflen, fmt, value...)                      \
+#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)             \
 static ssize_t name## _read(struct file *file, char __user *userbuf,   \
                            size_t count, loff_t *ppos)                 \
 {                                                                      \
@@ -77,20 +65,16 @@ static ssize_t name## _read(struct file *file, char __user *userbuf,        \
        res = scnprintf(buf, buflen, fmt "\n", ##value);                \
        return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
 }                                                                      \
-
-#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)             \
-DEBUGFS_READ(name, buflen, fmt, ## value)                              \
+                                                                       \
 static const struct file_operations name## _ops = {                    \
        .read = name## _read,                                           \
        .open = mac80211_open_file_generic,                             \
 };
 
-#define DEBUGFS_ADD_MODE(name, mode)                                   \
-       local->debugfs.name = debugfs_create_file(#name, mode, phyd,    \
+#define DEBUGFS_ADD(name)                                              \
+       local->debugfs.name = debugfs_create_file(#name, 0444, phyd,    \
                                                  local, &name## _ops);
 
-#define DEBUGFS_ADD(name)      DEBUGFS_ADD_MODE(name, 0444)
-
 #define DEBUGFS_DEL(name)                                              \
        debugfs_remove(local->debugfs.name);                            \
        local->debugfs.name = NULL;
@@ -100,16 +84,12 @@ DEBUGFS_READONLY_FILE(channel, 20, "%d",
                      local->hw.conf.channel);
 DEBUGFS_READONLY_FILE(frequency, 20, "%d",
                      local->hw.conf.freq);
-DEBUGFS_READONLY_FILE(radar_detect, 20, "%d",
-                     local->hw.conf.radar_detect);
 DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d",
                      local->hw.conf.antenna_sel_tx);
 DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d",
                      local->hw.conf.antenna_sel_rx);
 DEBUGFS_READONLY_FILE(bridge_packets, 20, "%d",
                      local->bridge_packets);
-DEBUGFS_READONLY_FILE(key_tx_rx_threshold, 20, "%d",
-                     local->key_tx_rx_threshold);
 DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
                      local->rts_threshold);
 DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
@@ -124,41 +104,21 @@ DEBUGFS_READONLY_FILE(mode, 20, "%s",
                      ieee80211_mode_str(local->hw.conf.phymode));
 DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x",
                      local->wep_iv & 0xffffff);
-DEBUGFS_READONLY_FILE(tx_power_reduction, 20, "%d.%d dBm",
-                     local->hw.conf.tx_power_reduction / 10,
-                     local->hw.conf.tx_power_reduction & 10);
+DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
+                     local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>");
 
-DEBUGFS_READ(rate_ctrl_alg, 100, "%s",
-            local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>");
+/* statistics stuff */
 
-static ssize_t rate_ctrl_alg_write(struct file *file, const char __user *userbuf,
-                                  size_t count, loff_t *ppos)
+static inline int rtnl_lock_local(struct ieee80211_local *local)
 {
-       struct ieee80211_local *local = file->private_data;
-       char buf[64];
-       ssize_t buf_size;
-       int res;
-
-       buf_size = min(count, ARRAY_SIZE(buf) - 1);
-       if (copy_from_user(buf, userbuf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = '\0';
-       res = rtnl_lock_local(local);
-       if (res)
-               return res;
-       res = ieee80211_init_rate_ctrl_alg(local, buf);
-       rtnl_unlock();
-       return res < 0 ? res : buf_size;
+       rtnl_lock();
+       if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) {
+               rtnl_unlock();
+               return -ENODEV;
+       }
+       return 0;
 }
 
-static const struct file_operations rate_ctrl_alg_ops = {
-       .read = rate_ctrl_alg_read,
-       .write = rate_ctrl_alg_write,
-       .open = mac80211_open_file_generic,
-};
-
-/* statistics stuff */
-
 #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...)                        \
        DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value)
 
@@ -336,11 +296,9 @@ void debugfs_hw_add(struct ieee80211_local *local)
 
        DEBUGFS_ADD(channel);
        DEBUGFS_ADD(frequency);
-       DEBUGFS_ADD(radar_detect);
        DEBUGFS_ADD(antenna_sel_tx);
        DEBUGFS_ADD(antenna_sel_rx);
        DEBUGFS_ADD(bridge_packets);
-       DEBUGFS_ADD(key_tx_rx_threshold);
        DEBUGFS_ADD(rts_threshold);
        DEBUGFS_ADD(fragmentation_threshold);
        DEBUGFS_ADD(short_retry_limit);
@@ -348,8 +306,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
        DEBUGFS_ADD(total_ps_buffered);
        DEBUGFS_ADD(mode);
        DEBUGFS_ADD(wep_iv);
-       DEBUGFS_ADD(tx_power_reduction);
-       DEBUGFS_ADD_MODE(rate_ctrl_alg, 0644);
        DEBUGFS_ADD(modes);
 
        statsd = debugfs_create_dir("statistics", phyd);
@@ -402,11 +358,9 @@ void debugfs_hw_del(struct ieee80211_local *local)
 {
        DEBUGFS_DEL(channel);
        DEBUGFS_DEL(frequency);
-       DEBUGFS_DEL(radar_detect);
        DEBUGFS_DEL(antenna_sel_tx);
        DEBUGFS_DEL(antenna_sel_rx);
        DEBUGFS_DEL(bridge_packets);
-       DEBUGFS_DEL(key_tx_rx_threshold);
        DEBUGFS_DEL(rts_threshold);
        DEBUGFS_DEL(fragmentation_threshold);
        DEBUGFS_DEL(short_retry_limit);
@@ -414,8 +368,6 @@ void debugfs_hw_del(struct ieee80211_local *local)
        DEBUGFS_DEL(total_ps_buffered);
        DEBUGFS_DEL(mode);
        DEBUGFS_DEL(wep_iv);
-       DEBUGFS_DEL(tx_power_reduction);
-       DEBUGFS_DEL(rate_ctrl_alg);
        DEBUGFS_DEL(modes);
 
        DEBUGFS_STATS_DEL(transmitted_fragment_count);
index 7d56dc9..8e4a1bc 100644 (file)
 #include "debugfs.h"
 #include "debugfs_key.h"
 
-#define KEY_READ(name, buflen, format_string)                          \
+#define KEY_READ(name, prop, buflen, format_string)                    \
 static ssize_t key_##name##_read(struct file *file,                    \
                                 char __user *userbuf,                  \
                                 size_t count, loff_t *ppos)            \
 {                                                                      \
        char buf[buflen];                                               \
        struct ieee80211_key *key = file->private_data;                 \
-       int res = scnprintf(buf, buflen, format_string, key->name);     \
+       int res = scnprintf(buf, buflen, format_string, key->prop);     \
        return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
 }
-#define KEY_READ_D(name) KEY_READ(name, 20, "%d\n")
+#define KEY_READ_D(name) KEY_READ(name, name, 20, "%d\n")
+#define KEY_READ_X(name) KEY_READ(name, name, 20, "0x%x\n")
 
 #define KEY_OPS(name)                                                  \
 static const struct file_operations key_ ##name## _ops = {             \
@@ -36,11 +37,27 @@ static const struct file_operations key_ ##name## _ops = {          \
                 KEY_READ_##format(name)                                \
                 KEY_OPS(name)
 
-KEY_FILE(keylen, D);
-KEY_FILE(force_sw_encrypt, D);
-KEY_FILE(keyidx, D);
-KEY_FILE(hw_key_idx, D);
+#define KEY_CONF_READ(name, buflen, format_string)                     \
+       KEY_READ(conf_##name, conf.name, buflen, format_string)
+#define KEY_CONF_READ_D(name) KEY_CONF_READ(name, 20, "%d\n")
+
+#define KEY_CONF_OPS(name)                                             \
+static const struct file_operations key_ ##name## _ops = {             \
+       .read = key_conf_##name##_read,                                 \
+       .open = mac80211_open_file_generic,                             \
+}
+
+#define KEY_CONF_FILE(name, format)                                    \
+                KEY_CONF_READ_##format(name)                           \
+                KEY_CONF_OPS(name)
+
+KEY_CONF_FILE(keylen, D);
+KEY_CONF_FILE(keyidx, D);
+KEY_CONF_FILE(hw_key_idx, D);
+KEY_FILE(flags, X);
 KEY_FILE(tx_rx_count, D);
+KEY_READ(ifindex, sdata->dev->ifindex, 20, "%d\n");
+KEY_OPS(ifindex);
 
 static ssize_t key_algorithm_read(struct file *file,
                                  char __user *userbuf,
@@ -49,7 +66,7 @@ static ssize_t key_algorithm_read(struct file *file,
        char *alg;
        struct ieee80211_key *key = file->private_data;
 
-       switch (key->alg) {
+       switch (key->conf.alg) {
        case ALG_WEP:
                alg = "WEP\n";
                break;
@@ -74,17 +91,20 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
        int len;
        struct ieee80211_key *key = file->private_data;
 
-       switch (key->alg) {
+       switch (key->conf.alg) {
        case ALG_WEP:
                len = scnprintf(buf, sizeof(buf), "\n");
+               break;
        case ALG_TKIP:
                len = scnprintf(buf, sizeof(buf), "%08x %04x\n",
                                key->u.tkip.iv32,
                                key->u.tkip.iv16);
+               break;
        case ALG_CCMP:
                tpn = key->u.ccmp.tx_pn;
                len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
                                tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
+               break;
        default:
                return 0;
        }
@@ -100,9 +120,10 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
        int i, len;
        const u8 *rpn;
 
-       switch (key->alg) {
+       switch (key->conf.alg) {
        case ALG_WEP:
                len = scnprintf(buf, sizeof(buf), "\n");
+               break;
        case ALG_TKIP:
                for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
                        p += scnprintf(p, sizeof(buf)+buf-p,
@@ -110,6 +131,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
                                       key->u.tkip.iv32_rx[i],
                                       key->u.tkip.iv16_rx[i]);
                len = p - buf;
+               break;
        case ALG_CCMP:
                for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
                        rpn = key->u.ccmp.rx_pn[i];
@@ -119,6 +141,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
                                       rpn[3], rpn[4], rpn[5]);
                }
                len = p - buf;
+               break;
        default:
                return 0;
        }
@@ -133,7 +156,7 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf,
        char buf[20];
        int len;
 
-       if (key->alg != ALG_CCMP)
+       if (key->conf.alg != ALG_CCMP)
                return 0;
        len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
        return simple_read_from_buffer(userbuf, count, ppos, buf, len);
@@ -144,12 +167,12 @@ static ssize_t key_key_read(struct file *file, char __user *userbuf,
                            size_t count, loff_t *ppos)
 {
        struct ieee80211_key *key = file->private_data;
-       int i, res, bufsize = 2*key->keylen+2;
+       int i, res, bufsize = 2 * key->conf.keylen + 2;
        char *buf = kmalloc(bufsize, GFP_KERNEL);
        char *p = buf;
 
-       for (i = 0; i < key->keylen; i++)
-               p += scnprintf(p, bufsize+buf-p, "%02x", key->key[i]);
+       for (i = 0; i < key->conf.keylen; i++)
+               p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]);
        p += scnprintf(p, bufsize+buf-p, "\n");
        res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
        kfree(buf);
@@ -164,12 +187,14 @@ KEY_OPS(key);
 void ieee80211_debugfs_key_add(struct ieee80211_local *local,
                               struct ieee80211_key *key)
 {
+       static int keycount;
        char buf[20];
 
        if (!local->debugfs.keys)
                return;
 
-       sprintf(buf, "%d", key->keyidx);
+       sprintf(buf, "%d", keycount);
+       keycount++;
        key->debugfs.dir = debugfs_create_dir(buf,
                                        local->debugfs.keys);
 
@@ -177,7 +202,7 @@ void ieee80211_debugfs_key_add(struct ieee80211_local *local,
                return;
 
        DEBUGFS_ADD(keylen);
-       DEBUGFS_ADD(force_sw_encrypt);
+       DEBUGFS_ADD(flags);
        DEBUGFS_ADD(keyidx);
        DEBUGFS_ADD(hw_key_idx);
        DEBUGFS_ADD(tx_rx_count);
@@ -186,6 +211,7 @@ void ieee80211_debugfs_key_add(struct ieee80211_local *local,
        DEBUGFS_ADD(rx_spec);
        DEBUGFS_ADD(replays);
        DEBUGFS_ADD(key);
+       DEBUGFS_ADD(ifindex);
 };
 
 #define DEBUGFS_DEL(name) \
@@ -197,7 +223,7 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
                return;
 
        DEBUGFS_DEL(keylen);
-       DEBUGFS_DEL(force_sw_encrypt);
+       DEBUGFS_DEL(flags);
        DEBUGFS_DEL(keyidx);
        DEBUGFS_DEL(hw_key_idx);
        DEBUGFS_DEL(tx_rx_count);
@@ -206,6 +232,7 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
        DEBUGFS_DEL(rx_spec);
        DEBUGFS_DEL(replays);
        DEBUGFS_DEL(key);
+       DEBUGFS_DEL(ifindex);
 
        debugfs_remove(key->debugfs.stalink);
        key->debugfs.stalink = NULL;
@@ -219,7 +246,7 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
        if (!sdata->debugfsdir)
                return;
 
-       sprintf(buf, "../keys/%d", sdata->default_key->keyidx);
+       sprintf(buf, "../keys/%d", sdata->default_key->conf.keyidx);
        sdata->debugfs.default_key =
                debugfs_create_symlink("default_key", sdata->debugfsdir, buf);
 }
@@ -239,7 +266,7 @@ void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
        if (!key->debugfs.dir)
                return;
 
-       sprintf(buf, "../sta/" MAC_FMT, MAC_ARG(sta->addr));
+       sprintf(buf, "../../stations/" MAC_FMT, MAC_ARG(sta->addr));
        key->debugfs.stalink =
                debugfs_create_symlink("station", key->debugfs.dir, buf);
 }
index 52a32e4..2b5e761 100644 (file)
@@ -87,267 +87,6 @@ static const struct file_operations name##_ops = {                  \
                IEEE80211_IF_FMT_##format(name, field)                  \
                __IEEE80211_IF_FILE(name)
 
-#define DEBUGFS_QOS_FILE(name, f)                                      \
-static ssize_t qos_ ##name## _write(struct file *file,                 \
-                                   const char __user *userbuf,         \
-                                   size_t count, loff_t *ppos)         \
-{                                                                      \
-       struct ieee80211_sub_if_data *sdata = file->private_data;       \
-                                                                       \
-       f(sdata->dev, &sdata->u.sta, &sdata->u.sta.tspec);              \
-                                                                       \
-       return count;                                                   \
-}                                                                      \
-                                                                       \
-static const struct file_operations qos_ ##name## _ops = {             \
-       .write = qos_ ##name## _write,                                  \
-       .open = mac80211_open_file_generic,                             \
-};
-
-#define DEBUGFS_QOS_ADD(name)                                          \
-       sdata->debugfs.sta.qos.name = debugfs_create_file(#name, 0444, qosd,\
-               sdata, &qos_ ##name## _ops);
-
-#define DEBUGFS_QOS_DEL(name)                                          \
-       do {                                                            \
-               debugfs_remove(sdata->debugfs.sta.qos.name);            \
-               sdata->debugfs.sta.qos.name = NULL;                     \
-       } while (0)
-
-DEBUGFS_QOS_FILE(addts_11e, ieee80211_send_addts);
-DEBUGFS_QOS_FILE(addts_wmm, wmm_send_addts);
-DEBUGFS_QOS_FILE(delts_11e, ieee80211_send_delts);
-DEBUGFS_QOS_FILE(delts_wmm, wmm_send_delts);
-
-static ssize_t qos_if_dls_mac(const struct ieee80211_sub_if_data *sdata,
-                             char *buf, int buflen)
-{
-       return scnprintf(buf, buflen, MAC_FMT "\n",
-                        MAC_ARG(sdata->u.sta.dls_mac));
-}
-
-static ssize_t qos_dls_mac_read(struct file *file,
-                               char __user *userbuf,
-                               size_t count, loff_t *ppos)
-{
-       return ieee80211_if_read(file->private_data,
-                                userbuf, count, ppos,
-                                qos_if_dls_mac);
-}
-
-static ssize_t qos_dls_mac_write(struct file *file, const char __user *userbuf,
-                                size_t count, loff_t *ppos)
-{
-       struct ieee80211_sub_if_data *sdata = file->private_data;
-       char buf[20];
-       size_t size;
-       u8 m[ETH_ALEN];
-
-       size = min(sizeof(buf) - 1, count);
-       buf[size] = '\0';
-       if (copy_from_user(buf, userbuf, size))
-               return -EFAULT;
-
-       if (sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
-                  &((u8*)(m))[0], &((u8*)(m))[1], &((u8*)(m))[2],
-                  &((u8*)(m))[3], &((u8*)(m))[4], &((u8*)(m))[5]) != ETH_ALEN){
-               printk(KERN_ERR "%s: sscanf input error\n", sdata->dev->name);
-               return -EINVAL;
-       }
-       memcpy(sdata->u.sta.dls_mac, m, ETH_ALEN);
-       return count;
-}
-
-static const struct file_operations qos_dls_mac_ops = {
-       .read = qos_dls_mac_read,
-       .write = qos_dls_mac_write,
-       .open = mac80211_open_file_generic,
-};
-
-static ssize_t qos_if_dls_op(const struct ieee80211_sub_if_data *sdata,
-                            char *buf, int buflen)
-{
-       return scnprintf(buf, buflen,
-                        "DLS Operation: Setup = 1; Teardown = 2\n");
-}
-
-static ssize_t qos_dls_op_read(struct file *file, char __user *userbuf,
-                              size_t count, loff_t *ppos)
-{
-       return ieee80211_if_read(file->private_data,
-                                userbuf, count, ppos,
-                                qos_if_dls_op);
-}
-
-static ssize_t qos_dls_op_write(struct file *file, const char __user *userbuf,
-                                size_t count, loff_t *ppos)
-{
-       struct ieee80211_sub_if_data *sdata = file->private_data;
-       char buf[20];
-       size_t size;
-       unsigned int opt;
-
-       size = min(sizeof(buf) - 1, count);
-       buf[size] = '\0';
-       if (copy_from_user(buf, userbuf, size))
-               return -EFAULT;
-
-       if (sscanf(buf, "%u", &opt) != 1) {
-               printk(KERN_ERR "%s: sscanf input error\n", sdata->dev->name);
-               return -EINVAL;
-       }
-       switch (opt) {
-       case 1:
-               ieee80211_send_dls_req(sdata->dev, &sdata->u.sta,
-                                      sdata->u.sta.dls_mac, 0);
-               break;
-       case 2:
-               ieee80211_send_dls_teardown(sdata->dev, &sdata->u.sta,
-                                           sdata->u.sta.dls_mac,
-                                           WLAN_REASON_QSTA_NOT_USE);
-               break;
-       default:
-               printk(KERN_ERR "Unknown DLS Operation: %d\n", opt);
-               break;
-       }
-       return count;
-}
-
-static const struct file_operations qos_dls_op_ops = {
-       .read = qos_dls_op_read,
-       .write = qos_dls_op_write,
-       .open = mac80211_open_file_generic,
-};
-
-#define DEBUGFS_TSINFO_FILE(_name, min_val, max_val)                   \
-static ssize_t tsinfo_ ##_name## _read(struct file *file,              \
-                                      char __user *userbuf,            \
-                                      size_t count, loff_t *ppos)      \
-{                                                                      \
-       char buf[20];                                                   \
-       struct ieee80211_sub_if_data *sdata = file->private_data;       \
-       int res = scnprintf(buf, count, "%u\n",                         \
-               IEEE80211_TSINFO_## _name (sdata->u.sta.tspec.ts_info));\
-       return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
-}                                                                      \
-                                                                       \
-static ssize_t tsinfo_ ##_name## _write(struct file *file,             \
-                                       const char __user *userbuf,     \
-                                       size_t count, loff_t *ppos)     \
-{                                                                      \
-       char buf[20];                                                   \
-       size_t size;                                                    \
-       int val;                                                        \
-       struct ieee80211_sub_if_data *sdata = file->private_data;       \
-                                                                       \
-       size = min(sizeof(buf) - 1, count);                             \
-       buf[size] = '\0';                                               \
-       if (copy_from_user(buf, userbuf, size))                         \
-               return -EFAULT;                                         \
-                                                                       \
-       val = simple_strtoul(buf, NULL, 0);                             \
-       if ((val < min_val) || (val > max_val)) {                       \
-               printk(KERN_ERR "%s: set value (%u) out of range "      \
-                      "[%u, %u]\n",sdata->dev->name,val,min_val,max_val);\
-               return -EINVAL;                                         \
-       }                                                               \
-       IEEE80211_SET_TSINFO_ ##_name (sdata->u.sta.tspec.ts_info, val);\
-       return count;                                                   \
-}                                                                      \
-                                                                       \
-static const struct file_operations tsinfo_ ##_name## _ops = {         \
-       .read = tsinfo_ ##_name## _read,                                \
-       .write = tsinfo_ ##_name## _write,                              \
-       .open = mac80211_open_file_generic,                             \
-};
-
-#define DEBUGFS_TSINFO_ADD_TSID                                                \
-       sdata->debugfs.sta.tsinfo.tsid =                                \
-               debugfs_create_file("tsid", 0444, tsinfod,              \
-                                   sdata, &tsinfo_TSID_ops);
-
-#define DEBUGFS_TSINFO_ADD_DIR                                         \
-       sdata->debugfs.sta.tsinfo.direction =                           \
-               debugfs_create_file("direction", 0444, tsinfod,         \
-                                   sdata, &tsinfo_DIR_ops);
-
-#define DEBUGFS_TSINFO_ADD_UP                                          \
-       sdata->debugfs.sta.tsinfo.up =                                  \
-               debugfs_create_file("up", 0444, tsinfod,                \
-                                   sdata, &tsinfo_UP_ops);
-
-#define DEBUGFS_TSINFO_DEL(name)                                       \
-       do {                                                            \
-               debugfs_remove(sdata->debugfs.sta.tsinfo.name);         \
-               sdata->debugfs.sta.tsinfo.name = NULL;                  \
-       } while (0)
-
-DEBUGFS_TSINFO_FILE(TSID, 8, 15);
-DEBUGFS_TSINFO_FILE(DIR, 0, 3);
-DEBUGFS_TSINFO_FILE(UP, 0, 7);
-
-#define DEBUGFS_TSPEC_FILE(name, format_string, endian_f1, endian_f2)  \
-static ssize_t tspec_ ##name## _read(struct file *file,                        \
-                                     char __user *userbuf,             \
-                                     size_t count, loff_t *ppos)       \
-{                                                                      \
-       char buf[20];                                                   \
-       struct ieee80211_sub_if_data *sdata = file->private_data;       \
-       int res = scnprintf(buf, count, format_string "\n",             \
-                           endian_f1(sdata->u.sta.tspec.name));        \
-       return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
-}                                                                      \
-                                                                       \
-static ssize_t tspec_ ##name## _write(struct file *file,               \
-                                      const char __user *userbuf,      \
-                                      size_t count, loff_t *ppos)      \
-{                                                                      \
-       char buf[20];                                                   \
-       size_t size;                                                    \
-       struct ieee80211_sub_if_data *sdata = file->private_data;       \
-                                                                       \
-       size = min(sizeof(buf) - 1, count);                             \
-       buf[size] = '\0';                                               \
-       if (copy_from_user(buf, userbuf, size))                         \
-               return -EFAULT;                                         \
-                                                                       \
-       sdata->u.sta.tspec.name = endian_f2(simple_strtoul(buf, NULL, 0));\
-       return count;                                                   \
-}                                                                      \
-                                                                       \
-static const struct file_operations tspec_ ##name## _ops = {           \
-       .read = tspec_ ##name## _read,                                  \
-       .write = tspec_ ##name## _write,                                \
-       .open = mac80211_open_file_generic,                             \
-};
-
-#define DEBUGFS_TSPEC_ADD(name)                                                \
-       sdata->debugfs.sta.tspec.name = debugfs_create_file(#name,      \
-               0444, tspecd, sdata, &tspec_ ##name## _ops);
-
-#define DEBUGFS_TSPEC_DEL(name)                                                \
-       do {                                                            \
-               debugfs_remove(sdata->debugfs.sta.tspec.name);          \
-               sdata->debugfs.sta.tspec.name = NULL;                   \
-       } while (0)
-
-DEBUGFS_TSPEC_FILE(nominal_msdu_size, "%hu", le16_to_cpu, cpu_to_le16);
-DEBUGFS_TSPEC_FILE(max_msdu_size, "%hu", le16_to_cpu, cpu_to_le16);
-DEBUGFS_TSPEC_FILE(min_service_interval, "%u", le32_to_cpu, cpu_to_le32);
-DEBUGFS_TSPEC_FILE(max_service_interval, "%u", le32_to_cpu, cpu_to_le32);
-DEBUGFS_TSPEC_FILE(inactivity_interval, "%u", le32_to_cpu, cpu_to_le32);
-DEBUGFS_TSPEC_FILE(suspension_interval, "%u", le32_to_cpu, cpu_to_le32);
-DEBUGFS_TSPEC_FILE(service_start_time, "%u", le32_to_cpu, cpu_to_le32);
-DEBUGFS_TSPEC_FILE(min_data_rate, "%u", le32_to_cpu, cpu_to_le32);
-DEBUGFS_TSPEC_FILE(mean_data_rate, "%u", le32_to_cpu, cpu_to_le32);
-DEBUGFS_TSPEC_FILE(peak_data_rate, "%u", le32_to_cpu, cpu_to_le32);
-DEBUGFS_TSPEC_FILE(burst_size, "%u", le32_to_cpu, cpu_to_le32);
-DEBUGFS_TSPEC_FILE(delay_bound, "%u", le32_to_cpu, cpu_to_le32);
-DEBUGFS_TSPEC_FILE(min_phy_rate, "%u", le32_to_cpu, cpu_to_le32);
-DEBUGFS_TSPEC_FILE(surplus_band_allow, "%hu", le16_to_cpu, cpu_to_le16);
-DEBUGFS_TSPEC_FILE(medium_time, "%hu", le16_to_cpu, cpu_to_le16);
-
-
 /* common attributes */
 IEEE80211_IF_FILE(channel_use, channel_use, DEC);
 IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
@@ -373,13 +112,13 @@ static ssize_t ieee80211_if_fmt_flags(
        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 {
        return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n",
-                        sdata->u.sta.ssid_set ? "SSID\n" : "",
-                        sdata->u.sta.bssid_set ? "BSSID\n" : "",
-                        sdata->u.sta.prev_bssid_set ? "prev BSSID\n" : "",
-                        sdata->u.sta.authenticated ? "AUTH\n" : "",
-                        sdata->u.sta.associated ? "ASSOC\n" : "",
-                        sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "",
-                        sdata->u.sta.use_protection ? "CTS prot\n" : "");
+                sdata->u.sta.flags & IEEE80211_STA_SSID_SET ? "SSID\n" : "",
+                sdata->u.sta.flags & IEEE80211_STA_BSSID_SET ? "BSSID\n" : "",
+                sdata->u.sta.flags & IEEE80211_STA_PREV_BSSID_SET ? "prev BSSID\n" : "",
+                sdata->u.sta.flags & IEEE80211_STA_AUTHENTICATED ? "AUTH\n" : "",
+                sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED ? "ASSOC\n" : "",
+                sdata->u.sta.flags & IEEE80211_STA_PROBEREQ_POLL ? "PROBEREQ POLL\n" : "",
+                sdata->flags & IEEE80211_SDATA_USE_PROTECTION ? "CTS prot\n" : "");
 }
 __IEEE80211_IF_FILE(flags);
 
@@ -422,33 +161,12 @@ __IEEE80211_IF_FILE(beacon_tail_len);
 /* WDS attributes */
 IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
 
-/* VLAN attributes */
-IEEE80211_IF_FILE(vlan_id, u.vlan.id, DEC);
-
-/* MONITOR attributes */
-static ssize_t ieee80211_if_fmt_mode(
-       const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
-{
-       struct ieee80211_local *local = sdata->local;
-
-       return scnprintf(buf, buflen, "%s\n",
-                        ((local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) ||
-                         local->open_count == local->monitors) ?
-                        "hard" : "soft");
-}
-__IEEE80211_IF_FILE(mode);
-
-
 #define DEBUGFS_ADD(name, type)\
        sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\
                sdata->debugfsdir, sdata, &name##_ops);
 
 static void add_sta_files(struct ieee80211_sub_if_data *sdata)
 {
-       struct dentry *qosd;
-       struct dentry *tsinfod;
-       struct dentry *tspecd;
-
        DEBUGFS_ADD(channel_use, sta);
        DEBUGFS_ADD(drop_unencrypted, sta);
        DEBUGFS_ADD(eapol, sta);
@@ -467,42 +185,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
        DEBUGFS_ADD(auth_alg, sta);
        DEBUGFS_ADD(auth_transaction, sta);
        DEBUGFS_ADD(flags, sta);
-
-       qosd = debugfs_create_dir("qos", sdata->debugfsdir);
-       sdata->debugfs.sta.qos_dir = qosd;
-
-       DEBUGFS_QOS_ADD(addts_11e);
-       DEBUGFS_QOS_ADD(addts_wmm);
-       DEBUGFS_QOS_ADD(delts_11e);
-       DEBUGFS_QOS_ADD(delts_wmm);
-       DEBUGFS_QOS_ADD(dls_mac);
-       DEBUGFS_QOS_ADD(dls_op);
-
-       tsinfod = debugfs_create_dir("ts_info", qosd);
-       sdata->debugfs.sta.tsinfo_dir = tsinfod;
-
-       DEBUGFS_TSINFO_ADD_TSID;
-       DEBUGFS_TSINFO_ADD_DIR;
-       DEBUGFS_TSINFO_ADD_UP;
-
-       tspecd = debugfs_create_dir("tspec", qosd);
-       sdata->debugfs.sta.tspec_dir = tspecd;
-
-       DEBUGFS_TSPEC_ADD(nominal_msdu_size);
-       DEBUGFS_TSPEC_ADD(max_msdu_size);
-       DEBUGFS_TSPEC_ADD(min_service_interval);
-       DEBUGFS_TSPEC_ADD(max_service_interval);
-       DEBUGFS_TSPEC_ADD(inactivity_interval);
-       DEBUGFS_TSPEC_ADD(suspension_interval);
-       DEBUGFS_TSPEC_ADD(service_start_time);
-       DEBUGFS_TSPEC_ADD(min_data_rate);
-       DEBUGFS_TSPEC_ADD(mean_data_rate);
-       DEBUGFS_TSPEC_ADD(peak_data_rate);
-       DEBUGFS_TSPEC_ADD(burst_size);
-       DEBUGFS_TSPEC_ADD(delay_bound);
-       DEBUGFS_TSPEC_ADD(min_phy_rate);
-       DEBUGFS_TSPEC_ADD(surplus_band_allow);
-       DEBUGFS_TSPEC_ADD(medium_time);
 }
 
 static void add_ap_files(struct ieee80211_sub_if_data *sdata)
@@ -537,12 +219,10 @@ static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
        DEBUGFS_ADD(drop_unencrypted, vlan);
        DEBUGFS_ADD(eapol, vlan);
        DEBUGFS_ADD(ieee8021_x, vlan);
-       DEBUGFS_ADD(vlan_id, vlan);
 }
 
 static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
 {
-       DEBUGFS_ADD(mode, monitor);
 }
 
 static void add_files(struct ieee80211_sub_if_data *sdata)
@@ -598,40 +278,6 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata)
        DEBUGFS_DEL(auth_alg, sta);
        DEBUGFS_DEL(auth_transaction, sta);
        DEBUGFS_DEL(flags, sta);
-
-       DEBUGFS_TSINFO_DEL(tsid);
-       DEBUGFS_TSINFO_DEL(direction);
-       DEBUGFS_TSINFO_DEL(up);
-
-       DEBUGFS_TSPEC_DEL(nominal_msdu_size);
-       DEBUGFS_TSPEC_DEL(max_msdu_size);
-       DEBUGFS_TSPEC_DEL(min_service_interval);
-       DEBUGFS_TSPEC_DEL(max_service_interval);
-       DEBUGFS_TSPEC_DEL(inactivity_interval);
-       DEBUGFS_TSPEC_DEL(suspension_interval);
-       DEBUGFS_TSPEC_DEL(service_start_time);
-       DEBUGFS_TSPEC_DEL(min_data_rate);
-       DEBUGFS_TSPEC_DEL(mean_data_rate);
-       DEBUGFS_TSPEC_DEL(peak_data_rate);
-       DEBUGFS_TSPEC_DEL(burst_size);
-       DEBUGFS_TSPEC_DEL(delay_bound);
-       DEBUGFS_TSPEC_DEL(min_phy_rate);
-       DEBUGFS_TSPEC_DEL(surplus_band_allow);
-       DEBUGFS_TSPEC_DEL(medium_time);
-
-       DEBUGFS_QOS_DEL(addts_11e);
-       DEBUGFS_QOS_DEL(addts_wmm);
-       DEBUGFS_QOS_DEL(delts_11e);
-       DEBUGFS_QOS_DEL(delts_wmm);
-       DEBUGFS_QOS_DEL(dls_mac);
-       DEBUGFS_QOS_DEL(dls_op);
-
-       debugfs_remove(sdata->debugfs.sta.tspec_dir);
-       sdata->debugfs.sta.tspec_dir = NULL;
-       debugfs_remove(sdata->debugfs.sta.tsinfo_dir);
-       sdata->debugfs.sta.tsinfo_dir = NULL;
-       debugfs_remove(sdata->debugfs.sta.qos_dir);
-       sdata->debugfs.sta.qos_dir = NULL;
 }
 
 static void del_ap_files(struct ieee80211_sub_if_data *sdata)
@@ -666,12 +312,10 @@ static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
        DEBUGFS_DEL(drop_unencrypted, vlan);
        DEBUGFS_DEL(eapol, vlan);
        DEBUGFS_DEL(ieee8021_x, vlan);
-       DEBUGFS_DEL(vlan_id, vlan);
 }
 
 static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
 {
-       DEBUGFS_DEL(mode, monitor);
 }
 
 static void del_files(struct ieee80211_sub_if_data *sdata, int type)
@@ -734,9 +378,9 @@ static int netdev_notify(struct notifier_block * nb,
                         void *ndev)
 {
        struct net_device *dev = ndev;
-       /* TODO
+       struct dentry *dir;
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        char buf[10+IFNAMSIZ];
-       */
 
        if (state != NETDEV_CHANGENAME)
                return 0;
@@ -747,10 +391,11 @@ static int netdev_notify(struct notifier_block * nb,
        if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
                return 0;
 
-       /* TODO
        sprintf(buf, "netdev:%s", dev->name);
-       debugfs_rename(IEEE80211_DEV_TO_SUB_IF(dev)->debugfsdir, buf);
-       */
+       dir = sdata->debugfsdir;
+       if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
+               printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs "
+                      "dir to %s\n", buf);
 
        return 0;
 }
index 6cfe35a..4ea0ea7 100644 (file)
@@ -60,9 +60,7 @@ static const struct file_operations sta_ ##name## _ops = {            \
                STA_OPS(name)
 
 STA_FILE(aid, aid, D);
-STA_FILE(key_idx_compression, key_idx_compression, D);
 STA_FILE(dev, dev->name, S);
-STA_FILE(vlan_id, vlan_id, D);
 STA_FILE(rx_packets, rx_packets, LU);
 STA_FILE(tx_packets, tx_packets, LU);
 STA_FILE(rx_bytes, rx_bytes, LU);
@@ -87,7 +85,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
 {
        char buf[100];
        struct sta_info *sta = file->private_data;
-       int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s",
+       int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
                sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "",
                sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
                sta->flags & WLAN_STA_PS ? "PS\n" : "",
@@ -96,7 +94,6 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
                sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
                sta->flags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
                sta->flags & WLAN_STA_WME ? "WME\n" : "",
-               sta->flags & WLAN_STA_HT ? "HT\n" : "",
                sta->flags & WLAN_STA_WDS ? "WDS\n" : "");
        return simple_read_from_buffer(userbuf, count, ppos, buf, res);
 }
diff --git a/package/mac80211/src/mac80211/event.c b/package/mac80211/src/mac80211/event.c
new file mode 100644 (file)
index 0000000..68a526c
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * mac80211 - events
+ */
+
+#include <linux/netdevice.h>
+#include <net/iw_handler.h>
+#include "ieee80211_i.h"
+
+/*
+ * indicate a failed Michael MIC to userspace; the passed packet
+ * (in the variable hdr) must be long enough to extract the TKIP
+ * fields like TSC
+ */
+void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx,
+                                    struct ieee80211_hdr *hdr)
+{
+       union iwreq_data wrqu;
+       char *buf = kmalloc(128, GFP_ATOMIC);
+
+       if (buf) {
+               /* TODO: needed parameters: count, key type, TSC */
+               sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
+                       "keyid=%d %scast addr=" MAC_FMT ")",
+                       keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
+                       MAC_ARG(hdr->addr2));
+               memset(&wrqu, 0, sizeof(wrqu));
+               wrqu.data.length = strlen(buf);
+               wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
+               kfree(buf);
+       }
+
+       /*
+        * TODO: re-add support for sending MIC failure indication
+        * with all info via nl80211
+        */
+}
diff --git a/package/mac80211/src/mac80211/hostapd_ioctl.h b/package/mac80211/src/mac80211/hostapd_ioctl.h
deleted file mode 100644 (file)
index e35233c..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Host AP (software wireless LAN access point) user space daemon for
- * Host AP kernel driver
- * Copyright 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- * Copyright 2002-2004, Instant802 Networks, Inc.
- * Copyright 2005, Devicescape Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef HOSTAPD_IOCTL_H
-#define HOSTAPD_IOCTL_H
-
-#ifdef __KERNEL__
-#include <linux/types.h>
-#endif /* __KERNEL__ */
-
-#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
-#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
-#define PRISM2_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 3)
-
-/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes:
- * This table is no longer added to, the whole sub-ioctl
- * mess shall be deleted completely. */
-enum {
-       PRISM2_PARAM_BEACON_INT = 3,
-       PRISM2_PARAM_AP_BRIDGE_PACKETS = 10,
-       PRISM2_PARAM_DTIM_PERIOD = 11,
-       PRISM2_PARAM_AP_AUTH_ALGS = 15,
-       PRISM2_PARAM_HOST_ENCRYPT = 17,
-       PRISM2_PARAM_HOST_DECRYPT = 18,
-       PRISM2_PARAM_IEEE_802_1X = 23,
-       PRISM2_PARAM_ANTSEL_TX = 24,
-       PRISM2_PARAM_ANTSEL_RX = 25,
-
-       /* Instant802 additions */
-       PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES = 1001,
-       PRISM2_PARAM_DROP_UNENCRYPTED = 1002,
-       PRISM2_PARAM_PREAMBLE = 1003,
-       PRISM2_PARAM_SHORT_SLOT_TIME = 1006,
-       PRISM2_PARAM_NEXT_MODE = 1008,
-       PRISM2_PARAM_CLEAR_KEYS = 1009,
-       PRISM2_PARAM_RADIO_ENABLED = 1010,
-       PRISM2_PARAM_ANTENNA_MODE = 1013,
-       PRISM2_PARAM_PRIVACY_INVOKED = 1014,
-       PRISM2_PARAM_BROADCAST_SSID = 1015,
-       PRISM2_PARAM_STAT_TIME = 1016,
-       PRISM2_PARAM_STA_ANTENNA_SEL = 1017,
-       PRISM2_PARAM_FORCE_UNICAST_RATE = 1018,
-       PRISM2_PARAM_RATE_CTRL_NUM_UP = 1019,
-       PRISM2_PARAM_RATE_CTRL_NUM_DOWN = 1020,
-       PRISM2_PARAM_MAX_RATECTRL_RATE = 1021,
-       PRISM2_PARAM_TX_POWER_REDUCTION = 1022,
-       PRISM2_PARAM_EAPOL = 1023,
-       PRISM2_PARAM_KEY_TX_RX_THRESHOLD = 1024,
-       PRISM2_PARAM_KEY_INDEX = 1025,
-       PRISM2_PARAM_DEFAULT_WEP_ONLY = 1026,
-       PRISM2_PARAM_WIFI_WME_NOACK_TEST = 1033,
-       PRISM2_PARAM_ALLOW_BROADCAST_ALWAYS = 1034,
-       PRISM2_PARAM_SCAN_FLAGS = 1035,
-       PRISM2_PARAM_HW_MODES = 1036,
-       PRISM2_PARAM_CREATE_IBSS = 1037,
-       PRISM2_PARAM_WMM_ENABLED = 1038,
-       PRISM2_PARAM_MIXED_CELL = 1039,
-       PRISM2_PARAM_KEY_MGMT = 1040,
-       PRISM2_PARAM_RADAR_DETECT = 1043,
-       PRISM2_PARAM_SPECTRUM_MGMT = 1044,
-       PRISM2_PARAM_USER_SPACE_MLME = 1045,
-       PRISM2_PARAM_MGMT_IF = 1046,
-};
-
-/* PRISM2_IOCTL_HOSTAPD ioctl() cmd:
- * This table is no longer added to, the hostapd ioctl
- * shall be deleted completely. */
-enum {
-       PRISM2_HOSTAPD_FLUSH = 1,
-       PRISM2_HOSTAPD_ADD_STA = 2,
-       PRISM2_HOSTAPD_REMOVE_STA = 3,
-       PRISM2_HOSTAPD_GET_INFO_STA = 4,
-       PRISM2_SET_ENCRYPTION = 6,
-       PRISM2_GET_ENCRYPTION = 7,
-       PRISM2_HOSTAPD_SET_FLAGS_STA = 8,
-       PRISM2_HOSTAPD_MLME = 13,
-
-       /* Instant802 additions */
-       PRISM2_HOSTAPD_SET_BEACON = 1001,
-       PRISM2_HOSTAPD_GET_HW_FEATURES = 1002,
-       PRISM2_HOSTAPD_WPA_TRIGGER = 1004,
-       PRISM2_HOSTAPD_SET_RATE_SETS = 1005,
-       PRISM2_HOSTAPD_ADD_IF = 1006,
-       PRISM2_HOSTAPD_REMOVE_IF = 1007,
-       PRISM2_HOSTAPD_GET_DOT11COUNTERSTABLE = 1008,
-       PRISM2_HOSTAPD_GET_LOAD_STATS = 1009,
-       PRISM2_HOSTAPD_SET_STA_VLAN = 1010,
-       PRISM2_HOSTAPD_SET_GENERIC_INFO_ELEM = 1011,
-       PRISM2_HOSTAPD_SET_CHANNEL_FLAG = 1012,
-       PRISM2_HOSTAPD_SET_REGULATORY_DOMAIN = 1013,
-       PRISM2_HOSTAPD_SET_TX_QUEUE_PARAMS = 1014,
-       PRISM2_HOSTAPD_GET_TX_STATS = 1016,
-       PRISM2_HOSTAPD_UPDATE_IF = 1017,
-       PRISM2_HOSTAPD_SCAN_REQ = 1019,
-       PRISM2_STA_GET_STATE = 1020,
-       PRISM2_HOSTAPD_FLUSH_IFS = 1021,
-       PRISM2_HOSTAPD_SET_RADAR_PARAMS = 1023,
-       PRISM2_HOSTAPD_SET_QUIET_PARAMS = 1024,
-};
-
-#define PRISM2_HOSTAPD_MAX_BUF_SIZE 2048
-#define HOSTAP_CRYPT_ALG_NAME_LEN 16
-
-#ifndef ALIGNED
-#define ALIGNED __attribute__ ((aligned))
-#endif
-
-struct prism2_hostapd_param {
-       u32 cmd;
-       u8 sta_addr[ETH_ALEN];
-       u8 pad[2];
-       union {
-               struct {
-                       u16 aid;
-                       u16 capability;
-                       u8 supp_rates[32];
-                       u8 wds_flags;
-#define IEEE80211_STA_DYNAMIC_ENC BIT(0)
-                       u8 enc_flags;
-                       u16 listen_interval;
-               } add_sta;
-               struct {
-                       u32 inactive_msec;
-                       u32 rx_packets;
-                       u32 tx_packets;
-                       u32 rx_bytes;
-                       u32 tx_bytes;
-                       u32 current_tx_rate; /* in 100 kbps */
-                       u32 channel_use;
-                       u32 flags;
-                       u32 num_ps_buf_frames;
-                       u32 tx_retry_failed;
-                       u32 tx_retry_count;
-                       u32 last_rssi;
-                       u32 last_ack_rssi;
-               } get_info_sta;
-               struct {
-                       char alg[HOSTAP_CRYPT_ALG_NAME_LEN];
-                       u32 flags;
-                       u32 err;
-                       u8 idx;
-#define HOSTAP_SEQ_COUNTER_SIZE 8
-                       u8 seq_counter[HOSTAP_SEQ_COUNTER_SIZE];
-                       u16 key_len;
-                       u8 key[0] ALIGNED;
-               } crypt;
-               struct {
-                       u32 flags_and;
-                       u32 flags_or;
-               } set_flags_sta;
-               struct {
-                       u16 head_len;
-                       u16 tail_len;
-                       u8 data[0] ALIGNED; /* head_len + tail_len bytes */
-               } beacon;
-               struct {
-                       u16 num_modes;
-                       u16 flags;
-                       u8 data[0] ALIGNED; /* num_modes * feature data */
-               } hw_features;
-               struct {
-                       u8  now;
-                       s8  our_mode_only;
-                       s16 last_rx;
-                       u16 channel;
-                       s16 interval; /* seconds */
-                       s32 listen;   /* microseconds */
-               } scan;
-               struct {
-#define WPA_TRIGGER_FAIL_TX_MIC BIT(0)
-#define WPA_TRIGGER_FAIL_TX_ICV BIT(1)
-#define WPA_TRIGGER_FAIL_RX_MIC BIT(2)
-#define WPA_TRIGGER_FAIL_RX_ICV BIT(3)
-#define WPA_TRIGGER_TX_REPLAY BIT(4)
-#define WPA_TRIGGER_TX_REPLAY_FRAG BIT(5)
-#define WPA_TRIGGER_TX_SKIP_SEQ BIT(6)
-                       u32 trigger;
-               } wpa_trigger;
-               struct {
-                       u16 mode; /* MODE_* */
-                       u16 num_supported_rates;
-                       u16 num_basic_rates;
-                       u8 data[0] ALIGNED; /* num_supported_rates * u16 +
-                                            * num_basic_rates * u16 */
-               } set_rate_sets;
-               struct {
-                       u8 type; /* WDS, VLAN, etc */
-                       u8 name[IFNAMSIZ];
-                       u8 data[0] ALIGNED;
-               } if_info;
-               struct dot11_counters {
-                       u32 dot11TransmittedFragmentCount;
-                       u32 dot11MulticastTransmittedFrameCount;
-                       u32 dot11FailedCount;
-                       u32 dot11ReceivedFragmentCount;
-                       u32 dot11MulticastReceivedFrameCount;
-                       u32 dot11FCSErrorCount;
-                       u32 dot11TransmittedFrameCount;
-                       u32 dot11WEPUndecryptableCount;
-                       u32 dot11ACKFailureCount;
-                       u32 dot11RTSFailureCount;
-                       u32 dot11RTSSuccessCount;
-               } dot11CountersTable;
-               struct {
-#define LOAD_STATS_CLEAR BIT(1)
-                       u32 flags;
-                       u32 channel_use;
-               } get_load_stats;
-               struct {
-                       char vlan_name[IFNAMSIZ];
-                       int vlan_id;
-               } set_sta_vlan;
-               struct {
-                       u8 len;
-                       u8 data[0] ALIGNED;
-               } set_generic_info_elem;
-               struct {
-                       u16 mode; /* MODE_* */
-                       u16 chan;
-                       u32 flag;
-                       u8 power_level; /* regulatory limit in dBm */
-                       u8 antenna_max;
-               } set_channel_flag;
-               struct {
-                       u32 rd;
-               } set_regulatory_domain;
-               struct {
-                       u32 queue;
-                       s32 aifs;
-                       u32 cw_min;
-                       u32 cw_max;
-                       u32 burst_time; /* maximum burst time in 0.1 ms, i.e.,
-                                        * 10 = 1 ms */
-               } tx_queue_params;
-               struct ieee80211_tx_stats {
-                       struct {
-                               unsigned int len; /* num packets in queue */
-                               unsigned int limit; /* queue len (soft) limit
-                                                    */
-                               unsigned int count; /* total num frames sent */
-                       } data[4];
-               } get_tx_stats;
-               struct {
-                       u8 ssid_len;
-                       u8 ssid[0] ALIGNED;
-               } scan_req;
-               struct {
-                       u32 state;
-               } sta_get_state;
-               struct {
-#define MLME_STA_DEAUTH 0
-#define MLME_STA_DISASSOC 1
-                       u16 cmd;
-                       u16 reason_code;
-               } mlme;
-               struct {
-                       u8 radar_firpwr_threshold;
-                       u8 radar_rssi_threshold;
-                       u8 pulse_height_threshold;
-                       u8 pulse_rssi_threshold;
-                       u8 pulse_inband_threshold;
-               } radar;
-               struct {
-                       unsigned int period;
-                       unsigned int offset;
-                       unsigned int duration;
-               } quiet;
-               struct {
-                       u8 dummy[80]; /* Make sizeof() this struct large enough
-                                      * with some compiler versions. */
-               } dummy;
-       } u;
-};
-
-#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0)
-#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1)
-
-#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2
-#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3
-#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4
-#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5
-#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6
-#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7
-
-#define HOSTAP_HW_FLAG_NULLFUNC_OK BIT(0)
-
-enum {
-       IEEE80211_KEY_MGMT_NONE = 0,
-       IEEE80211_KEY_MGMT_IEEE8021X = 1,
-       IEEE80211_KEY_MGMT_WPA_PSK = 2,
-       IEEE80211_KEY_MGMT_WPA_EAP = 3,
-};
-
-
-/* Data structures used for get_hw_features ioctl */
-struct hostapd_ioctl_hw_modes_hdr {
-       int mode;
-       int num_channels;
-       int num_rates;
-};
-
-struct ieee80211_channel_data {
-       short chan; /* channel number (IEEE 802.11) */
-       short freq; /* frequency in MHz */
-       int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */
-};
-
-struct ieee80211_rate_data {
-       int rate; /* rate in 100 kbps */
-       int flags; /* IEEE80211_RATE_ flags */
-};
-
-
-/* ADD_IF, REMOVE_IF, and UPDATE_IF 'type' argument */
-enum {
-       HOSTAP_IF_WDS = 1, HOSTAP_IF_VLAN = 2, HOSTAP_IF_BSS = 3,
-       HOSTAP_IF_STA = 4
-};
-
-struct hostapd_if_wds {
-       u8 remote_addr[ETH_ALEN];
-};
-
-struct hostapd_if_vlan {
-       u8 id;
-};
-
-struct hostapd_if_bss {
-       u8 bssid[ETH_ALEN];
-};
-
-struct hostapd_if_sta {
-};
-
-#endif /* HOSTAPD_IOCTL_H */
index 5202c48..64fa720 100644 (file)
 #include <linux/if_arp.h>
 #include <linux/wireless.h>
 #include <linux/rtnetlink.h>
-#include <net/iw_handler.h>
-#include <linux/compiler.h>
 #include <linux/bitmap.h>
 #include <net/cfg80211.h>
 
-#include "ieee80211_common.h"
 #include "ieee80211_i.h"
 #include "ieee80211_rate.h"
 #include "wep.h"
-#include "wpa.h"
-#include "tkip.h"
 #include "wme.h"
 #include "aes_ccm.h"
 #include "ieee80211_led.h"
-#include "ieee80211_cfg.h"
+#include "cfg.h"
 #include "debugfs.h"
 #include "debugfs_netdev.h"
-#include "debugfs_key.h"
 
-/* privid for wiphys to determine whether they belong to us or not */
-void *mac80211_wiphy_privid = &mac80211_wiphy_privid;
-
-/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
-/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
-static const unsigned char rfc1042_header[] =
-       { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
-
-/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
-static const unsigned char bridge_tunnel_header[] =
-       { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
-
-/* No encapsulation header if EtherType < 0x600 (=length) */
-static const unsigned char eapol_header[] =
-       { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
-
-
-static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata,
-                                             struct ieee80211_hdr *hdr)
-{
-       /* Set the sequence number for this frame. */
-       hdr->seq_ctrl = cpu_to_le16(sdata->sequence);
+/*
+ * For seeing transmitted packets on monitor interfaces
+ * we have a radiotap header too.
+ */
+struct ieee80211_tx_status_rtap_hdr {
+       struct ieee80211_radiotap_header hdr;
+       __le16 tx_flags;
+       u8 data_retries;
+} __attribute__ ((packed));
 
-       /* Increase the sequence number. */
-       sdata->sequence = (sdata->sequence + 0x10) & IEEE80211_SCTL_SEQ;
-}
+/* common interface routines */
 
-struct ieee80211_key_conf *
-ieee80211_key_data2conf(struct ieee80211_local *local,
-                       const struct ieee80211_key *data)
+static int header_parse_80211(struct sk_buff *skb, unsigned char *haddr)
 {
-       struct ieee80211_key_conf *conf;
-
-       conf = kmalloc(sizeof(*conf) + data->keylen, GFP_ATOMIC);
-       if (!conf)
-               return NULL;
-
-       conf->hw_key_idx = data->hw_key_idx;
-       conf->alg = data->alg;
-       conf->keylen = data->keylen;
-       conf->flags = 0;
-       if (data->force_sw_encrypt)
-               conf->flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT;
-       conf->keyidx = data->keyidx;
-       if (data->default_tx_key)
-               conf->flags |= IEEE80211_KEY_DEFAULT_TX_KEY;
-       if (local->default_wep_only)
-               conf->flags |= IEEE80211_KEY_DEFAULT_WEP_ONLY;
-       memcpy(conf->key, data->key, data->keylen);
-
-       return conf;
+       memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
+       return ETH_ALEN;
 }
 
-struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
-                                         int idx, size_t key_len, gfp_t flags)
+/* must be called under mdev tx lock */
+static void ieee80211_configure_filter(struct ieee80211_local *local)
 {
-       struct ieee80211_key *key;
+       unsigned int changed_flags;
+       unsigned int new_flags = 0;
 
-       key = kzalloc(sizeof(struct ieee80211_key) + key_len, flags);
-       if (!key)
-               return NULL;
-       kref_init(&key->kref);
-       return key;
-}
+       if (atomic_read(&local->iff_promiscs))
+               new_flags |= FIF_PROMISC_IN_BSS;
 
-static void ieee80211_key_release(struct kref *kref)
-{
-       struct ieee80211_key *key;
+       if (atomic_read(&local->iff_allmultis))
+               new_flags |= FIF_ALLMULTI;
 
-       key = container_of(kref, struct ieee80211_key, kref);
-       if (key->alg == ALG_CCMP)
-               ieee80211_aes_key_free(key->u.ccmp.tfm);
-       ieee80211_debugfs_key_remove(key);
-       kfree(key);
-}
+       if (local->monitors)
+               new_flags |= FIF_CONTROL |
+                            FIF_OTHER_BSS |
+                            FIF_BCN_PRBRESP_PROMISC;
 
-void ieee80211_key_free(struct ieee80211_key *key)
-{
-       if (key)
-               kref_put(&key->kref, ieee80211_key_release);
-}
+       changed_flags = local->filter_flags ^ new_flags;
 
-static int rate_list_match(const int *rate_list, int rate)
-{
-       int i;
+       /* be a bit nasty */
+       new_flags |= (1<<31);
 
-       if (!rate_list)
-               return 0;
+       local->ops->configure_filter(local_to_hw(local),
+                                    changed_flags, &new_flags,
+                                    local->mdev->mc_count,
+                                    local->mdev->mc_list);
 
-       for (i = 0; rate_list[i] >= 0; i++)
-               if (rate_list[i] == rate)
-                       return 1;
+       WARN_ON(new_flags & (1<<31));
 
-       return 0;
+       local->filter_flags = new_flags & ~(1<<31);
 }
 
+/* master interface */
 
-void ieee80211_prepare_rates(struct ieee80211_local *local,
-                            struct ieee80211_hw_mode *mode)
+static int ieee80211_master_open(struct net_device *dev)
 {
-       int i;
-
-       for (i = 0; i < mode->num_rates; i++) {
-               struct ieee80211_rate *rate = &mode->rates[i];
-
-               rate->flags &= ~(IEEE80211_RATE_SUPPORTED |
-                                IEEE80211_RATE_BASIC);
-
-               if (local->supp_rates[mode->mode]) {
-                       if (!rate_list_match(local->supp_rates[mode->mode],
-                                            rate->rate))
-                               continue;
-               }
-
-               rate->flags |= IEEE80211_RATE_SUPPORTED;
-
-               /* Use configured basic rate set if it is available. If not,
-                * use defaults that are sane for most cases. */
-               if (local->basic_rates[mode->mode]) {
-                       if (rate_list_match(local->basic_rates[mode->mode],
-                                           rate->rate))
-                               rate->flags |= IEEE80211_RATE_BASIC;
-               } else switch (mode->mode) {
-               case MODE_IEEE80211A:
-                       if (rate->rate == 60 || rate->rate == 120 ||
-                           rate->rate == 240)
-                               rate->flags |= IEEE80211_RATE_BASIC;
-                       break;
-               case MODE_IEEE80211B:
-                       if (rate->rate == 10 || rate->rate == 20)
-                               rate->flags |= IEEE80211_RATE_BASIC;
-                       break;
-               case MODE_ATHEROS_TURBO:
-                       if (rate->rate == 120 || rate->rate == 240 ||
-                           rate->rate == 480)
-                               rate->flags |= IEEE80211_RATE_BASIC;
-                       break;
-               case MODE_IEEE80211G:
-                       if (rate->rate == 10 || rate->rate == 20 ||
-                           rate->rate == 55 || rate->rate == 110)
-                               rate->flags |= IEEE80211_RATE_BASIC;
-                       break;
-               }
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata;
+       int res = -EOPNOTSUPP;
 
-               /* Set ERP and MANDATORY flags based on phymode */
-               switch (mode->mode) {
-               case MODE_IEEE80211A:
-                       if (rate->rate == 60 || rate->rate == 120 ||
-                           rate->rate == 240)
-                               rate->flags |= IEEE80211_RATE_MANDATORY;
-                       break;
-               case MODE_IEEE80211B:
-                       if (rate->rate == 10)
-                               rate->flags |= IEEE80211_RATE_MANDATORY;
-                       break;
-               case MODE_ATHEROS_TURBO:
-                       break;
-               case MODE_IEEE80211G:
-                       if (rate->rate == 10 || rate->rate == 20 ||
-                           rate->rate == 55 || rate->rate == 110 ||
-                           rate->rate == 60 || rate->rate == 120 ||
-                           rate->rate == 240)
-                               rate->flags |= IEEE80211_RATE_MANDATORY;
+       /* we hold the RTNL here so can safely walk the list */
+       list_for_each_entry(sdata, &local->interfaces, list) {
+               if (sdata->dev != dev && netif_running(sdata->dev)) {
+                       res = 0;
                        break;
                }
-               if (ieee80211_is_erp_rate(mode->mode, rate->rate))
-                       rate->flags |= IEEE80211_RATE_ERP;
        }
+       return res;
 }
 
-
-static void ieee80211_key_threshold_notify(struct net_device *dev,
-                                          struct ieee80211_key *key,
-                                          struct sta_info *sta)
+static int ieee80211_master_stop(struct net_device *dev)
 {
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct sk_buff *skb;
-       struct ieee80211_msg_key_notification *msg;
-
-       /* if no one will get it anyway, don't even allocate it.
-        * unlikely because this is only relevant for APs
-        * where the device must be open... */
-       if (unlikely(!local->apdev))
-               return;
-
-       skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
-                           sizeof(struct ieee80211_msg_key_notification));
-       if (!skb)
-               return;
-
-       skb_reserve(skb, sizeof(struct ieee80211_frame_info));
-       msg = (struct ieee80211_msg_key_notification *)
-               skb_put(skb, sizeof(struct ieee80211_msg_key_notification));
-       msg->tx_rx_count = key->tx_rx_count;
-       memcpy(msg->ifname, dev->name, IFNAMSIZ);
-       if (sta)
-               memcpy(msg->addr, sta->addr, ETH_ALEN);
-       else
-               memset(msg->addr, 0xff, ETH_ALEN);
-
-       key->tx_rx_count = 0;
-
-       ieee80211_rx_mgmt(local, skb, NULL,
-                         ieee80211_msg_key_threshold_notification);
-}
-
-
-static u8 * ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len)
-{
-       u16 fc;
-
-       if (len < 24)
-               return NULL;
-
-       fc = le16_to_cpu(hdr->frame_control);
-
-       switch (fc & IEEE80211_FCTL_FTYPE) {
-       case IEEE80211_FTYPE_DATA:
-               switch (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
-               case IEEE80211_FCTL_TODS:
-                       return hdr->addr1;
-               case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
-                       return NULL;
-               case IEEE80211_FCTL_FROMDS:
-                       return hdr->addr2;
-               case 0:
-                       return hdr->addr3;
-               }
-               break;
-       case IEEE80211_FTYPE_MGMT:
-               return hdr->addr3;
-       case IEEE80211_FTYPE_CTL:
-               if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)
-                       return hdr->addr1;
-               else
-                       return NULL;
-       }
-
-       return NULL;
-}
-
-int ieee80211_get_hdrlen(u16 fc)
-{
-       int hdrlen = 24;
+       struct ieee80211_sub_if_data *sdata;
 
-       switch (fc & IEEE80211_FCTL_FTYPE) {
-       case IEEE80211_FTYPE_DATA:
-               if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
-                       hdrlen = 30; /* Addr4 */
-               /*
-                * The QoS Control field is two bytes and its presence is
-                * indicated by the IEEE80211_STYPE_QOS_DATA bit. Add 2 to
-                * hdrlen if that bit is set.
-                * This works by masking out the bit and shifting it to
-                * bit position 1 so the result has the value 0 or 2.
-                */
-               hdrlen += (fc & IEEE80211_STYPE_QOS_DATA)
-                               >> (ilog2(IEEE80211_STYPE_QOS_DATA)-1);
-               break;
-       case IEEE80211_FTYPE_CTL:
-               /*
-                * ACK and CTS are 10 bytes, all others 16. To see how
-                * to get this condition consider
-                *   subtype mask:   0b0000000011110000 (0x00F0)
-                *   ACK subtype:    0b0000000011010000 (0x00D0)
-                *   CTS subtype:    0b0000000011000000 (0x00C0)
-                *   bits that matter:         ^^^      (0x00E0)
-                *   value of those: 0b0000000011000000 (0x00C0)
-                */
-               if ((fc & 0xE0) == 0xC0)
-                       hdrlen = 10;
-               else
-                       hdrlen = 16;
-               break;
-       }
+       /* we hold the RTNL here so can safely walk the list */
+       list_for_each_entry(sdata, &local->interfaces, list)
+               if (sdata->dev != dev && netif_running(sdata->dev))
+                       dev_close(sdata->dev);
 
-       return hdrlen;
+       return 0;
 }
-EXPORT_SYMBOL(ieee80211_get_hdrlen);
 
-int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
+static void ieee80211_master_set_multicast_list(struct net_device *dev)
 {
-       const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) skb->data;
-       int hdrlen;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
-       if (unlikely(skb->len < 10))
-               return 0;
-       hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
-       if (unlikely(hdrlen > skb->len))
-               return 0;
-       return hdrlen;
+       ieee80211_configure_filter(local);
 }
-EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
-
-static int ieee80211_get_radiotap_len(struct sk_buff *skb)
-{
-       struct ieee80211_radiotap_header *hdr =
-               (struct ieee80211_radiotap_header *) skb->data;
 
-       return le16_to_cpu(hdr->it_len);
-}
+/* regular interfaces */
 
-#ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP
-static void ieee80211_dump_frame(const char *ifname, const char *title,
-                                const struct sk_buff *skb)
+static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
 {
-       const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-       u16 fc;
-       int hdrlen;
-
-       printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len);
-       if (skb->len < 4) {
-               printk("\n");
-               return;
+       /* FIX: what would be proper limits for MTU?
+        * This interface uses 802.3 frames. */
+       if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6) {
+               printk(KERN_WARNING "%s: invalid MTU %d\n",
+                      dev->name, new_mtu);
+               return -EINVAL;
        }
 
-       fc = le16_to_cpu(hdr->frame_control);
-       hdrlen = ieee80211_get_hdrlen(fc);
-       if (hdrlen > skb->len)
-               hdrlen = skb->len;
-       if (hdrlen >= 4)
-               printk(" FC=0x%04x DUR=0x%04x",
-                      fc, le16_to_cpu(hdr->duration_id));
-       if (hdrlen >= 10)
-               printk(" A1=" MAC_FMT, MAC_ARG(hdr->addr1));
-       if (hdrlen >= 16)
-               printk(" A2=" MAC_FMT, MAC_ARG(hdr->addr2));
-       if (hdrlen >= 24)
-               printk(" A3=" MAC_FMT, MAC_ARG(hdr->addr3));
-       if (hdrlen >= 30)
-               printk(" A4=" MAC_FMT, MAC_ARG(hdr->addr4));
-       printk("\n");
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+       printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+       dev->mtu = new_mtu;
+       return 0;
 }
-#else /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */
-static inline void ieee80211_dump_frame(const char *ifname, const char *title,
-                                       struct sk_buff *skb)
+
+static inline int identical_mac_addr_allowed(int type1, int type2)
 {
+       return (type1 == IEEE80211_IF_TYPE_MNTR ||
+               type2 == IEEE80211_IF_TYPE_MNTR ||
+               (type1 == IEEE80211_IF_TYPE_AP &&
+                type2 == IEEE80211_IF_TYPE_WDS) ||
+               (type1 == IEEE80211_IF_TYPE_WDS &&
+                (type2 == IEEE80211_IF_TYPE_WDS ||
+                 type2 == IEEE80211_IF_TYPE_AP)) ||
+               (type1 == IEEE80211_IF_TYPE_AP &&
+                type2 == IEEE80211_IF_TYPE_VLAN) ||
+               (type1 == IEEE80211_IF_TYPE_VLAN &&
+                (type2 == IEEE80211_IF_TYPE_AP ||
+                 type2 == IEEE80211_IF_TYPE_VLAN)));
 }
-#endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */
-
 
-static int ieee80211_is_eapol(const struct sk_buff *skb)
+static int ieee80211_open(struct net_device *dev)
 {
-       const struct ieee80211_hdr *hdr;
-       u16 fc;
-       int hdrlen;
-
-       if (unlikely(skb->len < 10))
-               return 0;
-
-       hdr = (const struct ieee80211_hdr *) skb->data;
-       fc = le16_to_cpu(hdr->frame_control);
-
-       if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
-               return 0;
-
-       hdrlen = ieee80211_get_hdrlen(fc);
+       struct ieee80211_sub_if_data *sdata, *nsdata;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_if_init_conf conf;
+       int res;
 
-       if (unlikely(skb->len >= hdrlen + sizeof(eapol_header) &&
-                    memcmp(skb->data + hdrlen, eapol_header,
-                           sizeof(eapol_header)) == 0))
-               return 1;
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       return 0;
-}
+       /* we hold the RTNL here so can safely walk the list */
+       list_for_each_entry(nsdata, &local->interfaces, list) {
+               struct net_device *ndev = nsdata->dev;
 
+               if (ndev != dev && ndev != local->mdev && netif_running(ndev) &&
+                   compare_ether_addr(dev->dev_addr, ndev->dev_addr) == 0) {
+                       /*
+                        * check whether it may have the same address
+                        */
+                       if (!identical_mac_addr_allowed(sdata->type,
+                                                       nsdata->type))
+                               return -ENOTUNIQ;
 
-static ieee80211_txrx_result
-ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx)
-{
-       struct rate_control_extra extra;
-
-       memset(&extra, 0, sizeof(extra));
-       extra.mode = tx->u.tx.mode;
-       extra.mgmt_data = tx->sdata &&
-               tx->sdata->type == IEEE80211_IF_TYPE_MGMT;
-       extra.ethertype = tx->ethertype;
-
-       tx->u.tx.rate = rate_control_get_rate(tx->local, tx->dev, tx->skb,
-                                             &extra);
-       if (unlikely(extra.probe != NULL)) {
-               tx->u.tx.control->flags |= IEEE80211_TXCTL_RATE_CTRL_PROBE;
-               tx->u.tx.probe_last_frag = 1;
-               tx->u.tx.control->alt_retry_rate = tx->u.tx.rate->val;
-               tx->u.tx.rate = extra.probe;
-       } else {
-               tx->u.tx.control->alt_retry_rate = -1;
-       }
-       if (!tx->u.tx.rate)
-               return TXRX_DROP;
-       if (tx->u.tx.mode->mode == MODE_IEEE80211G &&
-           tx->local->cts_protect_erp_frames && tx->fragmented &&
-           extra.nonerp) {
-               tx->u.tx.last_frag_rate = tx->u.tx.rate;
-               tx->u.tx.probe_last_frag = extra.probe ? 1 : 0;
-
-               tx->u.tx.rate = extra.nonerp;
-               tx->u.tx.control->rate = extra.nonerp;
-               tx->u.tx.control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
-       } else {
-               tx->u.tx.last_frag_rate = tx->u.tx.rate;
-               tx->u.tx.control->rate = tx->u.tx.rate;
+                       /*
+                        * can only add VLANs to enabled APs
+                        */
+                       if (sdata->type == IEEE80211_IF_TYPE_VLAN &&
+                           nsdata->type == IEEE80211_IF_TYPE_AP &&
+                           netif_running(nsdata->dev))
+                               sdata->u.vlan.ap = nsdata;
+               }
        }
-       tx->u.tx.control->tx_rate = tx->u.tx.rate->val;
-       if ((tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) &&
-           tx->local->short_preamble &&
-           (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {
-               tx->u.tx.short_preamble = 1;
-               tx->u.tx.control->tx_rate = tx->u.tx.rate->val2;
+
+       switch (sdata->type) {
+       case IEEE80211_IF_TYPE_WDS:
+               if (is_zero_ether_addr(sdata->u.wds.remote_addr))
+                       return -ENOLINK;
+               break;
+       case IEEE80211_IF_TYPE_VLAN:
+               if (!sdata->u.vlan.ap)
+                       return -ENOLINK;
+               break;
+       case IEEE80211_IF_TYPE_AP:
+       case IEEE80211_IF_TYPE_STA:
+       case IEEE80211_IF_TYPE_MNTR:
+       case IEEE80211_IF_TYPE_IBSS:
+               /* no special treatment */
+               break;
+       case IEEE80211_IF_TYPE_INVALID:
+               /* cannot happen */
+               WARN_ON(1);
+               break;
        }
 
-       return TXRX_CONTINUE;
-}
+       if (local->open_count == 0) {
+               res = 0;
+               if (local->ops->start)
+                       res = local->ops->start(local_to_hw(local));
+               if (res)
+                       return res;
+       }
 
+       switch (sdata->type) {
+       case IEEE80211_IF_TYPE_VLAN:
+               list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans);
+               /* no need to tell driver */
+               break;
+       case IEEE80211_IF_TYPE_MNTR:
+               /* must be before the call to ieee80211_configure_filter */
+               local->monitors++;
+               if (local->monitors == 1) {
+                       netif_tx_lock_bh(local->mdev);
+                       ieee80211_configure_filter(local);
+                       netif_tx_unlock_bh(local->mdev);
 
-static ieee80211_txrx_result
-ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
-{
-       if (tx->sta)
-               tx->u.tx.control->key_idx = tx->sta->key_idx_compression;
-       else
-               tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID;
-
-       if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
-               tx->key = NULL;
-       else if (tx->sta && tx->sta->key)
-               tx->key = tx->sta->key;
-       else if (tx->sdata->default_key)
-               tx->key = tx->sdata->default_key;
-       else if (tx->sdata->drop_unencrypted &&
-                !(tx->sdata->eapol && ieee80211_is_eapol(tx->skb))) {
-               I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
-               return TXRX_DROP;
-       } else
-               tx->key = NULL;
-
-       if (tx->key) {
-               tx->key->tx_rx_count++;
-               if (unlikely(tx->local->key_tx_rx_threshold &&
-                            tx->key->tx_rx_count >
-                            tx->local->key_tx_rx_threshold)) {
-                       ieee80211_key_threshold_notify(tx->dev, tx->key,
-                                                      tx->sta);
+                       local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
+                       ieee80211_hw_config(local);
                }
-       }
-
-       return TXRX_CONTINUE;
-}
+               break;
+       case IEEE80211_IF_TYPE_STA:
+       case IEEE80211_IF_TYPE_IBSS:
+               sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
+               /* fall through */
+       default:
+               conf.if_id = dev->ifindex;
+               conf.type = sdata->type;
+               conf.mac_addr = dev->dev_addr;
+               res = local->ops->add_interface(local_to_hw(local), &conf);
+               if (res && !local->open_count && local->ops->stop)
+                       local->ops->stop(local_to_hw(local));
+               if (res)
+                       return res;
 
+               ieee80211_if_config(dev);
+               ieee80211_reset_erp_info(dev);
+               ieee80211_enable_keys(sdata);
 
-static ieee80211_txrx_result
-ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
-{
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
-       size_t hdrlen, per_fragm, num_fragm, payload_len, left;
-       struct sk_buff **frags, *first, *frag;
-       int i;
-       u16 seq;
-       u8 *pos;
-       int frag_threshold = tx->local->fragmentation_threshold;
-
-       if (!tx->fragmented)
-               return TXRX_CONTINUE;
-
-       first = tx->skb;
-
-       hdrlen = ieee80211_get_hdrlen(tx->fc);
-       payload_len = first->len - hdrlen;
-       per_fragm = frag_threshold - hdrlen - FCS_LEN;
-       num_fragm = (payload_len + per_fragm - 1) / per_fragm;
-
-       frags = kzalloc(num_fragm * sizeof(struct sk_buff *), GFP_ATOMIC);
-       if (!frags)
-               goto fail;
-
-       hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
-       seq = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ;
-       pos = first->data + hdrlen + per_fragm;
-       left = payload_len - per_fragm;
-       for (i = 0; i < num_fragm - 1; i++) {
-               struct ieee80211_hdr *fhdr;
-               size_t copylen;
-
-               if (left <= 0)
-                       goto fail;
-
-               /* reserve enough extra head and tail room for possible
-                * encryption */
-               frag = frags[i] =
-                       dev_alloc_skb(tx->local->hw.extra_tx_headroom +
-                                     frag_threshold +
-                                     IEEE80211_ENCRYPT_HEADROOM +
-                                     IEEE80211_ENCRYPT_TAILROOM);
-               if (!frag)
-                       goto fail;
-               /* Make sure that all fragments use the same priority so
-                * that they end up using the same TX queue */
-               frag->priority = first->priority;
-               skb_reserve(frag, tx->local->hw.extra_tx_headroom +
-                       IEEE80211_ENCRYPT_HEADROOM);
-               fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen);
-               memcpy(fhdr, first->data, hdrlen);
-               if (i == num_fragm - 2)
-                       fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS);
-               fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG));
-               copylen = left > per_fragm ? per_fragm : left;
-               memcpy(skb_put(frag, copylen), pos, copylen);
-
-               pos += copylen;
-               left -= copylen;
+               if (sdata->type == IEEE80211_IF_TYPE_STA &&
+                   !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
+                       netif_carrier_off(dev);
+               else
+                       netif_carrier_on(dev);
        }
-       skb_trim(first, hdrlen + per_fragm);
-
-       tx->u.tx.num_extra_frag = num_fragm - 1;
-       tx->u.tx.extra_frag = frags;
 
-       return TXRX_CONTINUE;
-
- fail:
-       printk(KERN_DEBUG "%s: failed to fragment frame\n", tx->dev->name);
-       if (frags) {
-               for (i = 0; i < num_fragm - 1; i++)
-                       if (frags[i])
-                               dev_kfree_skb(frags[i]);
-               kfree(frags);
+       if (local->open_count == 0) {
+               res = dev_open(local->mdev);
+               WARN_ON(res);
+               tasklet_enable(&local->tx_pending_tasklet);
+               tasklet_enable(&local->tasklet);
        }
-       I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment);
-       return TXRX_DROP;
-}
-
 
-static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb)
-{
-       if (tx->key->force_sw_encrypt) {
-               if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
-                       return -1;
-       } else {
-               tx->u.tx.control->key_idx = tx->key->hw_key_idx;
-               if (tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) {
-                       if (ieee80211_wep_add_iv(tx->local, skb, tx->key) ==
-                           NULL)
-                               return -1;
-               }
-       }
-       return 0;
-}
+       local->open_count++;
 
+       netif_start_queue(dev);
 
-void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx)
-{
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
-
-       hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-       if (tx->u.tx.extra_frag) {
-               struct ieee80211_hdr *fhdr;
-               int i;
-               for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
-                       fhdr = (struct ieee80211_hdr *)
-                               tx->u.tx.extra_frag[i]->data;
-                       fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-               }
-       }
+       return 0;
 }
 
-
-static ieee80211_txrx_result
-ieee80211_tx_h_wep_encrypt(struct ieee80211_txrx_data *tx)
+static int ieee80211_stop(struct net_device *dev)
 {
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
-       u16 fc;
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_if_init_conf conf;
 
-       fc = le16_to_cpu(hdr->frame_control);
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       if (!tx->key || tx->key->alg != ALG_WEP ||
-           ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
-            ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
-             (fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)))
-               return TXRX_CONTINUE;
+       netif_stop_queue(dev);
 
-       tx->u.tx.control->iv_len = WEP_IV_LEN;
-       tx->u.tx.control->icv_len = WEP_ICV_LEN;
-       ieee80211_tx_set_iswep(tx);
+       dev_mc_unsync(local->mdev, dev);
 
-       if (wep_encrypt_skb(tx, tx->skb) < 0) {
-               I802_DEBUG_INC(tx->local->tx_handlers_drop_wep);
-               return TXRX_DROP;
-       }
+       /* down all dependent devices, that is VLANs */
+       if (sdata->type == IEEE80211_IF_TYPE_AP) {
+               struct ieee80211_sub_if_data *vlan, *tmp;
 
-       if (tx->u.tx.extra_frag) {
-               int i;
-               for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
-                       if (wep_encrypt_skb(tx, tx->u.tx.extra_frag[i]) < 0) {
-                               I802_DEBUG_INC(tx->local->
-                                              tx_handlers_drop_wep);
-                               return TXRX_DROP;
-                       }
-               }
+               list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
+                                        u.vlan.list)
+                       dev_close(vlan->dev);
+               WARN_ON(!list_empty(&sdata->u.ap.vlans));
        }
 
-       return TXRX_CONTINUE;
-}
-
-
-static int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
-                                   int rate, int erp, int short_preamble)
-{
-       int dur;
+       local->open_count--;
 
-       /* calculate duration (in microseconds, rounded up to next higher
-        * integer if it includes a fractional microsecond) to send frame of
-        * len bytes (does not include FCS) at the given rate. Duration will
-        * also include SIFS.
-        *
-        * rate is in 100 kbps, so divident is multiplied by 10 in the
-        * DIV_ROUND_UP() operations.
-        */
+       switch (sdata->type) {
+       case IEEE80211_IF_TYPE_VLAN:
+               list_del(&sdata->u.vlan.list);
+               sdata->u.vlan.ap = NULL;
+               /* no need to tell driver */
+               break;
+       case IEEE80211_IF_TYPE_MNTR:
+               local->monitors--;
+               if (local->monitors == 0) {
+                       netif_tx_lock_bh(local->mdev);
+                       ieee80211_configure_filter(local);
+                       netif_tx_unlock_bh(local->mdev);
 
-       if (local->hw.conf.phymode == MODE_IEEE80211A || erp ||
-           local->hw.conf.phymode == MODE_ATHEROS_TURBO) {
-               /*
-                * OFDM:
-                *
-                * N_DBPS = DATARATE x 4
-                * N_SYM = Ceiling((16+8xLENGTH+6) / N_DBPS)
-                *      (16 = SIGNAL time, 6 = tail bits)
-                * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext
-                *
-                * T_SYM = 4 usec
-                * 802.11a - 17.5.2: aSIFSTime = 16 usec
-                * 802.11g - 19.8.4: aSIFSTime = 10 usec +
-                *      signal ext = 6 usec
-                */
-               /* FIX: Atheros Turbo may have different (shorter) duration? */
-               dur = 16; /* SIFS + signal ext */
-               dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */
-               dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */
-               dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10,
-                                       4 * rate); /* T_SYM x N_SYM */
-       } else {
+                       local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
+                       ieee80211_hw_config(local);
+               }
+               break;
+       case IEEE80211_IF_TYPE_STA:
+       case IEEE80211_IF_TYPE_IBSS:
+               sdata->u.sta.state = IEEE80211_DISABLED;
+               del_timer_sync(&sdata->u.sta.timer);
                /*
-                * 802.11b or 802.11g with 802.11b compatibility:
-                * 18.3.4: TXTIME = PreambleLength + PLCPHeaderTime +
-                * Ceiling(((LENGTH+PBCC)x8)/DATARATE). PBCC=0.
-                *
-                * 802.11 (DS): 15.3.3, 802.11b: 18.3.4
-                * aSIFSTime = 10 usec
-                * aPreambleLength = 144 usec or 72 usec with short preamble
-                * aPLCPHeaderLength = 48 usec or 24 usec with short preamble
+                * When we get here, the interface is marked down.
+                * Call synchronize_rcu() to wait for the RX path
+                * should it be using the interface and enqueuing
+                * frames at this very time on another CPU.
                 */
-               dur = 10; /* aSIFSTime = 10 usec */
-               dur += short_preamble ? (72 + 24) : (144 + 48);
+               synchronize_rcu();
+               skb_queue_purge(&sdata->u.sta.skb_queue);
 
-               dur += DIV_ROUND_UP(8 * (len + 4) * 10, rate);
+               if (!local->ops->hw_scan &&
+                   local->scan_dev == sdata->dev) {
+                       local->sta_scanning = 0;
+                       cancel_delayed_work(&local->scan_work);
+               }
+               flush_workqueue(local->hw.workqueue);
+               /* fall through */
+       default:
+               conf.if_id = dev->ifindex;
+               conf.type = sdata->type;
+               conf.mac_addr = dev->dev_addr;
+               /* disable all keys for as long as this netdev is down */
+               ieee80211_disable_keys(sdata);
+               local->ops->remove_interface(local_to_hw(local), &conf);
        }
 
-       return dur;
-}
-
-
-/* Exported duration function for driver use */
-__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
-                                       size_t frame_len, int rate)
-{
-       struct ieee80211_local *local = hw_to_local(hw);
-       u16 dur;
-       int erp;
-
-       erp = ieee80211_is_erp_rate(hw->conf.phymode, rate);
-       dur = ieee80211_frame_duration(local, frame_len, rate,
-                                      erp, local->short_preamble);
-
-       return cpu_to_le16(dur);
-}
-EXPORT_SYMBOL(ieee80211_generic_frame_duration);
-
+       if (local->open_count == 0) {
+               if (netif_running(local->mdev))
+                       dev_close(local->mdev);
 
-static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
-                             int next_frag_len)
-{
-       int rate, mrate, erp, dur, i;
-       struct ieee80211_rate *txrate = tx->u.tx.rate;
-       struct ieee80211_local *local = tx->local;
-       struct ieee80211_hw_mode *mode = tx->u.tx.mode;
+               if (local->ops->stop)
+                       local->ops->stop(local_to_hw(local));
 
-       erp = txrate->flags & IEEE80211_RATE_ERP;
-
-       /*
-        * data and mgmt (except PS Poll):
-        * - during CFP: 32768
-        * - during contention period:
-        *   if addr1 is group address: 0
-        *   if more fragments = 0 and addr1 is individual address: time to
-        *      transmit one ACK plus SIFS
-        *   if more fragments = 1 and addr1 is individual address: time to
-        *      transmit next fragment plus 2 x ACK plus 3 x SIFS
-        *
-        * IEEE 802.11, 9.6:
-        * - control response frame (CTS or ACK) shall be transmitted using the
-        *   same rate as the immediately previous frame in the frame exchange
-        *   sequence, if this rate belongs to the PHY mandatory rates, or else
-        *   at the highest possible rate belonging to the PHY rates in the
-        *   BSSBasicRateSet
-        */
-
-       if ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) {
-               /* TODO: These control frames are not currently sent by
-                * 80211.o, but should they be implemented, this function
-                * needs to be updated to support duration field calculation.
-                *
-                * RTS: time needed to transmit pending data/mgmt frame plus
-                *    one CTS frame plus one ACK frame plus 3 x SIFS
-                * CTS: duration of immediately previous RTS minus time
-                *    required to transmit CTS and its SIFS
-                * ACK: 0 if immediately previous directed data/mgmt had
-                *    more=0, with more=1 duration in ACK frame is duration
-                *    from previous frame minus time needed to transmit ACK
-                *    and its SIFS
-                * PS Poll: BIT(15) | BIT(14) | aid
-                */
-               return 0;
-       }
-
-       /* data/mgmt */
-       if (0 /* FIX: data/mgmt during CFP */)
-               return 32768;
-
-       if (group_addr) /* Group address as the destination - no ACK */
-               return 0;
-
-       /* Individual destination address:
-        * IEEE 802.11, Ch. 9.6 (after IEEE 802.11g changes)
-        * CTS and ACK frames shall be transmitted using the highest rate in
-        * basic rate set that is less than or equal to the rate of the
-        * immediately previous frame and that is using the same modulation
-        * (CCK or OFDM). If no basic rate set matches with these requirements,
-        * the highest mandatory rate of the PHY that is less than or equal to
-        * the rate of the previous frame is used.
-        * Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps
-        */
-       rate = -1;
-       mrate = 10; /* use 1 Mbps if everything fails */
-       for (i = 0; i < mode->num_rates; i++) {
-               struct ieee80211_rate *r = &mode->rates[i];
-               if (r->rate > txrate->rate)
-                       break;
-
-               if (IEEE80211_RATE_MODULATION(txrate->flags) !=
-                   IEEE80211_RATE_MODULATION(r->flags))
-                       continue;
-
-               if (r->flags & IEEE80211_RATE_BASIC)
-                       rate = r->rate;
-               else if (r->flags & IEEE80211_RATE_MANDATORY)
-                       mrate = r->rate;
-       }
-       if (rate == -1) {
-               /* No matching basic rate found; use highest suitable mandatory
-                * PHY rate */
-               rate = mrate;
-       }
-
-       /* Time needed to transmit ACK
-        * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up
-        * to closest integer */
-
-       dur = ieee80211_frame_duration(local, 10, rate, erp,
-                                      local->short_preamble);
-
-       if (next_frag_len) {
-               /* Frame is fragmented: duration increases with time needed to
-                * transmit next fragment plus ACK and 2 x SIFS. */
-               dur *= 2; /* ACK + SIFS */
-               /* next fragment */
-               dur += ieee80211_frame_duration(local, next_frag_len,
-                                               txrate->rate, erp,
-                                               local->short_preamble);
-       }
-
-       return dur;
-}
-
-
-static ieee80211_txrx_result
-ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
-{
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
-       u16 dur;
-       struct ieee80211_tx_control *control = tx->u.tx.control;
-       struct ieee80211_hw_mode *mode = tx->u.tx.mode;
-
-       if (!is_multicast_ether_addr(hdr->addr1)) {
-               if (tx->skb->len + FCS_LEN > tx->local->rts_threshold &&
-                   tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD) {
-                       control->flags |= IEEE80211_TXCTL_USE_RTS_CTS;
-                       control->retry_limit =
-                               tx->local->long_retry_limit;
-               } else {
-                       control->retry_limit =
-                               tx->local->short_retry_limit;
-               }
-       } else {
-               control->retry_limit = 1;
-       }
-
-       if (tx->fragmented) {
-               /* Do not use multiple retry rates when sending fragmented
-                * frames.
-                * TODO: The last fragment could still use multiple retry
-                * rates. */
-               control->alt_retry_rate = -1;
-       }
-
-       /* Use CTS protection for unicast frames sent using extended rates if
-        * there are associated non-ERP stations and RTS/CTS is not configured
-        * for the frame. */
-       if (mode->mode == MODE_IEEE80211G &&
-           (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) &&
-           tx->u.tx.unicast &&
-           tx->local->cts_protect_erp_frames &&
-           !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
-               control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;
-
-       /* Setup duration field for the first fragment of the frame. Duration
-        * for remaining fragments will be updated when they are being sent
-        * to low-level driver in ieee80211_tx(). */
-       dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1),
-                                tx->fragmented ? tx->u.tx.extra_frag[0]->len :
-                                0);
-       hdr->duration_id = cpu_to_le16(dur);
-
-       if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
-           (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
-               struct ieee80211_rate *rate;
-
-               /* Do not use multiple retry rates when using RTS/CTS */
-               control->alt_retry_rate = -1;
-
-               /* Use min(data rate, max base rate) as CTS/RTS rate */
-               rate = tx->u.tx.rate;
-               while (rate > mode->rates &&
-                      !(rate->flags & IEEE80211_RATE_BASIC))
-                       rate--;
-
-               control->rts_cts_rate = rate->val;
-               control->rts_rate = rate;
-       }
-
-       if (tx->sta) {
-               tx->sta->tx_packets++;
-               tx->sta->tx_fragments++;
-               tx->sta->tx_bytes += tx->skb->len;
-               if (tx->u.tx.extra_frag) {
-                       int i;
-                       tx->sta->tx_fragments += tx->u.tx.num_extra_frag;
-                       for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
-                               tx->sta->tx_bytes +=
-                                       tx->u.tx.extra_frag[i]->len;
-                       }
-               }
-       }
-
-       return TXRX_CONTINUE;
-}
-
-
-static ieee80211_txrx_result
-ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
-{
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-       struct sk_buff *skb = tx->skb;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-       u32 sta_flags;
-
-       if (unlikely(tx->local->sta_scanning != 0) &&
-           ((tx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
-            (tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ))
-               return TXRX_DROP;
-
-       if (tx->u.tx.ps_buffered)
-               return TXRX_CONTINUE;
-
-       sta_flags = tx->sta ? tx->sta->flags : 0;
-
-       if (likely(tx->u.tx.unicast)) {
-               if (unlikely(!(sta_flags & WLAN_STA_ASSOC) &&
-                            tx->sdata->type != IEEE80211_IF_TYPE_IBSS &&
-                            (tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-                       printk(KERN_DEBUG "%s: dropped data frame to not "
-                              "associated station " MAC_FMT "\n",
-                              tx->dev->name, MAC_ARG(hdr->addr1));
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-                       I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
-                       return TXRX_DROP;
-               }
-       } else {
-               if (unlikely((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
-                            tx->local->num_sta == 0 &&
-                            !tx->local->allow_broadcast_always &&
-                            tx->sdata->type != IEEE80211_IF_TYPE_IBSS)) {
-                       /*
-                        * No associated STAs - no need to send multicast
-                        * frames.
-                        */
-                       return TXRX_DROP;
-               }
-               return TXRX_CONTINUE;
-       }
-
-       if (unlikely(!tx->u.tx.mgmt_interface && tx->sdata->ieee802_1x &&
-                    !(sta_flags & WLAN_STA_AUTHORIZED))) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-               printk(KERN_DEBUG "%s: dropped frame to " MAC_FMT
-                      " (unauthorized port)\n", tx->dev->name,
-                      MAC_ARG(hdr->addr1));
-#endif
-               I802_DEBUG_INC(tx->local->tx_handlers_drop_unauth_port);
-               return TXRX_DROP;
-       }
-
-       return TXRX_CONTINUE;
-}
-
-static ieee80211_txrx_result
-ieee80211_tx_h_sequence(struct ieee80211_txrx_data *tx)
-{
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
-
-       if (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)) >= 24)
-               ieee80211_include_sequence(tx->sdata, hdr);
-
-       return TXRX_CONTINUE;
-}
-
-/* This function is called whenever the AP is about to exceed the maximum limit
- * of buffered frames for power saving STAs. This situation should not really
- * happen often during normal operation, so dropping the oldest buffered packet
- * from each queue should be OK to make some room for new frames. */
-static void purge_old_ps_buffers(struct ieee80211_local *local)
-{
-       int total = 0, purged = 0;
-       struct sk_buff *skb;
-       struct ieee80211_sub_if_data *sdata;
-       struct sta_info *sta;
-
-       read_lock(&local->sub_if_lock);
-       list_for_each_entry(sdata, &local->sub_if_list, list) {
-               struct ieee80211_if_ap *ap;
-               if (sdata->dev == local->mdev ||
-                   sdata->type != IEEE80211_IF_TYPE_AP)
-                       continue;
-               ap = &sdata->u.ap;
-               skb = skb_dequeue(&ap->ps_bc_buf);
-               if (skb) {
-                       purged++;
-                       dev_kfree_skb(skb);
-               }
-               total += skb_queue_len(&ap->ps_bc_buf);
-       }
-       read_unlock(&local->sub_if_lock);
-
-       spin_lock_bh(&local->sta_lock);
-       list_for_each_entry(sta, &local->sta_list, list) {
-               skb = skb_dequeue(&sta->ps_tx_buf);
-               if (skb) {
-                       purged++;
-                       dev_kfree_skb(skb);
-               }
-               total += skb_queue_len(&sta->ps_tx_buf);
-       }
-       spin_unlock_bh(&local->sta_lock);
-
-       local->total_ps_buffered = total;
-       printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n",
-              local->mdev->name, purged);
-}
-
-
-static inline ieee80211_txrx_result
-ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
-{
-       /* broadcast/multicast frame */
-       /* If any of the associated stations is in power save mode,
-        * the frame is buffered to be sent after DTIM beacon frame */
-       if ((tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) &&
-           tx->sdata->type != IEEE80211_IF_TYPE_WDS &&
-           tx->sdata->bss && atomic_read(&tx->sdata->bss->num_sta_ps) &&
-           !(tx->fc & IEEE80211_FCTL_ORDER)) {
-               if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
-                       purge_old_ps_buffers(tx->local);
-               if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >=
-                   AP_MAX_BC_BUFFER) {
-                       if (net_ratelimit()) {
-                               printk(KERN_DEBUG "%s: BC TX buffer full - "
-                                      "dropping the oldest frame\n",
-                                      tx->dev->name);
-                       }
-                       dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf));
-               } else
-                       tx->local->total_ps_buffered++;
-               skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
-               return TXRX_QUEUED;
-       }
-
-       return TXRX_CONTINUE;
-}
-
-
-static inline ieee80211_txrx_result
-ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
-{
-       struct sta_info *sta = tx->sta;
-
-       if (unlikely(!sta ||
-                    ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
-                     (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)))
-               return TXRX_CONTINUE;
-
-       if (unlikely((sta->flags & WLAN_STA_PS) && !sta->pspoll)) {
-               struct ieee80211_tx_packet_data *pkt_data;
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-               printk(KERN_DEBUG "STA " MAC_FMT " aid %d: PS buffer (entries "
-                      "before %d)\n",
-                      MAC_ARG(sta->addr), sta->aid,
-                      skb_queue_len(&sta->ps_tx_buf));
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
-               sta->flags |= WLAN_STA_TIM;
-               if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
-                       purge_old_ps_buffers(tx->local);
-               if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) {
-                       struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf);
-                       if (net_ratelimit()) {
-                               printk(KERN_DEBUG "%s: STA " MAC_FMT " TX "
-                                      "buffer full - dropping oldest frame\n",
-                                      tx->dev->name, MAC_ARG(sta->addr));
-                       }
-                       dev_kfree_skb(old);
-               } else
-                       tx->local->total_ps_buffered++;
-               /* Queue frame to be sent after STA sends an PS Poll frame */
-               if (skb_queue_empty(&sta->ps_tx_buf)) {
-                       if (tx->local->ops->set_tim)
-                               tx->local->ops->set_tim(local_to_hw(tx->local),
-                                                      sta->aid, 1);
-                       if (tx->sdata->bss)
-                               bss_tim_set(tx->local, tx->sdata->bss, sta->aid);
-               }
-               pkt_data = (struct ieee80211_tx_packet_data *)tx->skb->cb;
-               pkt_data->jiffies = jiffies;
-               skb_queue_tail(&sta->ps_tx_buf, tx->skb);
-               return TXRX_QUEUED;
-       }
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-       else if (unlikely(sta->flags & WLAN_STA_PS)) {
-               printk(KERN_DEBUG "%s: STA " MAC_FMT " in PS mode, but pspoll "
-                      "set -> send frame\n", tx->dev->name,
-                      MAC_ARG(sta->addr));
-       }
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
-       sta->pspoll = 0;
-
-       return TXRX_CONTINUE;
-}
-
-
-static ieee80211_txrx_result
-ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
-{
-       if (unlikely(tx->u.tx.ps_buffered))
-               return TXRX_CONTINUE;
-
-       if (tx->u.tx.unicast)
-               return ieee80211_tx_h_unicast_ps_buf(tx);
-       else
-               return ieee80211_tx_h_multicast_ps_buf(tx);
-}
-
-
-static void inline
-__ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
-                      struct sk_buff *skb,
-                      struct net_device *dev,
-                      struct ieee80211_tx_control *control)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-       int hdrlen;
-
-       memset(tx, 0, sizeof(*tx));
-       tx->skb = skb;
-       tx->dev = dev; /* use original interface */
-       tx->local = local;
-       tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       tx->sta = sta_info_get(local, hdr->addr1);
-       tx->fc = le16_to_cpu(hdr->frame_control);
-       control->power_level = local->hw.conf.power_level;
-       tx->u.tx.control = control;
-       tx->u.tx.unicast = !is_multicast_ether_addr(hdr->addr1);
-       if (is_multicast_ether_addr(hdr->addr1))
-               control->flags |= IEEE80211_TXCTL_NO_ACK;
-       else
-               control->flags &= ~IEEE80211_TXCTL_NO_ACK;
-       tx->fragmented = local->fragmentation_threshold <
-               IEEE80211_MAX_FRAG_THRESHOLD && tx->u.tx.unicast &&
-               skb->len + FCS_LEN > local->fragmentation_threshold &&
-               (!local->ops->set_frag_threshold);
-       if (!tx->sta)
-               control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
-       else if (tx->sta->clear_dst_mask) {
-               control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
-               tx->sta->clear_dst_mask = 0;
-       }
-       control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
-       if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta)
-               control->antenna_sel_tx = tx->sta->antenna_sel_tx;
-       hdrlen = ieee80211_get_hdrlen(tx->fc);
-       if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) {
-               u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)];
-               tx->ethertype = (pos[0] << 8) | pos[1];
-       }
-       control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT;
-
-}
-
-static int inline is_ieee80211_device(struct net_device *dev,
-                                     struct net_device *master)
-{
-       return (wdev_priv(dev->ieee80211_ptr) ==
-               wdev_priv(master->ieee80211_ptr));
-}
-
-/* Device in tx->dev has a reference added; use dev_put(tx->dev) when
- * finished with it. */
-static int inline ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
-                                      struct sk_buff *skb,
-                                      struct net_device *mdev,
-                                      struct ieee80211_tx_control *control)
-{
-       struct ieee80211_tx_packet_data *pkt_data;
-       struct net_device *dev;
-
-       pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
-       dev = dev_get_by_index(pkt_data->ifindex);
-       if (unlikely(dev && !is_ieee80211_device(dev, mdev))) {
-               dev_put(dev);
-               dev = NULL;
-       }
-       if (unlikely(!dev))
-               return -ENODEV;
-       __ieee80211_tx_prepare(tx, skb, dev, control);
-       return 0;
-}
-
-static inline int __ieee80211_queue_stopped(const struct ieee80211_local *local,
-                                           int queue)
-{
-       return test_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]);
-}
-
-static inline int __ieee80211_queue_pending(const struct ieee80211_local *local,
-                                           int queue)
-{
-       return test_bit(IEEE80211_LINK_STATE_PENDING, &local->state[queue]);
-}
-
-#define IEEE80211_TX_OK                0
-#define IEEE80211_TX_AGAIN     1
-#define IEEE80211_TX_FRAG_AGAIN        2
-
-static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
-                         struct ieee80211_txrx_data *tx)
-{
-       struct ieee80211_tx_control *control = tx->u.tx.control;
-       int ret, i;
-
-       if (!ieee80211_qdisc_installed(local->mdev) &&
-           __ieee80211_queue_stopped(local, 0)) {
-               netif_stop_queue(local->mdev);
-               return IEEE80211_TX_AGAIN;
-       }
-       if (skb) {
-               ieee80211_dump_frame(local->mdev->name, "TX to low-level driver", skb);
-               ret = local->ops->tx(local_to_hw(local), skb, control);
-               if (ret)
-                       return IEEE80211_TX_AGAIN;
-               local->mdev->trans_start = jiffies;
-               ieee80211_led_tx(local, 1);
-       }
-       if (tx->u.tx.extra_frag) {
-               control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |
-                                   IEEE80211_TXCTL_USE_CTS_PROTECT |
-                                   IEEE80211_TXCTL_CLEAR_DST_MASK |
-                                   IEEE80211_TXCTL_FIRST_FRAGMENT);
-               for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
-                       if (!tx->u.tx.extra_frag[i])
-                               continue;
-                       if (__ieee80211_queue_stopped(local, control->queue))
-                               return IEEE80211_TX_FRAG_AGAIN;
-                       if (i == tx->u.tx.num_extra_frag) {
-                               control->tx_rate = tx->u.tx.last_frag_hwrate;
-                               control->rate = tx->u.tx.last_frag_rate;
-                               if (tx->u.tx.probe_last_frag)
-                                       control->flags |=
-                                               IEEE80211_TXCTL_RATE_CTRL_PROBE;
-                               else
-                                       control->flags &=
-                                               ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
-                       }
-
-                       ieee80211_dump_frame(local->mdev->name,
-                                            "TX to low-level driver",
-                                            tx->u.tx.extra_frag[i]);
-                       ret = local->ops->tx(local_to_hw(local),
-                                           tx->u.tx.extra_frag[i],
-                                           control);
-                       if (ret)
-                               return IEEE80211_TX_FRAG_AGAIN;
-                       local->mdev->trans_start = jiffies;
-                       ieee80211_led_tx(local, 1);
-                       tx->u.tx.extra_frag[i] = NULL;
-               }
-               kfree(tx->u.tx.extra_frag);
-               tx->u.tx.extra_frag = NULL;
-       }
-       return IEEE80211_TX_OK;
-}
-
-static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
-                       struct ieee80211_tx_control *control, int mgmt)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct sta_info *sta;
-       ieee80211_tx_handler *handler;
-       struct ieee80211_txrx_data tx;
-       ieee80211_txrx_result res = TXRX_DROP;
-       int ret, i;
-
-       WARN_ON(__ieee80211_queue_pending(local, control->queue));
-
-       if (unlikely(skb->len < 10)) {
-               dev_kfree_skb(skb);
-               return 0;
-       }
-
-       __ieee80211_tx_prepare(&tx, skb, dev, control);
-       sta = tx.sta;
-       tx.u.tx.mgmt_interface = mgmt;
-       tx.u.tx.mode = local->hw.conf.mode;
-
-       for (handler = local->tx_handlers; *handler != NULL; handler++) {
-               res = (*handler)(&tx);
-               if (res != TXRX_CONTINUE)
-                       break;
-       }
-
-       skb = tx.skb; /* handlers are allowed to change skb */
-
-       if (sta)
-               sta_info_put(sta);
-
-       if (unlikely(res == TXRX_DROP)) {
-               I802_DEBUG_INC(local->tx_handlers_drop);
-               goto drop;
-       }
-
-       if (unlikely(res == TXRX_QUEUED)) {
-               I802_DEBUG_INC(local->tx_handlers_queued);
-               return 0;
-       }
-
-       if (tx.u.tx.extra_frag) {
-               for (i = 0; i < tx.u.tx.num_extra_frag; i++) {
-                       int next_len, dur;
-                       struct ieee80211_hdr *hdr =
-                               (struct ieee80211_hdr *)
-                               tx.u.tx.extra_frag[i]->data;
-
-                       if (i + 1 < tx.u.tx.num_extra_frag) {
-                               next_len = tx.u.tx.extra_frag[i + 1]->len;
-                       } else {
-                               next_len = 0;
-                               tx.u.tx.rate = tx.u.tx.last_frag_rate;
-                               tx.u.tx.last_frag_hwrate = tx.u.tx.rate->val;
-                       }
-                       dur = ieee80211_duration(&tx, 0, next_len);
-                       hdr->duration_id = cpu_to_le16(dur);
-               }
-       }
-
-retry:
-       ret = __ieee80211_tx(local, skb, &tx);
-       if (ret) {
-               struct ieee80211_tx_stored_packet *store =
-                       &local->pending_packet[control->queue];
-
-               if (ret == IEEE80211_TX_FRAG_AGAIN)
-                       skb = NULL;
-               set_bit(IEEE80211_LINK_STATE_PENDING,
-                       &local->state[control->queue]);
-               smp_mb();
-               /* When the driver gets out of buffers during sending of
-                * fragments and calls ieee80211_stop_queue, there is
-                * a small window between IEEE80211_LINK_STATE_XOFF and
-                * IEEE80211_LINK_STATE_PENDING flags are set. If a buffer
-                * gets available in that window (i.e. driver calls
-                * ieee80211_wake_queue), we would end up with ieee80211_tx
-                * called with IEEE80211_LINK_STATE_PENDING. Prevent this by
-                * continuing transmitting here when that situation is
-                * possible to have happened. */
-               if (!__ieee80211_queue_stopped(local, control->queue)) {
-                       clear_bit(IEEE80211_LINK_STATE_PENDING,
-                                 &local->state[control->queue]);
-                       goto retry;
-               }
-               memcpy(&store->control, control,
-                      sizeof(struct ieee80211_tx_control));
-               store->skb = skb;
-               store->extra_frag = tx.u.tx.extra_frag;
-               store->num_extra_frag = tx.u.tx.num_extra_frag;
-               store->last_frag_hwrate = tx.u.tx.last_frag_hwrate;
-               store->last_frag_rate = tx.u.tx.last_frag_rate;
-               store->last_frag_rate_ctrl_probe = tx.u.tx.probe_last_frag;
-       }
-       return 0;
-
- drop:
-       if (skb)
-               dev_kfree_skb(skb);
-       for (i = 0; i < tx.u.tx.num_extra_frag; i++)
-               if (tx.u.tx.extra_frag[i])
-                       dev_kfree_skb(tx.u.tx.extra_frag[i]);
-       kfree(tx.u.tx.extra_frag);
-       return 0;
-}
-
-static void ieee80211_tx_pending(unsigned long data)
-{
-       struct ieee80211_local *local = (struct ieee80211_local *)data;
-       struct net_device *dev = local->mdev;
-       struct ieee80211_tx_stored_packet *store;
-       struct ieee80211_txrx_data tx;
-       int i, ret, reschedule = 0;
-
-       netif_tx_lock_bh(dev);
-       for (i = 0; i < local->hw.queues; i++) {
-               if (__ieee80211_queue_stopped(local, i))
-                       continue;
-               if (!__ieee80211_queue_pending(local, i)) {
-                       reschedule = 1;
-                       continue;
-               }
-               store = &local->pending_packet[i];
-               tx.u.tx.control = &store->control;
-               tx.u.tx.extra_frag = store->extra_frag;
-               tx.u.tx.num_extra_frag = store->num_extra_frag;
-               tx.u.tx.last_frag_hwrate = store->last_frag_hwrate;
-               tx.u.tx.last_frag_rate = store->last_frag_rate;
-               tx.u.tx.probe_last_frag = store->last_frag_rate_ctrl_probe;
-               ret = __ieee80211_tx(local, store->skb, &tx);
-               if (ret) {
-                       if (ret == IEEE80211_TX_FRAG_AGAIN)
-                               store->skb = NULL;
-               } else {
-                       clear_bit(IEEE80211_LINK_STATE_PENDING,
-                                 &local->state[i]);
-                       reschedule = 1;
-               }
-       }
-       netif_tx_unlock_bh(dev);
-       if (reschedule) {
-               if (!ieee80211_qdisc_installed(dev)) {
-                       if (!__ieee80211_queue_stopped(local, 0))
-                               netif_wake_queue(dev);
-               } else
-                       netif_schedule(dev);
-       }
-}
-
-static void ieee80211_clear_tx_pending(struct ieee80211_local *local)
-{
-       int i, j;
-       struct ieee80211_tx_stored_packet *store;
-
-       for (i = 0; i < local->hw.queues; i++) {
-               if (!__ieee80211_queue_pending(local, i))
-                       continue;
-               store = &local->pending_packet[i];
-               kfree_skb(store->skb);
-               for (j = 0; j < store->num_extra_frag; j++)
-                       kfree_skb(store->extra_frag[j]);
-               kfree(store->extra_frag);
-               clear_bit(IEEE80211_LINK_STATE_PENDING, &local->state[i]);
-       }
-}
-
-static int ieee80211_master_start_xmit(struct sk_buff *skb,
-                                      struct net_device *dev)
-{
-       struct ieee80211_tx_control control;
-       struct ieee80211_tx_packet_data *pkt_data;
-       struct net_device *odev = NULL;
-       struct ieee80211_sub_if_data *osdata;
-       int headroom;
-       int ret;
-
-       /*
-        * copy control out of the skb so other people can use skb->cb
-        */
-       pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
-       memset(&control, 0, sizeof(struct ieee80211_tx_control));
-
-       if (pkt_data->ifindex)
-               odev = dev_get_by_index(pkt_data->ifindex);
-       if (unlikely(odev && !is_ieee80211_device(odev, dev))) {
-               dev_put(odev);
-               odev = NULL;
-       }
-       if (unlikely(!odev)) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-               printk(KERN_DEBUG "%s: Discarded packet with nonexistent "
-                      "originating device\n", dev->name);
-#endif
-               dev_kfree_skb(skb);
-               return 0;
-       }
-       osdata = IEEE80211_DEV_TO_SUB_IF(odev);
-
-       headroom = osdata->local->hw.extra_tx_headroom +
-               IEEE80211_ENCRYPT_HEADROOM;
-       if (skb_headroom(skb) < headroom) {
-               if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) {
-                       dev_kfree_skb(skb);
-                       return 0;
-               }
-       }
-
-       control.ifindex = odev->ifindex;
-       control.type = osdata->type;
-       if (pkt_data->req_tx_status)
-               control.flags |= IEEE80211_TXCTL_REQ_TX_STATUS;
-       if (pkt_data->do_not_encrypt)
-               control.flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
-       if (pkt_data->requeue)
-               control.flags |= IEEE80211_TXCTL_REQUEUE;
-       control.queue = pkt_data->queue;
-
-       ret = ieee80211_tx(odev, skb, &control,
-                          control.type == IEEE80211_IF_TYPE_MGMT);
-       dev_put(odev);
-
-       return ret;
-}
-
-
-/**
- * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type
- * subinterfaces (wlan#, WDS, and VLAN interfaces)
- * @skb: packet to be sent
- * @dev: incoming interface
- *
- * Returns: 0 on success (and frees skb in this case) or 1 on failure (skb will
- * not be freed, and caller is responsible for either retrying later or freeing
- * skb).
- *
- * This function takes in an Ethernet header and encapsulates it with suitable
- * IEEE 802.11 header based on which interface the packet is coming in. The
- * encapsulated packet will then be passed to master interface, wlan#.11, for
- * transmission (through low-level driver).
- */
-static int ieee80211_subif_start_xmit(struct sk_buff *skb,
-                                     struct net_device *dev)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_tx_packet_data *pkt_data;
-       struct ieee80211_sub_if_data *sdata;
-       int ret = 1, head_need;
-       u16 ethertype, hdrlen, fc;
-       struct ieee80211_hdr hdr;
-       const u8 *encaps_data;
-       int encaps_len, skip_header_bytes;
-       int nh_pos, h_pos, no_encrypt = 0;
-       struct sta_info *sta;
-
-       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       if (unlikely(skb->len < ETH_HLEN)) {
-               printk(KERN_DEBUG "%s: short skb (len=%d)\n",
-                      dev->name, skb->len);
-               ret = 0;
-               goto fail;
-       }
-
-       nh_pos = skb_network_header(skb) - skb->data;
-       h_pos = skb_transport_header(skb) - skb->data;
-
-       /* convert Ethernet header to proper 802.11 header (based on
-        * operation mode) */
-       ethertype = (skb->data[12] << 8) | skb->data[13];
-       /* TODO: handling for 802.1x authorized/unauthorized port */
-       fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
-
-       if (likely(sdata->type == IEEE80211_IF_TYPE_AP ||
-                  sdata->type == IEEE80211_IF_TYPE_VLAN)) {
-               fc |= IEEE80211_FCTL_FROMDS;
-               /* DA BSSID SA */
-               memcpy(hdr.addr1, skb->data, ETH_ALEN);
-               memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
-               memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
-               hdrlen = 24;
-       } else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
-               fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS;
-               /* RA TA DA SA */
-               memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN);
-               memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
-               memcpy(hdr.addr3, skb->data, ETH_ALEN);
-               memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
-               hdrlen = 30;
-       } else if (sdata->type == IEEE80211_IF_TYPE_STA) {
-               if (dls_link_status(local, skb->data) == DLS_STATUS_OK) {
-                       /* DA SA BSSID */
-                       memcpy(hdr.addr1, skb->data, ETH_ALEN);
-                       memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
-                       memcpy(hdr.addr3, sdata->u.sta.bssid, ETH_ALEN);
-               } else {
-                       fc |= IEEE80211_FCTL_TODS;
-                       /* BSSID SA DA */
-                       memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN);
-                       memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
-                       memcpy(hdr.addr3, skb->data, ETH_ALEN);
-               }
-               hdrlen = 24;
-       } else if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
-               /* DA SA BSSID */
-               memcpy(hdr.addr1, skb->data, ETH_ALEN);
-               memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
-               memcpy(hdr.addr3, sdata->u.sta.bssid, ETH_ALEN);
-               hdrlen = 24;
-       } else {
-               ret = 0;
-               goto fail;
-       }
-
-       /* receiver is QoS enabled, use a QoS type frame */
-       sta = sta_info_get(local, hdr.addr1);
-       if (sta) {
-               if (sta->flags & WLAN_STA_WME) {
-                       fc |= IEEE80211_STYPE_QOS_DATA;
-                       hdrlen += 2;
-               }
-               sta_info_put(sta);
-       }
-
-       hdr.frame_control = cpu_to_le16(fc);
-       hdr.duration_id = 0;
-       hdr.seq_ctrl = 0;
-
-       skip_header_bytes = ETH_HLEN;
-       if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
-               encaps_data = bridge_tunnel_header;
-               encaps_len = sizeof(bridge_tunnel_header);
-               skip_header_bytes -= 2;
-       } else if (ethertype >= 0x600) {
-               encaps_data = rfc1042_header;
-               encaps_len = sizeof(rfc1042_header);
-               skip_header_bytes -= 2;
-       } else {
-               encaps_data = NULL;
-               encaps_len = 0;
-       }
-
-       skb_pull(skb, skip_header_bytes);
-       nh_pos -= skip_header_bytes;
-       h_pos -= skip_header_bytes;
-
-       /* TODO: implement support for fragments so that there is no need to
-        * reallocate and copy payload; it might be enough to support one
-        * extra fragment that would be copied in the beginning of the frame
-        * data.. anyway, it would be nice to include this into skb structure
-        * somehow
-        *
-        * There are few options for this:
-        * use skb->cb as an extra space for 802.11 header
-        * allocate new buffer if not enough headroom
-        * make sure that there is enough headroom in every skb by increasing
-        * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and
-        * alloc_skb() (net/core/skbuff.c)
-        */
-       head_need = hdrlen + encaps_len + local->hw.extra_tx_headroom;
-       head_need -= skb_headroom(skb);
-
-       /* We are going to modify skb data, so make a copy of it if happens to
-        * be cloned. This could happen, e.g., with Linux bridge code passing
-        * us broadcast frames. */
-
-       if (head_need > 0 || skb_cloned(skb)) {
-#if 0
-               printk(KERN_DEBUG "%s: need to reallocate buffer for %d bytes "
-                      "of headroom\n", dev->name, head_need);
-#endif
-
-               if (skb_cloned(skb))
-                       I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
-               else
-                       I802_DEBUG_INC(local->tx_expand_skb_head);
-               /* Since we have to reallocate the buffer, make sure that there
-                * is enough room for possible WEP IV/ICV and TKIP (8 bytes
-                * before payload and 12 after). */
-               if (pskb_expand_head(skb, (head_need > 0 ? head_need + 8 : 8),
-                                    12, GFP_ATOMIC)) {
-                       printk(KERN_DEBUG "%s: failed to reallocate TX buffer"
-                              "\n", dev->name);
-                       goto fail;
-               }
-       }
-
-       if (encaps_data) {
-               memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
-               nh_pos += encaps_len;
-               h_pos += encaps_len;
-       }
-       memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
-       nh_pos += hdrlen;
-       h_pos += hdrlen;
-
-       pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
-       memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
-       pkt_data->ifindex = sdata->dev->ifindex;
-       pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
-       pkt_data->do_not_encrypt = no_encrypt;
-
-       skb->dev = local->mdev;
-       sdata->stats.tx_packets++;
-       sdata->stats.tx_bytes += skb->len;
-
-       /* Update skb pointers to various headers since this modified frame
-        * is going to go through Linux networking code that may potentially
-        * need things like pointer to IP header. */
-       skb_set_mac_header(skb, 0);
-       skb_set_network_header(skb, nh_pos);
-       skb_set_transport_header(skb, h_pos);
-
-       dev->trans_start = jiffies;
-       dev_queue_xmit(skb);
-
-       return 0;
-
- fail:
-       if (!ret)
-               dev_kfree_skb(skb);
-
-       return ret;
-}
-
-
-/*
- * This is the transmit routine for the 802.11 type interfaces
- * called by upper layers of the linux networking
- * stack when it has a frame to transmit
- */
-static int
-ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-       struct ieee80211_sub_if_data *sdata;
-       struct ieee80211_tx_packet_data *pkt_data;
-       struct ieee80211_hdr *hdr;
-       u16 fc;
-
-       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-       if (skb->len < 10) {
-               dev_kfree_skb(skb);
-               return 0;
-       }
-
-       if (skb_headroom(skb) < sdata->local->hw.extra_tx_headroom) {
-               if (pskb_expand_head(skb,
-                   sdata->local->hw.extra_tx_headroom, 0, GFP_ATOMIC)) {
-                       dev_kfree_skb(skb);
-                       return 0;
-               }
-       }
-
-       hdr = (struct ieee80211_hdr *) skb->data;
-       fc = le16_to_cpu(hdr->frame_control);
-
-       pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
-       memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
-       pkt_data->ifindex = sdata->dev->ifindex;
-       pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
-
-       skb->priority = 20; /* use hardcoded priority for mgmt TX queue */
-       skb->dev = sdata->local->mdev;
-
-       /*
-        * We're using the protocol field of the the frame control header
-        * to request TX callback for hostapd. BIT(1) is checked.
-        */
-       if ((fc & BIT(1)) == BIT(1)) {
-               pkt_data->req_tx_status = 1;
-               fc &= ~BIT(1);
-               hdr->frame_control = cpu_to_le16(fc);
-       }
-
-       pkt_data->do_not_encrypt = !(fc & IEEE80211_FCTL_PROTECTED);
-
-       sdata->stats.tx_packets++;
-       sdata->stats.tx_bytes += skb->len;
-
-       dev_queue_xmit(skb);
-
-       return 0;
-}
-
-
-static void ieee80211_beacon_add_tim(struct ieee80211_local *local,
-                                    struct ieee80211_if_ap *bss,
-                                    struct sk_buff *skb)
-{
-       u8 *pos, *tim;
-       int aid0 = 0;
-       int i, have_bits = 0, n1, n2;
-
-       /* Generate bitmap for TIM only if there are any STAs in power save
-        * mode. */
-       spin_lock_bh(&local->sta_lock);
-       if (atomic_read(&bss->num_sta_ps) > 0)
-               /* in the hope that this is faster than
-                * checking byte-for-byte */
-               have_bits = !bitmap_empty((unsigned long*)bss->tim,
-                                         IEEE80211_MAX_AID+1);
-
-       if (bss->dtim_count == 0)
-               bss->dtim_count = bss->dtim_period - 1;
-       else
-               bss->dtim_count--;
-
-       tim = pos = (u8 *) skb_put(skb, 6);
-       *pos++ = WLAN_EID_TIM;
-       *pos++ = 4;
-       *pos++ = bss->dtim_count;
-       *pos++ = bss->dtim_period;
-
-       if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf))
-               aid0 = 1;
-
-       if (have_bits) {
-               /* Find largest even number N1 so that bits numbered 1 through
-                * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits
-                * (N2 + 1) x 8 through 2007 are 0. */
-               n1 = 0;
-               for (i = 0; i < IEEE80211_MAX_TIM_LEN; i++) {
-                       if (bss->tim[i]) {
-                               n1 = i & 0xfe;
-                               break;
-                       }
-               }
-               n2 = n1;
-               for (i = IEEE80211_MAX_TIM_LEN - 1; i >= n1; i--) {
-                       if (bss->tim[i]) {
-                               n2 = i;
-                               break;
-                       }
-               }
-
-               /* Bitmap control */
-               *pos++ = n1 | aid0;
-               /* Part Virt Bitmap */
-               memcpy(pos, bss->tim + n1, n2 - n1 + 1);
-
-               tim[1] = n2 - n1 + 4;
-               skb_put(skb, n2 - n1);
-       } else {
-               *pos++ = aid0; /* Bitmap control */
-               *pos++ = 0; /* Part Virt Bitmap */
-       }
-       spin_unlock_bh(&local->sta_lock);
-}
-
-
-struct sk_buff * ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id,
-                                     struct ieee80211_tx_control *control)
-{
-       struct ieee80211_local *local = hw_to_local(hw);
-       struct sk_buff *skb;
-       struct net_device *bdev;
-       struct ieee80211_sub_if_data *sdata = NULL;
-       struct ieee80211_if_ap *ap = NULL;
-       struct ieee80211_rate *rate;
-       struct rate_control_extra extra;
-       u8 *b_head, *b_tail;
-       int bh_len, bt_len;
-
-       bdev = dev_get_by_index(if_id);
-       if (bdev) {
-               sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
-               ap = &sdata->u.ap;
-               dev_put(bdev);
-       }
-
-       if (!ap || sdata->type != IEEE80211_IF_TYPE_AP ||
-           !ap->beacon_head) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-               if (net_ratelimit())
-                       printk(KERN_DEBUG "no beacon data avail for idx=%d "
-                              "(%s)\n", if_id, bdev ? bdev->name : "N/A");
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-               return NULL;
-       }
-
-       /* Assume we are generating the normal beacon locally */
-       b_head = ap->beacon_head;
-       b_tail = ap->beacon_tail;
-       bh_len = ap->beacon_head_len;
-       bt_len = ap->beacon_tail_len;
-
-       skb = dev_alloc_skb(local->hw.extra_tx_headroom +
-               bh_len + bt_len + 256 /* maximum TIM len */);
-       if (!skb)
-               return NULL;
-
-       skb_reserve(skb, local->hw.extra_tx_headroom);
-       memcpy(skb_put(skb, bh_len), b_head, bh_len);
-
-       ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data);
-
-       ieee80211_beacon_add_tim(local, ap, skb);
-
-       if (b_tail) {
-               memcpy(skb_put(skb, bt_len), b_tail, bt_len);
-       }
-
-       if (control) {
-               memset(&extra, 0, sizeof(extra));
-               extra.mode = local->oper_hw_mode;
-
-               rate = rate_control_get_rate(local, local->mdev, skb, &extra);
-               if (!rate) {
-                       if (net_ratelimit()) {
-                               printk(KERN_DEBUG "%s: ieee80211_beacon_get: no rate "
-                                      "found\n", local->mdev->name);
-                       }
-                       dev_kfree_skb(skb);
-                       return NULL;
-               }
-
-               control->tx_rate = (local->short_preamble &&
-                                   (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
-                       rate->val2 : rate->val;
-               control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
-               control->power_level = local->hw.conf.power_level;
-               control->flags |= IEEE80211_TXCTL_NO_ACK;
-               control->retry_limit = 1;
-               control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
-       }
-
-       ap->num_beacons++;
-       return skb;
-}
-EXPORT_SYMBOL(ieee80211_beacon_get);
-
-__le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
-                             size_t frame_len,
-                             const struct ieee80211_tx_control *frame_txctl)
-{
-       struct ieee80211_local *local = hw_to_local(hw);
-       struct ieee80211_rate *rate;
-       int short_preamble = local->short_preamble;
-       int erp;
-       u16 dur;
-
-       rate = frame_txctl->rts_rate;
-       erp = !!(rate->flags & IEEE80211_RATE_ERP);
-
-       /* CTS duration */
-       dur = ieee80211_frame_duration(local, 10, rate->rate,
-                                      erp, short_preamble);
-       /* Data frame duration */
-       dur += ieee80211_frame_duration(local, frame_len, rate->rate,
-                                       erp, short_preamble);
-       /* ACK duration */
-       dur += ieee80211_frame_duration(local, 10, rate->rate,
-                                       erp, short_preamble);
-
-       return cpu_to_le16(dur);
-}
-EXPORT_SYMBOL(ieee80211_rts_duration);
-
-
-__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
-                                   size_t frame_len,
-                                   const struct ieee80211_tx_control *frame_txctl)
-{
-       struct ieee80211_local *local = hw_to_local(hw);
-       struct ieee80211_rate *rate;
-       int short_preamble = local->short_preamble;
-       int erp;
-       u16 dur;
-
-       rate = frame_txctl->rts_rate;
-       erp = !!(rate->flags & IEEE80211_RATE_ERP);
-
-       /* Data frame duration */
-       dur = ieee80211_frame_duration(local, frame_len, rate->rate,
-                                      erp, short_preamble);
-       if (!(frame_txctl->flags & IEEE80211_TXCTL_NO_ACK)) {
-               /* ACK duration */
-               dur += ieee80211_frame_duration(local, 10, rate->rate,
-                                               erp, short_preamble);
-       }
-
-       return cpu_to_le16(dur);
-}
-EXPORT_SYMBOL(ieee80211_ctstoself_duration);
-
-void ieee80211_rts_get(struct ieee80211_hw *hw,
-                      const void *frame, size_t frame_len,
-                      const struct ieee80211_tx_control *frame_txctl,
-                      struct ieee80211_rts *rts)
-{
-       const struct ieee80211_hdr *hdr = frame;
-       u16 fctl;
-
-       fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS;
-       rts->frame_control = cpu_to_le16(fctl);
-       rts->duration = ieee80211_rts_duration(hw, frame_len, frame_txctl);
-       memcpy(rts->ra, hdr->addr1, sizeof(rts->ra));
-       memcpy(rts->ta, hdr->addr2, sizeof(rts->ta));
-}
-EXPORT_SYMBOL(ieee80211_rts_get);
-
-void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
-                            const void *frame, size_t frame_len,
-                            const struct ieee80211_tx_control *frame_txctl,
-                            struct ieee80211_cts *cts)
-{
-       const struct ieee80211_hdr *hdr = frame;
-       u16 fctl;
-
-       fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS;
-       cts->frame_control = cpu_to_le16(fctl);
-       cts->duration = ieee80211_ctstoself_duration(hw, frame_len, frame_txctl);
-       memcpy(cts->ra, hdr->addr1, sizeof(cts->ra));
-}
-EXPORT_SYMBOL(ieee80211_ctstoself_get);
-
-struct sk_buff *
-ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id,
-                         struct ieee80211_tx_control *control)
-{
-       struct ieee80211_local *local = hw_to_local(hw);
-       struct sk_buff *skb;
-       struct sta_info *sta;
-       ieee80211_tx_handler *handler;
-       struct ieee80211_txrx_data tx;
-       ieee80211_txrx_result res = TXRX_DROP;
-       struct net_device *bdev;
-       struct ieee80211_sub_if_data *sdata;
-       struct ieee80211_if_ap *bss = NULL;
-
-       bdev = dev_get_by_index(if_id);
-       if (bdev) {
-               sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
-               bss = &sdata->u.ap;
-               dev_put(bdev);
-       }
-       if (!bss || sdata->type != IEEE80211_IF_TYPE_AP || !bss->beacon_head)
-               return NULL;
-
-       if (bss->dtim_count != 0)
-               return NULL; /* send buffered bc/mc only after DTIM beacon */
-       memset(control, 0, sizeof(*control));
-       while (1) {
-               skb = skb_dequeue(&bss->ps_bc_buf);
-               if (!skb)
-                       return NULL;
-               local->total_ps_buffered--;
-
-               if (!skb_queue_empty(&bss->ps_bc_buf) && skb->len >= 2) {
-                       struct ieee80211_hdr *hdr =
-                               (struct ieee80211_hdr *) skb->data;
-                       /* more buffered multicast/broadcast frames ==> set
-                        * MoreData flag in IEEE 802.11 header to inform PS
-                        * STAs */
-                       hdr->frame_control |=
-                               cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-               }
-
-               if (ieee80211_tx_prepare(&tx, skb, local->mdev, control) == 0)
-                       break;
-               dev_kfree_skb_any(skb);
-       }
-       sta = tx.sta;
-       tx.u.tx.ps_buffered = 1;
-
-       for (handler = local->tx_handlers; *handler != NULL; handler++) {
-               res = (*handler)(&tx);
-               if (res == TXRX_DROP || res == TXRX_QUEUED)
-                       break;
-       }
-       dev_put(tx.dev);
-       skb = tx.skb; /* handlers are allowed to change skb */
-
-       if (res == TXRX_DROP) {
-               I802_DEBUG_INC(local->tx_handlers_drop);
-               dev_kfree_skb(skb);
-               skb = NULL;
-       } else if (res == TXRX_QUEUED) {
-               I802_DEBUG_INC(local->tx_handlers_queued);
-               skb = NULL;
-       }
-
-       if (sta)
-               sta_info_put(sta);
-
-       return skb;
-}
-EXPORT_SYMBOL(ieee80211_get_buffered_bc);
-
-static int __ieee80211_if_config(struct net_device *dev,
-                                struct sk_buff *beacon,
-                                struct ieee80211_tx_control *control)
-{
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_if_conf conf;
-       static u8 scan_bssid[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
-       if (!local->ops->config_interface || !netif_running(dev))
-               return 0;
-
-       memset(&conf, 0, sizeof(conf));
-       conf.type = sdata->type;
-       if (sdata->type == IEEE80211_IF_TYPE_STA ||
-           sdata->type == IEEE80211_IF_TYPE_IBSS) {
-               if (local->sta_scanning &&
-                   local->scan_dev == dev)
-                       conf.bssid = scan_bssid;
-               else
-                       conf.bssid = sdata->u.sta.bssid;
-               conf.ssid = sdata->u.sta.ssid;
-               conf.ssid_len = sdata->u.sta.ssid_len;
-               conf.generic_elem = sdata->u.sta.extra_ie;
-               conf.generic_elem_len = sdata->u.sta.extra_ie_len;
-       } else if (sdata->type == IEEE80211_IF_TYPE_AP) {
-               conf.ssid = sdata->u.ap.ssid;
-               conf.ssid_len = sdata->u.ap.ssid_len;
-               conf.generic_elem = sdata->u.ap.generic_elem;
-               conf.generic_elem_len = sdata->u.ap.generic_elem_len;
-               conf.beacon = beacon;
-               conf.beacon_control = control;
-       }
-       return local->ops->config_interface(local_to_hw(local),
-                                          dev->ifindex, &conf);
-}
-
-int ieee80211_if_config(struct net_device *dev)
-{
-       return __ieee80211_if_config(dev, NULL, NULL);
-}
-
-int ieee80211_if_config_beacon(struct net_device *dev)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_tx_control control;
-       struct sk_buff *skb;
-
-       if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
-               return 0;
-       skb = ieee80211_beacon_get(local_to_hw(local), dev->ifindex, &control);
-       if (!skb)
-               return -ENOMEM;
-       return __ieee80211_if_config(dev, skb, &control);
-}
-
-int ieee80211_hw_config(struct ieee80211_local *local)
-{
-       struct ieee80211_hw_mode *mode;
-       struct ieee80211_channel *chan;
-       int ret = 0;
-
-       if (local->sta_scanning) {
-               chan = local->scan_channel;
-               mode = local->scan_hw_mode;
-       } else {
-               chan = local->oper_channel;
-               mode = local->oper_hw_mode;
-       }
-
-       local->hw.conf.channel = chan->chan;
-       local->hw.conf.channel_val = chan->val;
-       local->hw.conf.power_level = chan->power_level;
-       local->hw.conf.freq = chan->freq;
-       local->hw.conf.phymode = mode->mode;
-       local->hw.conf.antenna_max = chan->antenna_max;
-       local->hw.conf.chan = chan;
-       local->hw.conf.mode = mode;
-
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-       printk(KERN_DEBUG "HW CONFIG: channel=%d freq=%d "
-              "phymode=%d\n", local->hw.conf.channel, local->hw.conf.freq,
-              local->hw.conf.phymode);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-
-       if (local->ops->config)
-               ret = local->ops->config(local_to_hw(local), &local->hw.conf);
-
-       return ret;
-}
-
-
-static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
-{
-       /* FIX: what would be proper limits for MTU?
-        * This interface uses 802.3 frames. */
-       if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6) {
-               printk(KERN_WARNING "%s: invalid MTU %d\n",
-                      dev->name, new_mtu);
-               return -EINVAL;
-       }
-
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-       printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-       dev->mtu = new_mtu;
-       return 0;
-}
-
-
-static int ieee80211_change_mtu_apdev(struct net_device *dev, int new_mtu)
-{
-       /* FIX: what would be proper limits for MTU?
-        * This interface uses 802.11 frames. */
-       if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN) {
-               printk(KERN_WARNING "%s: invalid MTU %d\n",
-                      dev->name, new_mtu);
-               return -EINVAL;
-       }
-
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-       printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-       dev->mtu = new_mtu;
-       return 0;
-}
-
-enum netif_tx_lock_class {
-       TX_LOCK_NORMAL,
-       TX_LOCK_MASTER,
-};
-
-static inline void netif_tx_lock_nested(struct net_device *dev, int subclass)
-{
-       spin_lock_nested(&dev->_xmit_lock, subclass);
-       dev->xmit_lock_owner = smp_processor_id();
-}
-
-static void ieee80211_set_multicast_list(struct net_device *dev)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       unsigned short flags;
-
-       netif_tx_lock_nested(local->mdev, TX_LOCK_MASTER);
-       if (((dev->flags & IFF_ALLMULTI) != 0) ^ (sdata->allmulti != 0)) {
-               if (sdata->allmulti) {
-                       sdata->allmulti = 0;
-                       local->iff_allmultis--;
-               } else {
-                       sdata->allmulti = 1;
-                       local->iff_allmultis++;
-               }
-       }
-       if (((dev->flags & IFF_PROMISC) != 0) ^ (sdata->promisc != 0)) {
-               if (sdata->promisc) {
-                       sdata->promisc = 0;
-                       local->iff_promiscs--;
-               } else {
-                       sdata->promisc = 1;
-                       local->iff_promiscs++;
-               }
-       }
-       if (dev->mc_count != sdata->mc_count) {
-               local->mc_count = local->mc_count - sdata->mc_count +
-                                 dev->mc_count;
-               sdata->mc_count = dev->mc_count;
-       }
-       if (local->ops->set_multicast_list) {
-               flags = local->mdev->flags;
-               if (local->iff_allmultis)
-                       flags |= IFF_ALLMULTI;
-               if (local->iff_promiscs)
-                       flags |= IFF_PROMISC;
-               read_lock(&local->sub_if_lock);
-               local->ops->set_multicast_list(local_to_hw(local), flags,
-                                             local->mc_count);
-               read_unlock(&local->sub_if_lock);
-       }
-       netif_tx_unlock(local->mdev);
-}
-
-struct dev_mc_list *ieee80211_get_mc_list_item(struct ieee80211_hw *hw,
-                                              struct dev_mc_list *prev,
-                                              void **ptr)
-{
-       struct ieee80211_local *local = hw_to_local(hw);
-       struct ieee80211_sub_if_data *sdata = *ptr;
-       struct dev_mc_list *mc;
-
-       if (!prev) {
-               WARN_ON(sdata);
-               sdata = NULL;
-       }
-       if (!prev || !prev->next) {
-               if (sdata)
-                       sdata = list_entry(sdata->list.next,
-                                          struct ieee80211_sub_if_data, list);
-               else
-                       sdata = list_entry(local->sub_if_list.next,
-                                          struct ieee80211_sub_if_data, list);
-               if (&sdata->list != &local->sub_if_list)
-                       mc = sdata->dev->mc_list;
-               else
-                       mc = NULL;
-       } else
-               mc = prev->next;
-
-       *ptr = sdata;
-       return mc;
-}
-EXPORT_SYMBOL(ieee80211_get_mc_list_item);
-
-static struct net_device_stats *ieee80211_get_stats(struct net_device *dev)
-{
-       struct ieee80211_sub_if_data *sdata;
-       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       return &(sdata->stats);
-}
-
-static void ieee80211_if_shutdown(struct net_device *dev)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-       ASSERT_RTNL();
-       switch (sdata->type) {
-       case IEEE80211_IF_TYPE_STA:
-       case IEEE80211_IF_TYPE_IBSS:
-               sdata->u.sta.state = IEEE80211_DISABLED;
-               del_timer_sync(&sdata->u.sta.timer);
-               del_timer_sync(&sdata->u.sta.admit_timer);
-               skb_queue_purge(&sdata->u.sta.skb_queue);
-               if (!local->ops->hw_scan &&
-                   local->scan_dev == sdata->dev) {
-                       local->sta_scanning = 0;
-                       cancel_delayed_work(&local->scan_work);
-               }
-               flush_workqueue(local->hw.workqueue);
-               break;
-       }
-}
-
-static inline int identical_mac_addr_allowed(int type1, int type2)
-{
-       return (type1 == IEEE80211_IF_TYPE_MNTR ||
-               type2 == IEEE80211_IF_TYPE_MNTR ||
-               (type1 == IEEE80211_IF_TYPE_AP &&
-                type2 == IEEE80211_IF_TYPE_WDS) ||
-               (type1 == IEEE80211_IF_TYPE_WDS &&
-                (type2 == IEEE80211_IF_TYPE_WDS ||
-                 type2 == IEEE80211_IF_TYPE_AP)) ||
-               (type1 == IEEE80211_IF_TYPE_AP &&
-                type2 == IEEE80211_IF_TYPE_VLAN) ||
-               (type1 == IEEE80211_IF_TYPE_VLAN &&
-                (type2 == IEEE80211_IF_TYPE_AP ||
-                 type2 == IEEE80211_IF_TYPE_VLAN)));
-}
-
-static int ieee80211_master_open(struct net_device *dev)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_sub_if_data *sdata;
-       int res = -EOPNOTSUPP;
-
-       read_lock(&local->sub_if_lock);
-       list_for_each_entry(sdata, &local->sub_if_list, list) {
-               if (sdata->dev != dev && netif_running(sdata->dev)) {
-                       res = 0;
-                       break;
-               }
-       }
-       read_unlock(&local->sub_if_lock);
-       return res;
-}
-
-static int ieee80211_master_stop(struct net_device *dev)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_sub_if_data *sdata;
-
-       read_lock(&local->sub_if_lock);
-       list_for_each_entry(sdata, &local->sub_if_list, list)
-               if (sdata->dev != dev && netif_running(sdata->dev))
-                       dev_close(sdata->dev);
-       read_unlock(&local->sub_if_lock);
-
-       return 0;
-}
-
-static int ieee80211_mgmt_open(struct net_device *dev)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-
-       if (!netif_running(local->mdev))
-               return -EOPNOTSUPP;
-       return 0;
-}
-
-static int ieee80211_mgmt_stop(struct net_device *dev)
-{
-       return 0;
-}
-
-/* Check if running monitor interfaces should go to a "soft monitor" mode
- * and switch them if necessary. */
-static inline void ieee80211_start_soft_monitor(struct ieee80211_local *local)
-{
-       struct ieee80211_if_init_conf conf;
-
-       if (local->open_count && local->open_count == local->monitors &&
-           !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) &&
-           local->ops->remove_interface) {
-               conf.if_id = -1;
-               conf.type = IEEE80211_IF_TYPE_MNTR;
-               conf.mac_addr = NULL;
-               local->ops->remove_interface(local_to_hw(local), &conf);
-       }
-}
-
-/* Check if running monitor interfaces should go to a "hard monitor" mode
- * and switch them if necessary. */
-static void ieee80211_start_hard_monitor(struct ieee80211_local *local)
-{
-       struct ieee80211_if_init_conf conf;
-
-       if (local->open_count && local->open_count == local->monitors &&
-           !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) &&
-           local->ops->add_interface) {
-               conf.if_id = -1;
-               conf.type = IEEE80211_IF_TYPE_MNTR;
-               conf.mac_addr = NULL;
-               local->ops->add_interface(local_to_hw(local), &conf);
-       }
-}
-
-static int ieee80211_open(struct net_device *dev)
-{
-       struct ieee80211_sub_if_data *sdata, *nsdata;
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_if_init_conf conf;
-       int res;
-
-       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       read_lock(&local->sub_if_lock);
-       list_for_each_entry(nsdata, &local->sub_if_list, list) {
-               struct net_device *ndev = nsdata->dev;
-
-               if (ndev != dev && ndev != local->mdev && netif_running(ndev) &&
-                   compare_ether_addr(dev->dev_addr, ndev->dev_addr) == 0 &&
-                   !identical_mac_addr_allowed(sdata->type, nsdata->type)) {
-                       read_unlock(&local->sub_if_lock);
-                       return -ENOTUNIQ;
-               }
-       }
-       read_unlock(&local->sub_if_lock);
-
-       if (sdata->type == IEEE80211_IF_TYPE_WDS &&
-           is_zero_ether_addr(sdata->u.wds.remote_addr))
-               return -ENOLINK;
-
-       if (sdata->type == IEEE80211_IF_TYPE_MNTR && local->open_count &&
-           !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) {
-               /* run the interface in a "soft monitor" mode */
-               local->monitors++;
-               local->open_count++;
-               local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
-               return 0;
-       }
-       ieee80211_start_soft_monitor(local);
-
-       if (local->ops->add_interface) {
-               conf.if_id = dev->ifindex;
-               conf.type = sdata->type;
-               conf.mac_addr = dev->dev_addr;
-               res = local->ops->add_interface(local_to_hw(local), &conf);
-               if (res) {
-                       if (sdata->type == IEEE80211_IF_TYPE_MNTR)
-                               ieee80211_start_hard_monitor(local);
-                       return res;
-               }
-       } else {
-               if (sdata->type != IEEE80211_IF_TYPE_STA)
-                       return -EOPNOTSUPP;
-               if (local->open_count > 0)
-                       return -ENOBUFS;
-       }
-
-       if (local->open_count == 0) {
-               res = 0;
-               tasklet_enable(&local->tx_pending_tasklet);
-               tasklet_enable(&local->tasklet);
-               if (local->ops->open)
-                       res = local->ops->open(local_to_hw(local));
-               if (res == 0) {
-                       res = dev_open(local->mdev);
-                       if (res) {
-                               if (local->ops->stop)
-                                       local->ops->stop(local_to_hw(local));
-                       } else {
-                               res = ieee80211_hw_config(local);
-                               if (res && local->ops->stop)
-                                       local->ops->stop(local_to_hw(local));
-                               else if (!res && local->apdev)
-                                       dev_open(local->apdev);
-                       }
-               }
-               if (res) {
-                       if (local->ops->remove_interface)
-                               local->ops->remove_interface(local_to_hw(local),
-                                                           &conf);
-                       return res;
-               }
-       }
-       local->open_count++;
-
-       if (sdata->type == IEEE80211_IF_TYPE_MNTR) {
-               local->monitors++;
-               local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
-       } else
-               ieee80211_if_config(dev);
-
-       if (sdata->type == IEEE80211_IF_TYPE_STA &&
-           !local->user_space_mlme)
-               netif_carrier_off(dev);
-       else
-               netif_carrier_on(dev);
-
-       netif_start_queue(dev);
-       return 0;
-}
-
-
-static int ieee80211_stop(struct net_device *dev)
-{
-       struct ieee80211_sub_if_data *sdata;
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-
-       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-       if (sdata->type == IEEE80211_IF_TYPE_MNTR &&
-           local->open_count > 1 &&
-           !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) {
-               /* remove "soft monitor" interface */
-               local->open_count--;
-               local->monitors--;
-               if (!local->monitors)
-                       local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
-               return 0;
-       }
-
-       netif_stop_queue(dev);
-       ieee80211_if_shutdown(dev);
-
-       if (sdata->type == IEEE80211_IF_TYPE_MNTR) {
-               local->monitors--;
-               if (!local->monitors)
-                       local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
-       }
-
-       local->open_count--;
-       if (local->open_count == 0) {
-               if (netif_running(local->mdev))
-                       dev_close(local->mdev);
-               if (local->apdev)
-                       dev_close(local->apdev);
-               if (local->ops->stop)
-                       local->ops->stop(local_to_hw(local));
-               tasklet_disable(&local->tx_pending_tasklet);
-               tasklet_disable(&local->tasklet);
-       }
-       if (local->ops->remove_interface) {
-               struct ieee80211_if_init_conf conf;
-
-               conf.if_id = dev->ifindex;
-               conf.type = sdata->type;
-               conf.mac_addr = dev->dev_addr;
-               local->ops->remove_interface(local_to_hw(local), &conf);
-       }
-
-       ieee80211_start_hard_monitor(local);
-
-       return 0;
-}
-
-
-static int header_parse_80211(struct sk_buff *skb, unsigned char *haddr)
-{
-       memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
-       return ETH_ALEN;
-}
-
-static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
-{
-       return compare_ether_addr(raddr, addr) == 0 ||
-              is_broadcast_ether_addr(raddr);
-}
-
-
-inline static unsigned int calc_pad_len(unsigned int len)
-{
-       return ((4 - len) & 0x3);
-}
-
-static ieee80211_txrx_result
-ieee80211_rx_h_data_agg(struct ieee80211_txrx_data *rx)
-{
-       struct net_device *dev = rx->dev;
-       struct ieee80211_local *local = rx->local;
-       u16 fc, hdrlen, ethertype;
-       u8 *payload;
-       struct sk_buff *skb = rx->skb, *skb2, *frame;
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       const struct ethhdr* eth;
-       int remaining;
-
-       fc = rx->fc;
-       if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
-               return TXRX_CONTINUE;
-
-       if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
-               return TXRX_DROP;
-
-       if (!rx->u.rx.is_agg_frame)
-               return TXRX_CONTINUE;
-
-       hdrlen = ieee80211_get_hdrlen(fc);
-
-       payload = skb->data + hdrlen;
-
-       if (unlikely((skb->len - hdrlen) < 8)) {
-               if (net_ratelimit())
-                       printk(KERN_DEBUG "%s: RX too short data frame "
-                              "payload\n", dev->name);
-               return TXRX_DROP;
-       }
-
-       ethertype = (payload[6] << 8) | payload[7];
-
-       if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
-                   ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
-                  compare_ether_addr(payload, bridge_tunnel_header) == 0)) {
-               /* remove RFC1042 or Bridge-Tunnel encapsulation and
-               * replace EtherType */
-               eth = (struct ethhdr*) (skb->data + hdrlen + 6);
-               remaining = skb->len - (hdrlen + 6);
-       } else {
-               eth = (struct ethhdr*) (skb->data + hdrlen);
-               remaining = skb->len - hdrlen;
-       }
-
-       while ((u8*)eth < skb->data + skb->len) {
-               u8 padding;
-               unsigned int subframe_len = sizeof(struct ethhdr) +
-                                                  ntohs(eth->h_proto);
-
-               padding = calc_pad_len(subframe_len);
-               /* the last MSDU has no padding */
-               if (subframe_len > remaining)
-                       return TXRX_DROP;
-
-               frame = dev_alloc_skb(local->hw.extra_tx_headroom +
-                                     subframe_len);
-
-               if (frame == NULL)
-                       return TXRX_DROP;
-
-               memcpy(skb_put(frame, subframe_len), (u8*)eth, subframe_len);
-               skb_set_mac_header(frame, 0);
-               skb2 = NULL;
-
-               sdata->stats.rx_packets++;
-               sdata->stats.rx_bytes += frame->len;
-
-               if (local->bridge_packets &&
-                   (sdata->type == IEEE80211_IF_TYPE_AP ||
-                    sdata->type == IEEE80211_IF_TYPE_VLAN) &&
-                    rx->u.rx.ra_match) {
-                       if (is_multicast_ether_addr(frame->data)) {
-                               /* send multicast frames both to higher layers
-                               * in local net stack and back to the wireless
-                               * media */
-                               skb2 = skb_copy(frame, GFP_ATOMIC);
-                               if (!skb2)
-                                       printk(KERN_DEBUG "%s: failed to clone"
-                                              " multicast frame\n", dev->name);
-                       } else {
-                               struct sta_info *dsta;
-
-                               dsta = sta_info_get(local, frame->data);
-                               if (dsta && !dsta->dev)
-                                       printk(KERN_DEBUG "Station with null "
-                                              "dev structure!\n");
-                               else if (dsta && dsta->dev == dev) {
-                                       /* Destination station is associated
-                                       * to this AP, so send the frame
-                                       * directly to it and do not pass
-                                       * the frame to local net stack.
-                                       */
-                                       skb2 = frame;
-                                       frame = NULL;
-                               }
-                               if (dsta)
-                                       sta_info_put(dsta);
-                       }
-               }
-               if (frame) {
-                       /* deliver to local stack */
-                       frame->protocol = eth_type_trans(frame, dev);
-                       frame->priority = skb->priority;
-                       frame->dev = dev;
-                       netif_rx(frame);
-               }
-
-               if (skb2) {
-                       /* send to wireless media */
-                       skb2->protocol = __constant_htons(ETH_P_802_3);
-                       skb_set_network_header(skb2, 0);
-                       skb_set_mac_header(skb2, 0);
-                       skb2->priority = skb->priority;
-                       skb2->dev = dev;
-                       dev_queue_xmit(skb2);
-               }
-
-               eth = (struct ethhdr*)((u8*)eth + subframe_len + padding);
-
-               remaining -= (subframe_len + padding);
-       }
-
-       dev_kfree_skb(skb);
-       return TXRX_QUEUED;
-}
-
-static ieee80211_txrx_result
-ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
-{
-       struct net_device *dev = rx->dev;
-       struct ieee80211_local *local = rx->local;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
-       u16 fc, hdrlen, ethertype;
-       u8 *payload;
-       u8 dst[ETH_ALEN];
-       u8 src[ETH_ALEN];
-       struct sk_buff *skb = rx->skb, *skb2;
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-       fc = rx->fc;
-       if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
-               return TXRX_CONTINUE;
-
-       if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
-               return TXRX_DROP;
-
-       hdrlen = ieee80211_get_hdrlen(fc);
-
-       /* convert IEEE 802.11 header + possible LLC headers into Ethernet
-        * header
-        * IEEE 802.11 address fields:
-        * ToDS FromDS Addr1 Addr2 Addr3 Addr4
-        *   0     0   DA    SA    BSSID n/a
-        *   0     1   DA    BSSID SA    n/a
-        *   1     0   BSSID SA    DA    n/a
-        *   1     1   RA    TA    DA    SA
-        */
-
-       switch (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
-       case IEEE80211_FCTL_TODS:
-               /* BSSID SA DA */
-               memcpy(dst, hdr->addr3, ETH_ALEN);
-               memcpy(src, hdr->addr2, ETH_ALEN);
-
-               if (unlikely(sdata->type != IEEE80211_IF_TYPE_AP &&
-                            sdata->type != IEEE80211_IF_TYPE_VLAN)) {
-                       printk(KERN_DEBUG "%s: dropped ToDS frame (BSSID="
-                              MAC_FMT " SA=" MAC_FMT " DA=" MAC_FMT ")\n",
-                              dev->name, MAC_ARG(hdr->addr1),
-                              MAC_ARG(hdr->addr2), MAC_ARG(hdr->addr3));
-                       return TXRX_DROP;
-               }
-               break;
-       case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
-               /* RA TA DA SA */
-               memcpy(dst, hdr->addr3, ETH_ALEN);
-               memcpy(src, hdr->addr4, ETH_ALEN);
-
-               if (unlikely(sdata->type != IEEE80211_IF_TYPE_WDS)) {
-                       printk(KERN_DEBUG "%s: dropped FromDS&ToDS frame (RA="
-                              MAC_FMT " TA=" MAC_FMT " DA=" MAC_FMT " SA="
-                              MAC_FMT ")\n",
-                              rx->dev->name, MAC_ARG(hdr->addr1),
-                              MAC_ARG(hdr->addr2), MAC_ARG(hdr->addr3),
-                              MAC_ARG(hdr->addr4));
-                       return TXRX_DROP;
-               }
-               break;
-       case IEEE80211_FCTL_FROMDS:
-               /* DA BSSID SA */
-               memcpy(dst, hdr->addr1, ETH_ALEN);
-               memcpy(src, hdr->addr3, ETH_ALEN);
-
-               if (sdata->type != IEEE80211_IF_TYPE_STA) {
-                       return TXRX_DROP;
-               }
-               break;
-       case 0:
-               /* DA SA BSSID */
-               memcpy(dst, hdr->addr1, ETH_ALEN);
-               memcpy(src, hdr->addr2, ETH_ALEN);
-
-               if (sdata->type != IEEE80211_IF_TYPE_IBSS) {
-                       if (net_ratelimit()) {
-                               printk(KERN_DEBUG "%s: dropped IBSS frame (DA="
-                                      MAC_FMT " SA=" MAC_FMT " BSSID=" MAC_FMT
-                                      ")\n",
-                                      dev->name, MAC_ARG(hdr->addr1),
-                                      MAC_ARG(hdr->addr2),
-                                      MAC_ARG(hdr->addr3));
-                       }
-                       return TXRX_DROP;
-               }
-               break;
-       }
-
-       payload = skb->data + hdrlen;
-
-       if (unlikely(skb->len - hdrlen < 8)) {
-               if (net_ratelimit()) {
-                       printk(KERN_DEBUG "%s: RX too short data frame "
-                              "payload\n", dev->name);
-               }
-               return TXRX_DROP;
-       }
-
-       ethertype = (payload[6] << 8) | payload[7];
-
-       if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
-                   ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
-                  compare_ether_addr(payload, bridge_tunnel_header) == 0)) {
-               /* remove RFC1042 or Bridge-Tunnel encapsulation and
-                * replace EtherType */
-               skb_pull(skb, hdrlen + 6);
-               memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
-               memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
-       } else {
-               struct ethhdr *ehdr;
-               __be16 len;
-               skb_pull(skb, hdrlen);
-               len = htons(skb->len);
-               ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
-               memcpy(ehdr->h_dest, dst, ETH_ALEN);
-               memcpy(ehdr->h_source, src, ETH_ALEN);
-               ehdr->h_proto = len;
-       }
-       skb->dev = dev;
-
-       skb2 = NULL;
-
-       sdata->stats.rx_packets++;
-       sdata->stats.rx_bytes += skb->len;
-
-       if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP
-           || sdata->type == IEEE80211_IF_TYPE_VLAN) && rx->u.rx.ra_match) {
-               if (is_multicast_ether_addr(skb->data)) {
-                       /* send multicast frames both to higher layers in
-                        * local net stack and back to the wireless media */
-                       skb2 = skb_copy(skb, GFP_ATOMIC);
-                       if (!skb2)
-                               printk(KERN_DEBUG "%s: failed to clone "
-                                      "multicast frame\n", dev->name);
-               } else {
-                       struct sta_info *dsta;
-                       dsta = sta_info_get(local, skb->data);
-                       if (dsta && !dsta->dev) {
-                               printk(KERN_DEBUG "Station with null dev "
-                                      "structure!\n");
-                       } else if (dsta && dsta->dev == dev) {
-                               /* Destination station is associated to this
-                                * AP, so send the frame directly to it and
-                                * do not pass the frame to local net stack.
-                                */
-                               skb2 = skb;
-                               skb = NULL;
-                       }
-                       if (dsta)
-                               sta_info_put(dsta);
-               }
-       }
-
-       if (skb) {
-               /* deliver to local stack */
-               skb->protocol = eth_type_trans(skb, dev);
-               memset(skb->cb, 0, sizeof(skb->cb));
-               netif_rx(skb);
-       }
-
-       if (skb2) {
-               /* send to wireless media */
-               skb2->protocol = __constant_htons(ETH_P_802_3);
-               skb_set_network_header(skb2, 0);
-               skb_set_mac_header(skb2, 0);
-               dev_queue_xmit(skb2);
-       }
-
-       return TXRX_QUEUED;
-}
-
-
-static struct ieee80211_rate *
-ieee80211_get_rate(struct ieee80211_local *local, int phymode, int hw_rate)
-{
-       struct ieee80211_hw_mode *mode;
-       int r;
-
-       list_for_each_entry(mode, &local->modes_list, list) {
-               if (mode->mode != phymode)
-                       continue;
-               for (r = 0; r < mode->num_rates; r++) {
-                       struct ieee80211_rate *rate = &mode->rates[r];
-                       if (rate->val == hw_rate ||
-                           (rate->flags & IEEE80211_RATE_PREAMBLE2 &&
-                            rate->val2 == hw_rate))
-                               return rate;
-               }
-       }
-
-       return NULL;
-}
-
-static void
-ieee80211_fill_frame_info(struct ieee80211_local *local,
-                         struct ieee80211_frame_info *fi,
-                         struct ieee80211_rx_status *status)
-{
-       if (status) {
-               struct timespec ts;
-               struct ieee80211_rate *rate;
-
-               jiffies_to_timespec(jiffies, &ts);
-               fi->hosttime = cpu_to_be64((u64) ts.tv_sec * 1000000 +
-                                          ts.tv_nsec / 1000);
-               fi->mactime = cpu_to_be64(status->mactime);
-               switch (status->phymode) {
-               case MODE_IEEE80211A:
-                       fi->phytype = htonl(ieee80211_phytype_ofdm_dot11_a);
-                       break;
-               case MODE_IEEE80211B:
-                       fi->phytype = htonl(ieee80211_phytype_dsss_dot11_b);
-                       break;
-               case MODE_IEEE80211G:
-                       fi->phytype = htonl(ieee80211_phytype_pbcc_dot11_g);
-                       break;
-               case MODE_ATHEROS_TURBO:
-                       fi->phytype =
-                               htonl(ieee80211_phytype_dsss_dot11_turbo);
-                       break;
-               default:
-                       fi->phytype = htonl(0xAAAAAAAA);
-                       break;
-               }
-               fi->channel = htonl(status->channel);
-               rate = ieee80211_get_rate(local, status->phymode,
-                                         status->rate);
-               if (rate) {
-                       fi->datarate = htonl(rate->rate);
-                       if (rate->flags & IEEE80211_RATE_PREAMBLE2) {
-                               if (status->rate == rate->val)
-                                       fi->preamble = htonl(2); /* long */
-                               else if (status->rate == rate->val2)
-                                       fi->preamble = htonl(1); /* short */
-                       } else
-                               fi->preamble = htonl(0);
-               } else {
-                       fi->datarate = htonl(0);
-                       fi->preamble = htonl(0);
-               }
-
-               fi->antenna = htonl(status->antenna);
-               fi->priority = htonl(0xffffffff); /* no clue */
-               fi->ssi_type = htonl(ieee80211_ssi_raw);
-               fi->ssi_signal = htonl(status->ssi);
-               fi->ssi_noise = 0x00000000;
-               fi->encoding = 0;
-       } else {
-               /* clear everything because we really don't know.
-                * the msg_type field isn't present on monitor frames
-                * so we don't know whether it will be present or not,
-                * but it's ok to not clear it since it'll be assigned
-                * anyway */
-               memset(fi, 0, sizeof(*fi) - sizeof(fi->msg_type));
-
-               fi->ssi_type = htonl(ieee80211_ssi_none);
-       }
-       fi->version = htonl(IEEE80211_FI_VERSION);
-       fi->length = cpu_to_be32(sizeof(*fi) - sizeof(fi->msg_type));
-}
-
-/* this routine is actually not just for this, but also
- * for pushing fake 'management' frames into userspace.
- * it shall be replaced by a netlink-based system. */
-void
-ieee80211_rx_mgmt(struct ieee80211_local *local, struct sk_buff *skb,
-                 struct ieee80211_rx_status *status, u32 msg_type)
-{
-       struct ieee80211_frame_info *fi;
-       const size_t hlen = sizeof(struct ieee80211_frame_info);
-       struct ieee80211_sub_if_data *sdata;
-
-       skb->dev = local->apdev;
-
-       sdata = IEEE80211_DEV_TO_SUB_IF(local->apdev);
-
-       if (skb_headroom(skb) < hlen) {
-               I802_DEBUG_INC(local->rx_expand_skb_head);
-               if (pskb_expand_head(skb, hlen, 0, GFP_ATOMIC)) {
-                       dev_kfree_skb(skb);
-                       return;
-               }
-       }
-
-       fi = (struct ieee80211_frame_info *) skb_push(skb, hlen);
-
-       ieee80211_fill_frame_info(local, fi, status);
-       fi->msg_type = htonl(msg_type);
-
-       sdata->stats.rx_packets++;
-       sdata->stats.rx_bytes += skb->len;
-
-       skb_set_mac_header(skb, 0);
-       skb->ip_summed = CHECKSUM_UNNECESSARY;
-       skb->pkt_type = PACKET_OTHERHOST;
-       skb->protocol = htons(ETH_P_802_2);
-       memset(skb->cb, 0, sizeof(skb->cb));
-       netif_rx(skb);
-}
-
-static void
-ieee80211_rx_monitor(struct net_device *dev, struct sk_buff *skb,
-                    struct ieee80211_rx_status *status)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_sub_if_data *sdata;
-       struct ieee80211_rate *rate;
-       struct ieee80211_rtap_hdr {
-               struct ieee80211_radiotap_header hdr;
-               u8 flags;
-               u8 rate;
-               __le16 chan_freq;
-               __le16 chan_flags;
-               u8 antsignal;
-       } __attribute__ ((packed)) *rthdr;
-
-       skb->dev = dev;
-
-       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-       if (status->flag & RX_FLAG_RADIOTAP)
-               goto out;
-
-       if (skb_headroom(skb) < sizeof(*rthdr)) {
-               I802_DEBUG_INC(local->rx_expand_skb_head);
-               if (pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) {
-                       dev_kfree_skb(skb);
-                       return;
-               }
-       }
-
-       rthdr = (struct ieee80211_rtap_hdr *) skb_push(skb, sizeof(*rthdr));
-       memset(rthdr, 0, sizeof(*rthdr));
-       rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
-       rthdr->hdr.it_present =
-               cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
-                           (1 << IEEE80211_RADIOTAP_RATE) |
-                           (1 << IEEE80211_RADIOTAP_CHANNEL) |
-                           (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL));
-       rthdr->flags = local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS ?
-                      IEEE80211_RADIOTAP_F_FCS : 0;
-       rate = ieee80211_get_rate(local, status->phymode, status->rate);
-       if (rate)
-               rthdr->rate = rate->rate / 5;
-       rthdr->chan_freq = cpu_to_le16(status->freq);
-       rthdr->chan_flags =
-               status->phymode == MODE_IEEE80211A ?
-               cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ) :
-               cpu_to_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ);
-       rthdr->antsignal = status->ssi;
-
- out:
-       sdata->stats.rx_packets++;
-       sdata->stats.rx_bytes += skb->len;
-
-       skb_set_mac_header(skb, 0);
-       skb->ip_summed = CHECKSUM_UNNECESSARY;
-       skb->pkt_type = PACKET_OTHERHOST;
-       skb->protocol = htons(ETH_P_802_2);
-       memset(skb->cb, 0, sizeof(skb->cb));
-       netif_rx(skb);
-}
-
-int ieee80211_radar_status(struct ieee80211_hw *hw, int channel,
-                          int radar, int radar_type)
-{
-       struct sk_buff *skb;
-       struct ieee80211_radar_info *msg;
-       struct ieee80211_local *local = hw_to_local(hw);
-
-       if (!local->apdev)
-               return 0;
-
-       skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
-                           sizeof(struct ieee80211_radar_info));
-
-       if (!skb)
-               return -ENOMEM;
-       skb_reserve(skb, sizeof(struct ieee80211_frame_info));
-
-       msg = (struct ieee80211_radar_info *)
-               skb_put(skb, sizeof(struct ieee80211_radar_info));
-       msg->channel = channel;
-       msg->radar = radar;
-       msg->radar_type = radar_type;
-
-       ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_radar);
-       return 0;
-}
-EXPORT_SYMBOL(ieee80211_radar_status);
-
-int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw, u8 *peer_address,
-                             u16 aid)
-{
-       struct sk_buff *skb;
-       struct ieee80211_msg_set_aid_for_sta *msg;
-       struct ieee80211_local *local = hw_to_local(hw);
-
-       /* unlikely because if this event only happens for APs,
-        * which require an open ap device. */
-       if (unlikely(!local->apdev))
-               return 0;
-
-       skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
-                           sizeof(struct ieee80211_msg_set_aid_for_sta));
-
-       if (!skb)
-               return -ENOMEM;
-       skb_reserve(skb, sizeof(struct ieee80211_frame_info));
-
-       msg = (struct ieee80211_msg_set_aid_for_sta *)
-               skb_put(skb, sizeof(struct ieee80211_msg_set_aid_for_sta));
-       memcpy(msg->sta_address, peer_address, ETH_ALEN);
-       msg->aid = aid;
-
-       ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_set_aid_for_sta);
-       return 0;
-}
-EXPORT_SYMBOL(ieee80211_set_aid_for_sta);
-
-static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
-{
-       struct ieee80211_sub_if_data *sdata;
-       sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
-
-       if (sdata->bss)
-               atomic_inc(&sdata->bss->num_sta_ps);
-       sta->flags |= WLAN_STA_PS;
-       sta->pspoll = 0;
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-       printk(KERN_DEBUG "%s: STA " MAC_FMT " aid %d enters power "
-              "save mode\n", dev->name, MAC_ARG(sta->addr), sta->aid);
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
-}
-
-
-static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct sk_buff *skb;
-       int sent = 0;
-       struct ieee80211_sub_if_data *sdata;
-       struct ieee80211_tx_packet_data *pkt_data;
-
-       sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
-       if (sdata->bss)
-               atomic_dec(&sdata->bss->num_sta_ps);
-       sta->flags &= ~(WLAN_STA_PS | WLAN_STA_TIM);
-       sta->pspoll = 0;
-       if (!skb_queue_empty(&sta->ps_tx_buf)) {
-               if (local->ops->set_tim)
-                       local->ops->set_tim(local_to_hw(local), sta->aid, 0);
-               if (sdata->bss)
-                       bss_tim_clear(local, sdata->bss, sta->aid);
-       }
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-       printk(KERN_DEBUG "%s: STA " MAC_FMT " aid %d exits power "
-              "save mode\n", dev->name, MAC_ARG(sta->addr), sta->aid);
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
-       /* Send all buffered frames to the station */
-       while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
-               pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
-               sent++;
-               pkt_data->requeue = 1;
-               dev_queue_xmit(skb);
-       }
-       while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
-               pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
-               local->total_ps_buffered--;
-               sent++;
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-               printk(KERN_DEBUG "%s: STA " MAC_FMT " aid %d send PS frame "
-                      "since STA not sleeping anymore\n", dev->name,
-                      MAC_ARG(sta->addr), sta->aid);
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
-               pkt_data->requeue = 1;
-               dev_queue_xmit(skb);
-       }
-
-       return sent;
-}
-
-
-static ieee80211_txrx_result
-ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
-{
-       struct sk_buff *skb;
-       int no_pending_pkts;
-
-       if (likely(!rx->sta ||
-                  (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL ||
-                  (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL ||
-                  !rx->u.rx.ra_match))
-               return TXRX_CONTINUE;
-
-       skb = skb_dequeue(&rx->sta->tx_filtered);
-       if (!skb) {
-               skb = skb_dequeue(&rx->sta->ps_tx_buf);
-               if (skb)
-                       rx->local->total_ps_buffered--;
-       }
-       no_pending_pkts = skb_queue_empty(&rx->sta->tx_filtered) &&
-               skb_queue_empty(&rx->sta->ps_tx_buf);
-
-       if (skb) {
-               struct ieee80211_hdr *hdr =
-                       (struct ieee80211_hdr *) skb->data;
-
-               /* tell TX path to send one frame even though the STA may
-                * still remain is PS mode after this frame exchange */
-               rx->sta->pspoll = 1;
-
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-               printk(KERN_DEBUG "STA " MAC_FMT " aid %d: PS Poll (entries "
-                      "after %d)\n",
-                      MAC_ARG(rx->sta->addr), rx->sta->aid,
-                      skb_queue_len(&rx->sta->ps_tx_buf));
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
-
-               /* Use MoreData flag to indicate whether there are more
-                * buffered frames for this STA */
-               if (no_pending_pkts) {
-                       hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
-                       rx->sta->flags &= ~WLAN_STA_TIM;
-               } else
-                       hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-
-               dev_queue_xmit(skb);
-
-               if (no_pending_pkts) {
-                       if (rx->local->ops->set_tim)
-                               rx->local->ops->set_tim(local_to_hw(rx->local),
-                                                      rx->sta->aid, 0);
-                       if (rx->sdata->bss)
-                               bss_tim_clear(rx->local, rx->sdata->bss, rx->sta->aid);
-               }
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-       } else if (!rx->u.rx.sent_ps_buffered) {
-               printk(KERN_DEBUG "%s: STA " MAC_FMT " sent PS Poll even "
-                      "though there is no buffered frames for it\n",
-                      rx->dev->name, MAC_ARG(rx->sta->addr));
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
-
-       }
-
-       /* Free PS Poll skb here instead of returning TXRX_DROP that would
-        * count as an dropped frame. */
-       dev_kfree_skb(rx->skb);
-
-       return TXRX_QUEUED;
-}
-
-
-static inline struct ieee80211_fragment_entry *
-ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
-                        unsigned int frag, unsigned int seq, int rx_queue,
-                        struct sk_buff **skb)
-{
-       struct ieee80211_fragment_entry *entry;
-       int idx;
-
-       idx = sdata->fragment_next;
-       entry = &sdata->fragments[sdata->fragment_next++];
-       if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)
-               sdata->fragment_next = 0;
-
-       if (!skb_queue_empty(&entry->skb_list)) {
-#ifdef CONFIG_MAC80211_DEBUG
-               struct ieee80211_hdr *hdr =
-                       (struct ieee80211_hdr *) entry->skb_list.next->data;
-               printk(KERN_DEBUG "%s: RX reassembly removed oldest "
-                      "fragment entry (idx=%d age=%lu seq=%d last_frag=%d "
-                      "addr1=" MAC_FMT " addr2=" MAC_FMT "\n",
-                      sdata->dev->name, idx,
-                      jiffies - entry->first_frag_time, entry->seq,
-                      entry->last_frag, MAC_ARG(hdr->addr1),
-                      MAC_ARG(hdr->addr2));
-#endif /* CONFIG_MAC80211_DEBUG */
-               __skb_queue_purge(&entry->skb_list);
-       }
-
-       __skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */
-       *skb = NULL;
-       entry->first_frag_time = jiffies;
-       entry->seq = seq;
-       entry->rx_queue = rx_queue;
-       entry->last_frag = frag;
-       entry->ccmp = 0;
-       entry->extra_len = 0;
-
-       return entry;
-}
-
-
-static inline struct ieee80211_fragment_entry *
-ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
-                         u16 fc, unsigned int frag, unsigned int seq,
-                         int rx_queue, struct ieee80211_hdr *hdr)
-{
-       struct ieee80211_fragment_entry *entry;
-       int i, idx;
-
-       idx = sdata->fragment_next;
-       for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
-               struct ieee80211_hdr *f_hdr;
-               u16 f_fc;
-
-               idx--;
-               if (idx < 0)
-                       idx = IEEE80211_FRAGMENT_MAX - 1;
-
-               entry = &sdata->fragments[idx];
-               if (skb_queue_empty(&entry->skb_list) || entry->seq != seq ||
-                   entry->rx_queue != rx_queue ||
-                   entry->last_frag + 1 != frag)
-                       continue;
-
-               f_hdr = (struct ieee80211_hdr *) entry->skb_list.next->data;
-               f_fc = le16_to_cpu(f_hdr->frame_control);
-
-               if ((fc & IEEE80211_FCTL_FTYPE) != (f_fc & IEEE80211_FCTL_FTYPE) ||
-                   compare_ether_addr(hdr->addr1, f_hdr->addr1) != 0 ||
-                   compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0)
-                       continue;
-
-               if (entry->first_frag_time + 2 * HZ < jiffies) {
-                       __skb_queue_purge(&entry->skb_list);
-                       continue;
-               }
-               return entry;
-       }
-
-       return NULL;
-}
-
-
-static ieee80211_txrx_result
-ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
-{
-       struct ieee80211_hdr *hdr;
-       u16 sc;
-       unsigned int frag, seq;
-       struct ieee80211_fragment_entry *entry;
-       struct sk_buff *skb;
-
-       hdr = (struct ieee80211_hdr *) rx->skb->data;
-       sc = le16_to_cpu(hdr->seq_ctrl);
-       frag = sc & IEEE80211_SCTL_FRAG;
-
-       if (likely((!(rx->fc & IEEE80211_FCTL_MOREFRAGS) && frag == 0) ||
-                  (rx->skb)->len < 24 ||
-                  is_multicast_ether_addr(hdr->addr1))) {
-               /* not fragmented */
-               goto out;
-       }
-       I802_DEBUG_INC(rx->local->rx_handlers_fragments);
-
-       seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
-
-       if (frag == 0) {
-               /* This is the first fragment of a new frame. */
-               entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
-                                                rx->u.rx.queue, &(rx->skb));
-               if (rx->key && rx->key->alg == ALG_CCMP &&
-                   (rx->fc & IEEE80211_FCTL_PROTECTED)) {
-                       /* Store CCMP PN so that we can verify that the next
-                        * fragment has a sequential PN value. */
-                       entry->ccmp = 1;
-                       memcpy(entry->last_pn,
-                              rx->key->u.ccmp.rx_pn[rx->u.rx.queue],
-                              CCMP_PN_LEN);
-               }
-               return TXRX_QUEUED;
-       }
-
-       /* This is a fragment for a frame that should already be pending in
-        * fragment cache. Add this fragment to the end of the pending entry.
-        */
-       entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq,
-                                         rx->u.rx.queue, hdr);
-       if (!entry) {
-               I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
-               return TXRX_DROP;
-       }
-
-       /* Verify that MPDUs within one MSDU have sequential PN values.
-        * (IEEE 802.11i, 8.3.3.4.5) */
-       if (entry->ccmp) {
-               int i;
-               u8 pn[CCMP_PN_LEN], *rpn;
-               if (!rx->key || rx->key->alg != ALG_CCMP)
-                       return TXRX_DROP;
-               memcpy(pn, entry->last_pn, CCMP_PN_LEN);
-               for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
-                       pn[i]++;
-                       if (pn[i])
-                               break;
-               }
-               rpn = rx->key->u.ccmp.rx_pn[rx->u.rx.queue];
-               if (memcmp(pn, rpn, CCMP_PN_LEN) != 0) {
-                       printk(KERN_DEBUG "%s: defrag: CCMP PN not sequential"
-                              " A2=" MAC_FMT " PN=%02x%02x%02x%02x%02x%02x "
-                              "(expected %02x%02x%02x%02x%02x%02x)\n",
-                              rx->dev->name, MAC_ARG(hdr->addr2),
-                              rpn[0], rpn[1], rpn[2], rpn[3], rpn[4], rpn[5],
-                              pn[0], pn[1], pn[2], pn[3], pn[4], pn[5]);
-                       return TXRX_DROP;
-               }
-               memcpy(entry->last_pn, pn, CCMP_PN_LEN);
-       }
-
-       skb_pull(rx->skb, ieee80211_get_hdrlen(rx->fc));
-       __skb_queue_tail(&entry->skb_list, rx->skb);
-       entry->last_frag = frag;
-       entry->extra_len += rx->skb->len;
-       if (rx->fc & IEEE80211_FCTL_MOREFRAGS) {
-               rx->skb = NULL;
-               return TXRX_QUEUED;
-       }
-
-       rx->skb = __skb_dequeue(&entry->skb_list);
-       if (skb_tailroom(rx->skb) < entry->extra_len) {
-               I802_DEBUG_INC(rx->local->rx_expand_skb_head2);
-               if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len,
-                                             GFP_ATOMIC))) {
-                       I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
-                       __skb_queue_purge(&entry->skb_list);
-                       return TXRX_DROP;
-               }
-       }
-       while ((skb = __skb_dequeue(&entry->skb_list))) {
-               memcpy(skb_put(rx->skb, skb->len), skb->data, skb->len);
-               dev_kfree_skb(skb);
-       }
-
-       /* Complete frame has been reassembled - process it now */
-       rx->fragmented = 1;
-
- out:
-       if (rx->sta)
-               rx->sta->rx_packets++;
-       if (is_multicast_ether_addr(hdr->addr1))
-               rx->local->dot11MulticastReceivedFrameCount++;
-       else
-               ieee80211_led_rx(rx->local);
-       return TXRX_CONTINUE;
-}
-
-
-static ieee80211_txrx_result
-ieee80211_rx_h_monitor(struct ieee80211_txrx_data *rx)
-{
-       if (rx->sdata->type == IEEE80211_IF_TYPE_MNTR) {
-               ieee80211_rx_monitor(rx->dev, rx->skb, rx->u.rx.status);
-               return TXRX_QUEUED;
-       }
-
-       if (rx->u.rx.status->flag & RX_FLAG_RADIOTAP)
-               skb_pull(rx->skb, ieee80211_get_radiotap_len(rx->skb));
-
-       return TXRX_CONTINUE;
-}
-
-
-static ieee80211_txrx_result
-ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
-{
-       struct ieee80211_hdr *hdr;
-       int always_sta_key;
-       hdr = (struct ieee80211_hdr *) rx->skb->data;
-
-       /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
-       if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
-               if (unlikely(rx->fc & IEEE80211_FCTL_RETRY &&
-                            rx->sta->last_seq_ctrl[rx->u.rx.queue] ==
-                            hdr->seq_ctrl)) {
-                       if (rx->u.rx.ra_match) {
-&n