fix up hostapd for mac80211
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@9554 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
6fe9aab05a
commit
77a96c5437
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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 (a<b)
|
||||
+ return a;
|
||||
+ return b;
|
||||
+}
|
||||
+
|
||||
+static int get_key_handler(struct nl_msg *msg, void *arg)
|
||||
+{
|
||||
+ struct nlattr *tb[NL80211_ATTR_MAX];
|
||||
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
||||
+
|
||||
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
||||
+ genlmsg_attrlen(gnlh, 0), NULL);
|
||||
+
|
||||
+ /*
|
||||
+ * TODO: validate the key index and mac address!
|
||||
+ * Otherwise, there's a race condition as soon as
|
||||
+ * the kernel starts sending key notifications.
|
||||
+ */
|
||||
+
|
||||
+ if (tb[NL80211_ATTR_KEY_SEQ])
|
||||
+ memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),
|
||||
+ min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));
|
||||
+ 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)
|
||||
{
|
||||
struct i802_driver_data *drv = priv;
|
||||
- struct prism2_hostapd_param *param;
|
||||
- size_t param_len;
|
||||
- int ret;
|
||||
+ struct nl_msg *msg;
|
||||
+ struct nl_cb *cb = NULL;
|
||||
+ int ret = -1;
|
||||
+ int err = 0;
|
||||
+ int finished = 0;
|
||||
|
||||
- param_len = sizeof(struct prism2_hostapd_param) + 32;
|
||||
- param = os_zalloc(param_len);
|
||||
- if (param == NULL)
|
||||
- return -1;
|
||||
+ msg = nlmsg_alloc();
|
||||
+ if (!msg)
|
||||
+ goto out;
|
||||
|
||||
- param->cmd = 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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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/compat.h>
|
||||
#include <net80211/ieee80211.h>
|
||||
#ifdef WME_NUM_AC
|
||||
-/* Assume this is built against BSD branch of madwifi driver. */
|
||||
-#define MADWIFI_BSD
|
||||
-#include <net80211/_ieee80211.h>
|
||||
-#endif /* WME_NUM_AC */
|
||||
#include <net80211/ieee80211_crypto.h>
|
||||
#include <net80211/ieee80211_ioctl.h>
|
||||
+#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,
|
||||
};
|
||||
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/err.h>
|
||||
-#include <asm/scatterlist.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#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 <BSSID,SSID> 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 <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/types.h>
|
||||
@@ -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 <linux/crypto.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mm.h>
|
||||
-#include <asm/scatterlist.h>
|
||||
+#include <linux/scatterlist.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#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
|
|
@ -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 <jkmaline@cc.hut.fi>
|
||||
+ * Copyright 2002-2004, Instant802 Networks, Inc.
|
||||
+ * Copyright 2005, Devicescape Software, Inc.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#ifndef HOSTAPD_IOCTL_H
|
||||
+#define HOSTAPD_IOCTL_H
|
||||
+
|
||||
+#ifdef __KERNEL__
|
||||
+#include <linux/types.h>
|
||||
+#endif /* __KERNEL__ */
|
||||
+
|
||||
+#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
|
||||
+#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
|
||||
+#define PRISM2_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 3)
|
||||
+
|
||||
+/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes:
|
||||
+ * This table is no longer added to, the whole sub-ioctl
|
||||
+ * mess shall be deleted completely. */
|
||||
+enum {
|
||||
+ PRISM2_PARAM_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 */
|
|
@ -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 <net/mac80211.h>
|
||||
#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 */
|
|
@ -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 <linux/bitmap.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
+#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;
|
|
@ -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 <johannes@sipsolutions.net>
|
||||
|
||||
---
|
||||
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;
|
||||
}
|
|
@ -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 <johannes@sipsolutions.net>
|
||||
|
||||
---
|
||||
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;
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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 <johannes@sipsolutions.net>
|
||||
|
||||
---
|
||||
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 */
|
|
@ -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 <johannes@sipsolutions.net>
|
||||
|
||||
---
|
||||
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 <linux/ieee80211.h>
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/net_namespace.h>
|
||||
@@ -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,
|
||||
};
|
|
@ -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 <johannes@sipsolutions.net>
|
||||
|
||||
---
|
||||
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 <johannes@sipsolutions.net>
|
||||
+ * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||
*
|
||||
* 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,
|
|
@ -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 <johannes@sipsolutions.net>
|
||||
|
||||
---
|
||||
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 */
|
|
@ -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 <johannes@sipsolutions.net>
|
||||
|
||||
---
|
||||
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 <linux/ieee80211.h>
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
+#include <linux/rcupdate.h>
|
||||
#include <net/cfg80211.h>
|
||||
#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));
|
|
@ -0,0 +1,464 @@
|
|||
Subject: cfg80211/nl80211: station handling
|
||||
|
||||
This patch adds station handling to cfg80211/nl80211.
|
||||
|
||||
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
|
||||
|
||||
---
|
||||
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<<NL80211_STA_FLAG_AUTHORIZED,
|
||||
+ STATION_FLAG_SHORT_PREAMBLE = 1<<NL80211_STA_FLAG_SHORT_PREAMBLE,
|
||||
+ STATION_FLAG_WME = 1<<NL80211_STA_FLAG_WME,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct station_parameters - station parameters
|
||||
+ *
|
||||
+ * Used to change and create a new station.
|
||||
+ *
|
||||
+ * @vlan: vlan interface station should belong to
|
||||
+ * @supported_rates: supported rates in IEEE 802.11 format
|
||||
+ * (or NULL for no change)
|
||||
+ * @supported_rates_len: number of supported rates
|
||||
+ * @station_flags: station flags (see &enum station_flags)
|
||||
+ * @listen_interval: listen interval or -1 for no change
|
||||
+ * @aid: AID or zero for no change
|
||||
+ */
|
||||
+struct station_parameters {
|
||||
+ u8 *supported_rates;
|
||||
+ struct net_device *vlan;
|
||||
+ u32 station_flags;
|
||||
+ int listen_interval;
|
||||
+ u16 aid;
|
||||
+ u8 supported_rates_len;
|
||||
+};
|
||||
+
|
||||
/* from net/wireless.h */
|
||||
struct wiphy;
|
||||
|
||||
@@ -130,6 +171,12 @@ struct wiphy;
|
||||
* interface. This should reject the call when no beacon has been
|
||||
* configured.
|
||||
* @del_beacon: Remove beacon configuration and stop sending the beacon.
|
||||
+ *
|
||||
+ * @add_station: Add a new station.
|
||||
+ *
|
||||
+ * @del_station: Remove a station; @mac may be NULL to remove all stations.
|
||||
+ *
|
||||
+ * @change_station: Modify a given station.
|
||||
*/
|
||||
struct cfg80211_ops {
|
||||
int (*add_virtual_intf)(struct wiphy *wiphy, char *name,
|
||||
@@ -155,6 +202,13 @@ struct cfg80211_ops {
|
||||
int (*set_beacon)(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct beacon_parameters *info);
|
||||
int (*del_beacon)(struct wiphy *wiphy, struct net_device *dev);
|
||||
+
|
||||
+ int (*add_station)(struct wiphy *wiphy, struct net_device *dev,
|
||||
+ u8 *mac, struct station_parameters *params);
|
||||
+ int (*del_station)(struct wiphy *wiphy, struct net_device *dev,
|
||||
+ u8 *mac);
|
||||
+ int (*change_station)(struct wiphy *wiphy, struct net_device *dev,
|
||||
+ u8 *mac, struct station_parameters *params);
|
||||
};
|
||||
|
||||
#endif /* __NET_CFG80211_H */
|
||||
--- everything.orig/net/wireless/nl80211.c 2007-11-08 16:58:36.711524524 +0100
|
||||
+++ everything/net/wireless/nl80211.c 2007-11-08 17:15:15.981533909 +0100
|
||||
@@ -76,6 +76,12 @@ static struct nla_policy nl80211_policy[
|
||||
.len = IEEE80211_MAX_DATA_LEN },
|
||||
[NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY,
|
||||
.len = IEEE80211_MAX_DATA_LEN },
|
||||
+ [NL80211_ATTR_STA_AID] = { .type = NLA_U16 },
|
||||
+ [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
|
||||
+ [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
|
||||
+ [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
|
||||
+ .len = NL80211_MAX_SUPP_RATES },
|
||||
+ [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
/* message building helper */
|
||||
@@ -715,6 +721,211 @@ static int nl80211_del_beacon(struct sk_
|
||||
return err;
|
||||
}
|
||||
|
||||
+static
|
||||
+struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] __read_mostly = {
|
||||
+ [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
|
||||
+ [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
|
||||
+ [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
|
||||
+};
|
||||
+
|
||||
+static int parse_station_flags(struct nlattr *nla, u32 *staflags)
|
||||
+{
|
||||
+ struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
|
||||
+ int flag;
|
||||
+
|
||||
+ *staflags = 0;
|
||||
+
|
||||
+ if (!nla)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX,
|
||||
+ nla, sta_flags_policy))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ *staflags = STATION_FLAG_CHANGED;
|
||||
+
|
||||
+ for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
|
||||
+ if (flags[flag])
|
||||
+ *staflags |= (1<<flag);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
|
||||
+{
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Get vlan interface making sure it is on the right wiphy.
|
||||
+ */
|
||||
+static int get_vlan(struct nlattr *vlanattr,
|
||||
+ struct cfg80211_registered_device *rdev,
|
||||
+ struct net_device **vlan)
|
||||
+{
|
||||
+ *vlan = NULL;
|
||||
+
|
||||
+ if (vlanattr) {
|
||||
+ *vlan = dev_get_by_index(nla_get_u32(vlanattr));
|
||||
+ if (!*vlan)
|
||||
+ return -ENODEV;
|
||||
+ if (!(*vlan)->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 */
|
|
@ -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 <johannes@sipsolutions.net>
|
||||
|
||||
---
|
||||
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 <net/cfg80211.h>
|
||||
#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,
|
||||
};
|
|
@ -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 <johannes@sipsolutions.net>
|
||||
|
||||
---
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
|
@ -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 <johannes@sipsolutions.net>
|
||||
|
||||
---
|
||||
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,
|
||||
};
|
Loading…
Reference in New Issue