diff --git a/package/hostapd/Makefile b/package/hostapd/Makefile index 85f42dc6a1..d7910737b6 100644 --- a/package/hostapd/Makefile +++ b/package/hostapd/Makefile @@ -9,14 +9,15 @@ include $(TOPDIR)/rules.mk PKG_NAME:=hostapd -PKG_VERSION:=0.5.8 +PKG_REV:=03ec0ec5cdb974d51a4a2a566bea4c4568138576 +PKG_VERSION:=20071107_$(PKG_REV) PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=http://hostap.epitest.fi/releases/ -PKG_MD5SUM:=40416b48cae9c78e5a2452caf214aff3 - -PKG_BUILD_DEPENDS:=madwifi +PKG_SOURCE_URL:=git://w1.fi/srv/git/hostap.git +PKG_SOURCE_SUBDIR:=hostapd-$(PKG_VERSION) +PKG_SOURCE_VERSION:=$(PKG_REV) +PKG_BUILD_DEPENDS:=madwifi mac80211 include $(INCLUDE_DIR)/package.mk @@ -25,7 +26,7 @@ define Package/hostapd/Default CATEGORY:=Network TITLE:=IEEE 802.1x Authenticator URL:=http://hostap.epitest.fi/ - DEPENDS:=@!TARGET_avr32 @!TARGET_etrax + DEPENDS:=@!TARGET_avr32 @!TARGET_etrax $(if $(DUMP)$(CONFIG_LINUX_2_6_23),+libnl) endef define Package/hostapd @@ -34,9 +35,9 @@ $(call Package/hostapd/Default) DEPENDS+= +libopenssl endef -define Package/hostapd/conffiles -/etc/hostapd.conf -endef +#define Package/hostapd/conffiles +#/etc/hostapd.conf +#endef define Package/hostapd/description This package contains a full featured IEEE 802.1x/WPA/EAP/RADIUS @@ -48,9 +49,9 @@ $(call Package/hostapd/Default) TITLE+= (WPA-PSK only) endef -define Package/hostapd-mini/conffiles -/etc/hostapd.conf -endef +#define Package/hostapd-mini/conffiles +#/etc/hostapd.conf +#endef define Package/hostapd-mini/description This package contains a minimal IEEE 802.1x/WPA/EAP/RADIUS Authenticator @@ -69,38 +70,31 @@ define Package/hostapd-utils/description endef define Build/ConfigureTarget - $(CP) $(PKG_BUILD_DIR) $(PKG_BUILD_DIR)_$(1) - $(CP) ./files/$(1).config $(PKG_BUILD_DIR)_$(1)/.config -ifneq ($(CONFIG_PACKAGE_kmod-madwifi),) - echo "CONFIG_DRIVER_MADWIFI=y" >> $(PKG_BUILD_DIR)_$(1)/.config -endif + rm -rf $(PKG_BUILD_DIR)/hostapd.$(1) + $(CP) $(PKG_BUILD_DIR)/hostapd $(PKG_BUILD_DIR)/hostapd.$(1) + $(CP) ./files/$(1).config $(PKG_BUILD_DIR)/hostapd.$(1)/.config + [ -d $(STAGING_DIR)/usr/include/mac80211 ] || $(SED) 's,^CONFIG_DRIVER_DEVICESCAPE,#CONFIG_DRIVER_DEVICESCAPE,g' $(PKG_BUILD_DIR)/hostapd.$(1)/.config + [ -d $(STAGING_DIR)/usr/include/madwifi ] || $(SED) 's,^CONFIG_DRIVER_MADWIFI,#CONFIG_DRIVER_MADWIFI,g' $(PKG_BUILD_DIR)/hostapd.$(1)/.config endef define Build/CompileTarget - $(MAKE) -C $(PKG_BUILD_DIR)_$(1) \ + CFLAGS="$(TARGET_CFLAGS) -I$(STAGING_DIR)/usr/include/madwifi -I$(STAGING_DIR)/usr/include/mac80211 -I$(STAGING_DIR)/usr/include" \ + $(MAKE) -C $(PKG_BUILD_DIR)/hostapd.$(1) \ $(TARGET_CONFIGURE_OPTS) \ - OPTFLAGS="$(TARGET_CFLAGS)" \ - CPPFLAGS="$(TARGET_CPPFLAGS) -I$(STAGING_DIR)/usr/include/madwifi" \ - LDFLAGS="$(TARGET_LDFLAGS)" \ + LIBS="$(TARGET_LDFLAGS) -L$(STAGING_DIR)/usr/lib \ + $(if $(wildcard $(STAGING_DIR)/usr/include/mac80211/*),-lnl)" \ hostapd hostapd_cli - $(CP) $(PKG_BUILD_DIR)_$(1)/hostapd_cli $(PKG_BUILD_DIR)/ + $(CP) $(PKG_BUILD_DIR)/hostapd.$(1)/hostapd_cli $(PKG_BUILD_DIR)/ endef define Package/InstallTemplate - if [ \! -f "$(PKG_BUILD_DIR)_$(2)/hostapd" ]; then \ - rm -f $(PKG_BUILD_DIR)/.built; \ - $(MAKE) $(PKG_BUILD_DIR)/.built; \ - fi $(INSTALL_DIR) $$(1)/lib/wifi $(INSTALL_DATA) ./files/hostapd.sh $$(1)/lib/wifi/hostapd.sh - $(INSTALL_DIR) $$(1)/etc -ifneq ($(CONFIG_PACKAGE_kmod-madwifi),) - $(INSTALL_CONF) $(PKG_BUILD_DIR)_$(2)/madwifi.conf $$(1)/etc/hostapd.conf -else - $(INSTALL_CONF) $(PKG_BUILD_DIR)_$(2)/hostapd.conf $$(1)/etc/hostapd.conf -endif +# config is managed through uci +# $(INSTALL_DIR) $$(1)/etc +# $(INSTALL_CONF) $(PKG_BUILD_DIR)/hostapd.$(2)/hostapd.conf $$(1)/etc/hostapd.conf $(INSTALL_DIR) $$(1)/usr/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)_$(2)/hostapd $$(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostapd.$(2)/hostapd $$(1)/usr/sbin/ endef define Package/Template diff --git a/package/hostapd/files/default.config b/package/hostapd/files/default.config index de27420b9d..700217dada 100644 --- a/package/hostapd/files/default.config +++ b/package/hostapd/files/default.config @@ -13,15 +13,29 @@ CONFIG_DRIVER_HOSTAP=y # Driver interface for wired authenticator -#CONFIG_DRIVER_WIRED=y +CONFIG_DRIVER_WIRED=y # Driver interface for madwifi driver -#CONFIG_DRIVER_MADWIFI=y +CONFIG_DRIVER_MADWIFI=y #CFLAGS += -I../head # change to reflect local setup; directory for madwifi src # Driver interface for Prism54 driver #CONFIG_DRIVER_PRISM54=y +# Driver interface for drivers using Devicescape IEEE 802.11 stack +CONFIG_DRIVER_DEVICESCAPE=y +# Currently, driver_devicescape.c build requires some additional parameters +# to be able to include some of the kernel header files. Following lines can +# be used to set these (WIRELESS_DEV must point to the root directory of the +# wireless-dev.git tree). +#WIRELESS_DEV=/usr/src/wireless-dev +#CFLAGS += -I$(WIRELESS_DEV)/net/mac80211 +# driver_devicescape.c requires a rather new libnl, probably not +# shipped with your distribution yet +#LIBNL=/usr/src/libnl +#CFLAGS += -I$(LIBNL)/include +#LIBS += -L$(LIBNL)/lib + # Driver interface for FreeBSD net80211 layer (e.g., Atheros driver) #CONFIG_DRIVER_BSD=y #CFLAGS += -I/usr/local/include @@ -33,37 +47,76 @@ CONFIG_IAPP=y # WPA2/IEEE 802.11i RSN pre-authentication CONFIG_RSN_PREAUTH=y -# Integrated EAP authenticator +# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS) +CONFIG_PEERKEY=y + +# IEEE 802.11w (management frame protection) +# This version is an experimental implementation based on IEEE 802.11w/D1.0 +# draft and is subject to change since the standard has not yet been finalized. +# Driver support is also needed for IEEE 802.11w. +#CONFIG_IEEE80211W=y + +# Integrated EAP server CONFIG_EAP=y -# EAP-MD5 for the integrated EAP authenticator +# EAP-MD5 for the integrated EAP server CONFIG_EAP_MD5=y -# EAP-TLS for the integrated EAP authenticator +# EAP-TLS for the integrated EAP server CONFIG_EAP_TLS=y -# EAP-MSCHAPv2 for the integrated EAP authenticator +# EAP-MSCHAPv2 for the integrated EAP server CONFIG_EAP_MSCHAPV2=y -# EAP-PEAP for the integrated EAP authenticator +# EAP-PEAP for the integrated EAP server CONFIG_EAP_PEAP=y -# EAP-PSK for the integrated EAP authenticator -CONFIG_EAP_PSK=y - -# EAP-GTC for the integrated EAP authenticator +# EAP-GTC for the integrated EAP server CONFIG_EAP_GTC=y -# EAP-TTLS for the integrated EAP authenticator +# EAP-TTLS for the integrated EAP server CONFIG_EAP_TTLS=y -# EAP-SIM for the integrated EAP authenticator +# EAP-SIM for the integrated EAP server #CONFIG_EAP_SIM=y +# EAP-AKA for the integrated EAP server +#CONFIG_EAP_AKA=y + +# EAP-PAX for the integrated EAP server +#CONFIG_EAP_PAX=y + +# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK) +#CONFIG_EAP_PSK=y + +# EAP-SAKE for the integrated EAP server +#CONFIG_EAP_SAKE=y + +# EAP-GPSK for the integrated EAP server +#CONFIG_EAP_GPSK=y +# Include support for optional SHA256 cipher suite in EAP-GPSK +#CONFIG_EAP_GPSK_SHA256=y + +# EAP-FAST for the integrated EAP server +# Note: Default OpenSSL package does not include support for all the +# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL, +# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch) +# to add the needed functions. +#CONFIG_EAP_FAST=y + # PKCS#12 (PFX) support (used to read private key and certificate file from # a file that usually has extension .p12 or .pfx) CONFIG_PKCS12=y # RADIUS authentication server. This provides access to the integrated EAP -# authenticator from external hosts using RADIUS. +# server from external hosts using RADIUS. #CONFIG_RADIUS_SERVER=y + +# Build IPv6 support for RADIUS operations +CONFIG_IPV6=y + +# IEEE 802.11r/D4.1 (Fast BSS Transition) +# This enables an experimental implementation of a draft version of +# IEEE 802.11r. This draft is still subject to change, so it should be noted +# that this version may not comply with the final standard. +#CONFIG_IEEE80211R=y diff --git a/package/hostapd/files/mini.config b/package/hostapd/files/mini.config index cfdc485eed..a2f3f62bba 100644 --- a/package/hostapd/files/mini.config +++ b/package/hostapd/files/mini.config @@ -13,15 +13,29 @@ CONFIG_DRIVER_HOSTAP=y # Driver interface for wired authenticator -#CONFIG_DRIVER_WIRED=y +CONFIG_DRIVER_WIRED=y # Driver interface for madwifi driver -#CONFIG_DRIVER_MADWIFI=y +CONFIG_DRIVER_MADWIFI=y #CFLAGS += -I../head # change to reflect local setup; directory for madwifi src # Driver interface for Prism54 driver #CONFIG_DRIVER_PRISM54=y +# Driver interface for drivers using Devicescape IEEE 802.11 stack +CONFIG_DRIVER_DEVICESCAPE=y +# Currently, driver_devicescape.c build requires some additional parameters +# to be able to include some of the kernel header files. Following lines can +# be used to set these (WIRELESS_DEV must point to the root directory of the +# wireless-dev.git tree). +#WIRELESS_DEV=/usr/src/wireless-dev +#CFLAGS += -I$(WIRELESS_DEV)/net/mac80211 +# driver_devicescape.c requires a rather new libnl, probably not +# shipped with your distribution yet +#LIBNL=/usr/src/libnl +#CFLAGS += -I$(LIBNL)/include +#LIBS += -L$(LIBNL)/lib + # Driver interface for FreeBSD net80211 layer (e.g., Atheros driver) #CONFIG_DRIVER_BSD=y #CFLAGS += -I/usr/local/include @@ -33,37 +47,76 @@ CONFIG_IAPP=y # WPA2/IEEE 802.11i RSN pre-authentication CONFIG_RSN_PREAUTH=y -# Integrated EAP authenticator -CONFIG_EAP=y +# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS) +CONFIG_PEERKEY=y -# EAP-MD5 for the integrated EAP authenticator +# IEEE 802.11w (management frame protection) +# This version is an experimental implementation based on IEEE 802.11w/D1.0 +# draft and is subject to change since the standard has not yet been finalized. +# Driver support is also needed for IEEE 802.11w. +#CONFIG_IEEE80211W=y + +# Integrated EAP server +#CONFIG_EAP=y + +# EAP-MD5 for the integrated EAP server #CONFIG_EAP_MD5=y -# EAP-TLS for the integrated EAP authenticator +# EAP-TLS for the integrated EAP server #CONFIG_EAP_TLS=y -# EAP-MSCHAPv2 for the integrated EAP authenticator +# EAP-MSCHAPv2 for the integrated EAP server #CONFIG_EAP_MSCHAPV2=y -# EAP-PEAP for the integrated EAP authenticator +# EAP-PEAP for the integrated EAP server #CONFIG_EAP_PEAP=y -# EAP-PSK for the integrated EAP authenticator -CONFIG_EAP_PSK=y - -# EAP-GTC for the integrated EAP authenticator +# EAP-GTC for the integrated EAP server #CONFIG_EAP_GTC=y -# EAP-TTLS for the integrated EAP authenticator +# EAP-TTLS for the integrated EAP server #CONFIG_EAP_TTLS=y -# EAP-SIM for the integrated EAP authenticator +# EAP-SIM for the integrated EAP server #CONFIG_EAP_SIM=y +# EAP-AKA for the integrated EAP server +#CONFIG_EAP_AKA=y + +# EAP-PAX for the integrated EAP server +#CONFIG_EAP_PAX=y + +# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK) +#CONFIG_EAP_PSK=y + +# EAP-SAKE for the integrated EAP server +#CONFIG_EAP_SAKE=y + +# EAP-GPSK for the integrated EAP server +#CONFIG_EAP_GPSK=y +# Include support for optional SHA256 cipher suite in EAP-GPSK +#CONFIG_EAP_GPSK_SHA256=y + +# EAP-FAST for the integrated EAP server +# Note: Default OpenSSL package does not include support for all the +# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL, +# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch) +# to add the needed functions. +#CONFIG_EAP_FAST=y + # PKCS#12 (PFX) support (used to read private key and certificate file from # a file that usually has extension .p12 or .pfx) #CONFIG_PKCS12=y # RADIUS authentication server. This provides access to the integrated EAP -# authenticator from external hosts using RADIUS. +# server from external hosts using RADIUS. #CONFIG_RADIUS_SERVER=y + +# Build IPv6 support for RADIUS operations +#CONFIG_IPV6=y + +# IEEE 802.11r/D4.1 (Fast BSS Transition) +# This enables an experimental implementation of a draft version of +# IEEE 802.11r. This draft is still subject to change, so it should be noted +# that this version may not comply with the final standard. +#CONFIG_IEEE80211R=y diff --git a/package/hostapd/patches/001-cross_compile_fix.patch b/package/hostapd/patches/001-cross_compile_fix.patch deleted file mode 100644 index 669264cb64..0000000000 --- a/package/hostapd/patches/001-cross_compile_fix.patch +++ /dev/null @@ -1,36 +0,0 @@ -Common subdirectories: hostapd-0.5.2/logwatch and hostapd-0.5.2.new/logwatch -Index: hostapd-0.5.7/Makefile -=================================================================== ---- hostapd-0.5.7.orig/Makefile 2007-06-04 13:22:31.790022464 +0200 -+++ hostapd-0.5.7/Makefile 2007-06-04 13:22:31.856012432 +0200 -@@ -2,7 +2,7 @@ - DIR_WPA_SUPPLICANT=. - - ifndef CFLAGS --CFLAGS = -MMD -O2 -Wall -g -+CFLAGS = -MMD $(OPTFLAGS) $(CPPFLAGS) - endif - - # define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to -@@ -336,7 +336,7 @@ - for i in $(ALL); do cp $$i /usr/local/bin/$$i; done - - hostapd: $(OBJS) -- $(CC) -o hostapd $(OBJS) $(LIBS) -+ $(CC) -o hostapd $(OBJS) $(LDFLAGS) $(LIBS) - - driver_conf.c: Makefile .config - rm -f driver_conf.c -@@ -400,10 +400,10 @@ - endif - - nt_password_hash: $(NOBJS) -- $(CC) -o nt_password_hash $(NOBJS) $(LIBS_n) -+ $(CC) -o nt_password_hash $(NOBJS) $(LDFLAGS) $(LIBS_n) - - hlr_auc_gw: $(HOBJS) -- $(CC) -o hlr_auc_gw $(HOBJS) $(LIBS_h) -+ $(CC) -o hlr_auc_gw $(HOBJS) $(LDFLAGS) $(LIBS_h) - - clean: - rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw diff --git a/package/hostapd/patches/001-remove-michael-mic.patch b/package/hostapd/patches/001-remove-michael-mic.patch new file mode 100644 index 0000000000..de76c06930 --- /dev/null +++ b/package/hostapd/patches/001-remove-michael-mic.patch @@ -0,0 +1,18 @@ +--- + hostapd/driver_devicescape.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- hostap.orig/hostapd/driver_devicescape.c 2007-11-09 13:41:08.000000000 +0100 ++++ hostap/hostapd/driver_devicescape.c 2007-11-09 13:41:12.000000000 +0100 +@@ -1386,10 +1386,10 @@ static void handle_frame(struct hostapd_ + case ieee80211_msg_wep_frame_unknown_key: + ieee802_11_rx_unknown_key(hapd, buf, data_len); + return; +- */ + case ieee80211_msg_michael_mic_failure: + hostapd_michael_mic_failure(hapd, buf, data_len); + return; ++ */ + /* + * TODO + * We should be telling them to go away. But we don't support that now. diff --git a/package/hostapd/patches/002-use-nl80211-for-keys.patch b/package/hostapd/patches/002-use-nl80211-for-keys.patch new file mode 100644 index 0000000000..6b7fe80984 --- /dev/null +++ b/package/hostapd/patches/002-use-nl80211-for-keys.patch @@ -0,0 +1,112 @@ +--- + hostapd/driver_devicescape.c | 93 ++++++++++++++++++++++++++++++------------- + 1 file changed, 67 insertions(+), 26 deletions(-) + +--- hostap.orig/hostapd/driver_devicescape.c 2007-11-09 13:41:12.000000000 +0100 ++++ hostap/hostapd/driver_devicescape.c 2007-11-09 13:41:13.000000000 +0100 +@@ -150,38 +150,79 @@ static int i802_set_encryption(const cha + size_t key_len, int txkey) + { + struct i802_driver_data *drv = priv; +- struct prism2_hostapd_param *param; +- u8 *buf; +- size_t blen; +- int ret = 0; ++ struct nl_msg *msg; ++ int ret = -1; ++ int err = 0; + +- blen = sizeof(*param) + key_len; +- buf = os_zalloc(blen); +- if (buf == NULL) +- return -1; ++ msg = nlmsg_alloc(); ++ if (!msg) ++ goto out; + +- param = (struct prism2_hostapd_param *) buf; +- param->cmd = PRISM2_SET_ENCRYPTION; +- if (addr == NULL) +- memset(param->sta_addr, 0xff, ETH_ALEN); +- else +- memcpy(param->sta_addr, addr, ETH_ALEN); +- os_strlcpy((char *) param->u.crypt.alg, alg, +- HOSTAP_CRYPT_ALG_NAME_LEN); +- param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; +- param->u.crypt.idx = idx; +- param->u.crypt.key_len = key_len; +- memcpy(param->u.crypt.key, key, key_len); ++ if (strcmp(alg, "none") == 0) { ++ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++ 0, NL80211_CMD_DEL_KEY, 0); ++ } else { ++ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++ 0, NL80211_CMD_NEW_KEY, 0); ++ NLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key); ++ if (strcmp(alg, "WEP") == 0) { ++ if (key_len == 5) ++ NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, ++ 0x000FAC01); ++ else ++ NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, ++ 0x000FAC05); ++ } else if (strcmp(alg, "TKIP") == 0) ++ NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC02); ++ else if (strcmp(alg, "CCMP") == 0) ++ NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC04); ++ else ++ goto out; ++ } + +- if (hostapd_ioctl_iface(iface, drv, param, blen) && errno != ENOENT) { +- printf("%s: Failed to set encryption to alg '%s' addr " MACSTR +- " errno=%d\n", +- iface, alg, MAC2STR(param->sta_addr), errno); +- ret = -1; ++ if (addr) ++ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); ++ NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx); ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface)); ++ ++ if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || ++ (err = nl_wait_for_ack(drv->nl_handle)) < 0) { ++ if (err != -ENOENT) { ++ err = 0; ++ goto out; ++ } + } + +- free(buf); ++ if (!txkey) { ++ ret = 0; ++ goto out; ++ } ++ ++ nlmsg_free(msg); ++ ++ msg = nlmsg_alloc(); ++ if (!msg) ++ goto out; + ++ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++ 0, NL80211_CMD_SET_KEY, 0); ++ NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx); ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface)); ++ NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT); ++ ++ if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || ++ (err = nl_wait_for_ack(drv->nl_handle)) < 0) { ++ if (err != -ENOENT) { ++ err = 0; ++ goto out; ++ } ++ } ++ ++ ret = 0; ++ ++ out: ++ nla_put_failure: ++ nlmsg_free(msg); + return ret; + } + diff --git a/package/hostapd/patches/003-use-nl80211-for-beacons.patch b/package/hostapd/patches/003-use-nl80211-for-beacons.patch new file mode 100644 index 0000000000..34fa841d61 --- /dev/null +++ b/package/hostapd/patches/003-use-nl80211-for-beacons.patch @@ -0,0 +1,149 @@ +--- + hostapd/driver_devicescape.c | 111 +++++++++++++++++++++++++++++++------------ + 1 file changed, 82 insertions(+), 29 deletions(-) + +--- hostap.orig/hostapd/driver_devicescape.c 2007-11-09 13:41:13.000000000 +0100 ++++ hostap/hostapd/driver_devicescape.c 2007-11-09 13:41:13.000000000 +0100 +@@ -68,6 +68,8 @@ struct i802_driver_data { + struct nl_handle *nl_handle; + struct nl_cache *nl_cache; + struct genl_family *nl80211; ++ int dtim_period; ++ unsigned int beacon_set:1; + }; + + +@@ -908,37 +910,44 @@ static int i802_bss_remove(void *priv, c + } + + +-static int i802_set_beacon(const char *ifname, void *priv, ++static int i802_set_beacon(const char *iface, void *priv, + u8 *head, size_t head_len, + u8 *tail, size_t tail_len) + { + struct i802_driver_data *drv = priv; +- struct prism2_hostapd_param *param; +- int len, ret = 0; ++ struct nl_msg *msg; ++ u8 cmd = NL80211_CMD_NEW_BEACON; ++ int ret = -1; + +- param = os_zalloc(sizeof(*param) + head_len + tail_len); +- if (param == NULL) { +- printf("Failed to alloc memory for beacon ioctl\n"); +- return -1; +- } +- len = (¶m->u.beacon.data[0] - (u8 *) param) + head_len + tail_len; +- param->cmd = PRISM2_HOSTAPD_SET_BEACON; +- param->u.beacon.head_len = head_len; +- param->u.beacon.tail_len = tail_len; +- memcpy(¶m->u.beacon.data[0], head, head_len); +- memcpy(¶m->u.beacon.data[0] + head_len, tail, tail_len); +- +- if (len < (int) sizeof(*param)) +- len = sizeof(*param); +- if (hostapd_ioctl_iface(ifname, drv, param, len)) { +- printf("Could not set beacon data to kernel driver.\n"); +- printf("ifname='%s' head=%p head_len=%d tail=%p tail_len=%d " +- "cmd=%d\n", +- ifname, head, head_len, tail, tail_len, param->cmd); +- ret = -1; +- } ++ msg = nlmsg_alloc(); ++ if (!msg) ++ goto out; + +- free(param); ++ if (drv->beacon_set) ++ cmd = NL80211_CMD_SET_BEACON; ++ ++ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++ 0, cmd, 0); ++ NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, head_len, head); ++ NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, tail_len, tail); ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface)); ++ NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, 1000); ++ ++ if (!drv->dtim_period) ++ drv->dtim_period = 2; ++ NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period); ++ ++ if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || ++ nl_wait_for_ack(drv->nl_handle) < 0) ++ goto out; ++ ++ ret = 0; ++ ++ drv->beacon_set = 1; ++ ++ out: ++ nla_put_failure: ++ nlmsg_free(msg); + return ret; + } + +@@ -985,15 +994,59 @@ static int i802_set_internal_bridge(void + static int i802_set_beacon_int(void *priv, int value) + { + struct i802_driver_data *drv = priv; +- return hostap_ioctl_prism2param(drv, PRISM2_PARAM_BEACON_INT, value); ++ struct nl_msg *msg; ++ int ret = -1; ++ ++ msg = nlmsg_alloc(); ++ if (!msg) ++ goto out; ++ ++ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++ 0, NL80211_CMD_SET_BEACON, 0); ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); ++ ++ NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, value); ++ ++ if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || ++ nl_wait_for_ack(drv->nl_handle) < 0) ++ goto out; ++ ++ ret = 0; ++ ++ out: ++ nla_put_failure: ++ nlmsg_free(msg); ++ return ret; + } + + +-static int i802_set_dtim_period(const char *ifname, void *priv, int value) ++static int i802_set_dtim_period(const char *iface, void *priv, int value) + { + struct i802_driver_data *drv = priv; +- return hostap_ioctl_prism2param_iface(ifname, drv, +- PRISM2_PARAM_DTIM_PERIOD, value); ++ struct nl_msg *msg; ++ int ret = -1; ++ ++ msg = nlmsg_alloc(); ++ if (!msg) ++ goto out; ++ ++ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++ 0, NL80211_CMD_SET_BEACON, 0); ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface)); ++ ++ drv->dtim_period = value; ++ NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period); ++ ++ if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || ++ nl_wait_for_ack(drv->nl_handle) < 0) ++ goto out; ++ ++ ret = 0; ++ ++ out: ++ nla_put_failure: ++ nlmsg_free(msg); ++ return ret; + } + + diff --git a/package/hostapd/patches/004-use-nl80211-for-get-key.patch b/package/hostapd/patches/004-use-nl80211-for-get-key.patch new file mode 100644 index 0000000000..142c1939d2 --- /dev/null +++ b/package/hostapd/patches/004-use-nl80211-for-get-key.patch @@ -0,0 +1,116 @@ +--- + hostapd/driver_devicescape.c | 96 ++++++++++++++++++++++++++++++++++--------- + 1 file changed, 76 insertions(+), 20 deletions(-) + +--- hostap.orig/hostapd/driver_devicescape.c 2007-11-09 13:41:13.000000000 +0100 ++++ hostap/hostapd/driver_devicescape.c 2007-11-09 13:41:14.000000000 +0100 +@@ -228,33 +228,89 @@ static int i802_set_encryption(const cha + return ret; + } + ++static inline int min_int(int a, int b) ++{ ++ if (acmd = PRISM2_GET_ENCRYPTION; +- if (addr == NULL) +- memset(param->sta_addr, 0xff, ETH_ALEN); +- else +- memcpy(param->sta_addr, addr, ETH_ALEN); +- param->u.crypt.idx = idx; +- +- ret = hostapd_ioctl_iface(iface, drv, param, param_len); +- if (ret == 0) { +- memcpy(seq, param->u.crypt.seq_counter, +- HOSTAP_SEQ_COUNTER_SIZE); +- } +- free(param); ++ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++ 0, NL80211_CMD_GET_KEY, 0); ++ ++ if (addr) ++ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); ++ NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx); ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface)); ++ ++ cb = nl_cb_alloc(NL_CB_CUSTOM); ++ if (!cb) ++ goto out; ++ ++ memset(seq, 0, 6); ++ ++ if (nl_send_auto_complete(drv->nl_handle, msg) < 0) ++ goto out; ++ ++ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_key_handler, seq); ++ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished); ++ ++ err = nl_recvmsgs(drv->nl_handle, cb); ++ ++ if (!finished) ++ err = nl_wait_for_ack(drv->nl_handle); ++ ++ if (err < 0) ++ goto out; ++ ++ ret = 0; ++ ++ out: ++ nl_cb_put(cb); ++ nla_put_failure: ++ nlmsg_free(msg); + return ret; + } + diff --git a/package/hostapd/patches/005-pass-full-flags-to-sta-function.patch b/package/hostapd/patches/005-pass-full-flags-to-sta-function.patch new file mode 100644 index 0000000000..11c8c5fd46 --- /dev/null +++ b/package/hostapd/patches/005-pass-full-flags-to-sta-function.patch @@ -0,0 +1,173 @@ +--- + hostapd/driver.h | 8 ++++---- + hostapd/driver_bsd.c | 3 ++- + hostapd/driver_devicescape.c | 6 +++--- + hostapd/driver_hostap.c | 4 ++-- + hostapd/driver_madwifi.c | 3 ++- + hostapd/driver_prism54.c | 3 ++- + hostapd/ieee802_11.c | 4 ++-- + hostapd/ieee802_1x.c | 4 ++-- + hostapd/wme.c | 6 ++++-- + 9 files changed, 23 insertions(+), 18 deletions(-) + +--- hostap.orig/hostapd/driver.h 2007-11-09 13:41:07.000000000 +0100 ++++ hostap/hostapd/driver.h 2007-11-09 13:41:15.000000000 +0100 +@@ -92,7 +92,7 @@ struct wpa_driver_ops { + int (*get_retry)(void *priv, int *short_retry, int *long_retry); + + int (*sta_set_flags)(void *priv, const u8 *addr, +- int flags_or, int flags_and); ++ int total_flags, int flags_or, int flags_and); + int (*set_rate_sets)(void *priv, int *supp_rates, int *basic_rates, + int mode); + int (*set_channel_flag)(void *priv, int mode, int chan, int flag, +@@ -427,12 +427,12 @@ hostapd_get_retry(struct hostapd_data *h + + static inline int + hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, +- int flags_or, int flags_and) ++ int total_flags, int flags_or, int flags_and) + { + if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL) + return 0; +- return hapd->driver->sta_set_flags(hapd->drv_priv, addr, flags_or, +- flags_and); ++ return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags, ++ flags_or, flags_and); + } + + static inline int +--- hostap.orig/hostapd/driver_bsd.c 2007-11-09 13:41:07.000000000 +0100 ++++ hostap/hostapd/driver_bsd.c 2007-11-09 13:41:15.000000000 +0100 +@@ -322,7 +322,8 @@ bsd_set_sta_authorized(void *priv, const + } + + static int +-bsd_sta_set_flags(void *priv, const u8 *addr, int flags_or, int flags_and) ++bsd_sta_set_flags(void *priv, const u8 *addr, int total_flags, int flags_or, ++ int flags_and) + { + /* For now, only support setting Authorized flag */ + if (flags_or & WLAN_STA_AUTHORIZED) +--- hostap.orig/hostapd/driver_devicescape.c 2007-11-09 13:41:14.000000000 +0100 ++++ hostap/hostapd/driver_devicescape.c 2007-11-09 13:41:15.000000000 +0100 +@@ -76,7 +76,7 @@ struct i802_driver_data { + #define HAPD_DECL struct hostapd_data *hapd = iface->bss[0] + + static int i802_sta_set_flags(void *priv, const u8 *addr, +- int flags_or, int flags_and); ++ int total_flags, int flags_or, int flags_and); + + + static int hostapd_set_iface_flags(struct i802_driver_data *drv, int dev_up) +@@ -765,7 +765,7 @@ static int i802_sta_remove(void *priv, c + struct i802_driver_data *drv = priv; + struct prism2_hostapd_param param; + +- i802_sta_set_flags(drv, addr, 0, ~WLAN_STA_AUTHORIZED); ++ i802_sta_set_flags(drv, addr, 0, 0, ~WLAN_STA_AUTHORIZED); + + memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_REMOVE_STA; +@@ -777,7 +777,7 @@ static int i802_sta_remove(void *priv, c + + + static int i802_sta_set_flags(void *priv, const u8 *addr, +- int flags_or, int flags_and) ++ int total_flags, int flags_or, int flags_and) + { + struct i802_driver_data *drv = priv; + struct prism2_hostapd_param param; +--- hostap.orig/hostapd/driver_hostap.c 2007-11-09 13:41:07.000000000 +0100 ++++ hostap/hostapd/driver_hostap.c 2007-11-09 13:41:15.000000000 +0100 +@@ -374,7 +374,7 @@ static int hostap_send_eapol(void *priv, + + + static int hostap_sta_set_flags(void *priv, const u8 *addr, +- int flags_or, int flags_and) ++ int total_flags, int flags_or, int flags_and) + { + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param param; +@@ -694,7 +694,7 @@ static int hostap_sta_remove(void *priv, + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param param; + +- hostap_sta_set_flags(drv, addr, 0, ~WLAN_STA_AUTHORIZED); ++ hostap_sta_set_flags(drv, addr, 0, 0, ~WLAN_STA_AUTHORIZED); + + memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_REMOVE_STA; +--- hostap.orig/hostapd/driver_madwifi.c 2007-11-09 13:41:07.000000000 +0100 ++++ hostap/hostapd/driver_madwifi.c 2007-11-09 13:41:15.000000000 +0100 +@@ -410,7 +410,8 @@ madwifi_set_sta_authorized(void *priv, c + } + + static int +-madwifi_sta_set_flags(void *priv, const u8 *addr, int flags_or, int flags_and) ++madwifi_sta_set_flags(void *priv, const u8 *addr, int total_flags, ++ int flags_or, int flags_and) + { + /* For now, only support setting Authorized flag */ + if (flags_or & WLAN_STA_AUTHORIZED) +--- hostap.orig/hostapd/driver_prism54.c 2007-11-09 13:41:07.000000000 +0100 ++++ hostap/hostapd/driver_prism54.c 2007-11-09 13:41:15.000000000 +0100 +@@ -187,7 +187,8 @@ static int prism54_set_sta_authorized(vo + + + static int +-prism54_sta_set_flags(void *priv, const u8 *addr, int flags_or, int flags_and) ++prism54_sta_set_flags(void *priv, const u8 *addr, int total_flags, ++ int flags_or, int flags_and) + { + /* For now, only support setting Authorized flag */ + if (flags_or & WLAN_STA_AUTHORIZED) +--- hostap.orig/hostapd/ieee802_11.c 2007-11-09 13:41:07.000000000 +0100 ++++ hostap/hostapd/ieee802_11.c 2007-11-09 13:41:15.000000000 +0100 +@@ -1625,10 +1625,10 @@ static void handle_assoc_cb(struct hosta + ap_sta_bind_vlan(hapd, sta, 0); + } + if (sta->flags & WLAN_STA_SHORT_PREAMBLE) { +- hostapd_sta_set_flags(hapd, sta->addr, ++ hostapd_sta_set_flags(hapd, sta->addr, sta->flags, + WLAN_STA_SHORT_PREAMBLE, ~0); + } else { +- hostapd_sta_set_flags(hapd, sta->addr, ++ hostapd_sta_set_flags(hapd, sta->addr, sta->flags, + 0, ~WLAN_STA_SHORT_PREAMBLE); + } + +--- hostap.orig/hostapd/ieee802_1x.c 2007-11-09 13:41:07.000000000 +0100 ++++ hostap/hostapd/ieee802_1x.c 2007-11-09 13:41:15.000000000 +0100 +@@ -94,13 +94,13 @@ void ieee802_1x_set_sta_authorized(struc + + if (authorized) { + sta->flags |= WLAN_STA_AUTHORIZED; +- res = hostapd_sta_set_flags(hapd, sta->addr, ++ res = hostapd_sta_set_flags(hapd, sta->addr, sta->flags, + WLAN_STA_AUTHORIZED, ~0); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_DEBUG, "authorizing port"); + } else { + sta->flags &= ~WLAN_STA_AUTHORIZED; +- res = hostapd_sta_set_flags(hapd, sta->addr, ++ res = hostapd_sta_set_flags(hapd, sta->addr, sta->flags, + 0, ~WLAN_STA_AUTHORIZED); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_DEBUG, "unauthorizing port"); +--- hostap.orig/hostapd/wme.c 2007-11-09 13:41:07.000000000 +0100 ++++ hostap/hostapd/wme.c 2007-11-09 13:41:15.000000000 +0100 +@@ -110,9 +110,11 @@ int hostapd_wme_sta_config(struct hostap + { + /* update kernel STA data for WME related items (WLAN_STA_WPA flag) */ + if (sta->flags & WLAN_STA_WME) +- hostapd_sta_set_flags(hapd, sta->addr, WLAN_STA_WME, ~0); ++ hostapd_sta_set_flags(hapd, sta->addr, sta->flags, ++ WLAN_STA_WME, ~0); + else +- hostapd_sta_set_flags(hapd, sta->addr, 0, ~WLAN_STA_WME); ++ hostapd_sta_set_flags(hapd, sta->addr, sta->flags, ++ 0, ~WLAN_STA_WME); + + return 0; + } diff --git a/package/hostapd/patches/006-use-nl80211-for-sta.patch b/package/hostapd/patches/006-use-nl80211-for-sta.patch new file mode 100644 index 0000000000..f94ba42886 --- /dev/null +++ b/package/hostapd/patches/006-use-nl80211-for-sta.patch @@ -0,0 +1,411 @@ +--- + hostapd/driver_devicescape.c | 330 ++++++++++++++++++++++++++++++++----------- + 1 file changed, 249 insertions(+), 81 deletions(-) + +--- hostap.orig/hostapd/driver_devicescape.c 2007-11-09 13:41:15.000000000 +0100 ++++ hostap/hostapd/driver_devicescape.c 2007-11-09 13:41:16.000000000 +0100 +@@ -75,8 +75,14 @@ struct i802_driver_data { + + #define HAPD_DECL struct hostapd_data *hapd = iface->bss[0] + +-static int i802_sta_set_flags(void *priv, const u8 *addr, +- int total_flags, int flags_or, int flags_and); ++/* helper for netlink get routines */ ++static int ack_wait_handler(struct nl_msg *msg, void *arg) ++{ ++ int *finished = arg; ++ ++ *finished = 1; ++ return NL_STOP; ++} + + + static int hostapd_set_iface_flags(struct i802_driver_data *drv, int dev_up) +@@ -255,14 +261,6 @@ static int get_key_handler(struct nl_msg + return NL_SKIP; + } + +-static int ack_wait_handler(struct nl_msg *msg, void *arg) +-{ +- int *finished = arg; +- +- *finished = 1; +- return NL_STOP; +-} +- + static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr, + int idx, u8 *seq) + { +@@ -629,43 +627,126 @@ static int i802_get_retry(void *priv, in + static int i802_flush(void *priv) + { + struct i802_driver_data *drv = priv; +- struct prism2_hostapd_param param; ++ struct nl_msg *msg; ++ int ret = -1; + +- memset(¶m, 0, sizeof(param)); +- param.cmd = PRISM2_HOSTAPD_FLUSH; +- return hostapd_ioctl(drv, ¶m, sizeof(param)); ++ msg = nlmsg_alloc(); ++ if (!msg) ++ goto out; ++ ++ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++ 0, NL80211_CMD_NEW_STATION, 0); ++ ++ /* ++ * XXX: FIX! this needs to flush all VLANs too ++ */ ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ++ if_nametoindex(drv->iface)); ++ ++ ret = 0; ++ ++ if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || ++ nl_wait_for_ack(drv->nl_handle) < 0) { ++ ret = -1; ++ } ++ ++ nla_put_failure: ++ nlmsg_free(msg); ++ ++ out: ++ return ret; + } + + ++static int get_sta_handler(struct nl_msg *msg, void *arg) ++{ ++ struct nlattr *tb[NL80211_ATTR_MAX + 1]; ++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); ++ struct hostap_sta_driver_data *data = arg; ++ struct nlattr *stats[NL80211_STA_STAT_MAX + 1]; ++ static struct nla_policy stats_policy[NL80211_STA_STAT_MAX + 1] = { ++ [NL80211_STA_STAT_INACTIVE_TIME] = { .type = NLA_U32 }, ++ [NL80211_STA_STAT_RX_BYTES] = { .type = NLA_U32 }, ++ [NL80211_STA_STAT_TX_BYTES] = { .type = NLA_U32 }, ++ }; ++ ++ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), ++ genlmsg_attrlen(gnlh, 0), NULL); ++ ++ /* ++ * TODO: validate the interface and mac address! ++ * Otherwise, there's a race condition as soon as ++ * the kernel starts sending station notifications. ++ */ ++ ++ if (!tb[NL80211_ATTR_STA_STATS]) { ++ printf("sta stats missing!\n"); ++ return NL_SKIP; ++ } ++ if (nla_parse_nested(stats, NL80211_STA_STAT_MAX, ++ tb[NL80211_ATTR_STA_STATS], ++ stats_policy)) { ++ printf("failed to parse nested attributes!\n"); ++ return NL_SKIP; ++ } ++ ++ if (stats[NL80211_STA_STAT_INACTIVE_TIME]) ++ data->inactive_msec = ++ nla_get_u32(stats[NL80211_STA_STAT_INACTIVE_TIME]); ++ if (stats[NL80211_STA_STAT_RX_BYTES]) ++ data->rx_bytes = nla_get_u32(stats[NL80211_STA_STAT_RX_BYTES]); ++ if (stats[NL80211_STA_STAT_TX_BYTES]) ++ data->rx_bytes = nla_get_u32(stats[NL80211_STA_STAT_TX_BYTES]); ++ ++ return NL_SKIP; ++} ++ + static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data, + const u8 *addr) + { + struct i802_driver_data *drv = priv; +- struct prism2_hostapd_param param; ++ struct nl_msg *msg; ++ struct nl_cb *cb = NULL; ++ int ret = -1; ++ int err = 0; ++ int finished = 0; + +- memset(data, 0, sizeof(*data)); ++ msg = nlmsg_alloc(); ++ if (!msg) ++ goto out; + +- memset(¶m, 0, sizeof(param)); +- param.cmd = PRISM2_HOSTAPD_GET_INFO_STA; +- memcpy(param.sta_addr, addr, ETH_ALEN); +- if (hostapd_ioctl(drv, ¶m, sizeof(param))) { +- printf(" Could not get station info from kernel driver.\n"); +- return -1; +- } ++ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++ 0, NL80211_CMD_GET_STATION, 0); ++ ++ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); ++ ++ cb = nl_cb_alloc(NL_CB_CUSTOM); ++ if (!cb) ++ goto out; ++ ++ if (nl_send_auto_complete(drv->nl_handle, msg) < 0) ++ goto out; ++ ++ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_sta_handler, data); ++ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished); ++ ++ err = nl_recvmsgs(drv->nl_handle, cb); ++ ++ if (!finished) ++ err = nl_wait_for_ack(drv->nl_handle); ++ ++ if (err < 0) ++ goto out; ++ ++ ret = 0; ++ ++ out: ++ nl_cb_put(cb); ++ nla_put_failure: ++ nlmsg_free(msg); ++ return ret; + +- data->inactive_msec = param.u.get_info_sta.inactive_msec; +- data->rx_packets = param.u.get_info_sta.rx_packets; +- data->tx_packets = param.u.get_info_sta.tx_packets; +- data->rx_bytes = param.u.get_info_sta.rx_bytes; +- data->tx_bytes = param.u.get_info_sta.tx_bytes; +- data->current_tx_rate = param.u.get_info_sta.current_tx_rate; +- data->flags = param.u.get_info_sta.flags; +- data->num_ps_buf_frames = param.u.get_info_sta.num_ps_buf_frames; +- data->tx_retry_failed = param.u.get_info_sta.tx_retry_failed; +- data->tx_retry_count = param.u.get_info_sta.tx_retry_count; +- data->last_rssi = param.u.get_info_sta.last_rssi; +- data->last_ack_rssi = param.u.get_info_sta.last_ack_rssi; +- return 0; + } + + +@@ -744,35 +825,68 @@ static int i802_sta_add(const char *ifna + size_t supp_rates_len, int flags) + { + struct i802_driver_data *drv = priv; +- struct prism2_hostapd_param param; +- size_t len; ++ struct nl_msg *msg; ++ int ret = -1; + +- memset(¶m, 0, sizeof(param)); +- param.cmd = PRISM2_HOSTAPD_ADD_STA; +- memcpy(param.sta_addr, addr, ETH_ALEN); +- param.u.add_sta.aid = aid; +- param.u.add_sta.capability = capability; +- len = supp_rates_len; +- if (len > sizeof(param.u.add_sta.supp_rates)) +- len = sizeof(param.u.add_sta.supp_rates); +- memcpy(param.u.add_sta.supp_rates, supp_rates, len); +- return hostapd_ioctl_iface(ifname, drv, ¶m, sizeof(param)); ++ msg = nlmsg_alloc(); ++ if (!msg) ++ goto out; ++ ++ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++ 0, NL80211_CMD_NEW_STATION, 0); ++ ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ++ if_nametoindex(drv->iface)); ++ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); ++ NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, aid); ++ NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, supp_rates_len, ++ supp_rates); ++ NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL, 0); ++ ++ ret = 0; ++ ++ if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || ++ nl_wait_for_ack(drv->nl_handle) < 0) { ++ ret = -1; ++ } ++ ++ nla_put_failure: ++ nlmsg_free(msg); ++ ++ out: ++ return ret; + } + + + static int i802_sta_remove(void *priv, const u8 *addr) + { + struct i802_driver_data *drv = priv; +- struct prism2_hostapd_param param; ++ struct nl_msg *msg; ++ int ret = -1; + +- i802_sta_set_flags(drv, addr, 0, 0, ~WLAN_STA_AUTHORIZED); ++ msg = nlmsg_alloc(); ++ if (!msg) ++ goto out; + +- memset(¶m, 0, sizeof(param)); +- param.cmd = PRISM2_HOSTAPD_REMOVE_STA; +- memcpy(param.sta_addr, addr, ETH_ALEN); +- if (hostapd_ioctl(drv, ¶m, sizeof(param))) +- return -1; +- return 0; ++ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++ 0, NL80211_CMD_DEL_STATION, 0); ++ ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ++ if_nametoindex(drv->iface)); ++ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); ++ ++ ret = 0; ++ ++ if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || ++ nl_wait_for_ack(drv->nl_handle) < 0) { ++ ret = -1; ++ } ++ ++ nla_put_failure: ++ nlmsg_free(msg); ++ ++ out: ++ return ret; + } + + +@@ -780,14 +894,51 @@ static int i802_sta_set_flags(void *priv + int total_flags, int flags_or, int flags_and) + { + struct i802_driver_data *drv = priv; +- struct prism2_hostapd_param param; ++ struct nl_msg *msg, *flags = NULL; ++ int ret = -1; + +- memset(¶m, 0, sizeof(param)); +- param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA; +- memcpy(param.sta_addr, addr, ETH_ALEN); +- param.u.set_flags_sta.flags_or = flags_or; +- param.u.set_flags_sta.flags_and = flags_and; +- return hostapd_ioctl(drv, ¶m, sizeof(param)); ++ msg = nlmsg_alloc(); ++ if (!msg) ++ goto out; ++ ++ flags = nlmsg_alloc(); ++ if (!flags) ++ goto free_msg; ++ ++ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++ 0, NL80211_CMD_SET_STATION, 0); ++ ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ++ if_nametoindex(drv->iface)); ++ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); ++ ++ if (total_flags & WLAN_STA_AUTHORIZED) ++ NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED); ++ ++ if (total_flags & WLAN_STA_WME) ++ NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME); ++ ++ if (total_flags & WLAN_STA_SHORT_PREAMBLE) ++ NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE); ++ ++ if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags)) ++ goto nla_put_failure; ++ ++ ret = 0; ++ ++ if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || ++ nl_wait_for_ack(drv->nl_handle) < 0) { ++ ret = -1; ++ } ++ ++ nla_put_failure: ++ nlmsg_free(flags); ++ ++ free_msg: ++ nlmsg_free(msg); ++ ++ out: ++ return ret; + } + + +@@ -1257,18 +1408,38 @@ static struct hostapd_hw_modes * i802_ge + } + + +-static int i802_set_sta_vlan(void *priv, const u8 *addr, const char *ifname, +- int vlan_id) ++static int i802_set_sta_vlan(void *priv, const u8 *addr, ++ const char *ifname, int vlan_id) + { + struct i802_driver_data *drv = priv; +- struct prism2_hostapd_param param; ++ struct nl_msg *msg; ++ int ret = -1; + +- memset(¶m, 0, sizeof(param)); +- param.cmd = PRISM2_HOSTAPD_SET_STA_VLAN; +- memcpy(param.sta_addr, addr, ETH_ALEN); +- os_strlcpy(param.u.set_sta_vlan.vlan_name, ifname, IFNAMSIZ); +- param.u.set_sta_vlan.vlan_id = vlan_id; +- return hostapd_ioctl(drv, ¶m, sizeof(param)); ++ msg = nlmsg_alloc(); ++ if (!msg) ++ goto out; ++ ++ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, ++ 0, NL80211_CMD_SET_STATION, 0); ++ ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ++ if_nametoindex(drv->iface)); ++ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ++ if_nametoindex(ifname)); ++ ++ ret = 0; ++ ++ if (nl_send_auto_complete(drv->nl_handle, msg) < 0 || ++ nl_wait_for_ack(drv->nl_handle) < 0) { ++ ret = -1; ++ } ++ ++ nla_put_failure: ++ nlmsg_free(msg); ++ ++ out: ++ return ret; + } + + +@@ -1750,17 +1921,14 @@ static int i802_init_sockets(struct i802 + + static int i802_get_inact_sec(void *priv, const u8 *addr) + { +- struct i802_driver_data *drv = priv; +- struct prism2_hostapd_param param; ++ struct hostap_sta_driver_data data; ++ int ret; + +- memset(¶m, 0, sizeof(param)); +- param.cmd = PRISM2_HOSTAPD_GET_INFO_STA; +- memcpy(param.sta_addr, addr, ETH_ALEN); +- if (hostapd_ioctl(drv, ¶m, sizeof(param))) { ++ data.inactive_msec = -1; ++ ret = i802_read_sta_data(priv, &data, addr); ++ if (ret || data.inactive_msec == -1) + return -1; +- } +- +- return param.u.get_info_sta.inactive_msec / 1000; ++ return data.inactive_msec / 1000; + } + + diff --git a/package/hostapd/patches/100-madwifi_fixes.patch b/package/hostapd/patches/100-madwifi_fixes.patch deleted file mode 100644 index 74d0c44d63..0000000000 --- a/package/hostapd/patches/100-madwifi_fixes.patch +++ /dev/null @@ -1,54 +0,0 @@ -Index: hostapd-0.5.7/driver_madwifi.c -=================================================================== ---- hostapd-0.5.7.orig/driver_madwifi.c 2007-06-04 13:22:31.768025808 +0200 -+++ hostapd-0.5.7/driver_madwifi.c 2007-06-04 13:22:32.051982640 +0200 -@@ -21,12 +21,9 @@ - #include - #include - #ifdef WME_NUM_AC --/* Assume this is built against BSD branch of madwifi driver. */ --#define MADWIFI_BSD --#include --#endif /* WME_NUM_AC */ - #include - #include -+#endif /* WME_NUM_AC */ - - #ifdef IEEE80211_IOCTL_SETWMMPARAMS - /* Assume this is built against madwifi-ng */ -@@ -169,6 +166,11 @@ - return 0; - } - -+static int madwifi_get_inact_sec(void *priv, const u8 *addr) -+{ -+ return 0; -+} -+ - static int - set80211param(struct madwifi_driver_data *drv, int op, int arg) - { -@@ -1258,7 +1260,6 @@ - goto bad; - } - -- madwifi_set_iface_flags(drv, 0); /* mark down during setup */ - madwifi_set_privacy(drv->iface, drv, 0); /* default to no privacy */ - - hapd->driver = &drv->ops; -@@ -1281,7 +1282,6 @@ - - drv->hapd->driver = NULL; - -- (void) madwifi_set_iface_flags(drv, 0); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit) -@@ -1367,6 +1367,7 @@ - .get_ssid = madwifi_get_ssid, - .set_countermeasures = madwifi_set_countermeasures, - .sta_clear_stats = madwifi_sta_clear_stats, -+ .get_inact_sec = madwifi_get_inact_sec, - .commit = madwifi_commit, - }; - diff --git a/package/libnl/Makefile b/package/libnl/Makefile index 9f334108ed..28958f4a51 100644 --- a/package/libnl/Makefile +++ b/package/libnl/Makefile @@ -36,16 +36,19 @@ define Build/Compile install endef -define Build/InstallDev +ifneq ($(CONFIG_LINUX_2_6_23),) + define Build/InstallDev $(CP) $(PKG_INSTALL_DIR)/* $(1)/ -endef + $(CP) $(PKG_BUILD_DIR)/include/linux $(1)/usr/include/ + endef -define Build/UninstallDev -endef + define Build/UninstallDev + endef -define Package/libnl/install + define Package/libnl/install $(INSTALL_DIR) $(1)/usr/lib $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/libnl.so.1 $(1)/usr/lib/ -endef + endef +endif $(eval $(call BuildPackage,libnl)) diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile index 476160d55f..65f2005d13 100644 --- a/package/mac80211/Makefile +++ b/package/mac80211/Makefile @@ -19,10 +19,9 @@ define KernelPackage/mac80211 TITLE:=Linux 802.11 Wireless Networking Stack DEPENDS:=@LINUX_2_6_23 +kmod-crypto-arc4 +kmod-crypto-aes +wireless-tools FILES:= \ - $(PKG_BUILD_DIR)/mac80211/mac80211.$(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) + $(PKG_BUILD_DIR)/net/mac80211/mac80211.$(LINUX_KMOD_SUFFIX) \ + $(PKG_BUILD_DIR)/net/wireless/cfg80211.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,20,cfg80211 mac80211) endef define KernelPackage/mac80211/description @@ -32,7 +31,7 @@ endef CONFOPTS:=MAC80211 CFG80211 NL80211 BUILDFLAGS:= \ - $(foreach opt,$(CONFOPTS),-DCONFIG_$(opt) ) \ + $(foreach opt,$(CONFOPTS),-DCONFIG_$(opt) -DCONFIG_MAC80211_RCSIMPLE=1) \ $(if $(CONFIG_LEDS_TRIGGERS), -DCONFIG_MAC80211_LEDS -DCONFIG_LEDS_TRIGGERS) MAKE_OPTS:= \ @@ -41,24 +40,26 @@ MAKE_OPTS:= \ EXTRA_CFLAGS="$(BUILDFLAGS)" \ $(foreach opt,$(CONFOPTS),CONFIG_$(opt)=m) \ CONFIG_NL80211=y \ + CONFIG_MAC80211_RCSIMPLE=y \ CONFIG_MAC80211_LEDS=$(CONFIG_LEDS_TRIGGERS) \ - LINUXINCLUDE="-I${CURDIR}/src/include -I$(LINUX_DIR)/include -include linux/autoconf.h" \ + LINUXINCLUDE="-I$(PKG_BUILD_DIR)/include -I$(LINUX_DIR)/include -include linux/autoconf.h" \ 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/ + rm -rf $(PKG_BUILD_DIR) + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ + $(Build/Patch) + $(if $(QUILT),touch $(PKG_BUILD_DIR)/.quilt_used) endef 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 + $(MAKE) -C "$(LINUX_DIR)" $(MAKE_OPTS) SUBDIRS="$(PKG_BUILD_DIR)/net/wireless" modules + $(MAKE) -C "$(LINUX_DIR)" $(MAKE_OPTS) SUBDIRS="$(PKG_BUILD_DIR)/net/mac80211" modules endef define Build/InstallDev mkdir -p $(1)/usr/include/mac80211 - $(CP) ./src/include/* $(1)/usr/include/mac80211/ + $(CP) $(PKG_BUILD_DIR)/net/mac80211/*.h $(PKG_BUILD_DIR)/include/* $(1)/usr/include/mac80211/ endef define Build/UninstallDev diff --git a/package/mac80211/patches/000-mac80211_update.patch b/package/mac80211/patches/000-mac80211_update.patch new file mode 100644 index 0000000000..7a1a1e271b --- /dev/null +++ b/package/mac80211/patches/000-mac80211_update.patch @@ -0,0 +1,933 @@ +Index: mac80211/include/linux/ieee80211.h +=================================================================== +--- mac80211.orig/include/linux/ieee80211.h 2007-11-11 15:45:23.153490050 +0100 ++++ mac80211/include/linux/ieee80211.h 2007-11-11 15:45:30.417904025 +0100 +@@ -81,18 +81,18 @@ + + + /* miscellaneous IEEE 802.11 constants */ +-#define IEEE80211_MAX_FRAG_THRESHOLD 2346 +-#define IEEE80211_MAX_RTS_THRESHOLD 2347 ++#define IEEE80211_MAX_FRAG_THRESHOLD 2352 ++#define IEEE80211_MAX_RTS_THRESHOLD 2353 + #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) */ ++ 802.11e clarifies the figure in section 7.1.2. The frame body is ++ up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */ ++#define IEEE80211_MAX_DATA_LEN 2304 ++/* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ ++#define IEEE80211_MAX_FRAME_LEN 2352 + + #define IEEE80211_MAX_SSID_LEN 32 + +Index: mac80211/include/linux/nl80211.h +=================================================================== +--- mac80211.orig/include/linux/nl80211.h 2007-11-11 15:45:23.161490506 +0100 ++++ mac80211/include/linux/nl80211.h 2007-11-11 15:45:30.421904255 +0100 +@@ -25,7 +25,7 @@ + * 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_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 +Index: mac80211/include/net/mac80211.h +=================================================================== +--- mac80211.orig/include/net/mac80211.h 2007-11-11 15:45:23.169490961 +0100 ++++ mac80211/include/net/mac80211.h 2007-11-11 15:45:30.429904707 +0100 +@@ -706,11 +706,16 @@ + * + * @queues: number of available hardware transmit queues for + * data packets. WMM/QoS requires at least four. ++ * ++ * @rate_control_algorithm: rate control algorithm for this hardware. ++ * If unset (NULL), the default algorithm will be used. Must be ++ * set before calling ieee80211_register_hw(). + */ + struct ieee80211_hw { + struct ieee80211_conf conf; + struct wiphy *wiphy; + struct workqueue_struct *workqueue; ++ const char *rate_control_algorithm; + void *priv; + u32 flags; + unsigned int extra_tx_headroom; +@@ -936,27 +941,11 @@ + * 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. +@@ -1029,14 +1018,9 @@ + 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); +Index: mac80211/net/mac80211/aes_ccm.c +=================================================================== +--- mac80211.orig/net/mac80211/aes_ccm.c 2007-11-11 15:45:23.177491419 +0100 ++++ mac80211/net/mac80211/aes_ccm.c 2007-11-11 15:45:30.433904936 +0100 +@@ -7,10 +7,10 @@ + * published by the Free Software Foundation. + */ + ++#include + #include + #include + #include +-#include + + #include + #include "ieee80211_key.h" +@@ -63,7 +63,7 @@ + s_0 = scratch + AES_BLOCK_LEN; + e = scratch + 2 * AES_BLOCK_LEN; + +- num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; ++ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); + last_len = data_len % AES_BLOCK_LEN; + aes_ccm_prepare(tfm, b_0, aad, b, s_0, b); + +@@ -102,7 +102,7 @@ + s_0 = scratch + AES_BLOCK_LEN; + a = scratch + 2 * AES_BLOCK_LEN; + +- num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; ++ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); + last_len = data_len % AES_BLOCK_LEN; + aes_ccm_prepare(tfm, b_0, aad, b, s_0, a); + +Index: mac80211/net/mac80211/ieee80211.c +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211.c 2007-11-11 15:45:23.185491871 +0100 ++++ mac80211/net/mac80211/ieee80211.c 2007-11-11 15:45:30.437905164 +0100 +@@ -1061,7 +1061,8 @@ + ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); + ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP); + +- result = ieee80211_init_rate_ctrl_alg(local, NULL); ++ result = ieee80211_init_rate_ctrl_alg(local, ++ hw->rate_control_algorithm); + if (result < 0) { + printk(KERN_DEBUG "%s: Failed to initialize rate control " + "algorithm\n", wiphy_name(local->hw.wiphy)); +@@ -1222,8 +1223,17 @@ + + BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb)); + ++#ifdef CONFIG_MAC80211_RCSIMPLE ++ ret = ieee80211_rate_control_register(&mac80211_rcsimple); ++ if (ret) ++ return ret; ++#endif ++ + ret = ieee80211_wme_register(); + if (ret) { ++#ifdef CONFIG_MAC80211_RCSIMPLE ++ ieee80211_rate_control_unregister(&mac80211_rcsimple); ++#endif + printk(KERN_DEBUG "ieee80211_init: failed to " + "initialize WME (err=%d)\n", ret); + return ret; +@@ -1237,6 +1247,10 @@ + + static void __exit ieee80211_exit(void) + { ++#ifdef CONFIG_MAC80211_RCSIMPLE ++ ieee80211_rate_control_unregister(&mac80211_rcsimple); ++#endif ++ + ieee80211_wme_unregister(); + ieee80211_debugfs_netdev_exit(); + } +Index: mac80211/net/mac80211/ieee80211_i.h +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211_i.h 2007-11-11 15:45:23.189492100 +0100 ++++ mac80211/net/mac80211/ieee80211_i.h 2007-11-11 15:45:30.441905395 +0100 +@@ -232,6 +232,7 @@ + #define IEEE80211_STA_AUTO_SSID_SEL BIT(10) + #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) + #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) ++#define IEEE80211_STA_PRIVACY_INVOKED BIT(13) + struct ieee80211_if_sta { + enum { + IEEE80211_DISABLED, IEEE80211_AUTHENTICATE, +@@ -261,7 +262,6 @@ + unsigned long request; + struct sk_buff_head skb_queue; + +- int key_management_enabled; + unsigned long last_probe; + + #define IEEE80211_AUTH_ALG_OPEN BIT(0) +Index: mac80211/net/mac80211/ieee80211_ioctl.c +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211_ioctl.c 2007-11-11 15:45:23.197492559 +0100 ++++ mac80211/net/mac80211/ieee80211_ioctl.c 2007-11-11 15:45:30.441905395 +0100 +@@ -305,9 +305,12 @@ + ((chan->chan == channel) || (chan->freq == freq))) { + local->oper_channel = chan; + local->oper_hw_mode = mode; +- set++; ++ set = 1; ++ break; + } + } ++ if (set) ++ break; + } + + if (set) { +@@ -507,10 +510,11 @@ + + static int ieee80211_ioctl_siwscan(struct net_device *dev, + struct iw_request_info *info, +- struct iw_point *data, char *extra) ++ union iwreq_data *wrqu, char *extra) + { + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct iw_scan_req *req = NULL; + u8 *ssid = NULL; + size_t ssid_len = 0; + +@@ -535,6 +539,14 @@ + return -EOPNOTSUPP; + } + ++ /* if SSID was specified explicitly then use that */ ++ if (wrqu->data.length == sizeof(struct iw_scan_req) && ++ wrqu->data.flags & IW_SCAN_THIS_ESSID) { ++ req = (struct iw_scan_req *)extra; ++ ssid = req->essid; ++ ssid_len = req->essid_len; ++ } ++ + return ieee80211_sta_req_scan(dev, ssid, ssid_len); + } + +@@ -621,22 +633,35 @@ + { + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + bool need_reconfig = 0; ++ u8 new_power_level; + + if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) + return -EINVAL; + if (data->txpower.flags & IW_TXPOW_RANGE) + return -EINVAL; +- if (!data->txpower.fixed) +- return -EINVAL; + +- if (local->hw.conf.power_level != data->txpower.value) { +- local->hw.conf.power_level = data->txpower.value; ++ if (data->txpower.fixed) { ++ new_power_level = data->txpower.value; ++ } else { ++ /* Automatic power level. Get the px power from the current ++ * channel. */ ++ struct ieee80211_channel* chan = local->oper_channel; ++ if (!chan) ++ return -EINVAL; ++ ++ new_power_level = chan->power_level; ++ } ++ ++ if (local->hw.conf.power_level != new_power_level) { ++ local->hw.conf.power_level = new_power_level; + need_reconfig = 1; + } ++ + if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) { + local->hw.conf.radio_enabled = !(data->txpower.disabled); + need_reconfig = 1; + } ++ + if (need_reconfig) { + ieee80211_hw_config(local); + /* The return value of hw_config is not of big interest here, +@@ -904,7 +929,6 @@ + struct iw_request_info *info, + struct iw_param *data, char *extra) + { +- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + int ret = 0; + +@@ -914,18 +938,21 @@ + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_WPA_ENABLED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: +- break; + case IW_AUTH_KEY_MGMT: ++ break; ++ case IW_AUTH_PRIVACY_INVOKED: + if (sdata->type != IEEE80211_IF_TYPE_STA) + ret = -EINVAL; + else { ++ sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; + /* +- * Key management was set by wpa_supplicant, +- * we only need this to associate to a network +- * that has privacy enabled regardless of not +- * having a key. ++ * Privacy invoked by wpa_supplicant, store the ++ * value and allow associating to a protected ++ * network without having a key up front. + */ +- sdata->u.sta.key_management_enabled = !!data->value; ++ if (data->value) ++ sdata->u.sta.flags |= ++ IEEE80211_STA_PRIVACY_INVOKED; + } + break; + case IW_AUTH_80211_AUTH_ALG: +@@ -935,11 +962,6 @@ + else + ret = -EOPNOTSUPP; + break; +- case IW_AUTH_PRIVACY_INVOKED: +- if (local->ops->set_privacy_invoked) +- ret = local->ops->set_privacy_invoked( +- local_to_hw(local), data->value); +- break; + default: + ret = -EOPNOTSUPP; + break; +Index: mac80211/net/mac80211/ieee80211_rate.c +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211_rate.c 2007-11-11 15:45:23.205493011 +0100 ++++ mac80211/net/mac80211/ieee80211_rate.c 2007-11-11 15:45:30.441905395 +0100 +@@ -25,13 +25,25 @@ + { + struct rate_control_alg *alg; + ++ if (!ops->name) ++ return -EINVAL; ++ ++ mutex_lock(&rate_ctrl_mutex); ++ list_for_each_entry(alg, &rate_ctrl_algs, list) { ++ if (!strcmp(alg->ops->name, ops->name)) { ++ /* don't register an algorithm twice */ ++ WARN_ON(1); ++ return -EALREADY; ++ } ++ } ++ + alg = kzalloc(sizeof(*alg), GFP_KERNEL); + if (alg == NULL) { ++ mutex_unlock(&rate_ctrl_mutex); + return -ENOMEM; + } + alg->ops = ops; + +- mutex_lock(&rate_ctrl_mutex); + list_add_tail(&alg->list, &rate_ctrl_algs); + mutex_unlock(&rate_ctrl_mutex); + +@@ -61,9 +73,12 @@ + struct rate_control_alg *alg; + struct rate_control_ops *ops = NULL; + ++ if (!name) ++ return NULL; ++ + mutex_lock(&rate_ctrl_mutex); + list_for_each_entry(alg, &rate_ctrl_algs, list) { +- if (!name || !strcmp(alg->ops->name, name)) ++ if (!strcmp(alg->ops->name, name)) + if (try_module_get(alg->ops->module)) { + ops = alg->ops; + break; +@@ -80,9 +95,12 @@ + { + struct rate_control_ops *ops; + ++ if (!name) ++ name = "simple"; ++ + ops = ieee80211_try_rate_control_ops_get(name); + if (!ops) { +- request_module("rc80211_%s", name ? name : "default"); ++ request_module("rc80211_%s", name); + ops = ieee80211_try_rate_control_ops_get(name); + } + return ops; +Index: mac80211/net/mac80211/ieee80211_rate.h +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211_rate.h 2007-11-11 15:45:23.213493469 +0100 ++++ mac80211/net/mac80211/ieee80211_rate.h 2007-11-11 15:45:30.445905621 +0100 +@@ -65,6 +65,9 @@ + struct kref kref; + }; + ++/* default 'simple' algorithm */ ++extern struct rate_control_ops mac80211_rcsimple; ++ + int ieee80211_rate_control_register(struct rate_control_ops *ops); + void ieee80211_rate_control_unregister(struct rate_control_ops *ops); + +Index: mac80211/net/mac80211/ieee80211_sta.c +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211_sta.c 2007-11-11 15:45:23.217493699 +0100 ++++ mac80211/net/mac80211/ieee80211_sta.c 2007-11-11 15:46:32.885463850 +0100 +@@ -12,7 +12,6 @@ + */ + + /* TODO: +- * BSS table: use as the key to support multi-SSID APs + * order BSS list by RSSI(?) ("quality of AP") + * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, + * SSID) +@@ -61,7 +60,8 @@ + static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, + u8 *ssid, size_t ssid_len); + static struct ieee80211_sta_bss * +-ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid); ++ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, ++ u8 *ssid, u8 ssid_len); + static void ieee80211_rx_bss_put(struct net_device *dev, + struct ieee80211_sta_bss *bss); + static int ieee80211_sta_find_ibss(struct net_device *dev, +@@ -108,14 +108,11 @@ + u8 wmm_param_len; + }; + +-enum ParseRes { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 }; +- +-static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len, +- struct ieee802_11_elems *elems) ++static void ieee802_11_parse_elems(u8 *start, size_t len, ++ struct ieee802_11_elems *elems) + { + size_t left = len; + u8 *pos = start; +- int unknown = 0; + + memset(elems, 0, sizeof(*elems)); + +@@ -126,15 +123,8 @@ + elen = *pos++; + left -= 2; + +- if (elen > left) { +-#if 0 +- if (net_ratelimit()) +- printk(KERN_DEBUG "IEEE 802.11 element parse " +- "failed (id=%d elen=%d left=%d)\n", +- id, elen, left); +-#endif +- return ParseFailed; +- } ++ if (elen > left) ++ return; + + switch (id) { + case WLAN_EID_SSID: +@@ -201,28 +191,15 @@ + elems->ext_supp_rates_len = elen; + break; + default: +-#if 0 +- printk(KERN_DEBUG "IEEE 802.11 element parse ignored " +- "unknown element (id=%d elen=%d)\n", +- id, elen); +-#endif +- unknown++; + break; + } + + left -= elen; + pos += elen; + } +- +- /* Do not trigger error if left == 1 as Apple Airport base stations +- * send AssocResps that are one spurious byte too long. */ +- +- return unknown ? ParseUnknown : ParseOK; + } + + +- +- + static int ecw2cw(int ecw) + { + int cw = 1; +@@ -426,7 +403,9 @@ + if (sdata->type != IEEE80211_IF_TYPE_STA) + return; + +- bss = ieee80211_rx_bss_get(dev, ifsta->bssid); ++ bss = ieee80211_rx_bss_get(dev, ifsta->bssid, ++ local->hw.conf.channel, ++ ifsta->ssid, ifsta->ssid_len); + if (bss) { + if (bss->has_erp_value) + ieee80211_handle_erp_ie(dev, bss->erp_value); +@@ -571,7 +550,8 @@ + capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | + WLAN_CAPABILITY_SHORT_PREAMBLE; + } +- bss = ieee80211_rx_bss_get(dev, ifsta->bssid); ++ bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, ++ ifsta->ssid, ifsta->ssid_len); + if (bss) { + if (bss->capability & WLAN_CAPABILITY_PRIVACY) + capab |= WLAN_CAPABILITY_PRIVACY; +@@ -719,24 +699,30 @@ + static int ieee80211_privacy_mismatch(struct net_device *dev, + struct ieee80211_if_sta *ifsta) + { ++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sta_bss *bss; +- int res = 0; ++ int bss_privacy; ++ int wep_privacy; ++ int privacy_invoked; + +- if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL) || +- ifsta->key_management_enabled) ++ if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL)) + return 0; + +- bss = ieee80211_rx_bss_get(dev, ifsta->bssid); ++ bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, ++ ifsta->ssid, ifsta->ssid_len); + if (!bss) + return 0; + +- if (ieee80211_sta_wep_configured(dev) != +- !!(bss->capability & WLAN_CAPABILITY_PRIVACY)) +- res = 1; ++ bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY); ++ wep_privacy = !!ieee80211_sta_wep_configured(dev); ++ privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); + + ieee80211_rx_bss_put(dev, bss); + +- return res; ++ if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked)) ++ return 0; ++ ++ return 1; + } + + +@@ -920,12 +906,7 @@ + + printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name); + pos = mgmt->u.auth.variable; +- if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) +- == ParseFailed) { +- printk(KERN_DEBUG "%s: failed to parse Auth(challenge)\n", +- dev->name); +- return; +- } ++ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); + if (!elems.challenge) { + printk(KERN_DEBUG "%s: no challenge IE in shared key auth " + "frame\n", dev->name); +@@ -1214,12 +1195,7 @@ + } + + pos = mgmt->u.assoc_resp.variable; +- if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) +- == ParseFailed) { +- printk(KERN_DEBUG "%s: failed to parse AssocResp\n", +- dev->name); +- return; +- } ++ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); + + if (!elems.supp_rates) { + printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", +@@ -1231,7 +1207,9 @@ + * update our stored copy */ + if (elems.erp_info && elems.erp_info_len >= 1) { + struct ieee80211_sta_bss *bss +- = ieee80211_rx_bss_get(dev, ifsta->bssid); ++ = ieee80211_rx_bss_get(dev, ifsta->bssid, ++ local->hw.conf.channel, ++ ifsta->ssid, ifsta->ssid_len); + if (bss) { + bss->erp_value = elems.erp_info[0]; + bss->has_erp_value = 1; +@@ -1261,7 +1239,9 @@ + " AP\n", dev->name); + return; + } +- bss = ieee80211_rx_bss_get(dev, ifsta->bssid); ++ bss = ieee80211_rx_bss_get(dev, ifsta->bssid, ++ local->hw.conf.channel, ++ ifsta->ssid, ifsta->ssid_len); + if (bss) { + sta->last_rssi = bss->rssi; + sta->last_signal = bss->signal; +@@ -1337,7 +1317,8 @@ + + + static struct ieee80211_sta_bss * +-ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) ++ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel, ++ u8 *ssid, u8 ssid_len) + { + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sta_bss *bss; +@@ -1348,6 +1329,11 @@ + atomic_inc(&bss->users); + atomic_inc(&bss->users); + memcpy(bss->bssid, bssid, ETH_ALEN); ++ bss->channel = channel; ++ if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { ++ memcpy(bss->ssid, ssid, ssid_len); ++ bss->ssid_len = ssid_len; ++ } + + spin_lock_bh(&local->sta_bss_lock); + /* TODO: order by RSSI? */ +@@ -1359,7 +1345,8 @@ + + + static struct ieee80211_sta_bss * +-ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid) ++ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, ++ u8 *ssid, u8 ssid_len) + { + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sta_bss *bss; +@@ -1367,7 +1354,10 @@ + spin_lock_bh(&local->sta_bss_lock); + bss = local->sta_bss_hash[STA_HASH(bssid)]; + while (bss) { +- if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) { ++ if (!memcmp(bss->bssid, bssid, ETH_ALEN) && ++ bss->channel == channel && ++ bss->ssid_len == ssid_len && ++ (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { + atomic_inc(&bss->users); + break; + } +@@ -1429,7 +1419,7 @@ + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee802_11_elems elems; + size_t baselen; +- int channel, invalid = 0, clen; ++ int channel, clen; + struct ieee80211_sta_bss *bss; + struct sta_info *sta; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +@@ -1473,9 +1463,7 @@ + #endif /* CONFIG_MAC80211_IBSS_DEBUG */ + } + +- if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, +- &elems) == ParseFailed) +- invalid = 1; ++ ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); + + if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates && + memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && +@@ -1533,9 +1521,11 @@ + else + channel = rx_status->channel; + +- bss = ieee80211_rx_bss_get(dev, mgmt->bssid); ++ bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel, ++ elems.ssid, elems.ssid_len); + if (!bss) { +- bss = ieee80211_rx_bss_add(dev, mgmt->bssid); ++ bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel, ++ elems.ssid, elems.ssid_len); + if (!bss) + return; + } else { +@@ -1561,10 +1551,6 @@ + + bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); + bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); +- if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { +- memcpy(bss->ssid, elems.ssid, elems.ssid_len); +- bss->ssid_len = elems.ssid_len; +- } + + bss->supp_rates_len = 0; + if (elems.supp_rates) { +@@ -1635,7 +1621,6 @@ + + + bss->hw_mode = rx_status->phymode; +- bss->channel = channel; + bss->freq = rx_status->freq; + if (channel != rx_status->channel && + (bss->hw_mode == MODE_IEEE80211G || +@@ -1695,9 +1680,7 @@ + if (baselen > len) + return; + +- if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, +- &elems) == ParseFailed) +- return; ++ ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); + + if (elems.erp_info && elems.erp_info_len >= 1) + ieee80211_handle_erp_ie(dev, elems.erp_info[0]); +@@ -2098,7 +2081,8 @@ + { + int tmp, hidden_ssid; + +- if (!memcmp(ifsta->ssid, ssid, ssid_len)) ++ if (ssid_len == ifsta->ssid_len && ++ !memcmp(ifsta->ssid, ssid, ssid_len)) + return 1; + + if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) +@@ -2357,7 +2341,7 @@ + { + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sta_bss *bss; +- struct ieee80211_sub_if_data *sdata; ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_hw_mode *mode; + u8 bssid[ETH_ALEN], *pos; + int i; +@@ -2379,18 +2363,17 @@ + printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID " MAC_FMT "\n", + dev->name, MAC_ARG(bssid)); + +- bss = ieee80211_rx_bss_add(dev, bssid); ++ bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel, ++ sdata->u.sta.ssid, sdata->u.sta.ssid_len); + if (!bss) + return -ENOMEM; + +- sdata = IEEE80211_DEV_TO_SUB_IF(dev); + mode = local->oper_hw_mode; + + if (local->hw.conf.beacon_int == 0) + local->hw.conf.beacon_int = 100; + bss->beacon_int = local->hw.conf.beacon_int; + bss->hw_mode = local->hw.conf.phymode; +- bss->channel = local->hw.conf.channel; + bss->freq = local->hw.conf.freq; + bss->last_update = jiffies; + bss->capability = WLAN_CAPABILITY_IBSS; +@@ -2448,7 +2431,8 @@ + MAC_FMT "\n", MAC_ARG(bssid), MAC_ARG(ifsta->bssid)); + #endif /* CONFIG_MAC80211_IBSS_DEBUG */ + if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && +- (bss = ieee80211_rx_bss_get(dev, bssid))) { ++ (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel, ++ ifsta->ssid, ifsta->ssid_len))) { + printk(KERN_DEBUG "%s: Selected IBSS BSSID " MAC_FMT + " based on configured SSID\n", + dev->name, MAC_ARG(bssid)); +Index: mac80211/net/mac80211/Kconfig +=================================================================== +--- mac80211.orig/net/mac80211/Kconfig 2007-11-11 15:45:23.225494151 +0100 ++++ mac80211/net/mac80211/Kconfig 2007-11-11 15:45:30.449905846 +0100 +@@ -13,6 +13,18 @@ + This option enables the hardware independent IEEE 802.11 + networking stack. + ++config MAC80211_RCSIMPLE ++ bool "'simple' rate control algorithm" if EMBEDDED ++ default y ++ depends on MAC80211 ++ help ++ This option allows you to turn off the 'simple' rate ++ control algorithm in mac80211. If you do turn it off, ++ you absolutely need another rate control algorithm. ++ ++ Say Y unless you know you will have another algorithm ++ available. ++ + config MAC80211_LEDS + bool "Enable LED triggers" + depends on MAC80211 && LEDS_TRIGGERS +Index: mac80211/net/mac80211/Makefile +=================================================================== +--- mac80211.orig/net/mac80211/Makefile 2007-11-11 15:45:23.233494609 +0100 ++++ mac80211/net/mac80211/Makefile 2007-11-11 15:45:30.449905846 +0100 +@@ -1,8 +1,9 @@ +-obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o ++obj-$(CONFIG_MAC80211) += mac80211.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-$(CONFIG_MAC80211_RCSIMPLE) += rc80211_simple.o + + mac80211-objs := \ + ieee80211.o \ +Index: mac80211/net/mac80211/rc80211_simple.c +=================================================================== +--- mac80211.orig/net/mac80211/rc80211_simple.c 2007-11-11 15:45:23.237494839 +0100 ++++ mac80211/net/mac80211/rc80211_simple.c 2007-11-11 15:45:30.449905846 +0100 +@@ -7,7 +7,6 @@ + * published by the Free Software Foundation. + */ + +-#include + #include + #include + #include +@@ -29,8 +28,6 @@ + #define RATE_CONTROL_INTERVAL (HZ / 20) + #define RATE_CONTROL_MIN_TX 10 + +-MODULE_ALIAS("rc80211_default"); +- + static void rate_control_rate_inc(struct ieee80211_local *local, + struct sta_info *sta) + { +@@ -393,8 +390,7 @@ + } + #endif + +-static struct rate_control_ops rate_control_simple = { +- .module = THIS_MODULE, ++struct rate_control_ops mac80211_rcsimple = { + .name = "simple", + .tx_status = rate_control_simple_tx_status, + .get_rate = rate_control_simple_get_rate, +@@ -409,22 +405,3 @@ + .remove_sta_debugfs = rate_control_simple_remove_sta_debugfs, + #endif + }; +- +- +-static int __init rate_control_simple_init(void) +-{ +- return ieee80211_rate_control_register(&rate_control_simple); +-} +- +- +-static void __exit rate_control_simple_exit(void) +-{ +- ieee80211_rate_control_unregister(&rate_control_simple); +-} +- +- +-subsys_initcall(rate_control_simple_init); +-module_exit(rate_control_simple_exit); +- +-MODULE_DESCRIPTION("Simple rate control algorithm for ieee80211"); +-MODULE_LICENSE("GPL"); +Index: mac80211/net/mac80211/rx.c +=================================================================== +--- mac80211.orig/net/mac80211/rx.c 2007-11-11 15:45:23.245495291 +0100 ++++ mac80211/net/mac80211/rx.c 2007-11-11 15:45:30.449905846 +0100 +@@ -509,9 +509,11 @@ + rx->key->tx_rx_count++; + /* TODO: add threshold stuff again */ + } else { ++#ifdef CONFIG_MAC80211_DEBUG + if (net_ratelimit()) + printk(KERN_DEBUG "%s: RX protected frame," + " but have no key\n", rx->dev->name); ++#endif /* CONFIG_MAC80211_DEBUG */ + return TXRX_DROP; + } + +Index: mac80211/net/mac80211/wep.c +=================================================================== +--- mac80211.orig/net/mac80211/wep.c 2007-11-11 15:45:23.253495749 +0100 ++++ mac80211/net/mac80211/wep.c 2007-11-11 15:45:30.449905846 +0100 +@@ -16,7 +16,7 @@ + #include + #include + #include +-#include ++#include + + #include + #include "ieee80211_i.h" +@@ -138,9 +138,7 @@ + *icv = cpu_to_le32(~crc32_le(~0, data, data_len)); + + crypto_blkcipher_setkey(tfm, rc4key, klen); +- sg.page = virt_to_page(data); +- sg.offset = offset_in_page(data); +- sg.length = data_len + WEP_ICV_LEN; ++ sg_init_one(&sg, data, data_len + WEP_ICV_LEN); + crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length); + } + +@@ -204,9 +202,7 @@ + __le32 crc; + + crypto_blkcipher_setkey(tfm, rc4key, klen); +- sg.page = virt_to_page(data); +- sg.offset = offset_in_page(data); +- sg.length = data_len + WEP_ICV_LEN; ++ sg_init_one(&sg, data, data_len + WEP_ICV_LEN); + crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length); + + crc = cpu_to_le32(~crc32_le(~0, data, data_len)); +@@ -318,9 +314,11 @@ + + if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) { + if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) { ++#ifdef CONFIG_MAC80211_DEBUG + if (net_ratelimit()) + printk(KERN_DEBUG "%s: RX WEP frame, decrypt " + "failed\n", rx->dev->name); ++#endif /* CONFIG_MAC80211_DEBUG */ + return TXRX_DROP; + } + } else if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED)) { +Index: mac80211/net/wireless/Kconfig +=================================================================== +--- mac80211.orig/net/wireless/Kconfig 2007-11-11 15:45:23.261496205 +0100 ++++ mac80211/net/wireless/Kconfig 2007-11-11 15:45:30.453906075 +0100 +@@ -3,7 +3,7 @@ + + config NL80211 + bool "nl80211 new netlink interface support" +- depends CFG80211 ++ depends on CFG80211 + default y + ---help--- + This option turns on the new netlink interface diff --git a/package/mac80211/patches/008-add-hostapd-ioctl-header.patch b/package/mac80211/patches/008-add-hostapd-ioctl-header.patch new file mode 100644 index 0000000000..acea0ce969 --- /dev/null +++ b/package/mac80211/patches/008-add-hostapd-ioctl-header.patch @@ -0,0 +1,110 @@ +--- + net/mac80211/hostapd_ioctl.h | 103 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 103 insertions(+) + +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ everything/net/mac80211/hostapd_ioctl.h 2007-11-07 13:19:23.031516330 +0100 +@@ -0,0 +1,103 @@ ++/* ++ * Host AP (software wireless LAN access point) user space daemon for ++ * Host AP kernel driver ++ * Copyright 2002-2003, Jouni Malinen ++ * 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 ++#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_AP_BRIDGE_PACKETS = 10, ++ PRISM2_PARAM_IEEE_802_1X = 23, ++ ++ /* Instant802 additions */ ++ PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES = 1001, ++ PRISM2_PARAM_PREAMBLE = 1003, ++ PRISM2_PARAM_SHORT_SLOT_TIME = 1006, ++ PRISM2_PARAM_NEXT_MODE = 1008, ++ PRISM2_PARAM_PRIVACY_INVOKED = 1014, ++ PRISM2_PARAM_EAPOL = 1023, ++ 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, ++ ++ /* Instant802 additions */ ++ PRISM2_HOSTAPD_GET_HW_FEATURES = 1002, ++ PRISM2_HOSTAPD_SET_RATE_SETS = 1005, ++ PRISM2_HOSTAPD_SET_CHANNEL_FLAG = 1012, ++ PRISM2_HOSTAPD_SET_REGULATORY_DOMAIN = 1013, ++ PRISM2_HOSTAPD_SET_TX_QUEUE_PARAMS = 1014, ++}; ++ ++#define PRISM2_HOSTAPD_MAX_BUF_SIZE 2048 ++#define ALIGNED __attribute__ ((aligned)) ++ ++struct prism2_hostapd_param { ++ u32 cmd; ++ u8 sta_addr[ETH_ALEN]; ++ u8 pad[2]; ++ union { ++ struct { ++ u16 num_modes; ++ u16 flags; ++ u8 data[0] ALIGNED; /* num_modes * feature data */ ++ } hw_features; ++ 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 { ++ 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; ++ } u; ++}; ++ ++/* Data structures used for get_hw_features ioctl */ ++struct hostapd_ioctl_hw_modes_hdr { ++ int mode; ++ int num_channels; ++ int num_rates; ++}; ++ ++#endif /* HOSTAPD_IOCTL_H */ diff --git a/package/mac80211/patches/009-add-old-ioctl-skeleton.patch b/package/mac80211/patches/009-add-old-ioctl-skeleton.patch new file mode 100644 index 0000000000..fb9f25f62a --- /dev/null +++ b/package/mac80211/patches/009-add-old-ioctl-skeleton.patch @@ -0,0 +1,187 @@ +--- + net/mac80211/ieee80211.c | 5 + + net/mac80211/ieee80211_ioctl.c | 121 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 126 insertions(+) + +--- everything.orig/net/mac80211/ieee80211_ioctl.c 2007-11-07 13:06:34.902124618 +0100 ++++ everything/net/mac80211/ieee80211_ioctl.c 2007-11-07 13:19:24.311521482 +0100 +@@ -21,6 +21,7 @@ + + #include + #include "ieee80211_i.h" ++#include "hostapd_ioctl.h" + #include "ieee80211_rate.h" + #include "wpa.h" + #include "aes_ccm.h" +@@ -124,6 +125,47 @@ static int ieee80211_ioctl_siwgenie(stru + return -EOPNOTSUPP; + } + ++ ++static int ieee80211_ioctl_priv_hostapd(struct net_device *dev, ++ struct iw_point *p) ++{ ++ struct prism2_hostapd_param *param; ++ int ret = 0; ++ ++ if (p->length < sizeof(struct prism2_hostapd_param) || ++ p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) { ++ printk(KERN_DEBUG "%s: hostapd ioctl: ptr=%p len=%d min=%d " ++ "max=%d\n", dev->name, p->pointer, p->length, ++ (int)sizeof(struct prism2_hostapd_param), ++ PRISM2_HOSTAPD_MAX_BUF_SIZE); ++ return -EINVAL; ++ } ++ ++ param = kmalloc(p->length, GFP_KERNEL); ++ if (!param) ++ return -ENOMEM; ++ ++ if (copy_from_user(param, p->pointer, p->length)) { ++ ret = -EFAULT; ++ goto out; ++ } ++ ++ switch (param->cmd) { ++ default: ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ if (copy_to_user(p->pointer, param, p->length)) ++ ret = -EFAULT; ++ ++ out: ++ kfree(param); ++ ++ return ret; ++} ++ ++ + static int ieee80211_ioctl_giwname(struct net_device *dev, + struct iw_request_info *info, + char *name, char *extra) +@@ -819,6 +861,49 @@ static int ieee80211_ioctl_giwretry(stru + return 0; + } + ++static int ieee80211_ioctl_prism2_param(struct net_device *dev, ++ struct iw_request_info *info, ++ void *wrqu, char *extra) ++{ ++ struct ieee80211_sub_if_data *sdata; ++ int *i = (int *) extra; ++ int param = *i; ++ int ret = 0; ++ ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ ++ switch (param) { ++ default: ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ return ret; ++} ++ ++ ++static int ieee80211_ioctl_get_prism2_param(struct net_device *dev, ++ struct iw_request_info *info, ++ void *wrqu, char *extra) ++{ ++ struct ieee80211_sub_if_data *sdata; ++ int *param = (int *) extra; ++ int ret = 0; ++ ++ sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ ++ switch (*param) { ++ default: ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ return ret; ++} ++ + static int ieee80211_ioctl_siwmlme(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +@@ -1073,6 +1158,32 @@ static int ieee80211_ioctl_siwencodeext( + } + + ++static const struct iw_priv_args ieee80211_ioctl_priv[] = { ++ { PRISM2_IOCTL_PRISM2_PARAM, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "param" }, ++ { PRISM2_IOCTL_GET_PRISM2_PARAM, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param" }, ++}; ++ ++ ++int ieee80211_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ++{ ++ struct iwreq *wrq = (struct iwreq *) rq; ++ ++ switch (cmd) { ++ /* Private ioctls (iwpriv) that have not yet been converted ++ * into new wireless extensions API */ ++ case PRISM2_IOCTL_HOSTAPD: ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ return ieee80211_ioctl_priv_hostapd(dev, &wrq->u.data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++ + /* Structures to export the Wireless Handlers */ + + static const iw_handler ieee80211_handler[] = +@@ -1135,9 +1246,19 @@ static const iw_handler ieee80211_handle + (iw_handler) NULL, /* -- hole -- */ + }; + ++static const iw_handler ieee80211_private_handler[] = ++{ /* SIOCIWFIRSTPRIV + */ ++ (iw_handler) ieee80211_ioctl_prism2_param, /* 0 */ ++ (iw_handler) ieee80211_ioctl_get_prism2_param, /* 1 */ ++}; ++ + const struct iw_handler_def ieee80211_iw_handler_def = + { + .num_standard = ARRAY_SIZE(ieee80211_handler), ++ .num_private = ARRAY_SIZE(ieee80211_private_handler), ++ .num_private_args = ARRAY_SIZE(ieee80211_ioctl_priv), + .standard = (iw_handler *) ieee80211_handler, ++ .private = (iw_handler *) ieee80211_private_handler, ++ .private_args = (struct iw_priv_args *) ieee80211_ioctl_priv, + .get_wireless_stats = ieee80211_get_wireless_stats, + }; +--- everything.orig/net/mac80211/ieee80211.c 2007-11-07 13:18:36.001511500 +0100 ++++ everything/net/mac80211/ieee80211.c 2007-11-07 13:19:24.311521482 +0100 +@@ -413,6 +413,9 @@ static const struct header_ops ieee80211 + .cache_update = eth_header_cache_update, + }; + ++/* HACK */ ++extern int ieee80211_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); ++ + /* Must not be called for mdev */ + void ieee80211_if_setup(struct net_device *dev) + { +@@ -425,6 +428,8 @@ void ieee80211_if_setup(struct net_devic + dev->open = ieee80211_open; + dev->stop = ieee80211_stop; + dev->destructor = ieee80211_if_free; ++ ++ dev->do_ioctl = ieee80211_ioctl; + } + + /* WDS specialties */ diff --git a/package/mac80211/patches/010-add-mgmt-iface.patch b/package/mac80211/patches/010-add-mgmt-iface.patch new file mode 100644 index 0000000000..eae5ff6d5e --- /dev/null +++ b/package/mac80211/patches/010-add-mgmt-iface.patch @@ -0,0 +1,688 @@ +--- + include/net/mac80211.h | 1 + net/mac80211/ieee80211.c | 198 ++++++++++++++++++++++++++++++++++++++-- + net/mac80211/ieee80211_common.h | 64 ++++++++++++ + net/mac80211/ieee80211_i.h | 9 + + net/mac80211/ieee80211_iface.c | 66 +++++++++++++ + net/mac80211/ieee80211_ioctl.c | 21 ++++ + net/mac80211/ieee80211_rate.c | 3 + net/mac80211/ieee80211_rate.h | 2 + net/mac80211/ieee80211_sta.c | 2 + net/mac80211/rx.c | 29 ++++- + net/mac80211/tx.c | 14 ++ + net/mac80211/wme.c | 10 +- + 12 files changed, 399 insertions(+), 20 deletions(-) + +Index: mac80211/include/net/mac80211.h +=================================================================== +--- mac80211.orig/include/net/mac80211.h 2007-11-11 15:15:42.824034853 +0100 ++++ mac80211/include/net/mac80211.h 2007-11-11 15:15:53.784659457 +0100 +@@ -472,6 +472,7 @@ + enum ieee80211_if_types { + IEEE80211_IF_TYPE_INVALID, + IEEE80211_IF_TYPE_AP, ++ IEEE80211_IF_TYPE_MGMT, + IEEE80211_IF_TYPE_STA, + IEEE80211_IF_TYPE_IBSS, + IEEE80211_IF_TYPE_MNTR, +Index: mac80211/net/mac80211/ieee80211.c +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211.c 2007-11-11 15:15:51.536531354 +0100 ++++ mac80211/net/mac80211/ieee80211.c 2007-11-11 15:16:22.214279577 +0100 +@@ -23,6 +23,7 @@ + #include + #include + ++#include "ieee80211_common.h" + #include "ieee80211_i.h" + #include "ieee80211_rate.h" + #include "wep.h" +@@ -121,6 +122,152 @@ + ieee80211_configure_filter(local); + } + ++/* management interface */ ++ ++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; ++ 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 net_device *dev = local->apdev; ++ ++ skb->dev = dev; ++ ++ 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); ++ ++ dev->stats.rx_packets++; ++ dev->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 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; ++} ++ ++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; ++} ++ ++void ieee80211_if_mgmt_setup(struct net_device *dev) ++{ ++ ether_setup(dev); ++ dev->hard_start_xmit = ieee80211_mgmt_start_xmit; ++ dev->change_mtu = ieee80211_change_mtu_apdev; ++ dev->open = ieee80211_mgmt_open; ++ dev->stop = ieee80211_mgmt_stop; ++ dev->type = ARPHRD_IEEE80211_PRISM; ++ dev->hard_header_parse = &header_parse_80211; ++ dev->destructor = ieee80211_if_free; ++} ++ + /* regular interfaces */ + + static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) +@@ -198,6 +345,7 @@ + return -ENOLINK; + break; + case IEEE80211_IF_TYPE_AP: ++ case IEEE80211_IF_TYPE_MGMT: + case IEEE80211_IF_TYPE_STA: + case IEEE80211_IF_TYPE_MNTR: + case IEEE80211_IF_TYPE_IBSS: +@@ -262,6 +410,10 @@ + if (local->open_count == 0) { + res = dev_open(local->mdev); + WARN_ON(res); ++ if (local->apdev) { ++ res = dev_open(local->apdev); ++ WARN_ON(res); ++ } + tasklet_enable(&local->tx_pending_tasklet); + tasklet_enable(&local->tasklet); + } +@@ -347,6 +499,9 @@ + 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)); + +@@ -646,6 +801,8 @@ + pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT; + if (control->flags & IEEE80211_TXCTL_REQUEUE) + pkt_data->flags |= IEEE80211_TXPD_REQUEUE; ++ if (control->type == IEEE80211_IF_TYPE_MGMT) ++ pkt_data->flags |= IEEE80211_TXPD_MGMT_IFACE; + pkt_data->queue = control->queue; + + hdrlen = ieee80211_get_hdrlen_from_skb(skb); +@@ -698,6 +855,7 @@ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_local *local = hw_to_local(hw); + u16 frag, type; ++ u32 msg_type; + struct ieee80211_tx_status_rtap_hdr *rthdr; + struct ieee80211_sub_if_data *sdata; + int monitors; +@@ -812,9 +970,29 @@ + local->dot11FailedCount++; + } + ++ msg_type = (status->flags & IEEE80211_TX_STATUS_ACK) ? ++ ieee80211_msg_tx_callback_ack : ieee80211_msg_tx_callback_fail; ++ + /* this was a transmitted frame, but now we want to reuse it */ + skb_orphan(skb); + ++ if ((status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS) && ++ local->apdev) { ++ if (local->monitors) { ++ skb2 = skb_clone(skb, GFP_ATOMIC); ++ } else { ++ skb2 = skb; ++ skb = NULL; ++ } ++ ++ if (skb2) ++ /* Send frame to hostapd */ ++ ieee80211_rx_mgmt(local, skb2, NULL, msg_type); ++ ++ if (!skb) ++ return; ++ } ++ + if (!local->monitors) { + dev_kfree_skb(skb); + return; +@@ -1161,6 +1339,8 @@ + BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED); + + local->reg_state = IEEE80211_DEV_UNREGISTERED; ++ if (local->apdev) ++ ieee80211_if_del_mgmt(local); + + /* + * At this point, interface list manipulations are fine +Index: mac80211/net/mac80211/ieee80211_i.h +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211_i.h 2007-11-11 15:15:42.840035769 +0100 ++++ mac80211/net/mac80211/ieee80211_i.h 2007-11-11 15:15:53.792659922 +0100 +@@ -142,6 +142,7 @@ + * when using CTS protection with IEEE 802.11g. */ + struct ieee80211_rate *last_frag_rate; + int last_frag_hwrate; ++ int mgmt_interface; + + /* Extra fragments (in addition to the first fragment + * in skb) */ +@@ -163,6 +164,7 @@ + #define IEEE80211_TXPD_REQ_TX_STATUS BIT(0) + #define IEEE80211_TXPD_DO_NOT_ENCRYPT BIT(1) + #define IEEE80211_TXPD_REQUEUE BIT(2) ++#define IEEE80211_TXPD_MGMT_IFACE BIT(3) + /* Stored in sk_buff->cb */ + struct ieee80211_tx_packet_data { + int ifindex; +@@ -408,6 +410,7 @@ + struct list_head modes_list; + + struct net_device *mdev; /* wmaster# - "master" 802.11 device */ ++ struct net_device *apdev; /* wlan#ap - management frames (hostapd) */ + int open_count; + int monitors; + unsigned int filter_flags; /* FIF_* */ +@@ -701,11 +704,14 @@ + int ieee80211_hw_config(struct ieee80211_local *local); + int ieee80211_if_config(struct net_device *dev); + int ieee80211_if_config_beacon(struct net_device *dev); ++void ieee80211_rx_mgmt(struct ieee80211_local *local, struct sk_buff *skb, ++ struct ieee80211_rx_status *status, u32 msg_type); + void ieee80211_prepare_rates(struct ieee80211_local *local, + struct ieee80211_hw_mode *mode); + void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx); + int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr); + void ieee80211_if_setup(struct net_device *dev); ++void ieee80211_if_mgmt_setup(struct net_device *dev); + struct ieee80211_rate *ieee80211_get_rate(struct ieee80211_local *local, + int phymode, int hwrate); + +@@ -772,6 +778,8 @@ + int ieee80211_if_remove(struct net_device *dev, const char *name, int id); + void ieee80211_if_free(struct net_device *dev); + void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata); ++int ieee80211_if_add_mgmt(struct ieee80211_local *local); ++void ieee80211_if_del_mgmt(struct ieee80211_local *local); + + /* regdomain.c */ + void ieee80211_regdomain_init(void); +@@ -788,6 +796,7 @@ + int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev); + int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); + int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); ++int ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev); + + /* utility functions/constants */ + extern void *mac80211_wiphy_privid; /* for wiphy privid */ +Index: mac80211/net/mac80211/ieee80211_iface.c +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211_iface.c 2007-11-11 15:15:42.848036222 +0100 ++++ mac80211/net/mac80211/ieee80211_iface.c 2007-11-11 15:15:53.796660158 +0100 +@@ -96,6 +96,66 @@ + return ret; + } + ++int ieee80211_if_add_mgmt(struct ieee80211_local *local) ++{ ++ struct net_device *ndev; ++ struct ieee80211_sub_if_data *nsdata; ++ int ret; ++ ++ ASSERT_RTNL(); ++ ++ ndev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), "wmgmt%d", ++ ieee80211_if_mgmt_setup); ++ if (!ndev) ++ return -ENOMEM; ++ ret = dev_alloc_name(ndev, ndev->name); ++ if (ret < 0) ++ goto fail; ++ ++ memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); ++ SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); ++ ++ nsdata = IEEE80211_DEV_TO_SUB_IF(ndev); ++ ndev->ieee80211_ptr = &nsdata->wdev; ++ nsdata->wdev.wiphy = local->hw.wiphy; ++ nsdata->type = IEEE80211_IF_TYPE_MGMT; ++ nsdata->dev = ndev; ++ nsdata->local = local; ++ ieee80211_if_sdata_init(nsdata); ++ ++ ret = register_netdevice(ndev); ++ if (ret) ++ goto fail; ++ ++ /* ++ * Called even when register_netdevice fails, it would ++ * oops if assigned before initialising the rest. ++ */ ++ ndev->uninit = ieee80211_if_reinit; ++ ++ ieee80211_debugfs_add_netdev(nsdata); ++ ++ if (local->open_count > 0) ++ dev_open(ndev); ++ local->apdev = ndev; ++ return 0; ++ ++fail: ++ free_netdev(ndev); ++ return ret; ++} ++ ++void ieee80211_if_del_mgmt(struct ieee80211_local *local) ++{ ++ struct net_device *apdev; ++ ++ ASSERT_RTNL(); ++ apdev = local->apdev; ++ ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(apdev)); ++ local->apdev = NULL; ++ unregister_netdevice(apdev); ++} ++ + void ieee80211_if_set_type(struct net_device *dev, int type) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +@@ -183,6 +243,9 @@ + ieee80211_if_sdata_deinit(sdata); + + switch (sdata->type) { ++ case IEEE80211_IF_TYPE_MGMT: ++ /* nothing to do */ ++ break; + case IEEE80211_IF_TYPE_INVALID: + /* cannot happen */ + WARN_ON(1); +@@ -294,8 +357,11 @@ + + void ieee80211_if_free(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); + ++ /* local->apdev must be NULL when freeing management interface */ ++ BUG_ON(dev == local->apdev); + ieee80211_if_sdata_deinit(sdata); + free_netdev(dev); + } +Index: mac80211/net/mac80211/ieee80211_rate.c +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211_rate.c 2007-11-11 15:15:42.852036451 +0100 ++++ mac80211/net/mac80211/ieee80211_rate.c 2007-11-11 15:15:53.800660386 +0100 +@@ -145,7 +145,8 @@ + struct rate_control_ref *ref, *old; + + ASSERT_RTNL(); +- if (local->open_count || netif_running(local->mdev)) ++ if (local->open_count || netif_running(local->mdev) || ++ (local->apdev && netif_running(local->apdev))) + return -EBUSY; + + ref = rate_control_alloc(name, local); +Index: mac80211/net/mac80211/ieee80211_rate.h +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211_rate.h 2007-11-11 15:15:42.860036908 +0100 ++++ mac80211/net/mac80211/ieee80211_rate.h 2007-11-11 15:15:53.800660386 +0100 +@@ -30,6 +30,8 @@ + + /* parameters from the caller to rate_control_get_rate(): */ + struct ieee80211_hw_mode *mode; ++ int mgmt_data; /* this is data frame that is used for management ++ * (e.g., IEEE 802.1X EAPOL) */ + u16 ethertype; + }; + +Index: mac80211/net/mac80211/ieee80211_sta.c +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211_sta.c 2007-11-11 15:15:42.868037362 +0100 ++++ mac80211/net/mac80211/ieee80211_sta.c 2007-11-11 15:15:53.800660386 +0100 +@@ -475,6 +475,8 @@ + 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; ++ if (sdata->type == IEEE80211_IF_TYPE_MGMT) ++ pkt_data->flags |= IEEE80211_TXPD_MGMT_IFACE; + if (!encrypt) + pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT; + +Index: mac80211/net/mac80211/rx.c +=================================================================== +--- mac80211.orig/net/mac80211/rx.c 2007-11-11 15:15:42.872037591 +0100 ++++ mac80211/net/mac80211/rx.c 2007-11-11 15:15:53.804660611 +0100 +@@ -19,6 +19,7 @@ + + #include "ieee80211_i.h" + #include "ieee80211_led.h" ++#include "ieee80211_common.h" + #include "wep.h" + #include "wpa.h" + #include "tkip.h" +@@ -411,7 +412,12 @@ + return TXRX_DROP; + } + +- return TXRX_DROP; ++ if (!rx->local->apdev) ++ return TXRX_DROP; ++ ++ ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status, ++ ieee80211_msg_sta_not_assoc); ++ return TXRX_QUEUED; + } + + return TXRX_CONTINUE; +@@ -953,8 +959,15 @@ + { + if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb) && + rx->sdata->type != IEEE80211_IF_TYPE_STA && +- (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) +- return TXRX_CONTINUE; ++ (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) { ++ /* Pass both encrypted and unencrypted EAPOL frames to user ++ * space for processing. */ ++ if (!rx->local->apdev) ++ return TXRX_DROP; ++ ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status, ++ ieee80211_msg_normal); ++ return TXRX_QUEUED; ++ } + + if (unlikely(rx->sdata->ieee802_1x && + (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && +@@ -1196,8 +1209,13 @@ + sdata->type == IEEE80211_IF_TYPE_IBSS) && + !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) + ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status); +- else +- return TXRX_DROP; ++ else { ++ /* Management frames are sent to hostapd for processing */ ++ if (!rx->local->apdev) ++ return TXRX_DROP; ++ ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status, ++ ieee80211_msg_normal); ++ } + + return TXRX_QUEUED; + } +@@ -1407,6 +1425,7 @@ + /* take everything */ + break; + case IEEE80211_IF_TYPE_INVALID: ++ case IEEE80211_IF_TYPE_MGMT: + /* should never get here */ + WARN_ON(1); + break; +Index: mac80211/net/mac80211/tx.c +=================================================================== +--- mac80211.orig/net/mac80211/tx.c 2007-11-11 15:15:42.880038048 +0100 ++++ mac80211/net/mac80211/tx.c 2007-11-11 15:15:53.804660611 +0100 +@@ -258,7 +258,7 @@ + return TXRX_CONTINUE; + } + +- if (unlikely(/* !injected && */ tx->sdata->ieee802_1x && ++ 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 +@@ -568,6 +568,8 @@ + memset(&extra, 0, sizeof(extra)); + extra.mode = tx->u.tx.mode; + extra.ethertype = tx->ethertype; ++ extra.mgmt_data = tx->sdata && ++ tx->sdata->type == IEEE80211_IF_TYPE_MGMT; + + tx->u.tx.rate = rate_control_get_rate(tx->local, tx->dev, + tx->skb, &extra); +@@ -1076,7 +1078,7 @@ + } + + static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, +- struct ieee80211_tx_control *control) ++ struct ieee80211_tx_control *control, int mgmt) + { + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct sta_info *sta; +@@ -1107,6 +1109,7 @@ + rcu_read_lock(); + + sta = tx.sta; ++ tx.u.tx.mgmt_interface = mgmt; + tx.u.tx.mode = local->hw.conf.mode; + + for (handler = local->tx_handlers; *handler != NULL; +@@ -1253,7 +1256,8 @@ + control.flags |= IEEE80211_TXCTL_REQUEUE; + control.queue = pkt_data->queue; + +- ret = ieee80211_tx(odev, skb, &control); ++ ret = ieee80211_tx(odev, skb, &control, ++ control.type == IEEE80211_IF_TYPE_MGMT); + dev_put(odev); + + return ret; +@@ -1498,6 +1502,8 @@ + pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; + memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data)); + pkt_data->ifindex = dev->ifindex; ++ if (sdata->type == IEEE80211_IF_TYPE_MGMT) ++ pkt_data->flags |= IEEE80211_TXPD_MGMT_IFACE; + + skb->dev = local->mdev; + dev->stats.tx_packets++; +@@ -1555,6 +1561,8 @@ + 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; ++ if (sdata->type == IEEE80211_IF_TYPE_MGMT) ++ pkt_data->flags |= IEEE80211_TXPD_MGMT_IFACE; + + skb->priority = 20; /* use hardcoded priority for mgmt TX queue */ + skb->dev = sdata->local->mdev; +Index: mac80211/net/mac80211/wme.c +=================================================================== +--- mac80211.orig/net/mac80211/wme.c 2007-11-11 15:15:42.888038502 +0100 ++++ mac80211/net/mac80211/wme.c 2007-11-11 15:15:53.804660611 +0100 +@@ -94,6 +94,8 @@ + static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd) + { + struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr); ++ struct ieee80211_tx_packet_data *pkt_data = ++ (struct ieee80211_tx_packet_data *) skb->cb; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + unsigned short fc = le16_to_cpu(hdr->frame_control); + int qos; +@@ -106,8 +108,12 @@ + return IEEE80211_TX_QUEUE_DATA0; + } + +- if (0 /* injected */) { +- /* use AC from radiotap */ ++ if (unlikely(pkt_data->flags & IEEE80211_TXPD_MGMT_IFACE)) { ++ /* Data frames from hostapd (mainly, EAPOL) use AC_VO ++ * and they will include QoS control fields if ++ * the target STA is using WME. */ ++ skb->priority = 7; ++ return ieee802_1d_to_ac[skb->priority]; + } + + /* is this a QoS frame? */ +Index: mac80211/net/mac80211/ieee80211_ioctl.c +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211_ioctl.c 2007-11-11 15:15:51.532531127 +0100 ++++ mac80211/net/mac80211/ieee80211_ioctl.c 2007-11-11 15:15:53.808660833 +0100 +@@ -840,16 +840,29 @@ + void *wrqu, char *extra) + { + struct ieee80211_sub_if_data *sdata; ++ struct ieee80211_local *local; + int *i = (int *) extra; + int param = *i; ++ int value = *(i + 1); + int ret = 0; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ local = sdata->local; + + switch (param) { ++ case PRISM2_PARAM_MGMT_IF: ++ if (value == 1) { ++ if (!local->apdev) ++ ret = ieee80211_if_add_mgmt(local); ++ } else if (value == 0) { ++ if (local->apdev) ++ ieee80211_if_del_mgmt(local); ++ } else ++ ret = -EINVAL; ++ break; + default: + ret = -EOPNOTSUPP; + break; +@@ -864,12 +877,20 @@ + void *wrqu, char *extra) + { + struct ieee80211_sub_if_data *sdata; ++ struct ieee80211_local *local; + int *param = (int *) extra; + int ret = 0; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ local = sdata->local; + + switch (*param) { ++ case PRISM2_PARAM_MGMT_IF: ++ if (local->apdev) ++ *param = local->apdev->ifindex; ++ else ++ ret = -ENOENT; ++ break; + default: + ret = -EOPNOTSUPP; + break; diff --git a/package/mac80211/patches/011-allow-ap-vlan-modes.patch b/package/mac80211/patches/011-allow-ap-vlan-modes.patch new file mode 100644 index 0000000000..d0edfe835c --- /dev/null +++ b/package/mac80211/patches/011-allow-ap-vlan-modes.patch @@ -0,0 +1,37 @@ +Subject: mac80211: allow AP and VLAN modes + +This adds AP/VLAN modes to the list of modes that a mac80211 +interface can be created in/switched into. + +Signed-off-by: Johannes Berg + +--- + net/mac80211/cfg.c | 4 ++++ + net/mac80211/ieee80211_ioctl.c | 3 +++ + 2 files changed, 7 insertions(+) + +--- everything.orig/net/mac80211/cfg.c 2007-10-30 15:33:43.227379286 +0100 ++++ everything/net/mac80211/cfg.c 2007-11-07 13:19:27.981515569 +0100 +@@ -25,6 +25,10 @@ nl80211_type_to_mac80211_type(enum nl802 + return IEEE80211_IF_TYPE_STA; + case NL80211_IFTYPE_MONITOR: + return IEEE80211_IF_TYPE_MNTR; ++ case NL80211_IFTYPE_AP: ++ return IEEE80211_IF_TYPE_AP; ++ case NL80211_IFTYPE_AP_VLAN: ++ return IEEE80211_IF_TYPE_VLAN; + default: + return IEEE80211_IF_TYPE_INVALID; + } +--- everything.orig/net/mac80211/ieee80211_ioctl.c 2007-11-07 13:19:25.851524684 +0100 ++++ everything/net/mac80211/ieee80211_ioctl.c 2007-11-07 13:19:27.981515569 +0100 +@@ -284,6 +284,9 @@ static int ieee80211_ioctl_siwmode(struc + case IW_MODE_MONITOR: + type = IEEE80211_IF_TYPE_MNTR; + break; ++ case IW_MODE_MASTER: ++ type = IEEE80211_IF_TYPE_AP; ++ break; + default: + return -EINVAL; + } diff --git a/package/mac80211/patches/012-mac80211-allow-wds.patch b/package/mac80211/patches/012-mac80211-allow-wds.patch new file mode 100644 index 0000000000..d5c57cd019 --- /dev/null +++ b/package/mac80211/patches/012-mac80211-allow-wds.patch @@ -0,0 +1,22 @@ +Subject: mac80211: allow WDS mode + +This allows creating interfaces in WDS mode or switching +existing ones into WDS mode (both via cfg80211.) + +Signed-off-by: Johannes Berg + +--- + net/mac80211/cfg.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- everything.orig/net/mac80211/cfg.c 2007-11-07 13:19:27.981515569 +0100 ++++ everything/net/mac80211/cfg.c 2007-11-07 13:19:29.441515732 +0100 +@@ -29,6 +29,8 @@ nl80211_type_to_mac80211_type(enum nl802 + return IEEE80211_IF_TYPE_AP; + case NL80211_IFTYPE_AP_VLAN: + return IEEE80211_IF_TYPE_VLAN; ++ case NL80211_IFTYPE_WDS: ++ return IEEE80211_IF_TYPE_WDS; + default: + return IEEE80211_IF_TYPE_INVALID; + } diff --git a/package/mac80211/patches/013-prism2-ioctl-bridge-packets.patch b/package/mac80211/patches/013-prism2-ioctl-bridge-packets.patch new file mode 100644 index 0000000000..d418ad3497 --- /dev/null +++ b/package/mac80211/patches/013-prism2-ioctl-bridge-packets.patch @@ -0,0 +1,26 @@ +--- + net/mac80211/ieee80211_ioctl.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- everything.orig/net/mac80211/ieee80211_ioctl.c 2007-11-07 13:19:27.981515569 +0100 ++++ everything/net/mac80211/ieee80211_ioctl.c 2007-11-07 13:19:30.781513182 +0100 +@@ -882,6 +882,9 @@ static int ieee80211_ioctl_prism2_param( + local = sdata->local; + + switch (param) { ++ case PRISM2_PARAM_AP_BRIDGE_PACKETS: ++ local->bridge_packets = value; ++ break; + case PRISM2_PARAM_MGMT_IF: + if (value == 1) { + if (!local->apdev) +@@ -914,6 +917,9 @@ static int ieee80211_ioctl_get_prism2_pa + local = sdata->local; + + switch (*param) { ++ case PRISM2_PARAM_AP_BRIDGE_PACKETS: ++ *param = local->bridge_packets; ++ break; + case PRISM2_PARAM_MGMT_IF: + if (local->apdev) + *param = local->apdev->ifindex; diff --git a/package/mac80211/patches/014-prism2-ioctl-8021x.patch b/package/mac80211/patches/014-prism2-ioctl-8021x.patch new file mode 100644 index 0000000000..5feb01ea32 --- /dev/null +++ b/package/mac80211/patches/014-prism2-ioctl-8021x.patch @@ -0,0 +1,26 @@ +--- + net/mac80211/ieee80211_ioctl.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- everything.orig/net/mac80211/ieee80211_ioctl.c 2007-11-07 13:19:30.781513182 +0100 ++++ everything/net/mac80211/ieee80211_ioctl.c 2007-11-07 13:19:32.281514919 +0100 +@@ -882,6 +882,9 @@ static int ieee80211_ioctl_prism2_param( + local = sdata->local; + + switch (param) { ++ case PRISM2_PARAM_IEEE_802_1X: ++ sdata->ieee802_1x = value; ++ break; + case PRISM2_PARAM_AP_BRIDGE_PACKETS: + local->bridge_packets = value; + break; +@@ -917,6 +920,9 @@ static int ieee80211_ioctl_get_prism2_pa + local = sdata->local; + + switch (*param) { ++ case PRISM2_PARAM_IEEE_802_1X: ++ *param = sdata->ieee802_1x; ++ break; + case PRISM2_PARAM_AP_BRIDGE_PACKETS: + *param = local->bridge_packets; + break; diff --git a/package/mac80211/patches/015-hostapd-ioctl-hw-features.patch b/package/mac80211/patches/015-hostapd-ioctl-hw-features.patch new file mode 100644 index 0000000000..d6e5dfd073 --- /dev/null +++ b/package/mac80211/patches/015-hostapd-ioctl-hw-features.patch @@ -0,0 +1,122 @@ +--- + net/mac80211/ieee80211_ioctl.c | 102 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 102 insertions(+) + +--- everything.orig/net/mac80211/ieee80211_ioctl.c 2007-11-07 13:19:32.281514919 +0100 ++++ everything/net/mac80211/ieee80211_ioctl.c 2007-11-07 13:19:33.681513453 +0100 +@@ -125,6 +125,105 @@ static int ieee80211_ioctl_siwgenie(stru + return -EOPNOTSUPP; + } + ++/* ++ * Wow. This ioctl interface is such crap, it's tied ++ * to internal definitions. I hope it dies soon. ++ */ ++static int mode_to_hostapd_mode(enum ieee80211_phymode mode) ++{ ++ switch (mode) { ++ case MODE_IEEE80211A: ++ return 0; ++ case MODE_IEEE80211B: ++ return 1; ++ case MODE_IEEE80211G: ++ return 3; ++ case NUM_IEEE80211_MODES: ++ WARN_ON(1); ++ break; ++ } ++ WARN_ON(1); ++ return -1; ++} ++ ++static int channel_flags_to_hostapd_flags(int flags) ++{ ++ int res = 0; ++ ++ if (flags & IEEE80211_CHAN_W_SCAN) ++ res |= 1; ++ if (flags & IEEE80211_CHAN_W_ACTIVE_SCAN) ++ res |= 2; ++ if (flags & IEEE80211_CHAN_W_IBSS) ++ res |= 4; ++ ++ return res; ++} ++ ++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 */ ++}; ++ ++static int ieee80211_ioctl_get_hw_features(struct net_device *dev, ++ struct prism2_hostapd_param *param, ++ int param_len) ++{ ++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); ++ u8 *pos = param->u.hw_features.data; ++ int left = param_len - (pos - (u8 *) param); ++ int i; ++ struct hostapd_ioctl_hw_modes_hdr *hdr; ++ struct ieee80211_rate_data *rate; ++ struct ieee80211_channel_data *chan; ++ struct ieee80211_hw_mode *mode; ++ ++ param->u.hw_features.flags = 0; ++ ++ param->u.hw_features.num_modes = 0; ++ list_for_each_entry(mode, &local->modes_list, list) { ++ int clen, rlen; ++ ++ param->u.hw_features.num_modes++; ++ clen = ++ mode->num_channels * sizeof(struct ieee80211_channel_data); ++ rlen = mode->num_rates * sizeof(struct ieee80211_rate_data); ++ if (left < sizeof(*hdr) + clen + rlen) ++ return -E2BIG; ++ left -= sizeof(*hdr) + clen + rlen; ++ ++ hdr = (struct hostapd_ioctl_hw_modes_hdr *)pos; ++ hdr->mode = mode_to_hostapd_mode(mode->mode); ++ hdr->num_channels = mode->num_channels; ++ hdr->num_rates = mode->num_rates; ++ ++ pos = (u8 *) (hdr + 1); ++ chan = (struct ieee80211_channel_data *)pos; ++ for (i = 0; i < mode->num_channels; i++) { ++ chan[i].chan = mode->channels[i].chan; ++ chan[i].freq = mode->channels[i].freq; ++ chan[i].flag = channel_flags_to_hostapd_flags( ++ mode->channels[i].flag); ++ } ++ pos += clen; ++ ++ rate = (struct ieee80211_rate_data *)pos; ++ for (i = 0; i < mode->num_rates; i++) { ++ rate[i].rate = mode->rates[i].rate; ++ rate[i].flags = mode->rates[i].flags; ++ } ++ pos += rlen; ++ } ++ ++ return 0; ++} ++ + + static int ieee80211_ioctl_priv_hostapd(struct net_device *dev, + struct iw_point *p) +@@ -151,6 +250,9 @@ static int ieee80211_ioctl_priv_hostapd( + } + + switch (param->cmd) { ++ case PRISM2_HOSTAPD_GET_HW_FEATURES: ++ ret = ieee80211_ioctl_get_hw_features(dev, param, p->length); ++ break; + default: + ret = -EOPNOTSUPP; + break; diff --git a/package/mac80211/patches/016-prism2-ioctl-eapol.patch b/package/mac80211/patches/016-prism2-ioctl-eapol.patch new file mode 100644 index 0000000000..5ce57587ab --- /dev/null +++ b/package/mac80211/patches/016-prism2-ioctl-eapol.patch @@ -0,0 +1,26 @@ +--- + net/mac80211/ieee80211_ioctl.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- everything.orig/net/mac80211/ieee80211_ioctl.c 2007-11-07 13:19:33.681513453 +0100 ++++ everything/net/mac80211/ieee80211_ioctl.c 2007-11-07 13:19:35.171517576 +0100 +@@ -984,6 +984,9 @@ static int ieee80211_ioctl_prism2_param( + local = sdata->local; + + switch (param) { ++ case PRISM2_PARAM_EAPOL: ++ sdata->eapol = value; ++ break; + case PRISM2_PARAM_IEEE_802_1X: + sdata->ieee802_1x = value; + break; +@@ -1022,6 +1025,9 @@ static int ieee80211_ioctl_get_prism2_pa + local = sdata->local; + + switch (*param) { ++ case PRISM2_PARAM_EAPOL: ++ *param = sdata->eapol; ++ break; + case PRISM2_PARAM_IEEE_802_1X: + *param = sdata->ieee802_1x; + break; diff --git a/package/mac80211/patches/017-nl80211-add-key-mgmt.patch b/package/mac80211/patches/017-nl80211-add-key-mgmt.patch new file mode 100644 index 0000000000..f5b1d45c15 --- /dev/null +++ b/package/mac80211/patches/017-nl80211-add-key-mgmt.patch @@ -0,0 +1,470 @@ +Subject: cfg80211/nl80211: introduce key handling + +This introduces key handling to cfg80211/nl80211. Default +and group keys can be added, changed and removed; sequence +counters for each key can be retrieved. + +Signed-off-by: Johannes Berg + +--- + include/linux/nl80211.h | 34 +++++ + include/net/cfg80211.h | 44 +++++++ + net/wireless/core.c | 3 + net/wireless/nl80211.c | 289 ++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 370 insertions(+) + +--- everything.orig/include/linux/nl80211.h 2007-10-30 15:33:43.587381346 +0100 ++++ everything/include/linux/nl80211.h 2007-11-07 13:19:37.861516599 +0100 +@@ -37,6 +37,16 @@ + * userspace to request deletion of a virtual interface, then requires + * attribute %NL80211_ATTR_IFINDEX. + * ++ * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified ++ * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. ++ * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT or ++ * %NL80211_ATTR_KEY_THRESHOLD. ++ * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, ++ * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC and %NL80211_ATTR_KEY_CIPHER ++ * attributes. ++ * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX ++ * or %NL80211_ATTR_MAC. ++ * + * @NL80211_CMD_MAX: highest used command number + * @__NL80211_CMD_AFTER_LAST: internal use + */ +@@ -54,6 +64,11 @@ enum nl80211_commands { + NL80211_CMD_NEW_INTERFACE, + NL80211_CMD_DEL_INTERFACE, + ++ NL80211_CMD_GET_KEY, ++ NL80211_CMD_SET_KEY, ++ NL80211_CMD_NEW_KEY, ++ NL80211_CMD_DEL_KEY, ++ + /* add commands here */ + + /* used to define NL80211_CMD_MAX below */ +@@ -75,6 +90,17 @@ enum nl80211_commands { + * @NL80211_ATTR_IFNAME: network interface name + * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype + * ++ * @NL80211_ATTR_MAC: MAC address (various uses) ++ * ++ * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of ++ * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC ++ * keys ++ * @NL80211_ATTR_KEY_IDX: key ID (u8, 0-3) ++ * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 ++ * section 7.3.2.25.1, e.g. 0x000FAC04) ++ * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and ++ * CCMP keys, each six bytes in little endian ++ * + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use + */ +@@ -89,6 +115,14 @@ enum nl80211_attrs { + NL80211_ATTR_IFNAME, + NL80211_ATTR_IFTYPE, + ++ NL80211_ATTR_MAC, ++ ++ NL80211_ATTR_KEY_DATA, ++ NL80211_ATTR_KEY_IDX, ++ NL80211_ATTR_KEY_CIPHER, ++ NL80211_ATTR_KEY_SEQ, ++ NL80211_ATTR_KEY_DEFAULT, ++ + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +--- everything.orig/net/wireless/nl80211.c 2007-10-30 15:33:43.637380153 +0100 ++++ everything/net/wireless/nl80211.c 2007-11-07 13:19:38.201511066 +0100 +@@ -61,6 +61,14 @@ static struct nla_policy nl80211_policy[ + [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, + [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, + [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, ++ ++ [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN }, ++ ++ [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, ++ .len = WLAN_MAX_KEY_LEN }, ++ [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, ++ [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, ++ [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, + }; + + /* message building helper */ +@@ -335,6 +343,263 @@ static int nl80211_del_interface(struct + return err; + } + ++struct get_key_cookie { ++ struct sk_buff *msg; ++ int error; ++}; ++ ++static void get_key_callback(void *c, struct key_params *params) ++{ ++ struct get_key_cookie *cookie = c; ++ ++ if (params->key) ++ NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA, ++ params->key_len, params->key); ++ ++ if (params->seq) ++ NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ, ++ params->seq_len, params->seq); ++ ++ if (params->cipher) ++ NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER, ++ params->cipher); ++ ++ return; ++ nla_put_failure: ++ cookie->error = 1; ++} ++ ++static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) ++{ ++ struct cfg80211_registered_device *drv; ++ int err; ++ struct net_device *dev; ++ u8 key_idx = 0; ++ u8 *mac_addr = NULL; ++ struct get_key_cookie cookie = { ++ .error = 0, ++ }; ++ void *hdr; ++ struct sk_buff *msg; ++ ++ if (info->attrs[NL80211_ATTR_KEY_IDX]) ++ key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); ++ ++ if (key_idx > 3) ++ return -EINVAL; ++ ++ if (info->attrs[NL80211_ATTR_MAC]) ++ mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); ++ ++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev); ++ if (err) ++ return err; ++ ++ if (!drv->ops->get_key) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); ++ if (!msg) { ++ err = -ENOMEM; ++ goto out; ++ } ++ ++ hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, ++ NL80211_CMD_NEW_KEY); ++ ++ if (IS_ERR(hdr)) { ++ err = PTR_ERR(hdr); ++ goto out; ++ } ++ ++ cookie.msg = msg; ++ ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); ++ NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); ++ if (mac_addr) ++ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); ++ ++ rtnl_lock(); ++ err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr, ++ &cookie, get_key_callback); ++ rtnl_unlock(); ++ ++ if (err) ++ goto out; ++ ++ if (cookie.error) ++ goto nla_put_failure; ++ ++ genlmsg_end(msg, hdr); ++ err = genlmsg_unicast(msg, info->snd_pid); ++ goto out; ++ ++ nla_put_failure: ++ err = -ENOBUFS; ++ nlmsg_free(msg); ++ out: ++ cfg80211_put_dev(drv); ++ dev_put(dev); ++ return err; ++} ++ ++static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) ++{ ++ struct cfg80211_registered_device *drv; ++ int err; ++ struct net_device *dev; ++ u8 key_idx; ++ ++ if (!info->attrs[NL80211_ATTR_KEY_IDX]) ++ return -EINVAL; ++ ++ key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); ++ ++ if (key_idx > 3) ++ return -EINVAL; ++ ++ /* currently only support setting default key */ ++ if (!info->attrs[NL80211_ATTR_KEY_DEFAULT]) ++ return -EINVAL; ++ ++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev); ++ if (err) ++ return err; ++ ++ if (!drv->ops->set_default_key) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ rtnl_lock(); ++ err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx); ++ rtnl_unlock(); ++ ++ out: ++ cfg80211_put_dev(drv); ++ dev_put(dev); ++ return err; ++} ++ ++static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) ++{ ++ struct cfg80211_registered_device *drv; ++ int err; ++ struct net_device *dev; ++ struct key_params params; ++ u8 key_idx = 0; ++ u8 *mac_addr = NULL; ++ ++ memset(¶ms, 0, sizeof(params)); ++ ++ if (!info->attrs[NL80211_ATTR_KEY_CIPHER]) ++ return -EINVAL; ++ ++ if (info->attrs[NL80211_ATTR_KEY_DATA]) { ++ params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]); ++ params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]); ++ } ++ ++ if (info->attrs[NL80211_ATTR_KEY_IDX]) ++ key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); ++ ++ params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]); ++ ++ if (info->attrs[NL80211_ATTR_MAC]) ++ mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); ++ ++ if (key_idx > 3) ++ return -EINVAL; ++ ++ /* ++ * Disallow pairwise keys with non-zero index unless it's WEP ++ * (because current deployments use pairwise WEP keys with ++ * non-zero indizes but 802.11i clearly specifies to use zero) ++ */ ++ if (mac_addr && key_idx && ++ params.cipher != WLAN_CIPHER_SUITE_WEP40 && ++ params.cipher != WLAN_CIPHER_SUITE_WEP104) ++ return -EINVAL; ++ ++ /* TODO: add definitions for the lengths to linux/ieee80211.h */ ++ switch (params.cipher) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ if (params.key_len != 5) ++ return -EINVAL; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ if (params.key_len != 32) ++ return -EINVAL; ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ if (params.key_len != 16) ++ return -EINVAL; ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ if (params.key_len != 13) ++ return -EINVAL; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev); ++ if (err) ++ return err; ++ ++ if (!drv->ops->add_key) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ rtnl_lock(); ++ err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, ¶ms); ++ rtnl_unlock(); ++ ++ out: ++ cfg80211_put_dev(drv); ++ dev_put(dev); ++ return err; ++} ++ ++static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) ++{ ++ struct cfg80211_registered_device *drv; ++ int err; ++ struct net_device *dev; ++ u8 key_idx = 0; ++ u8 *mac_addr = NULL; ++ ++ if (info->attrs[NL80211_ATTR_KEY_IDX]) ++ key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); ++ ++ if (key_idx > 3) ++ return -EINVAL; ++ ++ if (info->attrs[NL80211_ATTR_MAC]) ++ mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); ++ ++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev); ++ if (err) ++ return err; ++ ++ if (!drv->ops->del_key) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ rtnl_lock(); ++ err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr); ++ rtnl_unlock(); ++ ++ out: ++ cfg80211_put_dev(drv); ++ dev_put(dev); ++ return err; ++} ++ + static struct genl_ops nl80211_ops[] = { + { + .cmd = NL80211_CMD_GET_WIPHY, +@@ -374,6 +639,30 @@ static struct genl_ops nl80211_ops[] = { + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, ++ { ++ .cmd = NL80211_CMD_GET_KEY, ++ .doit = nl80211_get_key, ++ .policy = nl80211_policy, ++ .flags = GENL_ADMIN_PERM, ++ }, ++ { ++ .cmd = NL80211_CMD_SET_KEY, ++ .doit = nl80211_set_key, ++ .policy = nl80211_policy, ++ .flags = GENL_ADMIN_PERM, ++ }, ++ { ++ .cmd = NL80211_CMD_NEW_KEY, ++ .doit = nl80211_new_key, ++ .policy = nl80211_policy, ++ .flags = GENL_ADMIN_PERM, ++ }, ++ { ++ .cmd = NL80211_CMD_DEL_KEY, ++ .doit = nl80211_del_key, ++ .policy = nl80211_policy, ++ .flags = GENL_ADMIN_PERM, ++ }, + }; + + /* multicast groups */ +--- everything.orig/net/wireless/core.c 2007-10-30 15:33:43.677380478 +0100 ++++ everything/net/wireless/core.c 2007-11-07 13:19:38.221513833 +0100 +@@ -184,6 +184,9 @@ struct wiphy *wiphy_new(struct cfg80211_ + struct cfg80211_registered_device *drv; + int alloc_size; + ++ WARN_ON(!ops->add_key && ops->del_key); ++ WARN_ON(ops->add_key && !ops->del_key); ++ + alloc_size = sizeof(*drv) + sizeof_priv; + + drv = kzalloc(alloc_size, GFP_KERNEL); +--- everything.orig/include/net/cfg80211.h 2007-10-30 15:33:43.617381780 +0100 ++++ everything/include/net/cfg80211.h 2007-11-07 13:19:38.231512748 +0100 +@@ -49,6 +49,26 @@ extern int ieee80211_radiotap_iterator_n + struct ieee80211_radiotap_iterator *iterator); + + ++ /** ++ * struct key_params - key information ++ * ++ * Information about a key ++ * ++ * @key: key material ++ * @key_len: length of key material ++ * @cipher: cipher suite selector ++ * @seq: sequence counter (IV/PN) for TKIP and CCMP keys, only used ++ * with the get_key() callback, must be in little endian, ++ * length given by @seq_len. ++ */ ++struct key_params { ++ u8 *key; ++ u8 *seq; ++ int key_len; ++ int seq_len; ++ u32 cipher; ++}; ++ + /* from net/wireless.h */ + struct wiphy; + +@@ -71,6 +91,18 @@ struct wiphy; + * + * @change_virtual_intf: change type of virtual interface + * ++ * @add_key: add a key with the given parameters. @mac_addr will be %NULL ++ * when adding a group key. ++ * ++ * @get_key: get information about the key with the given parameters. ++ * @mac_addr will be %NULL when requesting information for a group ++ * key. All pointers given to the @callback function need not be valid ++ * after it returns. ++ * ++ * @del_key: remove a key given the @mac_addr (%NULL for a group key) ++ * and @key_index ++ * ++ * @set_default_key: set the default key on an interface + */ + struct cfg80211_ops { + int (*add_virtual_intf)(struct wiphy *wiphy, char *name, +@@ -78,6 +110,18 @@ struct cfg80211_ops { + int (*del_virtual_intf)(struct wiphy *wiphy, int ifindex); + int (*change_virtual_intf)(struct wiphy *wiphy, int ifindex, + enum nl80211_iftype type); ++ ++ int (*add_key)(struct wiphy *wiphy, struct net_device *netdev, ++ u8 key_index, u8 *mac_addr, ++ struct key_params *params); ++ int (*get_key)(struct wiphy *wiphy, struct net_device *netdev, ++ u8 key_index, u8 *mac_addr, void *cookie, ++ void (*callback)(void *cookie, struct key_params*)); ++ int (*del_key)(struct wiphy *wiphy, struct net_device *netdev, ++ u8 key_index, u8 *mac_addr); ++ int (*set_default_key)(struct wiphy *wiphy, ++ struct net_device *netdev, ++ u8 key_index); + }; + + #endif /* __NET_CFG80211_H */ diff --git a/package/mac80211/patches/018-mac80211-cfg80211-keys.patch b/package/mac80211/patches/018-mac80211-cfg80211-keys.patch new file mode 100644 index 0000000000..0c98623a2d --- /dev/null +++ b/package/mac80211/patches/018-mac80211-cfg80211-keys.patch @@ -0,0 +1,120 @@ +Subject: mac80211: support adding/removing keys via cfg80211 + +This adds the necessary hooks to mac80211 to allow userspace +to edit keys with cfg80211 (through nl80211.) + +Signed-off-by: Johannes Berg + +--- + net/mac80211/cfg.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 91 insertions(+) + +--- everything.orig/net/mac80211/cfg.c 2007-11-07 13:19:29.441515732 +0100 ++++ everything/net/mac80211/cfg.c 2007-11-07 13:19:39.531517685 +0100 +@@ -6,6 +6,7 @@ + * This file is GPLv2 as found in COPYING. + */ + ++#include + #include + #include + #include +@@ -105,8 +106,98 @@ static int ieee80211_change_iface(struct + return 0; + } + ++static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, ++ u8 key_idx, u8 *mac_addr, ++ struct key_params *params) ++{ ++ struct ieee80211_sub_if_data *sdata; ++ struct sta_info *sta = NULL; ++ enum ieee80211_key_alg alg; ++ int ret; ++ ++ sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ ++ switch (params->cipher) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ case WLAN_CIPHER_SUITE_WEP104: ++ alg = ALG_WEP; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ alg = ALG_TKIP; ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ alg = ALG_CCMP; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (mac_addr) { ++ sta = sta_info_get(sdata->local, mac_addr); ++ if (!sta) ++ return -ENOENT; ++ } ++ ++ ret = 0; ++ if (!ieee80211_key_alloc(sdata, sta, alg, key_idx, ++ params->key_len, params->key)) ++ ret = -ENOMEM; ++ ++ if (sta) ++ sta_info_put(sta); ++ ++ return ret; ++} ++ ++static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, ++ u8 key_idx, u8 *mac_addr) ++{ ++ struct ieee80211_sub_if_data *sdata; ++ struct sta_info *sta; ++ int ret; ++ ++ sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ ++ if (mac_addr) { ++ sta = sta_info_get(sdata->local, mac_addr); ++ if (!sta) ++ return -ENOENT; ++ ++ ret = 0; ++ if (sta->key) ++ ieee80211_key_free(sta->key); ++ else ++ ret = -ENOENT; ++ ++ sta_info_put(sta); ++ return ret; ++ } ++ ++ if (!sdata->keys[key_idx]) ++ return -ENOENT; ++ ++ ieee80211_key_free(sdata->keys[key_idx]); ++ ++ return 0; ++} ++ ++static int ieee80211_config_default_key(struct wiphy *wiphy, ++ struct net_device *dev, ++ u8 key_idx) ++{ ++ struct ieee80211_sub_if_data *sdata; ++ ++ sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ ieee80211_set_default_key(sdata, key_idx); ++ ++ 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, ++ .add_key = ieee80211_add_key, ++ .del_key = ieee80211_del_key, ++ .set_default_key = ieee80211_config_default_key, + }; diff --git a/package/mac80211/patches/019-mac80211-key-seq-nl80211.patch b/package/mac80211/patches/019-mac80211-key-seq-nl80211.patch new file mode 100644 index 0000000000..5d0020b7fe --- /dev/null +++ b/package/mac80211/patches/019-mac80211-key-seq-nl80211.patch @@ -0,0 +1,161 @@ +Subject: mac80211: support getting key sequence counters via cfg80211 + +This implements cfg80211's get_key() to allow retrieving the sequence +counter for a TKIP or CCMP key from userspace. It also cleans up and +documents the associated low-level driver interface. + +Signed-off-by: Johannes Berg + +--- + include/net/mac80211.h | 14 ++------ + net/mac80211/cfg.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 89 insertions(+), 10 deletions(-) + +Index: mac80211/net/mac80211/cfg.c +=================================================================== +--- mac80211.orig/net/mac80211/cfg.c 2007-11-11 15:46:41.497954646 +0100 ++++ mac80211/net/mac80211/cfg.c 2007-11-11 15:46:51.346515884 +0100 +@@ -1,7 +1,7 @@ + /* + * mac80211 configuration hooks for cfg80211 + * +- * Copyright 2006 Johannes Berg ++ * Copyright 2006, 2007 Johannes Berg + * + * This file is GPLv2 as found in COPYING. + */ +@@ -180,6 +180,88 @@ + return 0; + } + ++static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, ++ u8 key_idx, u8 *mac_addr, void *cookie, ++ void (*callback)(void *cookie, ++ struct key_params *params)) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct sta_info *sta = NULL; ++ u8 seq[6] = {0}; ++ struct key_params params; ++ struct ieee80211_key *key; ++ u32 iv32; ++ u16 iv16; ++ int err = -ENOENT; ++ ++ if (mac_addr) { ++ sta = sta_info_get(sdata->local, mac_addr); ++ if (!sta) ++ goto out; ++ ++ key = sta->key; ++ } else ++ key = sdata->keys[key_idx]; ++ ++ if (!key) ++ goto out; ++ ++ memset(¶ms, 0, sizeof(params)); ++ ++ switch (key->conf.alg) { ++ case ALG_TKIP: ++ params.cipher = WLAN_CIPHER_SUITE_TKIP; ++ ++ iv32 = key->u.tkip.iv32; ++ iv16 = key->u.tkip.iv16; ++ ++ if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && ++ sdata->local->ops->get_tkip_seq) ++ sdata->local->ops->get_tkip_seq( ++ local_to_hw(sdata->local), ++ key->conf.hw_key_idx, ++ &iv32, &iv16); ++ ++ seq[0] = iv16 & 0xff; ++ seq[1] = (iv16 >> 8) & 0xff; ++ seq[2] = iv32 & 0xff; ++ seq[3] = (iv32 >> 8) & 0xff; ++ seq[4] = (iv32 >> 16) & 0xff; ++ seq[5] = (iv32 >> 24) & 0xff; ++ params.seq = seq; ++ params.seq_len = 6; ++ break; ++ case ALG_CCMP: ++ params.cipher = WLAN_CIPHER_SUITE_CCMP; ++ seq[0] = key->u.ccmp.tx_pn[5]; ++ seq[1] = key->u.ccmp.tx_pn[4]; ++ seq[2] = key->u.ccmp.tx_pn[3]; ++ seq[3] = key->u.ccmp.tx_pn[2]; ++ seq[4] = key->u.ccmp.tx_pn[1]; ++ seq[5] = key->u.ccmp.tx_pn[0]; ++ params.seq = seq; ++ params.seq_len = 6; ++ break; ++ case ALG_WEP: ++ if (key->conf.keylen == 5) ++ params.cipher = WLAN_CIPHER_SUITE_WEP40; ++ else ++ params.cipher = WLAN_CIPHER_SUITE_WEP104; ++ break; ++ } ++ ++ params.key = key->conf.key; ++ params.key_len = key->conf.keylen; ++ ++ callback(cookie, ¶ms); ++ err = 0; ++ ++ out: ++ if (sta) ++ sta_info_put(sta); ++ return err; ++} ++ + static int ieee80211_config_default_key(struct wiphy *wiphy, + struct net_device *dev, + u8 key_idx) +@@ -198,5 +280,6 @@ + .change_virtual_intf = ieee80211_change_iface, + .add_key = ieee80211_add_key, + .del_key = ieee80211_del_key, ++ .get_key = ieee80211_get_key, + .set_default_key = ieee80211_config_default_key, + }; +Index: mac80211/include/net/mac80211.h +=================================================================== +--- mac80211.orig/include/net/mac80211.h 2007-11-11 15:46:41.377947807 +0100 ++++ mac80211/include/net/mac80211.h 2007-11-11 15:47:08.183475366 +0100 +@@ -598,9 +598,6 @@ + u8 key[0]; + }; + +-#define IEEE80211_SEQ_COUNTER_RX 0 +-#define IEEE80211_SEQ_COUNTER_TX 1 +- + /** + * enum set_key_cmd - key command + * +@@ -947,9 +944,9 @@ + * + * @get_stats: return low-level statistics + * +- * @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. ++ * @get_tkip_seq: If your device implements TKIP encryption in hardware this ++ * callback should be provided to read the TKIP transmit IVs (both IV32 ++ * and IV16) for the given key from hardware. + * + * @set_rts_threshold: Configuration of RTS threshold (if device needs it) + * +@@ -1022,9 +1019,8 @@ + 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 (*get_sequence_counter)(struct ieee80211_hw *hw, +- u8* addr, u8 keyidx, u8 txrx, +- u32* iv32, u16* iv16); ++ void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx, ++ 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, diff --git a/package/mac80211/patches/020-nl80211-beacon-parameters.patch b/package/mac80211/patches/020-nl80211-beacon-parameters.patch new file mode 100644 index 0000000000..51836f332f --- /dev/null +++ b/package/mac80211/patches/020-nl80211-beacon-parameters.patch @@ -0,0 +1,279 @@ +Subject: cfg80211/nl80211: add beacon settings + +This adds the necessary API to cfg80211/nl80211 to allow +changing beaconing settings. + +Signed-off-by: Johannes Berg + +--- + include/linux/nl80211.h | 24 ++++++++ + include/net/cfg80211.h | 33 +++++++++++ + net/wireless/nl80211.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 190 insertions(+) + +--- everything.orig/include/net/cfg80211.h 2007-11-08 11:50:57.412840007 +0100 ++++ everything/include/net/cfg80211.h 2007-11-08 16:50:38.421522842 +0100 +@@ -69,6 +69,26 @@ struct key_params { + u32 cipher; + }; + ++/** ++ * struct beacon_parameters - beacon parameters ++ * ++ * Used to configure the beacon for an interface. ++ * ++ * @head: head portion of beacon (before TIM IE) ++ * or %NULL if not changed ++ * @tail: tail portion of beacon (after TIM IE) ++ * or %NULL if not changed ++ * @interval: beacon interval or zero if not changed ++ * @dtim_period: DTIM period or zero if not changed ++ * @head_len: length of @head ++ * @tail_len: length of @tail ++ */ ++struct beacon_parameters { ++ u8 *head, *tail; ++ int interval, dtim_period; ++ int head_len, tail_len; ++}; ++ + /* from net/wireless.h */ + struct wiphy; + +@@ -103,6 +123,13 @@ struct wiphy; + * and @key_index + * + * @set_default_key: set the default key on an interface ++ * ++ * @add_beacon: Add a beacon with given parameters, @head, @interval ++ * and @dtim_period will be valid, @tail is optional. ++ * @set_beacon: Change the beacon parameters for an access point mode ++ * interface. This should reject the call when no beacon has been ++ * configured. ++ * @del_beacon: Remove beacon configuration and stop sending the beacon. + */ + struct cfg80211_ops { + int (*add_virtual_intf)(struct wiphy *wiphy, char *name, +@@ -122,6 +149,12 @@ struct cfg80211_ops { + int (*set_default_key)(struct wiphy *wiphy, + struct net_device *netdev, + u8 key_index); ++ ++ int (*add_beacon)(struct wiphy *wiphy, struct net_device *dev, ++ struct beacon_parameters *info); ++ int (*set_beacon)(struct wiphy *wiphy, struct net_device *dev, ++ struct beacon_parameters *info); ++ int (*del_beacon)(struct wiphy *wiphy, struct net_device *dev); + }; + + #endif /* __NET_CFG80211_H */ +--- everything.orig/include/linux/nl80211.h 2007-11-08 11:50:57.362839952 +0100 ++++ everything/include/linux/nl80211.h 2007-11-08 16:56:32.431522732 +0100 +@@ -47,6 +47,15 @@ + * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX + * or %NL80211_ATTR_MAC. + * ++ * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a ++ * %NL80222_CMD_NEW_BEACON message) ++ * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface ++ * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD, ++ * %NL80211_BEACON_HEAD and %NL80211_BEACON_TAIL attributes. ++ * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface, ++ * parameters are like for %NL80211_CMD_SET_BEACON. ++ * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it ++ * + * @NL80211_CMD_MAX: highest used command number + * @__NL80211_CMD_AFTER_LAST: internal use + */ +@@ -69,6 +78,11 @@ enum nl80211_commands { + NL80211_CMD_NEW_KEY, + NL80211_CMD_DEL_KEY, + ++ NL80211_CMD_GET_BEACON, ++ NL80211_CMD_SET_BEACON, ++ NL80211_CMD_NEW_BEACON, ++ NL80211_CMD_DEL_BEACON, ++ + /* add commands here */ + + /* used to define NL80211_CMD_MAX below */ +@@ -101,6 +115,11 @@ enum nl80211_commands { + * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and + * CCMP keys, each six bytes in little endian + * ++ * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU ++ * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing ++ * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE ++ * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE ++ * + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use + */ +@@ -123,6 +142,11 @@ enum nl80211_attrs { + NL80211_ATTR_KEY_SEQ, + NL80211_ATTR_KEY_DEFAULT, + ++ NL80211_ATTR_BEACON_INTERVAL, ++ NL80211_ATTR_DTIM_PERIOD, ++ NL80211_ATTR_BEACON_HEAD, ++ NL80211_ATTR_BEACON_TAIL, ++ + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +--- everything.orig/net/wireless/nl80211.c 2007-11-08 11:50:57.382836589 +0100 ++++ everything/net/wireless/nl80211.c 2007-11-08 16:58:36.711524524 +0100 +@@ -69,6 +69,13 @@ static struct nla_policy nl80211_policy[ + [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, + [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, + [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, ++ ++ [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, ++ [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, ++ [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY, ++ .len = IEEE80211_MAX_DATA_LEN }, ++ [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY, ++ .len = IEEE80211_MAX_DATA_LEN }, + }; + + /* message building helper */ +@@ -600,6 +607,114 @@ static int nl80211_del_key(struct sk_buf + return err; + } + ++static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) ++{ ++ int (*call)(struct wiphy *wiphy, struct net_device *dev, ++ struct beacon_parameters *info); ++ struct cfg80211_registered_device *drv; ++ int err; ++ struct net_device *dev; ++ struct beacon_parameters params; ++ int haveinfo = 0; ++ ++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev); ++ if (err) ++ return err; ++ ++ switch (info->genlhdr->cmd) { ++ case NL80211_CMD_NEW_BEACON: ++ /* these are required for NEW_BEACON */ ++ if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] || ++ !info->attrs[NL80211_ATTR_DTIM_PERIOD] || ++ !info->attrs[NL80211_ATTR_BEACON_HEAD]) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ call = drv->ops->add_beacon; ++ break; ++ case NL80211_CMD_SET_BEACON: ++ call = drv->ops->set_beacon; ++ break; ++ default: ++ WARN_ON(1); ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ if (!call) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ memset(¶ms, 0, sizeof(params)); ++ ++ if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) { ++ params.interval = ++ nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); ++ haveinfo = 1; ++ } ++ ++ if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) { ++ params.dtim_period = ++ nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); ++ haveinfo = 1; ++ } ++ ++ if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { ++ params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); ++ params.head_len = ++ nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]); ++ haveinfo = 1; ++ } ++ ++ if (info->attrs[NL80211_ATTR_BEACON_TAIL]) { ++ params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]); ++ params.tail_len = ++ nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]); ++ haveinfo = 1; ++ } ++ ++ if (!haveinfo) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ rtnl_lock(); ++ err = call(&drv->wiphy, dev, ¶ms); ++ rtnl_unlock(); ++ ++ out: ++ cfg80211_put_dev(drv); ++ dev_put(dev); ++ return err; ++} ++ ++static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) ++{ ++ struct cfg80211_registered_device *drv; ++ int err; ++ struct net_device *dev; ++ ++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev); ++ if (err) ++ return err; ++ ++ if (!drv->ops->del_beacon) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ rtnl_lock(); ++ err = drv->ops->del_beacon(&drv->wiphy, dev); ++ rtnl_unlock(); ++ ++ out: ++ cfg80211_put_dev(drv); ++ dev_put(dev); ++ return err; ++} ++ + static struct genl_ops nl80211_ops[] = { + { + .cmd = NL80211_CMD_GET_WIPHY, +@@ -663,6 +778,24 @@ static struct genl_ops nl80211_ops[] = { + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, ++ { ++ .cmd = NL80211_CMD_SET_BEACON, ++ .policy = nl80211_policy, ++ .flags = GENL_ADMIN_PERM, ++ .doit = nl80211_addset_beacon, ++ }, ++ { ++ .cmd = NL80211_CMD_NEW_BEACON, ++ .policy = nl80211_policy, ++ .flags = GENL_ADMIN_PERM, ++ .doit = nl80211_addset_beacon, ++ }, ++ { ++ .cmd = NL80211_CMD_DEL_BEACON, ++ .policy = nl80211_policy, ++ .flags = GENL_ADMIN_PERM, ++ .doit = nl80211_del_beacon, ++ }, + }; + + /* multicast groups */ diff --git a/package/mac80211/patches/021-mac80211-beacon-via-nl80211.patch b/package/mac80211/patches/021-mac80211-beacon-via-nl80211.patch new file mode 100644 index 0000000000..702c68f98f --- /dev/null +++ b/package/mac80211/patches/021-mac80211-beacon-via-nl80211.patch @@ -0,0 +1,484 @@ +Subject: mac80211: add beacon configuration via cfg80211 + +This patch implements the cfg80211 hooks for configuring beaconing +on an access point interface in mac80211. While doing so, it fixes +a number of races that could badly crash the machine when the +beacon is changed while being requested by the driver. + +Signed-off-by: Johannes Berg + +--- +The dtim_count field should possibly also be part of the beacon +structure, but the possible race there doesn't really matter, +worst thing is that one beacon will be sent with a wrong dtim +count if (and only if) userspace changes the dtim period during +operation. + + net/mac80211/cfg.c | 156 +++++++++++++++++++++++++++++++++++++++++ + net/mac80211/debugfs_netdev.c | 27 ------- + net/mac80211/ieee80211_i.h | 14 ++- + net/mac80211/ieee80211_iface.c | 4 - + net/mac80211/tx.c | 63 ++++++++++------ + 5 files changed, 204 insertions(+), 60 deletions(-) + +Index: mac80211/net/mac80211/cfg.c +=================================================================== +--- mac80211.orig/net/mac80211/cfg.c 2007-11-11 15:17:12.837164411 +0100 ++++ mac80211/net/mac80211/cfg.c 2007-11-11 15:18:36.853952256 +0100 +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include "ieee80211_i.h" + #include "cfg.h" +@@ -274,6 +275,158 @@ + return 0; + } + ++/* ++ * This handles both adding a beacon and setting new beacon info ++ */ ++static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, ++ struct beacon_parameters *params) ++{ ++ struct beacon_data *new, *old; ++ int new_head_len, new_tail_len; ++ int size; ++ int err = -EINVAL; ++ ++ old = sdata->u.ap.beacon; ++ ++ /* head must not be zero-length */ ++ if (params->head && !params->head_len) ++ return -EINVAL; ++ ++ /* ++ * This is a kludge. beacon interval should really be part ++ * of the beacon information. ++ */ ++ if (params->interval) { ++ sdata->local->hw.conf.beacon_int = params->interval; ++ if (ieee80211_hw_config(sdata->local)) ++ return -EINVAL; ++ /* ++ * We updated some parameter so if below bails out ++ * it's not an error. ++ */ ++ err = 0; ++ } ++ ++ /* Need to have a beacon head if we don't have one yet */ ++ if (!params->head && !old) ++ return err; ++ ++ /* sorry, no way to start beaconing without dtim period */ ++ if (!params->dtim_period && !old) ++ return err; ++ ++ /* new or old head? */ ++ if (params->head) ++ new_head_len = params->head_len; ++ else ++ new_head_len = old->head_len; ++ ++ /* new or old tail? */ ++ if (params->tail || !old) ++ /* params->tail_len will be zero for !params->tail */ ++ new_tail_len = params->tail_len; ++ else ++ new_tail_len = old->tail_len; ++ ++ size = sizeof(*new) + new_head_len + new_tail_len; ++ ++ new = kzalloc(size, GFP_KERNEL); ++ if (!new) ++ return -ENOMEM; ++ ++ /* start filling the new info now */ ++ ++ /* new or old dtim period? */ ++ if (params->dtim_period) ++ new->dtim_period = params->dtim_period; ++ else ++ new->dtim_period = old->dtim_period; ++ ++ /* ++ * pointers go into the block we allocated, ++ * memory is | beacon_data | head | tail | ++ */ ++ new->head = ((u8 *) new) + sizeof(*new); ++ new->tail = new->head + new_head_len; ++ new->head_len = new_head_len; ++ new->tail_len = new_tail_len; ++ ++ /* copy in head */ ++ if (params->head) ++ memcpy(new->head, params->head, new_head_len); ++ else ++ memcpy(new->head, old->head, new_head_len); ++ ++ /* copy in optional tail */ ++ if (params->tail) ++ memcpy(new->tail, params->tail, new_tail_len); ++ else ++ if (old) ++ memcpy(new->tail, old->tail, new_tail_len); ++ ++ rcu_assign_pointer(sdata->u.ap.beacon, new); ++ ++ synchronize_rcu(); ++ ++ kfree(old); ++ ++ return ieee80211_if_config_beacon(sdata->dev); ++} ++ ++static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, ++ struct beacon_parameters *params) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct beacon_data *old; ++ ++ if (sdata->type != IEEE80211_IF_TYPE_AP) ++ return -EINVAL; ++ ++ old = sdata->u.ap.beacon; ++ ++ if (old) ++ return -EALREADY; ++ ++ return ieee80211_config_beacon(sdata, params); ++} ++ ++static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, ++ struct beacon_parameters *params) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct beacon_data *old; ++ ++ if (sdata->type != IEEE80211_IF_TYPE_AP) ++ return -EINVAL; ++ ++ old = sdata->u.ap.beacon; ++ ++ if (!old) ++ return -ENOENT; ++ ++ return ieee80211_config_beacon(sdata, params); ++} ++ ++static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct beacon_data *old; ++ ++ if (sdata->type != IEEE80211_IF_TYPE_AP) ++ return -EINVAL; ++ ++ old = sdata->u.ap.beacon; ++ ++ if (!old) ++ return -ENOENT; ++ ++ rcu_assign_pointer(sdata->u.ap.beacon, NULL); ++ synchronize_rcu(); ++ kfree(old); ++ ++ return ieee80211_if_config_beacon(dev); ++} ++ + struct cfg80211_ops mac80211_config_ops = { + .add_virtual_intf = ieee80211_add_iface, + .del_virtual_intf = ieee80211_del_iface, +@@ -282,4 +435,7 @@ + .del_key = ieee80211_del_key, + .get_key = ieee80211_get_key, + .set_default_key = ieee80211_config_default_key, ++ .add_beacon = ieee80211_add_beacon, ++ .set_beacon = ieee80211_set_beacon, ++ .del_beacon = ieee80211_del_beacon, + }; +Index: mac80211/net/mac80211/debugfs_netdev.c +=================================================================== +--- mac80211.orig/net/mac80211/debugfs_netdev.c 2007-10-14 00:42:30.054156000 +0200 ++++ mac80211/net/mac80211/debugfs_netdev.c 2007-11-11 15:18:11.852527505 +0100 +@@ -124,7 +124,6 @@ + + /* AP attributes */ + IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); +-IEEE80211_IF_FILE(dtim_period, u.ap.dtim_period, DEC); + IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); + IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC); + IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC); +@@ -138,26 +137,6 @@ + } + __IEEE80211_IF_FILE(num_buffered_multicast); + +-static ssize_t ieee80211_if_fmt_beacon_head_len( +- const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) +-{ +- if (sdata->u.ap.beacon_head) +- return scnprintf(buf, buflen, "%d\n", +- sdata->u.ap.beacon_head_len); +- return scnprintf(buf, buflen, "\n"); +-} +-__IEEE80211_IF_FILE(beacon_head_len); +- +-static ssize_t ieee80211_if_fmt_beacon_tail_len( +- const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) +-{ +- if (sdata->u.ap.beacon_tail) +- return scnprintf(buf, buflen, "%d\n", +- sdata->u.ap.beacon_tail_len); +- return scnprintf(buf, buflen, "\n"); +-} +-__IEEE80211_IF_FILE(beacon_tail_len); +- + /* WDS attributes */ + IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); + +@@ -194,14 +173,11 @@ + DEBUGFS_ADD(eapol, ap); + DEBUGFS_ADD(ieee8021_x, ap); + DEBUGFS_ADD(num_sta_ps, ap); +- DEBUGFS_ADD(dtim_period, ap); + DEBUGFS_ADD(dtim_count, ap); + DEBUGFS_ADD(num_beacons, ap); + DEBUGFS_ADD(force_unicast_rateidx, ap); + DEBUGFS_ADD(max_ratectrl_rateidx, ap); + DEBUGFS_ADD(num_buffered_multicast, ap); +- DEBUGFS_ADD(beacon_head_len, ap); +- DEBUGFS_ADD(beacon_tail_len, ap); + } + + static void add_wds_files(struct ieee80211_sub_if_data *sdata) +@@ -287,14 +263,11 @@ + DEBUGFS_DEL(eapol, ap); + DEBUGFS_DEL(ieee8021_x, ap); + DEBUGFS_DEL(num_sta_ps, ap); +- DEBUGFS_DEL(dtim_period, ap); + DEBUGFS_DEL(dtim_count, ap); + DEBUGFS_DEL(num_beacons, ap); + DEBUGFS_DEL(force_unicast_rateidx, ap); + DEBUGFS_DEL(max_ratectrl_rateidx, ap); + DEBUGFS_DEL(num_buffered_multicast, ap); +- DEBUGFS_DEL(beacon_head_len, ap); +- DEBUGFS_DEL(beacon_tail_len, ap); + } + + static void del_wds_files(struct ieee80211_sub_if_data *sdata) +Index: mac80211/net/mac80211/ieee80211_i.h +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211_i.h 2007-11-11 15:15:53.792659922 +0100 ++++ mac80211/net/mac80211/ieee80211_i.h 2007-11-11 15:18:11.864528190 +0100 +@@ -190,9 +190,14 @@ + typedef ieee80211_txrx_result (*ieee80211_rx_handler) + (struct ieee80211_txrx_data *rx); + ++struct beacon_data { ++ u8 *head, *tail; ++ int head_len, tail_len; ++ int dtim_period; ++}; ++ + struct ieee80211_if_ap { +- u8 *beacon_head, *beacon_tail; +- int beacon_head_len, beacon_tail_len; ++ struct beacon_data *beacon; + + struct list_head vlans; + +@@ -205,7 +210,7 @@ + u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; + atomic_t num_sta_ps; /* number of stations in PS mode */ + struct sk_buff_head ps_bc_buf; +- int dtim_period, dtim_count; ++ int dtim_count; + int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ + int max_ratectrl_rateidx; /* max TX rateidx for rate control */ + int num_beacons; /* number of TXed beacon frames for this BSS */ +@@ -361,14 +366,11 @@ + struct dentry *eapol; + struct dentry *ieee8021_x; + struct dentry *num_sta_ps; +- struct dentry *dtim_period; + struct dentry *dtim_count; + struct dentry *num_beacons; + struct dentry *force_unicast_rateidx; + struct dentry *max_ratectrl_rateidx; + struct dentry *num_buffered_multicast; +- struct dentry *beacon_head_len; +- struct dentry *beacon_tail_len; + } ap; + struct { + struct dentry *channel_use; +Index: mac80211/net/mac80211/ieee80211_iface.c +=================================================================== +--- mac80211.orig/net/mac80211/ieee80211_iface.c 2007-11-11 15:15:53.796660158 +0100 ++++ mac80211/net/mac80211/ieee80211_iface.c 2007-11-11 15:18:11.868528415 +0100 +@@ -187,7 +187,6 @@ + sdata->u.vlan.ap = NULL; + break; + case IEEE80211_IF_TYPE_AP: +- sdata->u.ap.dtim_period = 2; + sdata->u.ap.force_unicast_rateidx = -1; + sdata->u.ap.max_ratectrl_rateidx = -1; + skb_queue_head_init(&sdata->u.ap.ps_bc_buf); +@@ -271,8 +270,7 @@ + } + } + +- kfree(sdata->u.ap.beacon_head); +- kfree(sdata->u.ap.beacon_tail); ++ kfree(sdata->u.ap.beacon); + + while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { + local->total_ps_buffered--; +Index: mac80211/net/mac80211/tx.c +=================================================================== +--- mac80211.orig/net/mac80211/tx.c 2007-11-11 15:15:53.804660611 +0100 ++++ mac80211/net/mac80211/tx.c 2007-11-11 15:18:11.868528415 +0100 +@@ -1656,7 +1656,8 @@ + + static void ieee80211_beacon_add_tim(struct ieee80211_local *local, + struct ieee80211_if_ap *bss, +- struct sk_buff *skb) ++ struct sk_buff *skb, ++ struct beacon_data *beacon) + { + u8 *pos, *tim; + int aid0 = 0; +@@ -1672,7 +1673,7 @@ + IEEE80211_MAX_AID+1); + + if (bss->dtim_count == 0) +- bss->dtim_count = bss->dtim_period - 1; ++ bss->dtim_count = beacon->dtim_period - 1; + else + bss->dtim_count--; + +@@ -1680,7 +1681,7 @@ + *pos++ = WLAN_EID_TIM; + *pos++ = 4; + *pos++ = bss->dtim_count; +- *pos++ = bss->dtim_period; ++ *pos++ = beacon->dtim_period; + + if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf)) + aid0 = 1; +@@ -1728,8 +1729,9 @@ + 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; ++ struct beacon_data *beacon; ++ ++ rcu_read_lock(); + + bdev = dev_get_by_index(if_id); + if (bdev) { +@@ -1738,37 +1740,35 @@ + dev_put(bdev); + } + +- if (!ap || sdata->type != IEEE80211_IF_TYPE_AP || +- !ap->beacon_head) { ++ beacon = rcu_dereference(ap->beacon); ++ ++ if (!ap || sdata->type != IEEE80211_IF_TYPE_AP || !beacon) { + #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; ++ skb = NULL; ++ goto out; + } + +- /* 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->tx_headroom + +- bh_len + bt_len + 256 /* maximum TIM len */); ++ /* headroom, head length, tail length and maximum TIM length */ ++ skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + ++ beacon->tail_len + 256); + if (!skb) +- return NULL; ++ goto out; + + skb_reserve(skb, local->tx_headroom); +- memcpy(skb_put(skb, bh_len), b_head, bh_len); ++ memcpy(skb_put(skb, beacon->head_len), beacon->head, ++ beacon->head_len); + + ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data); + +- ieee80211_beacon_add_tim(local, ap, skb); ++ ieee80211_beacon_add_tim(local, ap, skb, beacon); + +- if (b_tail) { +- memcpy(skb_put(skb, bt_len), b_tail, bt_len); +- } ++ if (beacon->tail) ++ memcpy(skb_put(skb, beacon->tail_len), beacon->tail, ++ beacon->tail_len); + + if (control) { + memset(&extra, 0, sizeof(extra)); +@@ -1781,7 +1781,8 @@ + "found\n", wiphy_name(local->hw.wiphy)); + } + dev_kfree_skb(skb); +- return NULL; ++ skb = NULL; ++ goto out; + } + + control->tx_rate = +@@ -1796,6 +1797,9 @@ + } + + ap->num_beacons++; ++ ++ out: ++ rcu_read_unlock(); + return skb; + } + EXPORT_SYMBOL(ieee80211_beacon_get); +@@ -1844,6 +1848,7 @@ + struct net_device *bdev; + struct ieee80211_sub_if_data *sdata; + struct ieee80211_if_ap *bss = NULL; ++ struct beacon_data *beacon; + + bdev = dev_get_by_index(if_id); + if (bdev) { +@@ -1851,9 +1856,19 @@ + bss = &sdata->u.ap; + dev_put(bdev); + } +- if (!bss || sdata->type != IEEE80211_IF_TYPE_AP || !bss->beacon_head) ++ ++ if (!bss) + return NULL; + ++ rcu_read_lock(); ++ beacon = rcu_dereference(bss->beacon); ++ ++ if (sdata->type != IEEE80211_IF_TYPE_AP || !beacon || !beacon->head) { ++ rcu_read_unlock(); ++ return NULL; ++ } ++ rcu_read_unlock(); ++ + if (bss->dtim_count != 0) + return NULL; /* send buffered bc/mc only after DTIM beacon */ + memset(control, 0, sizeof(*control)); diff --git a/package/mac80211/patches/022-nl80211-sta.patch b/package/mac80211/patches/022-nl80211-sta.patch new file mode 100644 index 0000000000..4d08721f82 --- /dev/null +++ b/package/mac80211/patches/022-nl80211-sta.patch @@ -0,0 +1,464 @@ +Subject: cfg80211/nl80211: station handling + +This patch adds station handling to cfg80211/nl80211. + +Signed-off-by: Johannes Berg + +--- + include/linux/nl80211.h | 68 +++++++++++++ + include/net/cfg80211.h | 54 ++++++++++ + net/wireless/nl80211.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 358 insertions(+) + +--- everything.orig/include/linux/nl80211.h 2007-11-08 16:56:32.431522732 +0100 ++++ everything/include/linux/nl80211.h 2007-11-08 17:15:15.961529840 +0100 +@@ -7,6 +7,18 @@ + */ + + /** ++ * DOC: Station handling ++ * ++ * Stations are added per interface, but a special case exists with VLAN ++ * interfaces. When a station is bound to an AP interface, it may be moved ++ * into a VLAN identified by a VLAN interface index (%NL80211_ATTR_STA_VLAN). ++ * The station is still assumed to belong to the AP interface it was added ++ * to. ++ * ++ * TODO: need more info? ++ */ ++ ++/** + * enum nl80211_commands - supported nl80211 commands + * + * @NL80211_CMD_UNSPEC: unspecified command to catch errors +@@ -56,6 +68,16 @@ + * parameters are like for %NL80211_CMD_SET_BEACON. + * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it + * ++ * @NL80211_CMD_GET_STATION: Get station attributes for station identified by ++ * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. ++ * @NL80211_CMD_SET_STATION: Set station attributes for station identified by ++ * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. ++ * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the ++ * the interface identified by %NL80211_ATTR_IFINDEX. ++ * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC ++ * or, if no MAC address given, all stations, on the interface identified ++ * by %NL80211_ATTR_IFINDEX. ++ * + * @NL80211_CMD_MAX: highest used command number + * @__NL80211_CMD_AFTER_LAST: internal use + */ +@@ -83,6 +105,11 @@ enum nl80211_commands { + NL80211_CMD_NEW_BEACON, + NL80211_CMD_DEL_BEACON, + ++ NL80211_CMD_GET_STATION, ++ NL80211_CMD_SET_STATION, ++ NL80211_CMD_NEW_STATION, ++ NL80211_CMD_DEL_STATION, ++ + /* add commands here */ + + /* used to define NL80211_CMD_MAX below */ +@@ -120,6 +147,17 @@ enum nl80211_commands { + * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE + * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE + * ++ * @NL80211_ATTR_STA_AID: Association ID for the station (u16) ++ * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of ++ * &enum nl80211_sta_flags. ++ * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by ++ * IEEE 802.11 7.3.1.6 (u16). ++ * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported ++ * rates as defined by IEEE 802.11 7.3.2.2 but without the length ++ * restriction (at most %NL80211_MAX_SUPP_RATES). ++ * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station ++ * to, or the AP interface the station was originally added to to. ++ * + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use + */ +@@ -147,12 +185,20 @@ enum nl80211_attrs { + NL80211_ATTR_BEACON_HEAD, + NL80211_ATTR_BEACON_TAIL, + ++ NL80211_ATTR_STA_AID, ++ NL80211_ATTR_STA_FLAGS, ++ NL80211_ATTR_STA_LISTEN_INTERVAL, ++ NL80211_ATTR_STA_SUPPORTED_RATES, ++ NL80211_ATTR_STA_VLAN, ++ + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, + NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 + }; + ++#define NL80211_MAX_SUPP_RATES 32 ++ + /** + * enum nl80211_iftype - (virtual) interface types + * +@@ -184,4 +230,26 @@ enum nl80211_iftype { + NL80211_IFTYPE_MAX = __NL80211_IFTYPE_AFTER_LAST - 1 + }; + ++/** ++ * enum nl80211_sta_flags - station flags ++ * ++ * Station flags. When a station is added to an AP interface, it is ++ * assumed to be already associated (and hence authenticated.) ++ * ++ * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X) ++ * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames ++ * with short barker preamble ++ * @NL80211_STA_FLAG_WME: station is WME/QoS capable ++ */ ++enum nl80211_sta_flags { ++ __NL80211_STA_FLAG_INVALID, ++ NL80211_STA_FLAG_AUTHORIZED, ++ NL80211_STA_FLAG_SHORT_PREAMBLE, ++ NL80211_STA_FLAG_WME, ++ ++ /* keep last */ ++ __NL80211_STA_FLAG_AFTER_LAST, ++ NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 ++}; ++ + #endif /* __LINUX_NL80211_H */ +--- everything.orig/include/net/cfg80211.h 2007-11-08 16:50:38.421522842 +0100 ++++ everything/include/net/cfg80211.h 2007-11-08 17:15:15.971532444 +0100 +@@ -89,6 +89,47 @@ struct beacon_parameters { + int head_len, tail_len; + }; + ++/** ++ * enum station_flags - station flags ++ * ++ * Station capability flags. Note that these must be the bits ++ * according to the nl80211 flags. ++ * ++ * @STATION_FLAG_CHANGED: station flags were changed ++ * @STATION_FLAG_AUTHORIZED: station is authorized to send frames (802.1X) ++ * @STATION_FLAG_SHORT_PREAMBLE: station is capable of receiving frames ++ * with short preambles ++ * @STATION_FLAG_WME: station is WME/QoS capable ++ */ ++enum station_flags { ++ STATION_FLAG_CHANGED = 1<<0, ++ STATION_FLAG_AUTHORIZED = 1<ieee80211_ptr) ++ return -EINVAL; ++ if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy) ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) ++{ ++ struct cfg80211_registered_device *drv; ++ int err; ++ struct net_device *dev; ++ struct station_parameters params; ++ u8 *mac_addr = NULL; ++ ++ memset(¶ms, 0, sizeof(params)); ++ ++ params.listen_interval = -1; ++ ++ if (info->attrs[NL80211_ATTR_STA_AID]) ++ return -EINVAL; ++ ++ if (!info->attrs[NL80211_ATTR_MAC]) ++ return -EINVAL; ++ ++ mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); ++ ++ if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) { ++ params.supported_rates = ++ nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); ++ params.supported_rates_len = ++ nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); ++ } ++ ++ if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) ++ params.listen_interval = ++ nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); ++ ++ if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], ++ ¶ms.station_flags)) ++ return -EINVAL; ++ ++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev); ++ if (err) ++ return err; ++ ++ err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); ++ if (err) ++ goto out; ++ ++ if (!drv->ops->change_station) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ rtnl_lock(); ++ err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, ¶ms); ++ rtnl_unlock(); ++ ++ out: ++ if (params.vlan) ++ dev_put(params.vlan); ++ cfg80211_put_dev(drv); ++ dev_put(dev); ++ return err; ++} ++ ++static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) ++{ ++ struct cfg80211_registered_device *drv; ++ int err; ++ struct net_device *dev; ++ struct station_parameters params; ++ u8 *mac_addr = NULL; ++ ++ memset(¶ms, 0, sizeof(params)); ++ ++ if (!info->attrs[NL80211_ATTR_MAC]) ++ return -EINVAL; ++ ++ if (!info->attrs[NL80211_ATTR_STA_AID]) ++ return -EINVAL; ++ ++ if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) ++ return -EINVAL; ++ ++ if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) ++ return -EINVAL; ++ ++ mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); ++ params.supported_rates = ++ nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); ++ params.supported_rates_len = ++ nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); ++ params.listen_interval = ++ nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); ++ params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); ++ ++ if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], ++ ¶ms.station_flags)) ++ return -EINVAL; ++ ++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev); ++ if (err) ++ return err; ++ ++ err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); ++ if (err) ++ goto out; ++ ++ if (!drv->ops->add_station) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ rtnl_lock(); ++ err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, ¶ms); ++ rtnl_unlock(); ++ ++ out: ++ if (params.vlan) ++ dev_put(params.vlan); ++ cfg80211_put_dev(drv); ++ dev_put(dev); ++ return err; ++} ++ ++static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) ++{ ++ struct cfg80211_registered_device *drv; ++ int err; ++ struct net_device *dev; ++ u8 *mac_addr = NULL; ++ ++ if (info->attrs[NL80211_ATTR_MAC]) ++ mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); ++ ++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev); ++ if (err) ++ return err; ++ ++ if (!drv->ops->del_station) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ rtnl_lock(); ++ err = drv->ops->del_station(&drv->wiphy, dev, mac_addr); ++ rtnl_unlock(); ++ ++ out: ++ cfg80211_put_dev(drv); ++ dev_put(dev); ++ return err; ++} ++ + static struct genl_ops nl80211_ops[] = { + { + .cmd = NL80211_CMD_GET_WIPHY, +@@ -796,6 +1007,31 @@ static struct genl_ops nl80211_ops[] = { + .flags = GENL_ADMIN_PERM, + .doit = nl80211_del_beacon, + }, ++ { ++ .cmd = NL80211_CMD_GET_STATION, ++ .doit = nl80211_get_station, ++ /* TODO: implement dumpit */ ++ .policy = nl80211_policy, ++ .flags = GENL_ADMIN_PERM, ++ }, ++ { ++ .cmd = NL80211_CMD_SET_STATION, ++ .doit = nl80211_set_station, ++ .policy = nl80211_policy, ++ .flags = GENL_ADMIN_PERM, ++ }, ++ { ++ .cmd = NL80211_CMD_NEW_STATION, ++ .doit = nl80211_new_station, ++ .policy = nl80211_policy, ++ .flags = GENL_ADMIN_PERM, ++ }, ++ { ++ .cmd = NL80211_CMD_DEL_STATION, ++ .doit = nl80211_del_station, ++ .policy = nl80211_policy, ++ .flags = GENL_ADMIN_PERM, ++ }, + }; + + /* multicast groups */ diff --git a/package/mac80211/patches/023-mac80211-implement-sta.patch b/package/mac80211/patches/023-mac80211-implement-sta.patch new file mode 100644 index 0000000000..095067676c --- /dev/null +++ b/package/mac80211/patches/023-mac80211-implement-sta.patch @@ -0,0 +1,224 @@ +Subject: mac80211: implement cfg80211's station handling + +This implements station handling from userspace via cfg80211 +in mac80211. + +Signed-off-by: Johannes Berg + +--- + net/mac80211/cfg.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 192 insertions(+) + +--- everything.orig/net/mac80211/cfg.c 2007-11-08 17:11:52.351521702 +0100 ++++ everything/net/mac80211/cfg.c 2007-11-08 17:15:51.801523493 +0100 +@@ -14,6 +14,7 @@ + #include + #include "ieee80211_i.h" + #include "cfg.h" ++#include "ieee80211_rate.h" + + static enum ieee80211_if_types + nl80211_type_to_mac80211_type(enum nl80211_iftype type) +@@ -428,6 +429,194 @@ static int ieee80211_del_beacon(struct w + return ieee80211_if_config_beacon(dev); + } + ++/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ ++struct iapp_layer2_update { ++ u8 da[ETH_ALEN]; /* broadcast */ ++ u8 sa[ETH_ALEN]; /* STA addr */ ++ __be16 len; /* 6 */ ++ u8 dsap; /* 0 */ ++ u8 ssap; /* 0 */ ++ u8 control; ++ u8 xid_info[3]; ++} __attribute__ ((packed)); ++ ++static void ieee80211_send_layer2_update(struct sta_info *sta) ++{ ++ struct iapp_layer2_update *msg; ++ struct sk_buff *skb; ++ ++ /* Send Level 2 Update Frame to update forwarding tables in layer 2 ++ * bridge devices */ ++ ++ skb = dev_alloc_skb(sizeof(*msg)); ++ if (!skb) ++ return; ++ msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg)); ++ ++ /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) ++ * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ ++ ++ memset(msg->da, 0xff, ETH_ALEN); ++ memcpy(msg->sa, sta->addr, ETH_ALEN); ++ msg->len = htons(6); ++ msg->dsap = 0; ++ msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */ ++ msg->control = 0xaf; /* XID response lsb.1111F101. ++ * F=0 (no poll command; unsolicited frame) */ ++ msg->xid_info[0] = 0x81; /* XID format identifier */ ++ msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */ ++ msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */ ++ ++ skb->dev = sta->dev; ++ skb->protocol = eth_type_trans(skb, sta->dev); ++ memset(skb->cb, 0, sizeof(skb->cb)); ++ netif_rx(skb); ++} ++ ++static void sta_apply_parameters(struct ieee80211_local *local, ++ struct sta_info *sta, ++ struct station_parameters *params) ++{ ++ u32 rates; ++ int i, j; ++ struct ieee80211_hw_mode *mode; ++ ++ if (params->station_flags & STATION_FLAG_CHANGED) { ++ sta->flags &= ~WLAN_STA_AUTHORIZED; ++ if (params->station_flags & STATION_FLAG_AUTHORIZED) ++ sta->flags |= WLAN_STA_AUTHORIZED; ++ ++ sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; ++ if (params->station_flags & STATION_FLAG_SHORT_PREAMBLE) ++ sta->flags |= WLAN_STA_SHORT_PREAMBLE; ++ ++ sta->flags &= ~WLAN_STA_WME; ++ if (params->station_flags & STATION_FLAG_WME) ++ sta->flags |= WLAN_STA_WME; ++ } ++ ++ if (params->aid) { ++ sta->aid = params->aid; ++ if (sta->aid > IEEE80211_MAX_AID) ++ sta->aid = 0; /* XXX: should this be an error? */ ++ } ++ ++ if (params->listen_interval >= 0) ++ sta->listen_interval = params->listen_interval; ++ ++ if (params->supported_rates) { ++ rates = 0; ++ mode = local->oper_hw_mode; ++ for (i = 0; i < params->supported_rates_len; i++) { ++ int rate = (params->supported_rates[i] & 0x7f) * 5; ++ for (j = 0; j < mode->num_rates; j++) { ++ if (mode->rates[j].rate == rate) ++ rates |= BIT(j); ++ } ++ } ++ sta->supp_rates = rates; ++ } ++} ++ ++static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, ++ u8 *mac, struct station_parameters *params) ++{ ++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); ++ struct sta_info *sta; ++ struct ieee80211_sub_if_data *sdata; ++ ++ /* Prevent a race with changing the rate control algorithm */ ++ if (!netif_running(dev)) ++ return -ENETDOWN; ++ ++ /* XXX: get sta belonging to dev */ ++ sta = sta_info_get(local, mac); ++ if (sta) { ++ sta_info_put(sta); ++ return -EEXIST; ++ } ++ ++ if (params->vlan) { ++ sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); ++ ++ if (sdata->type != IEEE80211_IF_TYPE_VLAN || ++ sdata->type != IEEE80211_IF_TYPE_AP) ++ return -EINVAL; ++ } else ++ sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ ++ sta = sta_info_add(local, dev, mac, GFP_KERNEL); ++ if (!sta) ++ return -ENOMEM; ++ ++ sta->dev = sdata->dev; ++ if (sdata->type == IEEE80211_IF_TYPE_VLAN || ++ sdata->type == IEEE80211_IF_TYPE_AP) ++ ieee80211_send_layer2_update(sta); ++ ++ sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; ++ ++ sta_apply_parameters(local, sta, params); ++ ++ rate_control_rate_init(sta, local); ++ ++ sta_info_put(sta); ++ ++ return 0; ++} ++ ++static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, ++ u8 *mac) ++{ ++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); ++ struct sta_info *sta; ++ ++ if (mac) { ++ /* XXX: get sta belonging to dev */ ++ sta = sta_info_get(local, mac); ++ if (!sta) ++ return -ENOENT; ++ ++ sta_info_free(sta); ++ sta_info_put(sta); ++ } else ++ sta_info_flush(local, dev); ++ ++ return 0; ++} ++ ++static int ieee80211_change_station(struct wiphy *wiphy, ++ struct net_device *dev, ++ u8 *mac, ++ struct station_parameters *params) ++{ ++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); ++ struct sta_info *sta; ++ struct ieee80211_sub_if_data *vlansdata; ++ ++ /* XXX: get sta belonging to dev */ ++ sta = sta_info_get(local, mac); ++ if (!sta) ++ return -ENOENT; ++ ++ if (params->vlan && params->vlan != sta->dev) { ++ vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); ++ ++ if (vlansdata->type != IEEE80211_IF_TYPE_VLAN || ++ vlansdata->type != IEEE80211_IF_TYPE_AP) ++ return -EINVAL; ++ ++ sta->dev = params->vlan; ++ ieee80211_send_layer2_update(sta); ++ } ++ ++ sta_apply_parameters(local, sta, params); ++ ++ sta_info_put(sta); ++ ++ return 0; ++} ++ + struct cfg80211_ops mac80211_config_ops = { + .add_virtual_intf = ieee80211_add_iface, + .del_virtual_intf = ieee80211_del_iface, +@@ -439,4 +628,7 @@ struct cfg80211_ops mac80211_config_ops + .add_beacon = ieee80211_add_beacon, + .set_beacon = ieee80211_set_beacon, + .del_beacon = ieee80211_del_beacon, ++ .add_station = ieee80211_add_station, ++ .del_station = ieee80211_del_station, ++ .change_station = ieee80211_change_station, + }; diff --git a/package/mac80211/patches/024-nl80211-get-sta.patch b/package/mac80211/patches/024-nl80211-get-sta.patch new file mode 100644 index 0000000000..198ad1876b --- /dev/null +++ b/package/mac80211/patches/024-nl80211-get-sta.patch @@ -0,0 +1,208 @@ +Subject: cfg80211/nl80211: implement station attribute retrieval + +After a station is added to the kernel's structures, userspace +has to be able to retrieve statistics about that station, especially +whether the station was idle and how much bytes were transferred +to and from it. This adds the necessary code to nl80211. + +Signed-off-by: Johannes Berg + +--- + include/linux/nl80211.h | 28 ++++++++++++++++ + include/net/cfg80211.h | 35 ++++++++++++++++++++ + net/wireless/nl80211.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 144 insertions(+), 1 deletion(-) + +--- everything.orig/include/linux/nl80211.h 2007-11-08 17:15:15.961529840 +0100 ++++ everything/include/linux/nl80211.h 2007-11-08 17:17:00.891547364 +0100 +@@ -157,6 +157,9 @@ enum nl80211_commands { + * restriction (at most %NL80211_MAX_SUPP_RATES). + * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station + * to, or the AP interface the station was originally added to to. ++ * @NL80211_ATTR_STA_STATS: statistics for a station, part of station info ++ * given for %NL80211_CMD_GET_STATION, nested attribute containing ++ * info as possible, see &enum nl80211_sta_stats. + * + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use +@@ -190,6 +193,7 @@ enum nl80211_attrs { + NL80211_ATTR_STA_LISTEN_INTERVAL, + NL80211_ATTR_STA_SUPPORTED_RATES, + NL80211_ATTR_STA_VLAN, ++ NL80211_ATTR_STA_STATS, + + /* add attributes here, update the policy in nl80211.c */ + +@@ -252,4 +256,28 @@ enum nl80211_sta_flags { + NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 + }; + ++/** ++ * enum nl80211_sta_stats - station statistics ++ * ++ * These attribute types are used with %NL80211_ATTR_STA_STATS ++ * when getting information about a station. ++ * ++ * @__NL80211_STA_STAT_INVALID: attribute number 0 is reserved ++ * @NL80211_STA_STAT_INACTIVE_TIME: time since last activity (u32, msecs) ++ * @NL80211_STA_STAT_RX_BYTES: total received bytes (u32, from this station) ++ * @NL80211_STA_STAT_TX_BYTES: total transmitted bytes (u32, to this station) ++ * @__NL80211_STA_STAT_AFTER_LAST: internal ++ * @NL80211_STA_STAT_MAX: highest possible station stats attribute ++ */ ++enum nl80211_sta_stats { ++ __NL80211_STA_STAT_INVALID, ++ NL80211_STA_STAT_INACTIVE_TIME, ++ NL80211_STA_STAT_RX_BYTES, ++ NL80211_STA_STAT_TX_BYTES, ++ ++ /* keep last */ ++ __NL80211_STA_STAT_AFTER_LAST, ++ NL80211_STA_STAT_MAX = __NL80211_STA_STAT_AFTER_LAST - 1 ++}; ++ + #endif /* __LINUX_NL80211_H */ +--- everything.orig/include/net/cfg80211.h 2007-11-08 17:15:15.971532444 +0100 ++++ everything/include/net/cfg80211.h 2007-11-08 17:17:00.891547364 +0100 +@@ -130,6 +130,39 @@ struct station_parameters { + u8 supported_rates_len; + }; + ++/** ++ * enum station_stats_flags - station statistics flags ++ * ++ * Used by the driver to indicate which info in &struct station_stats ++ * it has filled in during get_station(). ++ * ++ * @STATION_STAT_INACTIVE_TIME: @inactive_time filled ++ * @STATION_STAT_RX_BYTES: @rx_bytes filled ++ * @STATION_STAT_TX_BYTES: @tx_bytes filled ++ */ ++enum station_stats_flags { ++ STATION_STAT_INACTIVE_TIME = 1<<0, ++ STATION_STAT_RX_BYTES = 1<<1, ++ STATION_STAT_TX_BYTES = 1<<2, ++}; ++ ++/** ++ * struct station_stats - station statistics ++ * ++ * Station information filled by driver for get_station(). ++ * ++ * @filled: bitflag of flags from &enum station_stats_flags ++ * @inactive_time: time since last station activity (tx/rx) in milliseconds ++ * @rx_bytes: bytes received from this station ++ * @tx_bytes: bytes transmitted to this station ++ */ ++struct station_stats { ++ u32 filled; ++ u32 inactive_time; ++ u32 rx_bytes; ++ u32 tx_bytes; ++}; ++ + /* from net/wireless.h */ + struct wiphy; + +@@ -209,6 +242,8 @@ struct cfg80211_ops { + u8 *mac); + int (*change_station)(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_parameters *params); ++ int (*get_station)(struct wiphy *wiphy, struct net_device *dev, ++ u8 *mac, struct station_stats *stats); + }; + + #endif /* __NET_CFG80211_H */ +--- everything.orig/net/wireless/nl80211.c 2007-11-08 17:15:15.981533909 +0100 ++++ everything/net/wireless/nl80211.c 2007-11-08 17:17:00.901534235 +0100 +@@ -751,9 +751,89 @@ static int parse_station_flags(struct nl + return 0; + } + ++static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, ++ int flags, struct net_device *dev, ++ u8 *mac_addr, struct station_stats *stats) ++{ ++ void *hdr; ++ struct nlattr *statsattr; ++ ++ hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); ++ if (!hdr) ++ return -1; ++ ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); ++ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); ++ ++ statsattr = nla_nest_start(msg, NL80211_ATTR_STA_STATS); ++ if (!statsattr) ++ goto nla_put_failure; ++ if (stats->filled & STATION_STAT_INACTIVE_TIME) ++ NLA_PUT_U32(msg, NL80211_STA_STAT_INACTIVE_TIME, ++ stats->inactive_time); ++ if (stats->filled & STATION_STAT_RX_BYTES) ++ NLA_PUT_U32(msg, NL80211_STA_STAT_RX_BYTES, ++ stats->rx_bytes); ++ if (stats->filled & STATION_STAT_TX_BYTES) ++ NLA_PUT_U32(msg, NL80211_STA_STAT_TX_BYTES, ++ stats->tx_bytes); ++ ++ nla_nest_end(msg, statsattr); ++ ++ return genlmsg_end(msg, hdr); ++ ++ nla_put_failure: ++ return genlmsg_cancel(msg, hdr); ++} ++ ++ + static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) + { +- return -EOPNOTSUPP; ++ struct cfg80211_registered_device *drv; ++ int err; ++ struct net_device *dev; ++ struct station_stats stats; ++ struct sk_buff *msg; ++ u8 *mac_addr = NULL; ++ ++ memset(&stats, 0, sizeof(stats)); ++ ++ if (!info->attrs[NL80211_ATTR_MAC]) ++ return -EINVAL; ++ ++ mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); ++ ++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev); ++ if (err) ++ return err; ++ ++ if (!drv->ops->get_station) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ rtnl_lock(); ++ err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &stats); ++ rtnl_unlock(); ++ ++ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); ++ if (!msg) ++ goto out; ++ ++ if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0, ++ dev, mac_addr, &stats) < 0) ++ goto out_free; ++ ++ err = genlmsg_unicast(msg, info->snd_pid); ++ goto out; ++ ++ out_free: ++ nlmsg_free(msg); ++ ++ out: ++ cfg80211_put_dev(drv); ++ dev_put(dev); ++ return err; + } + + /* diff --git a/package/mac80211/patches/025-mac80211-get-sta.patch b/package/mac80211/patches/025-mac80211-get-sta.patch new file mode 100644 index 0000000000..868ca86fa3 --- /dev/null +++ b/package/mac80211/patches/025-mac80211-get-sta.patch @@ -0,0 +1,51 @@ +Subject: mac80211: implement station stats retrieval + +This implements the required cfg80211 callback in mac80211 +to allow userspace to get station statistics. + +Signed-off-by: Johannes Berg + +--- + net/mac80211/cfg.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +--- everything.orig/net/mac80211/cfg.c 2007-11-08 17:15:51.801523493 +0100 ++++ everything/net/mac80211/cfg.c 2007-11-08 17:17:01.921529351 +0100 +@@ -617,6 +617,31 @@ static int ieee80211_change_station(stru + return 0; + } + ++static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, ++ u8 *mac, struct station_stats *stats) ++{ ++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); ++ struct sta_info *sta; ++ ++ sta = sta_info_get(local, mac); ++ if (!sta) ++ return -ENOENT; ++ ++ /* XXX: verify sta->dev == dev */ ++ ++ stats->filled = STATION_STAT_INACTIVE_TIME | ++ STATION_STAT_RX_BYTES | ++ STATION_STAT_TX_BYTES; ++ ++ stats->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); ++ stats->rx_bytes = sta->rx_bytes; ++ stats->tx_bytes = sta->tx_bytes; ++ ++ sta_info_put(sta); ++ ++ return 0; ++} ++ + struct cfg80211_ops mac80211_config_ops = { + .add_virtual_intf = ieee80211_add_iface, + .del_virtual_intf = ieee80211_del_iface, +@@ -631,4 +656,5 @@ struct cfg80211_ops mac80211_config_ops + .add_station = ieee80211_add_station, + .del_station = ieee80211_del_station, + .change_station = ieee80211_change_station, ++ .get_station = ieee80211_get_station, + }; diff --git a/package/mac80211/src/mac80211/Kconfig b/package/mac80211/src/net/mac80211/Kconfig similarity index 100% rename from package/mac80211/src/mac80211/Kconfig rename to package/mac80211/src/net/mac80211/Kconfig diff --git a/package/mac80211/src/mac80211/Makefile b/package/mac80211/src/net/mac80211/Makefile similarity index 100% rename from package/mac80211/src/mac80211/Makefile rename to package/mac80211/src/net/mac80211/Makefile diff --git a/package/mac80211/src/mac80211/aes_ccm.c b/package/mac80211/src/net/mac80211/aes_ccm.c similarity index 100% rename from package/mac80211/src/mac80211/aes_ccm.c rename to package/mac80211/src/net/mac80211/aes_ccm.c diff --git a/package/mac80211/src/mac80211/aes_ccm.h b/package/mac80211/src/net/mac80211/aes_ccm.h similarity index 100% rename from package/mac80211/src/mac80211/aes_ccm.h rename to package/mac80211/src/net/mac80211/aes_ccm.h diff --git a/package/mac80211/src/mac80211/cfg.c b/package/mac80211/src/net/mac80211/cfg.c similarity index 100% rename from package/mac80211/src/mac80211/cfg.c rename to package/mac80211/src/net/mac80211/cfg.c diff --git a/package/mac80211/src/mac80211/cfg.h b/package/mac80211/src/net/mac80211/cfg.h similarity index 100% rename from package/mac80211/src/mac80211/cfg.h rename to package/mac80211/src/net/mac80211/cfg.h diff --git a/package/mac80211/src/mac80211/debugfs.c b/package/mac80211/src/net/mac80211/debugfs.c similarity index 100% rename from package/mac80211/src/mac80211/debugfs.c rename to package/mac80211/src/net/mac80211/debugfs.c diff --git a/package/mac80211/src/mac80211/debugfs.h b/package/mac80211/src/net/mac80211/debugfs.h similarity index 100% rename from package/mac80211/src/mac80211/debugfs.h rename to package/mac80211/src/net/mac80211/debugfs.h diff --git a/package/mac80211/src/mac80211/debugfs_key.c b/package/mac80211/src/net/mac80211/debugfs_key.c similarity index 100% rename from package/mac80211/src/mac80211/debugfs_key.c rename to package/mac80211/src/net/mac80211/debugfs_key.c diff --git a/package/mac80211/src/mac80211/debugfs_key.h b/package/mac80211/src/net/mac80211/debugfs_key.h similarity index 100% rename from package/mac80211/src/mac80211/debugfs_key.h rename to package/mac80211/src/net/mac80211/debugfs_key.h diff --git a/package/mac80211/src/mac80211/debugfs_netdev.c b/package/mac80211/src/net/mac80211/debugfs_netdev.c similarity index 100% rename from package/mac80211/src/mac80211/debugfs_netdev.c rename to package/mac80211/src/net/mac80211/debugfs_netdev.c diff --git a/package/mac80211/src/mac80211/debugfs_netdev.h b/package/mac80211/src/net/mac80211/debugfs_netdev.h similarity index 100% rename from package/mac80211/src/mac80211/debugfs_netdev.h rename to package/mac80211/src/net/mac80211/debugfs_netdev.h diff --git a/package/mac80211/src/mac80211/debugfs_sta.c b/package/mac80211/src/net/mac80211/debugfs_sta.c similarity index 100% rename from package/mac80211/src/mac80211/debugfs_sta.c rename to package/mac80211/src/net/mac80211/debugfs_sta.c diff --git a/package/mac80211/src/mac80211/debugfs_sta.h b/package/mac80211/src/net/mac80211/debugfs_sta.h similarity index 100% rename from package/mac80211/src/mac80211/debugfs_sta.h rename to package/mac80211/src/net/mac80211/debugfs_sta.h diff --git a/package/mac80211/src/mac80211/event.c b/package/mac80211/src/net/mac80211/event.c similarity index 100% rename from package/mac80211/src/mac80211/event.c rename to package/mac80211/src/net/mac80211/event.c diff --git a/package/mac80211/src/mac80211/ieee80211.c b/package/mac80211/src/net/mac80211/ieee80211.c similarity index 100% rename from package/mac80211/src/mac80211/ieee80211.c rename to package/mac80211/src/net/mac80211/ieee80211.c diff --git a/package/mac80211/src/mac80211/ieee80211_common.h b/package/mac80211/src/net/mac80211/ieee80211_common.h similarity index 100% rename from package/mac80211/src/mac80211/ieee80211_common.h rename to package/mac80211/src/net/mac80211/ieee80211_common.h diff --git a/package/mac80211/src/mac80211/ieee80211_i.h b/package/mac80211/src/net/mac80211/ieee80211_i.h similarity index 100% rename from package/mac80211/src/mac80211/ieee80211_i.h rename to package/mac80211/src/net/mac80211/ieee80211_i.h diff --git a/package/mac80211/src/mac80211/ieee80211_iface.c b/package/mac80211/src/net/mac80211/ieee80211_iface.c similarity index 100% rename from package/mac80211/src/mac80211/ieee80211_iface.c rename to package/mac80211/src/net/mac80211/ieee80211_iface.c diff --git a/package/mac80211/src/mac80211/ieee80211_ioctl.c b/package/mac80211/src/net/mac80211/ieee80211_ioctl.c similarity index 100% rename from package/mac80211/src/mac80211/ieee80211_ioctl.c rename to package/mac80211/src/net/mac80211/ieee80211_ioctl.c diff --git a/package/mac80211/src/mac80211/ieee80211_key.h b/package/mac80211/src/net/mac80211/ieee80211_key.h similarity index 100% rename from package/mac80211/src/mac80211/ieee80211_key.h rename to package/mac80211/src/net/mac80211/ieee80211_key.h diff --git a/package/mac80211/src/mac80211/ieee80211_led.c b/package/mac80211/src/net/mac80211/ieee80211_led.c similarity index 100% rename from package/mac80211/src/mac80211/ieee80211_led.c rename to package/mac80211/src/net/mac80211/ieee80211_led.c diff --git a/package/mac80211/src/mac80211/ieee80211_led.h b/package/mac80211/src/net/mac80211/ieee80211_led.h similarity index 100% rename from package/mac80211/src/mac80211/ieee80211_led.h rename to package/mac80211/src/net/mac80211/ieee80211_led.h diff --git a/package/mac80211/src/mac80211/ieee80211_rate.c b/package/mac80211/src/net/mac80211/ieee80211_rate.c similarity index 100% rename from package/mac80211/src/mac80211/ieee80211_rate.c rename to package/mac80211/src/net/mac80211/ieee80211_rate.c diff --git a/package/mac80211/src/mac80211/ieee80211_rate.h b/package/mac80211/src/net/mac80211/ieee80211_rate.h similarity index 100% rename from package/mac80211/src/mac80211/ieee80211_rate.h rename to package/mac80211/src/net/mac80211/ieee80211_rate.h diff --git a/package/mac80211/src/mac80211/ieee80211_sta.c b/package/mac80211/src/net/mac80211/ieee80211_sta.c similarity index 100% rename from package/mac80211/src/mac80211/ieee80211_sta.c rename to package/mac80211/src/net/mac80211/ieee80211_sta.c diff --git a/package/mac80211/src/mac80211/key.c b/package/mac80211/src/net/mac80211/key.c similarity index 100% rename from package/mac80211/src/mac80211/key.c rename to package/mac80211/src/net/mac80211/key.c diff --git a/package/mac80211/src/mac80211/michael.c b/package/mac80211/src/net/mac80211/michael.c similarity index 100% rename from package/mac80211/src/mac80211/michael.c rename to package/mac80211/src/net/mac80211/michael.c diff --git a/package/mac80211/src/mac80211/michael.h b/package/mac80211/src/net/mac80211/michael.h similarity index 100% rename from package/mac80211/src/mac80211/michael.h rename to package/mac80211/src/net/mac80211/michael.h diff --git a/package/mac80211/src/mac80211/rc80211_simple.c b/package/mac80211/src/net/mac80211/rc80211_simple.c similarity index 100% rename from package/mac80211/src/mac80211/rc80211_simple.c rename to package/mac80211/src/net/mac80211/rc80211_simple.c diff --git a/package/mac80211/src/mac80211/regdomain.c b/package/mac80211/src/net/mac80211/regdomain.c similarity index 100% rename from package/mac80211/src/mac80211/regdomain.c rename to package/mac80211/src/net/mac80211/regdomain.c diff --git a/package/mac80211/src/mac80211/rx.c b/package/mac80211/src/net/mac80211/rx.c similarity index 100% rename from package/mac80211/src/mac80211/rx.c rename to package/mac80211/src/net/mac80211/rx.c diff --git a/package/mac80211/src/mac80211/sta_info.c b/package/mac80211/src/net/mac80211/sta_info.c similarity index 100% rename from package/mac80211/src/mac80211/sta_info.c rename to package/mac80211/src/net/mac80211/sta_info.c diff --git a/package/mac80211/src/mac80211/sta_info.h b/package/mac80211/src/net/mac80211/sta_info.h similarity index 100% rename from package/mac80211/src/mac80211/sta_info.h rename to package/mac80211/src/net/mac80211/sta_info.h diff --git a/package/mac80211/src/mac80211/tkip.c b/package/mac80211/src/net/mac80211/tkip.c similarity index 100% rename from package/mac80211/src/mac80211/tkip.c rename to package/mac80211/src/net/mac80211/tkip.c diff --git a/package/mac80211/src/mac80211/tkip.h b/package/mac80211/src/net/mac80211/tkip.h similarity index 100% rename from package/mac80211/src/mac80211/tkip.h rename to package/mac80211/src/net/mac80211/tkip.h diff --git a/package/mac80211/src/mac80211/tx.c b/package/mac80211/src/net/mac80211/tx.c similarity index 100% rename from package/mac80211/src/mac80211/tx.c rename to package/mac80211/src/net/mac80211/tx.c diff --git a/package/mac80211/src/mac80211/util.c b/package/mac80211/src/net/mac80211/util.c similarity index 100% rename from package/mac80211/src/mac80211/util.c rename to package/mac80211/src/net/mac80211/util.c diff --git a/package/mac80211/src/mac80211/wep.c b/package/mac80211/src/net/mac80211/wep.c similarity index 100% rename from package/mac80211/src/mac80211/wep.c rename to package/mac80211/src/net/mac80211/wep.c diff --git a/package/mac80211/src/mac80211/wep.h b/package/mac80211/src/net/mac80211/wep.h similarity index 100% rename from package/mac80211/src/mac80211/wep.h rename to package/mac80211/src/net/mac80211/wep.h diff --git a/package/mac80211/src/mac80211/wme.c b/package/mac80211/src/net/mac80211/wme.c similarity index 100% rename from package/mac80211/src/mac80211/wme.c rename to package/mac80211/src/net/mac80211/wme.c diff --git a/package/mac80211/src/mac80211/wme.h b/package/mac80211/src/net/mac80211/wme.h similarity index 100% rename from package/mac80211/src/mac80211/wme.h rename to package/mac80211/src/net/mac80211/wme.h diff --git a/package/mac80211/src/mac80211/wpa.c b/package/mac80211/src/net/mac80211/wpa.c similarity index 100% rename from package/mac80211/src/mac80211/wpa.c rename to package/mac80211/src/net/mac80211/wpa.c diff --git a/package/mac80211/src/mac80211/wpa.h b/package/mac80211/src/net/mac80211/wpa.h similarity index 100% rename from package/mac80211/src/mac80211/wpa.h rename to package/mac80211/src/net/mac80211/wpa.h diff --git a/package/mac80211/src/wireless/Kconfig b/package/mac80211/src/net/wireless/Kconfig similarity index 100% rename from package/mac80211/src/wireless/Kconfig rename to package/mac80211/src/net/wireless/Kconfig diff --git a/package/mac80211/src/wireless/Makefile b/package/mac80211/src/net/wireless/Makefile similarity index 100% rename from package/mac80211/src/wireless/Makefile rename to package/mac80211/src/net/wireless/Makefile diff --git a/package/mac80211/src/wireless/core.c b/package/mac80211/src/net/wireless/core.c similarity index 100% rename from package/mac80211/src/wireless/core.c rename to package/mac80211/src/net/wireless/core.c diff --git a/package/mac80211/src/wireless/core.h b/package/mac80211/src/net/wireless/core.h similarity index 100% rename from package/mac80211/src/wireless/core.h rename to package/mac80211/src/net/wireless/core.h diff --git a/package/mac80211/src/wireless/nl80211.c b/package/mac80211/src/net/wireless/nl80211.c similarity index 100% rename from package/mac80211/src/wireless/nl80211.c rename to package/mac80211/src/net/wireless/nl80211.c diff --git a/package/mac80211/src/wireless/nl80211.h b/package/mac80211/src/net/wireless/nl80211.h similarity index 100% rename from package/mac80211/src/wireless/nl80211.h rename to package/mac80211/src/net/wireless/nl80211.h diff --git a/package/mac80211/src/wireless/radiotap.c b/package/mac80211/src/net/wireless/radiotap.c similarity index 100% rename from package/mac80211/src/wireless/radiotap.c rename to package/mac80211/src/net/wireless/radiotap.c diff --git a/package/mac80211/src/wireless/sysfs.c b/package/mac80211/src/net/wireless/sysfs.c similarity index 100% rename from package/mac80211/src/wireless/sysfs.c rename to package/mac80211/src/net/wireless/sysfs.c diff --git a/package/mac80211/src/wireless/sysfs.h b/package/mac80211/src/net/wireless/sysfs.h similarity index 100% rename from package/mac80211/src/wireless/sysfs.h rename to package/mac80211/src/net/wireless/sysfs.h