summaryrefslogtreecommitdiffstats
path: root/contrib/wpa/hostapd
diff options
context:
space:
mode:
authorrpaulo <rpaulo@FreeBSD.org>2010-06-14 15:37:48 +0000
committerrpaulo <rpaulo@FreeBSD.org>2010-06-14 15:37:48 +0000
commitce9c8f380b1fae326c166456a15ae504dce5c1d1 (patch)
tree14bf596282a14863f779d075d7a8f7e60c25f0a8 /contrib/wpa/hostapd
parentda0290f8d3606ed387adb04fec5d24de81a39032 (diff)
parent60c44471bf25f9e84d8701afe1bbcbcc88e18c89 (diff)
downloadFreeBSD-src-ce9c8f380b1fae326c166456a15ae504dce5c1d1.zip
FreeBSD-src-ce9c8f380b1fae326c166456a15ae504dce5c1d1.tar.gz
MFV hostapd & wpa_supplicant 0.6.10.
Diffstat (limited to 'contrib/wpa/hostapd')
-rw-r--r--contrib/wpa/hostapd/.gitignore7
-rw-r--r--contrib/wpa/hostapd/ChangeLog32
-rw-r--r--contrib/wpa/hostapd/Makefile635
-rw-r--r--contrib/wpa/hostapd/README-WPS9
-rw-r--r--contrib/wpa/hostapd/ap.h2
-rw-r--r--contrib/wpa/hostapd/beacon.c8
-rw-r--r--contrib/wpa/hostapd/config.c101
-rw-r--r--contrib/wpa/hostapd/config.h10
-rw-r--r--contrib/wpa/hostapd/ctrl_iface.c80
-rw-r--r--contrib/wpa/hostapd/doc/.gitignore4
-rw-r--r--contrib/wpa/hostapd/driver_bsd.c839
-rw-r--r--contrib/wpa/hostapd/driver_hostap.c1279
-rw-r--r--contrib/wpa/hostapd/driver_wired.c372
-rw-r--r--contrib/wpa/hostapd/drivers.c6
-rw-r--r--contrib/wpa/hostapd/hostapd.82
-rw-r--r--contrib/wpa/hostapd/hostapd.c44
-rw-r--r--contrib/wpa/hostapd/hostapd.conf47
-rw-r--r--contrib/wpa/hostapd/hostapd_cli.12
-rw-r--r--contrib/wpa/hostapd/hostapd_cli.c12
-rw-r--r--contrib/wpa/hostapd/hw_features.c7
-rw-r--r--contrib/wpa/hostapd/ieee802_11.c115
-rw-r--r--contrib/wpa/hostapd/ieee802_1x.c2
-rw-r--r--contrib/wpa/hostapd/preauth.c1
-rw-r--r--contrib/wpa/hostapd/radiotap.c287
-rw-r--r--contrib/wpa/hostapd/radiotap.h242
-rw-r--r--contrib/wpa/hostapd/radiotap_iter.h41
-rw-r--r--contrib/wpa/hostapd/wme.c285
-rw-r--r--contrib/wpa/hostapd/wme.h146
-rw-r--r--contrib/wpa/hostapd/wpa.c71
-rw-r--r--contrib/wpa/hostapd/wpa.h2
-rw-r--r--contrib/wpa/hostapd/wpa_auth_i.h2
-rw-r--r--contrib/wpa/hostapd/wpa_auth_ie.c4
-rw-r--r--contrib/wpa/hostapd/wpa_ft.c13
-rw-r--r--contrib/wpa/hostapd/wps_hostapd.c67
-rw-r--r--contrib/wpa/hostapd/wps_hostapd.h2
35 files changed, 4400 insertions, 378 deletions
diff --git a/contrib/wpa/hostapd/.gitignore b/contrib/wpa/hostapd/.gitignore
deleted file mode 100644
index 6dd2c2f..0000000
--- a/contrib/wpa/hostapd/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-*.d
-.config
-driver_conf.c
-hostapd
-hostapd_cli
-hlr_auc_gw
-nt_password_hash
diff --git a/contrib/wpa/hostapd/ChangeLog b/contrib/wpa/hostapd/ChangeLog
index 46f0852..18af4b1 100644
--- a/contrib/wpa/hostapd/ChangeLog
+++ b/contrib/wpa/hostapd/ChangeLog
@@ -1,5 +1,37 @@
ChangeLog for hostapd
+2010-01-12 - v0.6.10
+ * fixed SHA-256 based key derivation function to match with the
+ standard when using CCMP (for IEEE 802.11r and IEEE 802.11w)
+ (note: this breaks interoperability with previous version) [Bug 307]
+ * fixed WPS selected registrar expiration for internal PIN registrar
+ * disable PMTU discovery for RADIUS packets
+ * fixed WPS UPnP SSDP on 32-bit targets
+ * fixed WPS AP reconfiguration with drivers that do not use hostapd
+ MLME
+ * fixed RSN parameter setting for multi-BSS case
+ * added WPS workarounds for known interoperability issues with broken,
+ deployed implementation
+ * update IEEE 802.11w implementation to match with the published
+ standard
+ * fixed OpCode when proxying WSC_ACK or WSC_NACK from WPS ER
+ * fixed proxying of WSC_NACK to WPS ER
+ * fixed compilation with newer GnuTLS versions
+ * added support for defining timeout for WPS PINs
+ * fixed WPS Probe Request processing to handle missing required
+ attribute
+ * fixed PKCS#12 use with OpenSSL 1.0.0
+
+2009-03-23 - v0.6.9
+ * driver_nl80211: fixed STA accounting data collection (TX/RX bytes
+ reported correctly; TX/RX packets not yet available from kernel)
+ * fixed EAPOL/EAP reauthentication when using an external RADIUS
+ authentication server
+ * driver_prism54: fixed segmentation fault on initialization
+ * fixed TNC with EAP-TTLS
+ * fixed IEEE 802.11r key derivation function to match with the standard
+ (note: this breaks interoperability with previous version) [Bug 303]
+
2009-02-15 - v0.6.8
* increased hostapd_cli ping interval to 5 seconds and made this
configurable with a new command line options (-G<seconds>)
diff --git a/contrib/wpa/hostapd/Makefile b/contrib/wpa/hostapd/Makefile
new file mode 100644
index 0000000..3b3d7fe
--- /dev/null
+++ b/contrib/wpa/hostapd/Makefile
@@ -0,0 +1,635 @@
+ifndef CC
+CC=gcc
+endif
+
+ifndef CFLAGS
+CFLAGS = -MMD -O2 -Wall -g
+endif
+
+# define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to
+# a file (undefine it, if you want to save in binary size)
+CFLAGS += -DHOSTAPD_DUMP_STATE
+
+CFLAGS += -I../src
+CFLAGS += -I../src/crypto
+CFLAGS += -I../src/utils
+CFLAGS += -I../src/common
+
+# Uncomment following line and set the path to your kernel tree include
+# directory if your C library does not include all header files.
+# CFLAGS += -DUSE_KERNEL_HEADERS -I/usr/src/linux/include
+
+-include .config
+
+ifndef CONFIG_OS
+ifdef CONFIG_NATIVE_WINDOWS
+CONFIG_OS=win32
+else
+CONFIG_OS=unix
+endif
+endif
+
+ifeq ($(CONFIG_OS), internal)
+CFLAGS += -DOS_NO_C_LIB_DEFINES
+endif
+
+ifdef CONFIG_NATIVE_WINDOWS
+CFLAGS += -DCONFIG_NATIVE_WINDOWS
+LIBS += -lws2_32
+endif
+
+OBJS = hostapd.o ieee802_1x.o eapol_sm.o \
+ ieee802_11.o config.o ieee802_11_auth.o accounting.o \
+ sta_info.o wpa.o ctrl_iface.o \
+ drivers.o preauth.o pmksa_cache.o beacon.o \
+ hw_features.o wme.o ap_list.o \
+ mlme.o vlan_init.o wpa_auth_ie.o
+
+OBJS += ../src/utils/eloop.o
+OBJS += ../src/utils/common.o
+OBJS += ../src/utils/wpa_debug.o
+OBJS += ../src/utils/wpabuf.o
+OBJS += ../src/utils/os_$(CONFIG_OS).o
+OBJS += ../src/utils/ip_addr.o
+
+OBJS += ../src/common/ieee802_11_common.o
+OBJS += ../src/common/wpa_common.o
+
+OBJS += ../src/radius/radius.o
+OBJS += ../src/radius/radius_client.o
+
+OBJS += ../src/crypto/md5.o
+OBJS += ../src/crypto/rc4.o
+OBJS += ../src/crypto/md4.o
+OBJS += ../src/crypto/sha1.o
+OBJS += ../src/crypto/des.o
+OBJS += ../src/crypto/aes_wrap.o
+OBJS += ../src/crypto/aes.o
+
+HOBJS=../src/hlr_auc_gw/hlr_auc_gw.o ../src/utils/common.o ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).o ../src/hlr_auc_gw/milenage.o ../src/crypto/aes_wrap.o ../src/crypto/aes.o
+
+CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX
+
+ifdef CONFIG_IAPP
+CFLAGS += -DCONFIG_IAPP
+OBJS += iapp.o
+endif
+
+ifdef CONFIG_RSN_PREAUTH
+CFLAGS += -DCONFIG_RSN_PREAUTH
+CONFIG_L2_PACKET=y
+endif
+
+ifdef CONFIG_PEERKEY
+CFLAGS += -DCONFIG_PEERKEY
+OBJS += peerkey.o
+endif
+
+ifdef CONFIG_IEEE80211W
+CFLAGS += -DCONFIG_IEEE80211W
+NEED_SHA256=y
+endif
+
+ifdef CONFIG_IEEE80211R
+CFLAGS += -DCONFIG_IEEE80211R
+OBJS += wpa_ft.o
+NEED_SHA256=y
+endif
+
+ifdef CONFIG_IEEE80211N
+CFLAGS += -DCONFIG_IEEE80211N
+endif
+
+ifdef CONFIG_DRIVER_HOSTAP
+CFLAGS += -DCONFIG_DRIVER_HOSTAP
+OBJS += driver_hostap.o
+endif
+
+ifdef CONFIG_DRIVER_WIRED
+CFLAGS += -DCONFIG_DRIVER_WIRED
+OBJS += driver_wired.o
+endif
+
+ifdef CONFIG_DRIVER_MADWIFI
+CFLAGS += -DCONFIG_DRIVER_MADWIFI
+OBJS += driver_madwifi.o
+CONFIG_L2_PACKET=y
+endif
+
+ifdef CONFIG_DRIVER_ATHEROS
+CFLAGS += -DCONFIG_DRIVER_ATHEROS
+OBJS += driver_atheros.o
+CONFIG_L2_PACKET=y
+endif
+
+ifdef CONFIG_DRIVER_PRISM54
+CFLAGS += -DCONFIG_DRIVER_PRISM54
+OBJS += driver_prism54.o
+endif
+
+ifdef CONFIG_DRIVER_NL80211
+CFLAGS += -DCONFIG_DRIVER_NL80211
+OBJS += driver_nl80211.o radiotap.o
+LIBS += -lnl
+ifdef CONFIG_LIBNL20
+LIBS += -lnl-genl
+CFLAGS += -DCONFIG_LIBNL20
+endif
+endif
+
+ifdef CONFIG_DRIVER_BSD
+CFLAGS += -DCONFIG_DRIVER_BSD
+OBJS += driver_bsd.o
+CONFIG_L2_PACKET=y
+CONFIG_DNET_PCAP=y
+CONFIG_L2_FREEBSD=y
+endif
+
+ifdef CONFIG_DRIVER_TEST
+CFLAGS += -DCONFIG_DRIVER_TEST
+OBJS += driver_test.o
+endif
+
+ifdef CONFIG_DRIVER_NONE
+CFLAGS += -DCONFIG_DRIVER_NONE
+OBJS += driver_none.o
+endif
+
+ifdef CONFIG_L2_PACKET
+ifdef CONFIG_DNET_PCAP
+ifdef CONFIG_L2_FREEBSD
+LIBS += -lpcap
+OBJS += ../src/l2_packet/l2_packet_freebsd.o
+else
+LIBS += -ldnet -lpcap
+OBJS += ../src/l2_packet/l2_packet_pcap.o
+endif
+else
+OBJS += ../src/l2_packet/l2_packet_linux.o
+endif
+else
+OBJS += ../src/l2_packet/l2_packet_none.o
+endif
+
+
+ifdef CONFIG_EAP_MD5
+CFLAGS += -DEAP_MD5
+OBJS += ../src/eap_server/eap_md5.o
+CHAP=y
+endif
+
+ifdef CONFIG_EAP_TLS
+CFLAGS += -DEAP_TLS
+OBJS += ../src/eap_server/eap_tls.o
+TLS_FUNCS=y
+endif
+
+ifdef CONFIG_EAP_PEAP
+CFLAGS += -DEAP_PEAP
+OBJS += ../src/eap_server/eap_peap.o
+OBJS += ../src/eap_common/eap_peap_common.o
+TLS_FUNCS=y
+CONFIG_EAP_MSCHAPV2=y
+endif
+
+ifdef CONFIG_EAP_TTLS
+CFLAGS += -DEAP_TTLS
+OBJS += ../src/eap_server/eap_ttls.o
+TLS_FUNCS=y
+CHAP=y
+endif
+
+ifdef CONFIG_EAP_MSCHAPV2
+CFLAGS += -DEAP_MSCHAPv2
+OBJS += ../src/eap_server/eap_mschapv2.o
+MS_FUNCS=y
+endif
+
+ifdef CONFIG_EAP_GTC
+CFLAGS += -DEAP_GTC
+OBJS += ../src/eap_server/eap_gtc.o
+endif
+
+ifdef CONFIG_EAP_SIM
+CFLAGS += -DEAP_SIM
+OBJS += ../src/eap_server/eap_sim.o
+CONFIG_EAP_SIM_COMMON=y
+endif
+
+ifdef CONFIG_EAP_AKA
+CFLAGS += -DEAP_AKA
+OBJS += ../src/eap_server/eap_aka.o
+CONFIG_EAP_SIM_COMMON=y
+NEED_SHA256=y
+endif
+
+ifdef CONFIG_EAP_AKA_PRIME
+CFLAGS += -DEAP_AKA_PRIME
+endif
+
+ifdef CONFIG_EAP_SIM_COMMON
+OBJS += ../src/eap_common/eap_sim_common.o
+# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
+# replaced with another file implementating the interface specified in
+# eap_sim_db.h.
+OBJS += ../src/eap_server/eap_sim_db.o
+NEED_FIPS186_2_PRF=y
+endif
+
+ifdef CONFIG_EAP_PAX
+CFLAGS += -DEAP_PAX
+OBJS += ../src/eap_server/eap_pax.o ../src/eap_common/eap_pax_common.o
+endif
+
+ifdef CONFIG_EAP_PSK
+CFLAGS += -DEAP_PSK
+OBJS += ../src/eap_server/eap_psk.o ../src/eap_common/eap_psk_common.o
+endif
+
+ifdef CONFIG_EAP_SAKE
+CFLAGS += -DEAP_SAKE
+OBJS += ../src/eap_server/eap_sake.o ../src/eap_common/eap_sake_common.o
+endif
+
+ifdef CONFIG_EAP_GPSK
+CFLAGS += -DEAP_GPSK
+OBJS += ../src/eap_server/eap_gpsk.o ../src/eap_common/eap_gpsk_common.o
+ifdef CONFIG_EAP_GPSK_SHA256
+CFLAGS += -DEAP_GPSK_SHA256
+endif
+NEED_SHA256=y
+endif
+
+ifdef CONFIG_EAP_VENDOR_TEST
+CFLAGS += -DEAP_VENDOR_TEST
+OBJS += ../src/eap_server/eap_vendor_test.o
+endif
+
+ifdef CONFIG_EAP_FAST
+CFLAGS += -DEAP_FAST
+OBJS += ../src/eap_server/eap_fast.o
+OBJS += ../src/eap_common/eap_fast_common.o
+TLS_FUNCS=y
+NEED_T_PRF=y
+endif
+
+ifdef CONFIG_WPS
+CFLAGS += -DCONFIG_WPS -DEAP_WSC
+OBJS += ../src/utils/uuid.o
+OBJS += wps_hostapd.o
+OBJS += ../src/eap_server/eap_wsc.o ../src/eap_common/eap_wsc_common.o
+OBJS += ../src/wps/wps.o
+OBJS += ../src/wps/wps_common.o
+OBJS += ../src/wps/wps_attr_parse.o
+OBJS += ../src/wps/wps_attr_build.o
+OBJS += ../src/wps/wps_attr_process.o
+OBJS += ../src/wps/wps_dev_attr.o
+OBJS += ../src/wps/wps_enrollee.o
+OBJS += ../src/wps/wps_registrar.o
+NEED_DH_GROUPS=y
+NEED_SHA256=y
+NEED_CRYPTO=y
+NEED_BASE64=y
+
+ifdef CONFIG_WPS_UPNP
+CFLAGS += -DCONFIG_WPS_UPNP
+OBJS += ../src/wps/wps_upnp.o
+OBJS += ../src/wps/wps_upnp_ssdp.o
+OBJS += ../src/wps/wps_upnp_web.o
+OBJS += ../src/wps/wps_upnp_event.o
+OBJS += ../src/wps/httpread.o
+endif
+
+endif
+
+ifdef CONFIG_EAP_IKEV2
+CFLAGS += -DEAP_IKEV2
+OBJS += ../src/eap_server/eap_ikev2.o ../src/eap_server/ikev2.o
+OBJS += ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.o
+NEED_DH_GROUPS=y
+NEED_DH_GROUPS_ALL=y
+endif
+
+ifdef CONFIG_EAP_TNC
+CFLAGS += -DEAP_TNC
+OBJS += ../src/eap_server/eap_tnc.o
+OBJS += ../src/eap_server/tncs.o
+NEED_BASE64=y
+ifndef CONFIG_DRIVER_BSD
+LIBS += -ldl
+endif
+endif
+
+# Basic EAP functionality is needed for EAPOL
+OBJS += ../src/eap_server/eap.o
+OBJS += ../src/eap_common/eap_common.o
+OBJS += ../src/eap_server/eap_methods.o
+OBJS += ../src/eap_server/eap_identity.o
+
+ifdef CONFIG_EAP
+CFLAGS += -DEAP_SERVER
+endif
+
+ifndef CONFIG_TLS
+CONFIG_TLS=openssl
+endif
+
+ifeq ($(CONFIG_TLS), internal)
+ifndef CONFIG_CRYPTO
+CONFIG_CRYPTO=internal
+endif
+endif
+ifeq ($(CONFIG_CRYPTO), libtomcrypt)
+CFLAGS += -DCONFIG_INTERNAL_X509
+endif
+ifeq ($(CONFIG_CRYPTO), internal)
+CFLAGS += -DCONFIG_INTERNAL_X509
+endif
+
+
+ifdef TLS_FUNCS
+# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
+CFLAGS += -DEAP_TLS_FUNCS
+OBJS += ../src/eap_server/eap_tls_common.o
+NEED_TLS_PRF=y
+ifeq ($(CONFIG_TLS), openssl)
+OBJS += ../src/crypto/tls_openssl.o
+LIBS += -lssl -lcrypto
+LIBS_p += -lcrypto
+LIBS_h += -lcrypto
+endif
+ifeq ($(CONFIG_TLS), gnutls)
+OBJS += ../src/crypto/tls_gnutls.o
+LIBS += -lgnutls -lgcrypt -lgpg-error
+LIBS_p += -lgcrypt
+LIBS_h += -lgcrypt
+endif
+ifdef CONFIG_GNUTLS_EXTRA
+CFLAGS += -DCONFIG_GNUTLS_EXTRA
+LIBS += -lgnutls-extra
+endif
+ifeq ($(CONFIG_TLS), internal)
+OBJS += ../src/crypto/tls_internal.o
+OBJS += ../src/tls/tlsv1_common.o ../src/tls/tlsv1_record.o
+OBJS += ../src/tls/tlsv1_cred.o ../src/tls/tlsv1_server.o
+OBJS += ../src/tls/tlsv1_server_write.o ../src/tls/tlsv1_server_read.o
+OBJS += ../src/tls/asn1.o ../src/tls/x509v3.o
+OBJS_p += ../src/tls/asn1.o
+OBJS_p += ../src/crypto/rc4.o ../src/crypto/aes_wrap.o ../src/crypto/aes.o
+NEED_BASE64=y
+CFLAGS += -DCONFIG_TLS_INTERNAL
+CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
+ifeq ($(CONFIG_CRYPTO), internal)
+ifdef CONFIG_INTERNAL_LIBTOMMATH
+CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
+else
+LIBS += -ltommath
+LIBS_p += -ltommath
+endif
+endif
+ifeq ($(CONFIG_CRYPTO), libtomcrypt)
+LIBS += -ltomcrypt -ltfm
+LIBS_p += -ltomcrypt -ltfm
+endif
+endif
+NEED_CRYPTO=y
+else
+OBJS += ../src/crypto/tls_none.o
+endif
+
+ifdef CONFIG_PKCS12
+CFLAGS += -DPKCS12_FUNCS
+endif
+
+ifdef MS_FUNCS
+OBJS += ../src/crypto/ms_funcs.o
+NEED_CRYPTO=y
+endif
+
+ifdef CHAP
+OBJS += ../src/eap_common/chap.o
+endif
+
+ifdef NEED_CRYPTO
+ifndef TLS_FUNCS
+ifeq ($(CONFIG_TLS), openssl)
+LIBS += -lcrypto
+LIBS_p += -lcrypto
+LIBS_h += -lcrypto
+endif
+ifeq ($(CONFIG_TLS), gnutls)
+LIBS += -lgcrypt
+LIBS_p += -lgcrypt
+LIBS_h += -lgcrypt
+endif
+ifeq ($(CONFIG_TLS), internal)
+ifeq ($(CONFIG_CRYPTO), libtomcrypt)
+LIBS += -ltomcrypt -ltfm
+LIBS_p += -ltomcrypt -ltfm
+endif
+endif
+endif
+ifeq ($(CONFIG_TLS), openssl)
+OBJS += ../src/crypto/crypto_openssl.o
+OBJS_p += ../src/crypto/crypto_openssl.o
+HOBJS += ../src/crypto/crypto_openssl.o
+CONFIG_INTERNAL_SHA256=y
+endif
+ifeq ($(CONFIG_TLS), gnutls)
+OBJS += ../src/crypto/crypto_gnutls.o
+OBJS_p += ../src/crypto/crypto_gnutls.o
+HOBJS += ../src/crypto/crypto_gnutls.o
+CONFIG_INTERNAL_SHA256=y
+endif
+ifeq ($(CONFIG_TLS), internal)
+ifeq ($(CONFIG_CRYPTO), libtomcrypt)
+OBJS += ../src/crypto/crypto_libtomcrypt.o
+OBJS_p += ../src/crypto/crypto_libtomcrypt.o
+CONFIG_INTERNAL_SHA256=y
+endif
+ifeq ($(CONFIG_CRYPTO), internal)
+OBJS += ../src/crypto/crypto_internal.o ../src/tls/rsa.o ../src/tls/bignum.o
+OBJS_p += ../src/crypto/crypto_internal.o ../src/tls/rsa.o ../src/tls/bignum.o
+CFLAGS += -DCONFIG_CRYPTO_INTERNAL
+ifdef CONFIG_INTERNAL_LIBTOMMATH
+CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
+ifdef CONFIG_INTERNAL_LIBTOMMATH_FAST
+CFLAGS += -DLTM_FAST
+endif
+else
+LIBS += -ltommath
+LIBS_p += -ltommath
+endif
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_DES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD4=y
+CONFIG_INTERNAL_MD5=y
+CONFIG_INTERNAL_SHA256=y
+endif
+endif
+else
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD5=y
+CONFIG_INTERNAL_SHA256=y
+endif
+
+ifdef CONFIG_INTERNAL_AES
+CFLAGS += -DINTERNAL_AES
+endif
+ifdef CONFIG_INTERNAL_SHA1
+CFLAGS += -DINTERNAL_SHA1
+endif
+ifdef CONFIG_INTERNAL_SHA256
+CFLAGS += -DINTERNAL_SHA256
+endif
+ifdef CONFIG_INTERNAL_MD5
+CFLAGS += -DINTERNAL_MD5
+endif
+ifdef CONFIG_INTERNAL_MD4
+CFLAGS += -DINTERNAL_MD4
+endif
+ifdef CONFIG_INTERNAL_DES
+CFLAGS += -DINTERNAL_DES
+endif
+
+ifdef NEED_SHA256
+OBJS += ../src/crypto/sha256.o
+endif
+
+ifdef NEED_DH_GROUPS
+OBJS += ../src/crypto/dh_groups.o
+ifdef NEED_DH_GROUPS_ALL
+CFLAGS += -DALL_DH_GROUPS
+endif
+endif
+
+ifndef NEED_FIPS186_2_PRF
+CFLAGS += -DCONFIG_NO_FIPS186_2_PRF
+endif
+
+ifndef NEED_T_PRF
+CFLAGS += -DCONFIG_NO_T_PRF
+endif
+
+ifndef NEED_TLS_PRF
+CFLAGS += -DCONFIG_NO_TLS_PRF
+endif
+
+ifdef CONFIG_RADIUS_SERVER
+CFLAGS += -DRADIUS_SERVER
+OBJS += ../src/radius/radius_server.o
+endif
+
+ifdef CONFIG_IPV6
+CFLAGS += -DCONFIG_IPV6
+endif
+
+ifdef CONFIG_DRIVER_RADIUS_ACL
+CFLAGS += -DCONFIG_DRIVER_RADIUS_ACL
+endif
+
+ifdef CONFIG_FULL_DYNAMIC_VLAN
+# define CONFIG_FULL_DYNAMIC_VLAN to have hostapd manipulate bridges
+# and vlan interfaces for the vlan feature.
+CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN
+endif
+
+ifdef NEED_BASE64
+OBJS += ../src/utils/base64.o
+endif
+
+ifdef CONFIG_NO_STDOUT_DEBUG
+CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
+endif
+
+ifdef CONFIG_NO_AES_EXTRAS
+CFLAGS += -DCONFIG_NO_AES_UNWRAP
+CFLAGS += -DCONFIG_NO_AES_CTR -DCONFIG_NO_AES_OMAC1
+CFLAGS += -DCONFIG_NO_AES_EAX -DCONFIG_NO_AES_CBC
+CFLAGS += -DCONFIG_NO_AES_DECRYPT
+CFLAGS += -DCONFIG_NO_AES_ENCRYPT_BLOCK
+endif
+
+ALL=hostapd hostapd_cli
+
+all: verify_config $(ALL)
+
+Q=@
+E=echo
+ifeq ($(V), 1)
+Q=
+E=true
+endif
+
+%.o: %.c
+ $(Q)$(CC) -c -o $@ $(CFLAGS) $<
+ @$(E) " CC " $<
+
+verify_config:
+ @if [ ! -r .config ]; then \
+ echo 'Building hostapd requires a configuration file'; \
+ echo '(.config). See README for more instructions. You can'; \
+ echo 'run "cp defconfig .config" to create an example'; \
+ echo 'configuration.'; \
+ exit 1; \
+ fi
+
+install: all
+ for i in $(ALL); do cp $$i /usr/local/bin/$$i; done
+
+hostapd: $(OBJS)
+ $(CC) -o hostapd $(OBJS) $(LIBS)
+
+OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
+hostapd_cli: $(OBJS_c)
+ $(CC) -o hostapd_cli $(OBJS_c)
+
+NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o ../src/crypto/sha1.o ../src/crypto/rc4.o ../src/crypto/md5.o
+NOBJS += ../src/crypto/crypto_openssl.o ../src/utils/os_$(CONFIG_OS).o
+ifdef TLS_FUNCS
+LIBS_n += -lcrypto
+endif
+
+nt_password_hash: $(NOBJS)
+ $(CC) -o nt_password_hash $(NOBJS) $(LIBS_n)
+
+hlr_auc_gw: $(HOBJS)
+ $(CC) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
+
+clean:
+ $(MAKE) -C ../src clean
+ rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw
+ rm -f *.d
+
+%.eps: %.fig
+ fig2dev -L eps $*.fig $*.eps
+
+%.png: %.fig
+ fig2dev -L png -m 3 $*.fig | pngtopnm | pnmscale 0.4 | pnmtopng \
+ > $*.png
+
+docs-pics: doc/hostapd.png doc/hostapd.eps
+
+docs: docs-pics
+ (cd ..; doxygen hostapd/doc/doxygen.full; cd hostapd)
+ $(MAKE) -C doc/latex
+ cp doc/latex/refman.pdf hostapd-devel.pdf
+
+docs-fast: docs-pics
+ (cd ..; doxygen hostapd/doc/doxygen.fast; cd hostapd)
+
+clean-docs:
+ rm -rf doc/latex doc/html
+ rm -f doc/hostapd.{eps,png} hostapd-devel.pdf
+
+TEST_SRC_MILENAGE = ../src/hlr_auc_gw/milenage.c ../src/crypto/aes_wrap.c ../src/crypto/aes.c ../src/utils/common.c ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).c
+test-milenage: $(TEST_SRC_MILENAGE)
+ $(CC) -o test-milenage -Wall -Werror $(TEST_SRC_MILENAGE) \
+ -DTEST_MAIN_MILENAGE -I. -DINTERNAL_AES \
+ -I../src/crypto -I../src/utils
+ ./test-milenage
+ rm test-milenage
+
+-include $(OBJS:%.o=%.d)
diff --git a/contrib/wpa/hostapd/README-WPS b/contrib/wpa/hostapd/README-WPS
index b46d767..e0e370b 100644
--- a/contrib/wpa/hostapd/README-WPS
+++ b/contrib/wpa/hostapd/README-WPS
@@ -165,10 +165,17 @@ Example command to add a PIN (12345670) for an Enrollee:
hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c 12345670
If the UUID-E is not available (e.g., Enrollee waits for the Registrar
-to be selected before connecting), wildcard UUID may be used to allow the PIN to be used once with any UUID:
+to be selected before connecting), wildcard UUID may be used to allow
+the PIN to be used once with any UUID:
hostapd_cli wps_pin any 12345670
+To reduce likelihood of PIN being used with other devices or of
+forgetting an active PIN available for potential attackers, expiration
+time can be set for the new PIN:
+
+hostapd_cli wps_pin any 12345670 300
+
After this, the Enrollee can connect to the AP again and complete WPS
negotiation. At that point, a new, random WPA PSK is generated for the
diff --git a/contrib/wpa/hostapd/ap.h b/contrib/wpa/hostapd/ap.h
index 98f8ee7..2c6d7e9 100644
--- a/contrib/wpa/hostapd/ap.h
+++ b/contrib/wpa/hostapd/ap.h
@@ -30,7 +30,7 @@
#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
#define WLAN_STA_SHORT_PREAMBLE BIT(7)
#define WLAN_STA_PREAUTH BIT(8)
-#define WLAN_STA_WME BIT(9)
+#define WLAN_STA_WMM BIT(9)
#define WLAN_STA_MFP BIT(10)
#define WLAN_STA_HT BIT(11)
#define WLAN_STA_WPS BIT(12)
diff --git a/contrib/wpa/hostapd/beacon.c b/contrib/wpa/hostapd/beacon.c
index 31323e8..1f82d9c 100644
--- a/contrib/wpa/hostapd/beacon.c
+++ b/contrib/wpa/hostapd/beacon.c
@@ -298,8 +298,8 @@ void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
pos = hostapd_eid_wpa(hapd, pos, epos - pos, sta);
- /* Wi-Fi Wireless Multimedia Extensions */
- pos = hostapd_eid_wme(hapd, pos);
+ /* Wi-Fi Alliance WMM */
+ pos = hostapd_eid_wmm(hapd, pos);
pos = hostapd_eid_ht_capabilities_info(hapd, pos);
pos = hostapd_eid_ht_operation(hapd, pos);
@@ -395,8 +395,8 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
tailpos, NULL);
- /* Wi-Fi Wireless Multimedia Extensions */
- tailpos = hostapd_eid_wme(hapd, tailpos);
+ /* Wi-Fi Alliance WMM */
+ tailpos = hostapd_eid_wmm(hapd, tailpos);
#ifdef CONFIG_IEEE80211N
if (hapd->iconf->ieee80211n) {
diff --git a/contrib/wpa/hostapd/config.c b/contrib/wpa/hostapd/config.c
index 6ad14d2..692b1a4 100644
--- a/contrib/wpa/hostapd/config.c
+++ b/contrib/wpa/hostapd/config.c
@@ -201,15 +201,15 @@ static struct hostapd_config * hostapd_config_defaults(void)
struct hostapd_config *conf;
struct hostapd_bss_config *bss;
int i;
- const int aCWmin = 15, aCWmax = 1024;
- const struct hostapd_wme_ac_params ac_bk =
+ const int aCWmin = 4, aCWmax = 10;
+ const struct hostapd_wmm_ac_params ac_bk =
{ aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
- const struct hostapd_wme_ac_params ac_be =
+ const struct hostapd_wmm_ac_params ac_be =
{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
- const struct hostapd_wme_ac_params ac_vi = /* video traffic */
- { aCWmin >> 1, aCWmin, 2, 3000 / 32, 1 };
- const struct hostapd_wme_ac_params ac_vo = /* voice traffic */
- { aCWmin >> 2, aCWmin >> 1, 2, 1500 / 32, 1 };
+ const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
+ { aCWmin - 1, aCWmin, 2, 3000 / 32, 1 };
+ const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
+ { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 };
conf = os_zalloc(sizeof(*conf));
bss = os_zalloc(sizeof(*bss));
@@ -251,10 +251,10 @@ static struct hostapd_config * hostapd_config_defaults(void)
for (i = 0; i < NUM_TX_QUEUES; i++)
conf->tx_queue[i].aifs = -1; /* use hw default */
- conf->wme_ac_params[0] = ac_be;
- conf->wme_ac_params[1] = ac_bk;
- conf->wme_ac_params[2] = ac_vi;
- conf->wme_ac_params[3] = ac_vo;
+ conf->wmm_ac_params[0] = ac_be;
+ conf->wmm_ac_params[1] = ac_bk;
+ conf->wmm_ac_params[2] = ac_vi;
+ conf->wmm_ac_params[3] = ac_vo;
#ifdef CONFIG_IEEE80211N
conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
@@ -1166,14 +1166,14 @@ static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name,
}
-static int hostapd_config_wme_ac(struct hostapd_config *conf, char *name,
- char *val)
+static int hostapd_config_wmm_ac(struct hostapd_config *conf, char *name,
+ char *val)
{
int num, v;
char *pos;
- struct hostapd_wme_ac_params *ac;
+ struct hostapd_wmm_ac_params *ac;
- /* skip 'wme_ac_' prefix */
+ /* skip 'wme_ac_' or 'wmm_ac_' prefix */
pos = name + 7;
if (os_strncmp(pos, "be_", 3) == 0) {
num = 0;
@@ -1188,11 +1188,11 @@ static int hostapd_config_wme_ac(struct hostapd_config *conf, char *name,
num = 3;
pos += 3;
} else {
- wpa_printf(MSG_ERROR, "Unknown wme name '%s'", pos);
+ wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
return -1;
}
- ac = &conf->wme_ac_params[num];
+ ac = &conf->wmm_ac_params[num];
if (os_strcmp(pos, "aifs") == 0) {
v = atoi(val);
@@ -1221,7 +1221,7 @@ static int hostapd_config_wme_ac(struct hostapd_config *conf, char *name,
wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
return -1;
}
- ac->txopLimit = v;
+ ac->txop_limit = v;
} else if (os_strcmp(pos, "acm") == 0) {
v = atoi(val);
if (v < 0 || v > 1) {
@@ -1230,7 +1230,7 @@ static int hostapd_config_wme_ac(struct hostapd_config *conf, char *name,
}
ac->admission_control_mandatory = v;
} else {
- wpa_printf(MSG_ERROR, "Unknown wme_ac_ field '%s'", pos);
+ wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
return -1;
}
@@ -1452,13 +1452,13 @@ struct hostapd_config * hostapd_config_read(const char *fname)
} else if (os_strcmp(buf, "bridge") == 0) {
os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
} else if (os_strcmp(buf, "driver") == 0) {
- int i;
+ int j;
/* clear to get error below if setting is invalid */
conf->driver = NULL;
- for (i = 0; hostapd_drivers[i]; i++) {
- if (os_strcmp(pos, hostapd_drivers[i]->name) ==
+ for (j = 0; hostapd_drivers[j]; j++) {
+ if (os_strcmp(pos, hostapd_drivers[j]->name) ==
0) {
- conf->driver = hostapd_drivers[i];
+ conf->driver = hostapd_drivers[j];
break;
}
}
@@ -2070,11 +2070,13 @@ struct hostapd_config * hostapd_config_read(const char *fname)
"queue item", line);
errors++;
}
- } else if (os_strcmp(buf, "wme_enabled") == 0) {
- bss->wme_enabled = atoi(pos);
- } else if (os_strncmp(buf, "wme_ac_", 7) == 0) {
- if (hostapd_config_wme_ac(conf, buf, pos)) {
- wpa_printf(MSG_ERROR, "Line %d: invalid wme "
+ } else if (os_strcmp(buf, "wme_enabled") == 0 ||
+ os_strcmp(buf, "wmm_enabled") == 0) {
+ bss->wmm_enabled = atoi(pos);
+ } else if (os_strncmp(buf, "wme_ac_", 7) == 0 ||
+ os_strncmp(buf, "wmm_ac_", 7) == 0) {
+ if (hostapd_config_wmm_ac(conf, buf, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid WMM "
"ac item", line);
errors++;
}
@@ -2255,29 +2257,30 @@ struct hostapd_config * hostapd_config_read(const char *fname)
fclose(f);
- if (bss->individual_wep_key_len == 0) {
- /* individual keys are not use; can use key idx0 for broadcast
- * keys */
- bss->broadcast_key_idx_min = 0;
- }
-
- /* Select group cipher based on the enabled pairwise cipher suites */
- pairwise = 0;
- if (bss->wpa & 1)
- pairwise |= bss->wpa_pairwise;
- if (bss->wpa & 2) {
- if (bss->rsn_pairwise == 0)
- bss->rsn_pairwise = bss->wpa_pairwise;
- pairwise |= bss->rsn_pairwise;
- }
- if (pairwise & WPA_CIPHER_TKIP)
- bss->wpa_group = WPA_CIPHER_TKIP;
- else
- bss->wpa_group = WPA_CIPHER_CCMP;
-
for (i = 0; i < conf->num_bss; i++) {
bss = &conf->bss[i];
+ if (bss->individual_wep_key_len == 0) {
+ /* individual keys are not use; can use key idx0 for
+ * broadcast keys */
+ bss->broadcast_key_idx_min = 0;
+ }
+
+ /* Select group cipher based on the enabled pairwise cipher
+ * suites */
+ pairwise = 0;
+ if (bss->wpa & 1)
+ pairwise |= bss->wpa_pairwise;
+ if (bss->wpa & 2) {
+ if (bss->rsn_pairwise == 0)
+ bss->rsn_pairwise = bss->wpa_pairwise;
+ pairwise |= bss->rsn_pairwise;
+ }
+ if (pairwise & WPA_CIPHER_TKIP)
+ bss->wpa_group = WPA_CIPHER_TKIP;
+ else
+ bss->wpa_group = WPA_CIPHER_CCMP;
+
bss->radius->auth_server = bss->radius->auth_servers;
bss->radius->acct_server = bss->radius->acct_servers;
@@ -2476,6 +2479,8 @@ void hostapd_config_free(struct hostapd_config *conf)
for (i = 0; i < conf->num_bss; i++)
hostapd_config_free_bss(&conf->bss[i]);
os_free(conf->bss);
+ os_free(conf->supported_rates);
+ os_free(conf->basic_rates);
os_free(conf);
}
diff --git a/contrib/wpa/hostapd/config.h b/contrib/wpa/hostapd/config.h
index a3247f2..ea530d4 100644
--- a/contrib/wpa/hostapd/config.h
+++ b/contrib/wpa/hostapd/config.h
@@ -135,11 +135,11 @@ struct hostapd_tx_queue_params {
int configured;
};
-struct hostapd_wme_ac_params {
+struct hostapd_wmm_ac_params {
int cwmin;
int cwmax;
int aifs;
- int txopLimit; /* in units of 32us */
+ int txop_limit; /* in units of 32us */
int admission_control_mandatory;
};
@@ -271,7 +271,7 @@ struct hostapd_bss_config {
int ap_max_inactivity;
int ignore_broadcast_ssid;
- int wme_enabled;
+ int wmm_enabled;
struct hostapd_vlan *vlan, *vlan_tail;
@@ -371,13 +371,13 @@ struct hostapd_config {
struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES];
/*
- * WME AC parameters, in same order as 802.1D, i.e.
+ * WMM AC parameters, in same order as 802.1D, i.e.
* 0 = BE (best effort)
* 1 = BK (background)
* 2 = VI (video)
* 3 = VO (voice)
*/
- struct hostapd_wme_ac_params wme_ac_params[4];
+ struct hostapd_wmm_ac_params wmm_ac_params[4];
enum {
INTERNAL_BRIDGE_DO_NOT_CONTROL = -1,
diff --git a/contrib/wpa/hostapd/ctrl_iface.c b/contrib/wpa/hostapd/ctrl_iface.c
index fe63e7c..9dec724 100644
--- a/contrib/wpa/hostapd/ctrl_iface.c
+++ b/contrib/wpa/hostapd/ctrl_iface.c
@@ -18,6 +18,7 @@
#include <sys/un.h>
#include <sys/stat.h>
+#include <stddef.h>
#include "hostapd.h"
#include "eloop.h"
@@ -60,7 +61,8 @@ static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
dst->next = hapd->ctrl_dst;
hapd->ctrl_dst = dst;
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
- (u8 *) from->sun_path, fromlen);
+ (u8 *) from->sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path));
return 0;
}
@@ -74,15 +76,18 @@ static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
dst = hapd->ctrl_dst;
while (dst) {
if (fromlen == dst->addrlen &&
- os_memcmp(from->sun_path, dst->addr.sun_path, fromlen) ==
- 0) {
+ os_memcmp(from->sun_path, dst->addr.sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path))
+ == 0) {
if (prev == NULL)
hapd->ctrl_dst = dst->next;
else
prev->next = dst->next;
os_free(dst);
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
- (u8 *) from->sun_path, fromlen);
+ (u8 *) from->sun_path,
+ fromlen -
+ offsetof(struct sockaddr_un, sun_path));
return 0;
}
prev = dst;
@@ -104,10 +109,12 @@ static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
dst = hapd->ctrl_dst;
while (dst) {
if (fromlen == dst->addrlen &&
- os_memcmp(from->sun_path, dst->addr.sun_path, fromlen) ==
- 0) {
+ os_memcmp(from->sun_path, dst->addr.sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path))
+ == 0) {
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
- "level", (u8 *) from->sun_path, fromlen);
+ "level", (u8 *) from->sun_path, fromlen -
+ offsetof(struct sockaddr_un, sun_path));
dst->debug_level = atoi(level);
return 0;
}
@@ -246,10 +253,21 @@ static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
{
char *pin = os_strchr(txt, ' ');
+ char *timeout_txt;
+ int timeout;
+
if (pin == NULL)
return -1;
*pin++ = '\0';
- return hostapd_wps_add_pin(hapd, txt, pin);
+
+ timeout_txt = os_strchr(pin, ' ');
+ if (timeout_txt) {
+ *timeout_txt++ = '\0';
+ timeout = atoi(timeout_txt);
+ } else
+ timeout = 0;
+
+ return hostapd_wps_add_pin(hapd, txt, pin, timeout);
}
#endif /* CONFIG_WPS */
@@ -434,14 +452,44 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
}
os_memset(&addr, 0, sizeof(addr));
+#ifdef __FreeBSD__
+ addr.sun_len = sizeof(addr);
+#endif /* __FreeBSD__ */
addr.sun_family = AF_UNIX;
fname = hostapd_ctrl_iface_path(hapd);
if (fname == NULL)
goto fail;
os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- perror("bind(PF_UNIX)");
- goto fail;
+ wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
+ strerror(errno));
+ if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
+ " allow connections - assuming it was left"
+ "over from forced program termination");
+ if (unlink(fname) < 0) {
+ perror("unlink[ctrl_iface]");
+ wpa_printf(MSG_ERROR, "Could not unlink "
+ "existing ctrl_iface socket '%s'",
+ fname);
+ goto fail;
+ }
+ if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
+ 0) {
+ perror("bind(PF_UNIX)");
+ goto fail;
+ }
+ wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
+ "ctrl_iface socket '%s'", fname);
+ } else {
+ wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
+ "be in use - cannot override it");
+ wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
+ "not used anymore", fname);
+ os_free(fname);
+ fname = NULL;
+ goto fail;
+ }
}
if (hapd->conf->ctrl_interface_gid_set &&
@@ -536,15 +584,17 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
next = dst->next;
if (level >= dst->debug_level) {
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
- (u8 *) dst->addr.sun_path, dst->addrlen);
+ (u8 *) dst->addr.sun_path, dst->addrlen -
+ offsetof(struct sockaddr_un, sun_path));
msg.msg_name = &dst->addr;
msg.msg_namelen = dst->addrlen;
if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
- fprintf(stderr, "CTRL_IFACE monitor[%d]: ",
- idx);
- perror("sendmsg");
+ int _errno = errno;
+ wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
+ "%d - %s",
+ idx, errno, strerror(errno));
dst->errors++;
- if (dst->errors > 10) {
+ if (dst->errors > 10 || _errno == ENOENT) {
hostapd_ctrl_iface_detach(
hapd, &dst->addr,
dst->addrlen);
diff --git a/contrib/wpa/hostapd/doc/.gitignore b/contrib/wpa/hostapd/doc/.gitignore
deleted file mode 100644
index 987a5e9..0000000
--- a/contrib/wpa/hostapd/doc/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-html
-latex
-hostapd.eps
-hostapd.png
diff --git a/contrib/wpa/hostapd/driver_bsd.c b/contrib/wpa/hostapd/driver_bsd.c
new file mode 100644
index 0000000..43d57d9
--- /dev/null
+++ b/contrib/wpa/hostapd/driver_bsd.c
@@ -0,0 +1,839 @@
+/*
+ * hostapd / Driver interaction with BSD net80211 layer
+ * Copyright (c) 2004, Sam Leffler <sam@errno.com>
+ * Copyright (c) 2004, 2Wire, 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.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+
+#include <net80211/ieee80211.h>
+#include <net80211/ieee80211_crypto.h>
+#include <net80211/ieee80211_ioctl.h>
+
+/*
+ * Avoid conflicts with hostapd definitions by undefining couple of defines
+ * from net80211 header files.
+ */
+#undef RSN_VERSION
+#undef WPA_VERSION
+#undef WPA_OUI_TYPE
+#undef WME_OUI_TYPE
+
+#include "hostapd.h"
+#include "driver.h"
+#include "ieee802_1x.h"
+#include "eloop.h"
+#include "sta_info.h"
+#include "l2_packet/l2_packet.h"
+
+#include "eapol_sm.h"
+#include "wpa.h"
+#include "radius/radius.h"
+#include "ieee802_11.h"
+#include "common.h"
+
+struct bsd_driver_data {
+ struct hostapd_data *hapd; /* back pointer */
+
+ char iface[IFNAMSIZ + 1];
+ struct l2_packet_data *sock_xmit; /* raw packet xmit socket */
+ int ioctl_sock; /* socket for ioctl() use */
+ int wext_sock; /* socket for wireless events */
+};
+
+static int bsd_sta_deauth(void *priv, const u8 *addr, int reason_code);
+
+static int
+set80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len)
+{
+ struct ieee80211req ireq;
+
+ memset(&ireq, 0, sizeof(ireq));
+ os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ);
+ ireq.i_type = op;
+ ireq.i_len = arg_len;
+ ireq.i_data = (void *) arg;
+
+ if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) {
+ perror("ioctl[SIOCS80211]");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+get80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len)
+{
+ struct ieee80211req ireq;
+
+ memset(&ireq, 0, sizeof(ireq));
+ os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ);
+ ireq.i_type = op;
+ ireq.i_len = arg_len;
+ ireq.i_data = arg;
+
+ if (ioctl(drv->ioctl_sock, SIOCG80211, &ireq) < 0) {
+ perror("ioctl[SIOCG80211]");
+ return -1;
+ }
+ return ireq.i_len;
+}
+
+static int
+set80211param(struct bsd_driver_data *drv, int op, int arg)
+{
+ struct ieee80211req ireq;
+
+ memset(&ireq, 0, sizeof(ireq));
+ os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ);
+ ireq.i_type = op;
+ ireq.i_val = arg;
+
+ if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) {
+ perror("ioctl[SIOCS80211]");
+ return -1;
+ }
+ return 0;
+}
+
+static const char *
+ether_sprintf(const u8 *addr)
+{
+ static char buf[sizeof(MACSTR)];
+
+ if (addr != NULL)
+ snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
+ else
+ snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0);
+ return buf;
+}
+
+/*
+ * Configure WPA parameters.
+ */
+static int
+bsd_configure_wpa(struct bsd_driver_data *drv)
+{
+ static const char *ciphernames[] =
+ { "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" };
+ struct hostapd_data *hapd = drv->hapd;
+ struct hostapd_bss_config *conf = hapd->conf;
+ int v;
+
+ switch (conf->wpa_group) {
+ case WPA_CIPHER_CCMP:
+ v = IEEE80211_CIPHER_AES_CCM;
+ break;
+ case WPA_CIPHER_TKIP:
+ v = IEEE80211_CIPHER_TKIP;
+ break;
+ case WPA_CIPHER_WEP104:
+ v = IEEE80211_CIPHER_WEP;
+ break;
+ case WPA_CIPHER_WEP40:
+ v = IEEE80211_CIPHER_WEP;
+ break;
+ case WPA_CIPHER_NONE:
+ v = IEEE80211_CIPHER_NONE;
+ break;
+ default:
+ printf("Unknown group key cipher %u\n",
+ conf->wpa_group);
+ return -1;
+ }
+ wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)",
+ __func__, ciphernames[v], v);
+ if (set80211param(drv, IEEE80211_IOC_MCASTCIPHER, v)) {
+ printf("Unable to set group key cipher to %u (%s)\n",
+ v, ciphernames[v]);
+ return -1;
+ }
+ if (v == IEEE80211_CIPHER_WEP) {
+ /* key length is done only for specific ciphers */
+ v = (conf->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5);
+ if (set80211param(drv, IEEE80211_IOC_MCASTKEYLEN, v)) {
+ printf("Unable to set group key length to %u\n", v);
+ return -1;
+ }
+ }
+
+ v = 0;
+ if (conf->wpa_pairwise & WPA_CIPHER_CCMP)
+ v |= 1<<IEEE80211_CIPHER_AES_CCM;
+ if (conf->wpa_pairwise & WPA_CIPHER_TKIP)
+ v |= 1<<IEEE80211_CIPHER_TKIP;
+ if (conf->wpa_pairwise & WPA_CIPHER_NONE)
+ v |= 1<<IEEE80211_CIPHER_NONE;
+ wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v);
+ if (set80211param(drv, IEEE80211_IOC_UCASTCIPHERS, v)) {
+ printf("Unable to set pairwise key ciphers to 0x%x\n", v);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x",
+ __func__, conf->wpa_key_mgmt);
+ if (set80211param(drv, IEEE80211_IOC_KEYMGTALGS, conf->wpa_key_mgmt)) {
+ printf("Unable to set key management algorithms to 0x%x\n",
+ conf->wpa_key_mgmt);
+ return -1;
+ }
+
+ v = 0;
+ if (conf->rsn_preauth)
+ v |= BIT(0);
+ wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x",
+ __func__, conf->rsn_preauth);
+ if (set80211param(drv, IEEE80211_IOC_RSNCAPS, v)) {
+ printf("Unable to set RSN capabilities to 0x%x\n", v);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, conf->wpa);
+ if (set80211param(drv, IEEE80211_IOC_WPA, conf->wpa)) {
+ printf("Unable to set WPA to %u\n", conf->wpa);
+ return -1;
+ }
+ return 0;
+}
+
+
+static int
+bsd_set_iface_flags(void *priv, int dev_up)
+{
+ struct bsd_driver_data *drv = priv;
+ struct ifreq ifr;
+
+ wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up);
+
+ if (drv->ioctl_sock < 0)
+ return -1;
+
+ memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
+
+ if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
+ perror("ioctl[SIOCGIFFLAGS]");
+ return -1;
+ }
+
+ if (dev_up)
+ ifr.ifr_flags |= IFF_UP;
+ else
+ ifr.ifr_flags &= ~IFF_UP;
+
+ if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {
+ perror("ioctl[SIOCSIFFLAGS]");
+ return -1;
+ }
+
+ if (dev_up) {
+ memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
+ ifr.ifr_mtu = HOSTAPD_MTU;
+ if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {
+ perror("ioctl[SIOCSIFMTU]");
+ printf("Setting MTU failed - trying to survive with "
+ "current value\n");
+ }
+ }
+
+ return 0;
+}
+
+static int
+bsd_set_ieee8021x(const char *ifname, void *priv, int enabled)
+{
+ struct bsd_driver_data *drv = priv;
+ struct hostapd_data *hapd = drv->hapd;
+ struct hostapd_bss_config *conf = hapd->conf;
+
+ wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
+
+ if (!enabled) {
+ /* XXX restore state */
+ return set80211param(priv, IEEE80211_IOC_AUTHMODE,
+ IEEE80211_AUTH_AUTO);
+ }
+ if (!conf->wpa && !conf->ieee802_1x) {
+ hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
+ HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!");
+ return -1;
+ }
+ if (conf->wpa && bsd_configure_wpa(drv) != 0) {
+ hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
+ HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!");
+ return -1;
+ }
+ if (set80211param(priv, IEEE80211_IOC_AUTHMODE,
+ (conf->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) {
+ hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
+ HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!");
+ return -1;
+ }
+ return bsd_set_iface_flags(priv, 1);
+}
+
+static int
+bsd_set_privacy(const char *ifname, void *priv, int enabled)
+{
+ struct bsd_driver_data *drv = priv;
+
+ wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
+
+ return set80211param(drv, IEEE80211_IOC_PRIVACY, enabled);
+}
+
+static int
+bsd_set_sta_authorized(void *priv, const u8 *addr, int authorized)
+{
+ struct bsd_driver_data *drv = priv;
+ struct ieee80211req_mlme mlme;
+
+ wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d",
+ __func__, ether_sprintf(addr), authorized);
+
+ if (authorized)
+ mlme.im_op = IEEE80211_MLME_AUTHORIZE;
+ else
+ mlme.im_op = IEEE80211_MLME_UNAUTHORIZE;
+ mlme.im_reason = 0;
+ memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
+ return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
+}
+
+static int
+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)
+ return bsd_set_sta_authorized(priv, addr, 1);
+ if (!(flags_and & WLAN_STA_AUTHORIZED))
+ return bsd_set_sta_authorized(priv, addr, 0);
+ return 0;
+}
+
+static int
+bsd_del_key(void *priv, const u8 *addr, int key_idx)
+{
+ struct bsd_driver_data *drv = priv;
+ struct ieee80211req_del_key wk;
+
+ wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d",
+ __func__, ether_sprintf(addr), key_idx);
+
+ memset(&wk, 0, sizeof(wk));
+ if (addr != NULL) {
+ memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
+ wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */
+ } else {
+ wk.idk_keyix = key_idx;
+ }
+
+ return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
+}
+
+static int
+bsd_set_key(const char *ifname, void *priv, const char *alg,
+ const u8 *addr, int key_idx,
+ const u8 *key, size_t key_len, int txkey)
+{
+ struct bsd_driver_data *drv = priv;
+ struct ieee80211req_key wk;
+ u_int8_t cipher;
+
+ if (strcmp(alg, "none") == 0)
+ return bsd_del_key(drv, addr, key_idx);
+
+ wpa_printf(MSG_DEBUG, "%s: alg=%s addr=%s key_idx=%d",
+ __func__, alg, ether_sprintf(addr), key_idx);
+
+ if (strcmp(alg, "WEP") == 0)
+ cipher = IEEE80211_CIPHER_WEP;
+ else if (strcmp(alg, "TKIP") == 0)
+ cipher = IEEE80211_CIPHER_TKIP;
+ else if (strcmp(alg, "CCMP") == 0)
+ cipher = IEEE80211_CIPHER_AES_CCM;
+ else {
+ printf("%s: unknown/unsupported algorithm %s\n",
+ __func__, alg);
+ return -1;
+ }
+
+ if (key_len > sizeof(wk.ik_keydata)) {
+ printf("%s: key length %d too big\n", __func__, key_len);
+ return -3;
+ }
+
+ memset(&wk, 0, sizeof(wk));
+ wk.ik_type = cipher;
+ wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;
+ if (addr == NULL) {
+ memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
+ wk.ik_keyix = key_idx;
+ wk.ik_flags |= IEEE80211_KEY_DEFAULT;
+ } else {
+ memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
+ wk.ik_keyix = IEEE80211_KEYIX_NONE;
+ }
+ wk.ik_keylen = key_len;
+ memcpy(wk.ik_keydata, key, key_len);
+
+ return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
+}
+
+
+static int
+bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
+ u8 *seq)
+{
+ struct bsd_driver_data *drv = priv;
+ struct ieee80211req_key wk;
+
+ wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d",
+ __func__, ether_sprintf(addr), idx);
+
+ memset(&wk, 0, sizeof(wk));
+ if (addr == NULL)
+ memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
+ else
+ memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
+ wk.ik_keyix = idx;
+
+ if (get80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) {
+ printf("Failed to get encryption.\n");
+ return -1;
+ }
+
+#ifdef WORDS_BIGENDIAN
+ {
+ /*
+ * wk.ik_keytsc is in host byte order (big endian), need to
+ * swap it to match with the byte order used in WPA.
+ */
+ int i;
+ u8 tmp[WPA_KEY_RSC_LEN];
+ memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
+ for (i = 0; i < WPA_KEY_RSC_LEN; i++) {
+ seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1];
+ }
+ }
+#else /* WORDS_BIGENDIAN */
+ memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
+#endif /* WORDS_BIGENDIAN */
+ return 0;
+}
+
+
+static int
+bsd_flush(void *priv)
+{
+ u8 allsta[IEEE80211_ADDR_LEN];
+
+ memset(allsta, 0xff, IEEE80211_ADDR_LEN);
+ return bsd_sta_deauth(priv, allsta, IEEE80211_REASON_AUTH_LEAVE);
+}
+
+
+static int
+bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data,
+ const u8 *addr)
+{
+ struct bsd_driver_data *drv = priv;
+ struct ieee80211req_sta_stats stats;
+
+ memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN);
+ if (get80211var(drv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)) > 0) {
+ /* XXX? do packets counts include non-data frames? */
+ data->rx_packets = stats.is_stats.ns_rx_data;
+ data->rx_bytes = stats.is_stats.ns_rx_bytes;
+ data->tx_packets = stats.is_stats.ns_tx_data;
+ data->tx_bytes = stats.is_stats.ns_tx_bytes;
+ }
+ return 0;
+}
+
+static int
+bsd_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len)
+{
+ /*
+ * Do nothing; we setup parameters at startup that define the
+ * contents of the beacon information element.
+ */
+ return 0;
+}
+
+static int
+bsd_sta_deauth(void *priv, const u8 *addr, int reason_code)
+{
+ struct bsd_driver_data *drv = priv;
+ struct ieee80211req_mlme mlme;
+
+ wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d",
+ __func__, ether_sprintf(addr), reason_code);
+
+ mlme.im_op = IEEE80211_MLME_DEAUTH;
+ mlme.im_reason = reason_code;
+ memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
+ return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
+}
+
+static int
+bsd_sta_disassoc(void *priv, const u8 *addr, int reason_code)
+{
+ struct bsd_driver_data *drv = priv;
+ struct ieee80211req_mlme mlme;
+
+ wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d",
+ __func__, ether_sprintf(addr), reason_code);
+
+ mlme.im_op = IEEE80211_MLME_DISASSOC;
+ mlme.im_reason = reason_code;
+ memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
+ return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
+}
+
+static int
+bsd_del_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
+{
+ struct hostapd_data *hapd = drv->hapd;
+ struct hostapd_bss_config *conf = hapd->conf;
+ struct sta_info *sta;
+
+ hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_INFO, "deassociated");
+
+ sta = ap_get_sta(hapd, addr);
+ if (sta != NULL) {
+ sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+ if (conf->wpa)
+ wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
+ sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
+ ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
+ ap_free_sta(hapd, sta);
+ }
+ return 0;
+}
+
+static int
+bsd_new_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
+{
+ struct hostapd_data *hapd = drv->hapd;
+ struct hostapd_bss_config *conf = hapd->conf;
+ struct sta_info *sta;
+ struct ieee80211req_wpaie ie;
+ int new_assoc, ielen, res;
+
+ hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_INFO, "associated");
+
+ sta = ap_sta_add(hapd, addr);
+ if (sta == NULL)
+ return -1;
+ /*
+ * Fetch and validate any negotiated WPA/RSN parameters.
+ */
+ if (conf->wpa) {
+ memset(&ie, 0, sizeof(ie));
+ memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
+ if (get80211var(drv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) {
+ printf("Failed to get WPA/RSN information element.\n");
+ return -1; /* XXX not right */
+ }
+ ielen = ie.wpa_ie[1];
+ if (ielen == 0) {
+ printf("No WPA/RSN information element for station!\n");
+ return -1; /* XXX not right */
+ }
+ ielen += 2;
+ if (sta->wpa_sm == NULL)
+ sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
+ sta->addr);
+ if (sta->wpa_sm == NULL) {
+ printf("Failed to initialize WPA state machine\n");
+ return -1;
+ }
+ res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
+ ie.wpa_ie, ielen, NULL, 0);
+ if (res != WPA_IE_OK) {
+ printf("WPA/RSN information element rejected? "
+ "(res %u)\n", res);
+ return -1;
+ }
+ }
+
+ /*
+ * Now that the internal station state is setup
+ * kick the authenticator into action.
+ */
+ new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
+ sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
+ wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
+ hostapd_new_assoc_sta(hapd, sta, !new_assoc);
+ ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
+ return 0;
+}
+
+#include <net/route.h>
+#include <net80211/ieee80211_freebsd.h>
+
+static void
+bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
+{
+ struct bsd_driver_data *drv = ctx;
+ struct hostapd_data *hapd = drv->hapd;
+ char buf[2048];
+ struct if_announcemsghdr *ifan;
+ struct rt_msghdr *rtm;
+ struct ieee80211_michael_event *mic;
+ struct ieee80211_join_event *join;
+ struct ieee80211_leave_event *leave;
+ int n;
+
+ n = read(sock, buf, sizeof(buf));
+ if (n < 0) {
+ if (errno != EINTR && errno != EAGAIN)
+ perror("read(PF_ROUTE)");
+ return;
+ }
+
+ rtm = (struct rt_msghdr *) buf;
+ if (rtm->rtm_version != RTM_VERSION) {
+ wpa_printf(MSG_DEBUG, "Routing message version %d not "
+ "understood\n", rtm->rtm_version);
+ return;
+ }
+ ifan = (struct if_announcemsghdr *) rtm;
+ switch (rtm->rtm_type) {
+ case RTM_IEEE80211:
+ switch (ifan->ifan_what) {
+ case RTM_IEEE80211_ASSOC:
+ case RTM_IEEE80211_REASSOC:
+ case RTM_IEEE80211_DISASSOC:
+ case RTM_IEEE80211_SCAN:
+ break;
+ case RTM_IEEE80211_LEAVE:
+ leave = (struct ieee80211_leave_event *) &ifan[1];
+ bsd_del_sta(drv, leave->iev_addr);
+ break;
+ case RTM_IEEE80211_JOIN:
+#ifdef RTM_IEEE80211_REJOIN
+ case RTM_IEEE80211_REJOIN:
+#endif
+ join = (struct ieee80211_join_event *) &ifan[1];
+ bsd_new_sta(drv, join->iev_addr);
+ break;
+ case RTM_IEEE80211_REPLAY:
+ /* ignore */
+ break;
+ case RTM_IEEE80211_MICHAEL:
+ mic = (struct ieee80211_michael_event *) &ifan[1];
+ wpa_printf(MSG_DEBUG,
+ "Michael MIC failure wireless event: "
+ "keyix=%u src_addr=" MACSTR, mic->iev_keyix,
+ MAC2STR(mic->iev_src));
+ ieee80211_michael_mic_failure(hapd, mic->iev_src, 1);
+ break;
+ }
+ break;
+ }
+}
+
+static int
+bsd_wireless_event_init(void *priv)
+{
+ struct bsd_driver_data *drv = priv;
+ int s;
+
+ drv->wext_sock = -1;
+
+ s = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (s < 0) {
+ perror("socket(PF_ROUTE,SOCK_RAW)");
+ return -1;
+ }
+ eloop_register_read_sock(s, bsd_wireless_event_receive, drv, NULL);
+ drv->wext_sock = s;
+
+ return 0;
+}
+
+static void
+bsd_wireless_event_deinit(void *priv)
+{
+ struct bsd_driver_data *drv = priv;
+
+ if (drv != NULL) {
+ if (drv->wext_sock < 0)
+ return;
+ eloop_unregister_read_sock(drv->wext_sock);
+ close(drv->wext_sock);
+ }
+}
+
+
+static int
+bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
+ int encrypt, const u8 *own_addr)
+{
+ struct bsd_driver_data *drv = priv;
+ unsigned char buf[3000];
+ unsigned char *bp = buf;
+ struct l2_ethhdr *eth;
+ size_t len;
+ int status;
+
+ /*
+ * Prepend the Etherent header. If the caller left us
+ * space at the front we could just insert it but since
+ * we don't know we copy to a local buffer. Given the frequency
+ * and size of frames this probably doesn't matter.
+ */
+ len = data_len + sizeof(struct l2_ethhdr);
+ if (len > sizeof(buf)) {
+ bp = malloc(len);
+ if (bp == NULL) {
+ printf("EAPOL frame discarded, cannot malloc temp "
+ "buffer of size %u!\n", len);
+ return -1;
+ }
+ }
+ eth = (struct l2_ethhdr *) bp;
+ memcpy(eth->h_dest, addr, ETH_ALEN);
+ memcpy(eth->h_source, own_addr, ETH_ALEN);
+ eth->h_proto = htons(ETH_P_EAPOL);
+ memcpy(eth+1, data, data_len);
+
+ wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len);
+
+ status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len);
+
+ if (bp != buf)
+ free(bp);
+ return status;
+}
+
+static void
+handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
+{
+ struct bsd_driver_data *drv = ctx;
+ struct hostapd_data *hapd = drv->hapd;
+ struct sta_info *sta;
+
+ sta = ap_get_sta(hapd, src_addr);
+ if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
+ printf("Data frame from not associated STA %s\n",
+ ether_sprintf(src_addr));
+ /* XXX cannot happen */
+ return;
+ }
+ ieee802_1x_receive(hapd, src_addr, buf + sizeof(struct l2_ethhdr),
+ len - sizeof(struct l2_ethhdr));
+}
+
+static int
+bsd_get_ssid(const char *ifname, void *priv, u8 *buf, int len)
+{
+ struct bsd_driver_data *drv = priv;
+ int ssid_len = get80211var(drv, IEEE80211_IOC_SSID, buf, len);
+
+ wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, ssid_len, buf);
+
+ return ssid_len;
+}
+
+static int
+bsd_set_ssid(const char *ifname, void *priv, const u8 *buf, int len)
+{
+ struct bsd_driver_data *drv = priv;
+
+ wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, len, buf);
+
+ return set80211var(drv, IEEE80211_IOC_SSID, buf, len);
+}
+
+static void *
+bsd_init(struct hostapd_data *hapd)
+{
+ struct bsd_driver_data *drv;
+
+ drv = os_zalloc(sizeof(struct bsd_driver_data));
+ if (drv == NULL) {
+ printf("Could not allocate memory for bsd driver data\n");
+ goto bad;
+ }
+
+ drv->hapd = hapd;
+ drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
+ if (drv->ioctl_sock < 0) {
+ perror("socket[PF_INET,SOCK_DGRAM]");
+ goto bad;
+ }
+ memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
+
+ drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL,
+ handle_read, drv, 1);
+ if (drv->sock_xmit == NULL)
+ goto bad;
+ if (l2_packet_get_own_addr(drv->sock_xmit, hapd->own_addr))
+ goto bad;
+
+ bsd_set_iface_flags(drv, 0); /* mark down during setup */
+
+ return drv;
+bad:
+ if (drv->sock_xmit != NULL)
+ l2_packet_deinit(drv->sock_xmit);
+ if (drv->ioctl_sock >= 0)
+ close(drv->ioctl_sock);
+ if (drv != NULL)
+ free(drv);
+ return NULL;
+}
+
+
+static void
+bsd_deinit(void *priv)
+{
+ struct bsd_driver_data *drv = priv;
+
+ (void) bsd_set_iface_flags(drv, 0);
+ if (drv->ioctl_sock >= 0)
+ close(drv->ioctl_sock);
+ if (drv->sock_xmit != NULL)
+ l2_packet_deinit(drv->sock_xmit);
+ free(drv);
+}
+
+const struct wpa_driver_ops wpa_driver_bsd_ops = {
+ .name = "bsd",
+ .init = bsd_init,
+ .deinit = bsd_deinit,
+ .set_ieee8021x = bsd_set_ieee8021x,
+ .set_privacy = bsd_set_privacy,
+ .set_encryption = bsd_set_key,
+ .get_seqnum = bsd_get_seqnum,
+ .flush = bsd_flush,
+ .set_generic_elem = bsd_set_opt_ie,
+ .wireless_event_init = bsd_wireless_event_init,
+ .wireless_event_deinit = bsd_wireless_event_deinit,
+ .sta_set_flags = bsd_sta_set_flags,
+ .read_sta_data = bsd_read_sta_driver_data,
+ .send_eapol = bsd_send_eapol,
+ .sta_disassoc = bsd_sta_disassoc,
+ .sta_deauth = bsd_sta_deauth,
+ .set_ssid = bsd_set_ssid,
+ .get_ssid = bsd_get_ssid,
+};
diff --git a/contrib/wpa/hostapd/driver_hostap.c b/contrib/wpa/hostapd/driver_hostap.c
new file mode 100644
index 0000000..ceff099
--- /dev/null
+++ b/contrib/wpa/hostapd/driver_hostap.c
@@ -0,0 +1,1279 @@
+/*
+ * hostapd / Kernel driver communication with Linux Host AP driver
+ * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ *
+ * 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.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+#include <sys/ioctl.h>
+
+#ifdef USE_KERNEL_HEADERS
+/* compat-wireless does not include linux/compiler.h to define __user, so
+ * define it here */
+#ifndef __user
+#define __user
+#endif /* __user */
+#include <asm/types.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h> /* The L2 protocols */
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+#else /* USE_KERNEL_HEADERS */
+#include <net/if_arp.h>
+#include <netpacket/packet.h>
+#include "wireless_copy.h"
+#endif /* USE_KERNEL_HEADERS */
+
+#include "hostapd.h"
+#include "driver.h"
+#include "ieee802_1x.h"
+#include "eloop.h"
+#include "priv_netlink.h"
+#include "ieee802_11.h"
+#include "sta_info.h"
+#include "hostap_common.h"
+#include "hw_features.h"
+
+
+struct hostap_driver_data {
+ struct hostapd_data *hapd;
+
+ char iface[IFNAMSIZ + 1];
+ int sock; /* raw packet socket for driver access */
+ int ioctl_sock; /* socket for ioctl() use */
+ int wext_sock; /* socket for wireless events */
+
+ int we_version;
+
+ u8 *generic_ie;
+ size_t generic_ie_len;
+ u8 *wps_ie;
+ size_t wps_ie_len;
+};
+
+
+static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param,
+ int len);
+static int hostap_set_iface_flags(void *priv, int dev_up);
+
+static void handle_data(struct hostapd_data *hapd, u8 *buf, size_t len,
+ u16 stype)
+{
+ struct ieee80211_hdr *hdr;
+ u16 fc, ethertype;
+ u8 *pos, *sa;
+ size_t left;
+ struct sta_info *sta;
+
+ if (len < sizeof(struct ieee80211_hdr))
+ return;
+
+ hdr = (struct ieee80211_hdr *) buf;
+ fc = le_to_host16(hdr->frame_control);
+
+ if ((fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) != WLAN_FC_TODS) {
+ printf("Not ToDS data frame (fc=0x%04x)\n", fc);
+ return;
+ }
+
+ sa = hdr->addr2;
+ sta = ap_get_sta(hapd, sa);
+ if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
+ printf("Data frame from not associated STA " MACSTR "\n",
+ MAC2STR(sa));
+ if (sta && (sta->flags & WLAN_STA_AUTH))
+ hostapd_sta_disassoc(
+ hapd, sa,
+ WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+ else
+ hostapd_sta_deauth(
+ hapd, sa,
+ WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+ return;
+ }
+
+ pos = (u8 *) (hdr + 1);
+ left = len - sizeof(*hdr);
+
+ if (left < sizeof(rfc1042_header)) {
+ printf("Too short data frame\n");
+ return;
+ }
+
+ if (memcmp(pos, rfc1042_header, sizeof(rfc1042_header)) != 0) {
+ printf("Data frame with no RFC1042 header\n");
+ return;
+ }
+ pos += sizeof(rfc1042_header);
+ left -= sizeof(rfc1042_header);
+
+ if (left < 2) {
+ printf("No ethertype in data frame\n");
+ return;
+ }
+
+ ethertype = WPA_GET_BE16(pos);
+ pos += 2;
+ left -= 2;
+ switch (ethertype) {
+ case ETH_P_PAE:
+ ieee802_1x_receive(hapd, sa, pos, left);
+ break;
+
+ default:
+ printf("Unknown ethertype 0x%04x in data frame\n", ethertype);
+ break;
+ }
+}
+
+
+static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len,
+ int ok)
+{
+ struct ieee80211_hdr *hdr;
+ u16 fc, type, stype;
+ struct sta_info *sta;
+
+ hdr = (struct ieee80211_hdr *) buf;
+ fc = le_to_host16(hdr->frame_control);
+
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+
+ switch (type) {
+ case WLAN_FC_TYPE_MGMT:
+ wpa_printf(MSG_DEBUG, "MGMT (TX callback) %s",
+ ok ? "ACK" : "fail");
+ ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
+ break;
+ case WLAN_FC_TYPE_CTRL:
+ wpa_printf(MSG_DEBUG, "CTRL (TX callback) %s",
+ ok ? "ACK" : "fail");
+ break;
+ case WLAN_FC_TYPE_DATA:
+ wpa_printf(MSG_DEBUG, "DATA (TX callback) %s",
+ ok ? "ACK" : "fail");
+ sta = ap_get_sta(hapd, hdr->addr1);
+ if (sta && sta->flags & WLAN_STA_PENDING_POLL) {
+ wpa_printf(MSG_DEBUG, "STA " MACSTR
+ " %s pending activity poll",
+ MAC2STR(sta->addr),
+ ok ? "ACKed" : "did not ACK");
+ if (ok)
+ sta->flags &= ~WLAN_STA_PENDING_POLL;
+ }
+ if (sta)
+ ieee802_1x_tx_status(hapd, sta, buf, len, ok);
+ break;
+ default:
+ printf("unknown TX callback frame type %d\n", type);
+ break;
+ }
+}
+
+
+static void handle_frame(struct hostapd_data *hapd, u8 *buf, size_t len)
+{
+ struct ieee80211_hdr *hdr;
+ u16 fc, extra_len, type, stype;
+ unsigned char *extra = NULL;
+ size_t data_len = len;
+ int ver;
+
+ /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass
+ * these to user space */
+ if (len < 24) {
+ wpa_printf(MSG_MSGDUMP, "handle_frame: too short (%lu)",
+ (unsigned long) len);
+ return;
+ }
+
+ hdr = (struct ieee80211_hdr *) buf;
+ fc = le_to_host16(hdr->frame_control);
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+
+ if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON) {
+ wpa_hexdump(MSG_MSGDUMP, "Received management frame",
+ buf, len);
+ }
+
+ ver = fc & WLAN_FC_PVER;
+
+ /* protocol version 3 is reserved for indicating extra data after the
+ * payload, version 2 for indicating ACKed frame (TX callbacks), and
+ * version 1 for indicating failed frame (no ACK, TX callbacks) */
+ if (ver == 3) {
+ u8 *pos = buf + len - 2;
+ extra_len = WPA_GET_LE16(pos);
+ printf("extra data in frame (elen=%d)\n", extra_len);
+ if ((size_t) extra_len + 2 > len) {
+ printf(" extra data overflow\n");
+ return;
+ }
+ len -= extra_len + 2;
+ extra = buf + len;
+ } else if (ver == 1 || ver == 2) {
+ handle_tx_callback(hapd, buf, data_len, ver == 2 ? 1 : 0);
+ return;
+ } else if (ver != 0) {
+ printf("unknown protocol version %d\n", ver);
+ return;
+ }
+
+ switch (type) {
+ case WLAN_FC_TYPE_MGMT:
+ if (stype != WLAN_FC_STYPE_BEACON)
+ wpa_printf(MSG_MSGDUMP, "MGMT");
+ ieee802_11_mgmt(hapd, buf, data_len, stype, NULL);
+ break;
+ case WLAN_FC_TYPE_CTRL:
+ wpa_printf(MSG_DEBUG, "CTRL");
+ break;
+ case WLAN_FC_TYPE_DATA:
+ wpa_printf(MSG_DEBUG, "DATA");
+ handle_data(hapd, buf, data_len, stype);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "unknown frame type %d", type);
+ break;
+ }
+}
+
+
+static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
+{
+ struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
+ int len;
+ unsigned char buf[3000];
+
+ len = recv(sock, buf, sizeof(buf), 0);
+ if (len < 0) {
+ perror("recv");
+ return;
+ }
+
+ handle_frame(hapd, buf, len);
+}
+
+
+static int hostap_init_sockets(struct hostap_driver_data *drv)
+{
+ struct ifreq ifr;
+ struct sockaddr_ll addr;
+
+ drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ if (drv->sock < 0) {
+ perror("socket[PF_PACKET,SOCK_RAW]");
+ return -1;
+ }
+
+ if (eloop_register_read_sock(drv->sock, handle_read, drv->hapd, NULL))
+ {
+ printf("Could not register read socket\n");
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface);
+ if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
+ perror("ioctl(SIOCGIFINDEX)");
+ return -1;
+ }
+
+ if (hostap_set_iface_flags(drv, 1)) {
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sll_family = AF_PACKET;
+ addr.sll_ifindex = ifr.ifr_ifindex;
+ wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
+ addr.sll_ifindex);
+
+ if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("bind");
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
+ if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
+ perror("ioctl(SIOCGIFHWADDR)");
+ return -1;
+ }
+
+ if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
+ printf("Invalid HW-addr family 0x%04x\n",
+ ifr.ifr_hwaddr.sa_family);
+ return -1;
+ }
+ memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+
+ return 0;
+}
+
+
+static int hostap_send_mgmt_frame(void *priv, const void *msg, size_t len,
+ int flags)
+{
+ struct hostap_driver_data *drv = priv;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg;
+ int res;
+
+ /* Request TX callback */
+ hdr->frame_control |= host_to_le16(BIT(1));
+ res = send(drv->sock, msg, len, flags);
+ hdr->frame_control &= ~host_to_le16(BIT(1));
+
+ return res;
+}
+
+
+static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data,
+ size_t data_len, int encrypt, const u8 *own_addr)
+{
+ struct hostap_driver_data *drv = priv;
+ struct ieee80211_hdr *hdr;
+ size_t len;
+ u8 *pos;
+ int res;
+
+ len = sizeof(*hdr) + sizeof(rfc1042_header) + 2 + data_len;
+ hdr = os_zalloc(len);
+ if (hdr == NULL) {
+ printf("malloc() failed for hostapd_send_data(len=%lu)\n",
+ (unsigned long) len);
+ return -1;
+ }
+
+ hdr->frame_control =
+ IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
+ hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
+ if (encrypt)
+ hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
+ memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
+ memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
+ memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
+
+ pos = (u8 *) (hdr + 1);
+ memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
+ pos += sizeof(rfc1042_header);
+ *((u16 *) pos) = htons(ETH_P_PAE);
+ pos += 2;
+ memcpy(pos, data, data_len);
+
+ res = hostap_send_mgmt_frame(drv, (u8 *) hdr, len, 0);
+ free(hdr);
+
+ if (res < 0) {
+ perror("hostapd_send_eapol: send");
+ printf("hostapd_send_eapol - packet len: %lu - failed\n",
+ (unsigned long) len);
+ }
+
+ return res;
+}
+
+
+static int hostap_sta_set_flags(void *priv, const u8 *addr,
+ int total_flags, int flags_or, int flags_and)
+{
+ struct hostap_driver_data *drv = priv;
+ struct prism2_hostapd_param param;
+
+ memset(&param, 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, &param, sizeof(param));
+}
+
+
+static int hostap_set_iface_flags(void *priv, int dev_up)
+{
+ struct hostap_driver_data *drv = priv;
+ struct ifreq ifr;
+
+ if (drv->ioctl_sock < 0)
+ return -1;
+
+ memset(&ifr, 0, sizeof(ifr));
+ snprintf(ifr.ifr_name, IFNAMSIZ, "%sap", drv->iface);
+
+ if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
+ perror("ioctl[SIOCGIFFLAGS]");
+ return -1;
+ }
+
+ if (dev_up)
+ ifr.ifr_flags |= IFF_UP;
+ else
+ ifr.ifr_flags &= ~IFF_UP;
+
+ if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {
+ perror("ioctl[SIOCSIFFLAGS]");
+ return -1;
+ }
+
+ if (dev_up) {
+ memset(&ifr, 0, sizeof(ifr));
+ snprintf(ifr.ifr_name, IFNAMSIZ, "%sap", drv->iface);
+ ifr.ifr_mtu = HOSTAPD_MTU;
+ if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {
+ perror("ioctl[SIOCSIFMTU]");
+ printf("Setting MTU failed - trying to survive with "
+ "current value\n");
+ }
+ }
+
+ return 0;
+}
+
+
+static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param,
+ int len)
+{
+ struct hostap_driver_data *drv = priv;
+ struct iwreq iwr;
+
+ memset(&iwr, 0, sizeof(iwr));
+ os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
+ iwr.u.data.pointer = (caddr_t) param;
+ iwr.u.data.length = len;
+
+ if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {
+ perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int hostap_set_encryption(const char *ifname, void *priv,
+ const char *alg, const u8 *addr,
+ int idx, const u8 *key, size_t key_len,
+ int txkey)
+{
+ struct hostap_driver_data *drv = priv;
+ struct prism2_hostapd_param *param;
+ u8 *buf;
+ size_t blen;
+ int ret = 0;
+
+ blen = sizeof(*param) + key_len;
+ buf = os_zalloc(blen);
+ if (buf == NULL)
+ return -1;
+
+ 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((u8 *) (param + 1), key, key_len);
+
+ if (hostapd_ioctl(drv, param, blen)) {
+ printf("Failed to set encryption.\n");
+ ret = -1;
+ }
+ free(buf);
+
+ return ret;
+}
+
+
+static int hostap_get_seqnum(const char *ifname, void *priv, const u8 *addr,
+ int idx, u8 *seq)
+{
+ struct hostap_driver_data *drv = priv;
+ struct prism2_hostapd_param *param;
+ u8 *buf;
+ size_t blen;
+ int ret = 0;
+
+ blen = sizeof(*param) + 32;
+ buf = os_zalloc(blen);
+ if (buf == NULL)
+ return -1;
+
+ param = (struct prism2_hostapd_param *) buf;
+ 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;
+
+ if (hostapd_ioctl(drv, param, blen)) {
+ printf("Failed to get encryption.\n");
+ ret = -1;
+ } else {
+ memcpy(seq, param->u.crypt.seq, 8);
+ }
+ free(buf);
+
+ return ret;
+}
+
+
+static int hostap_ioctl_prism2param(void *priv, int param, int value)
+{
+ struct hostap_driver_data *drv = priv;
+ struct iwreq iwr;
+ int *i;
+
+ memset(&iwr, 0, sizeof(iwr));
+ os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
+ i = (int *) iwr.u.name;
+ *i++ = param;
+ *i++ = value;
+
+ if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) {
+ perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int hostap_set_ieee8021x(const char *ifname, void *priv, int enabled)
+{
+ struct hostap_driver_data *drv = priv;
+
+ /* enable kernel driver support for IEEE 802.1X */
+ if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_IEEE_802_1X, enabled)) {
+ printf("Could not setup IEEE 802.1X support in kernel driver."
+ "\n");
+ return -1;
+ }
+
+ if (!enabled)
+ return 0;
+
+ /* use host driver implementation of encryption to allow
+ * individual keys and passing plaintext EAPOL frames */
+ if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_DECRYPT, 1) ||
+ hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_ENCRYPT, 1)) {
+ printf("Could not setup host-based encryption in kernel "
+ "driver.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int hostap_set_privacy(const char *ifname, void *priv, int enabled)
+{
+ struct hostap_drvier_data *drv = priv;
+
+ return hostap_ioctl_prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED,
+ enabled);
+}
+
+
+static int hostap_set_ssid(const char *ifname, void *priv, const u8 *buf,
+ int len)
+{
+ struct hostap_driver_data *drv = priv;
+ struct iwreq iwr;
+
+ memset(&iwr, 0, sizeof(iwr));
+ os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
+ iwr.u.essid.flags = 1; /* SSID active */
+ iwr.u.essid.pointer = (caddr_t) buf;
+ iwr.u.essid.length = len + 1;
+
+ if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
+ perror("ioctl[SIOCSIWESSID]");
+ printf("len=%d\n", len);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int hostap_flush(void *priv)
+{
+ struct hostap_driver_data *drv = priv;
+ struct prism2_hostapd_param param;
+
+ memset(&param, 0, sizeof(param));
+ param.cmd = PRISM2_HOSTAPD_FLUSH;
+ return hostapd_ioctl(drv, &param, sizeof(param));
+}
+
+
+static int hostap_read_sta_data(void *priv,
+ struct hostap_sta_driver_data *data,
+ const u8 *addr)
+{
+ struct hostap_driver_data *drv = priv;
+ char buf[1024], line[128], *pos;
+ FILE *f;
+ unsigned long val;
+
+ memset(data, 0, sizeof(*data));
+ snprintf(buf, sizeof(buf), "/proc/net/hostap/%s/" MACSTR,
+ drv->iface, MAC2STR(addr));
+
+ f = fopen(buf, "r");
+ if (!f)
+ return -1;
+ /* Need to read proc file with in one piece, so use large enough
+ * buffer. */
+ setbuffer(f, buf, sizeof(buf));
+
+ while (fgets(line, sizeof(line), f)) {
+ pos = strchr(line, '=');
+ if (!pos)
+ continue;
+ *pos++ = '\0';
+ val = strtoul(pos, NULL, 10);
+ if (strcmp(line, "rx_packets") == 0)
+ data->rx_packets = val;
+ else if (strcmp(line, "tx_packets") == 0)
+ data->tx_packets = val;
+ else if (strcmp(line, "rx_bytes") == 0)
+ data->rx_bytes = val;
+ else if (strcmp(line, "tx_bytes") == 0)
+ data->tx_bytes = val;
+ }
+
+ fclose(f);
+
+ return 0;
+}
+
+
+static int hostap_sta_add(const char *ifname, void *priv, const u8 *addr,
+ u16 aid, u16 capability, u8 *supp_rates,
+ size_t supp_rates_len, int flags,
+ u16 listen_interval)
+{
+ struct hostap_driver_data *drv = priv;
+ struct prism2_hostapd_param param;
+ int tx_supp_rates = 0;
+ size_t i;
+
+#define WLAN_RATE_1M BIT(0)
+#define WLAN_RATE_2M BIT(1)
+#define WLAN_RATE_5M5 BIT(2)
+#define WLAN_RATE_11M BIT(3)
+
+ for (i = 0; i < supp_rates_len; i++) {
+ if ((supp_rates[i] & 0x7f) == 2)
+ tx_supp_rates |= WLAN_RATE_1M;
+ if ((supp_rates[i] & 0x7f) == 4)
+ tx_supp_rates |= WLAN_RATE_2M;
+ if ((supp_rates[i] & 0x7f) == 11)
+ tx_supp_rates |= WLAN_RATE_5M5;
+ if ((supp_rates[i] & 0x7f) == 22)
+ tx_supp_rates |= WLAN_RATE_11M;
+ }
+
+ memset(&param, 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;
+ param.u.add_sta.tx_supp_rates = tx_supp_rates;
+ return hostapd_ioctl(drv, &param, sizeof(param));
+}
+
+
+static int hostap_sta_remove(void *priv, const u8 *addr)
+{
+ struct hostap_driver_data *drv = priv;
+ struct prism2_hostapd_param param;
+
+ hostap_sta_set_flags(drv, addr, 0, 0, ~WLAN_STA_AUTHORIZED);
+
+ memset(&param, 0, sizeof(param));
+ param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
+ memcpy(param.sta_addr, addr, ETH_ALEN);
+ if (hostapd_ioctl(drv, &param, sizeof(param))) {
+ printf("Could not remove station from kernel driver.\n");
+ return -1;
+ }
+ return 0;
+}
+
+
+static int hostap_get_inact_sec(void *priv, const u8 *addr)
+{
+ struct hostap_driver_data *drv = priv;
+ struct prism2_hostapd_param param;
+
+ memset(&param, 0, sizeof(param));
+ param.cmd = PRISM2_HOSTAPD_GET_INFO_STA;
+ memcpy(param.sta_addr, addr, ETH_ALEN);
+ if (hostapd_ioctl(drv, &param, sizeof(param))) {
+ return -1;
+ }
+
+ return param.u.get_info_sta.inactive_sec;
+}
+
+
+static int hostap_sta_clear_stats(void *priv, const u8 *addr)
+{
+ struct hostap_driver_data *drv = priv;
+ struct prism2_hostapd_param param;
+
+ memset(&param, 0, sizeof(param));
+ param.cmd = PRISM2_HOSTAPD_STA_CLEAR_STATS;
+ memcpy(param.sta_addr, addr, ETH_ALEN);
+ if (hostapd_ioctl(drv, &param, sizeof(param))) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int hostap_set_assoc_ap(void *priv, const u8 *addr)
+{
+ struct hostap_driver_data *drv = priv;
+ struct prism2_hostapd_param param;
+
+ memset(&param, 0, sizeof(param));
+ param.cmd = PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR;
+ memcpy(param.sta_addr, addr, ETH_ALEN);
+ if (hostapd_ioctl(drv, &param, sizeof(param)))
+ return -1;
+
+ return 0;
+}
+
+
+static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv)
+{
+ struct prism2_hostapd_param *param;
+ int res;
+ size_t blen, elem_len;
+
+ elem_len = drv->generic_ie_len + drv->wps_ie_len;
+ blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + elem_len;
+ if (blen < sizeof(*param))
+ blen = sizeof(*param);
+
+ param = os_zalloc(blen);
+ if (param == NULL)
+ return -1;
+
+ param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT;
+ param->u.generic_elem.len = elem_len;
+ if (drv->generic_ie) {
+ os_memcpy(param->u.generic_elem.data, drv->generic_ie,
+ drv->generic_ie_len);
+ }
+ if (drv->wps_ie) {
+ os_memcpy(&param->u.generic_elem.data[drv->generic_ie_len],
+ drv->wps_ie, drv->wps_ie_len);
+ }
+ wpa_hexdump(MSG_DEBUG, "hostap: Set generic IE",
+ param->u.generic_elem.data, elem_len);
+ res = hostapd_ioctl(drv, param, blen);
+
+ os_free(param);
+
+ return res;
+}
+
+
+static int hostap_set_generic_elem(const char *ifname, void *priv,
+ const u8 *elem, size_t elem_len)
+{
+ struct hostap_driver_data *drv = priv;
+
+ os_free(drv->generic_ie);
+ drv->generic_ie = NULL;
+ drv->generic_ie_len = 0;
+ if (elem) {
+ drv->generic_ie = os_malloc(elem_len);
+ if (drv->generic_ie == NULL)
+ return -1;
+ os_memcpy(drv->generic_ie, elem, elem_len);
+ drv->generic_ie_len = elem_len;
+ }
+
+ return hostapd_ioctl_set_generic_elem(drv);
+}
+
+
+static int hostap_set_wps_beacon_ie(const char *ifname, void *priv,
+ const u8 *ie, size_t len)
+{
+ /* Host AP driver supports only one set of extra IEs, so we need to
+ * use the ProbeResp IEs also for Beacon frames since they include more
+ * information. */
+ return 0;
+}
+
+
+static int hostap_set_wps_probe_resp_ie(const char *ifname, void *priv,
+ const u8 *ie, size_t len)
+{
+ struct hostap_driver_data *drv = priv;
+
+ os_free(drv->wps_ie);
+ drv->wps_ie = NULL;
+ drv->wps_ie_len = 0;
+ if (ie) {
+ drv->wps_ie = os_malloc(len);
+ if (drv->wps_ie == NULL)
+ return -1;
+ os_memcpy(drv->wps_ie, ie, len);
+ drv->wps_ie_len = len;
+ }
+
+ return hostapd_ioctl_set_generic_elem(drv);
+}
+
+
+static void
+hostapd_wireless_event_wireless_custom(struct hostap_driver_data *drv,
+ char *custom)
+{
+ wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
+
+ if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
+ char *pos;
+ u8 addr[ETH_ALEN];
+ pos = strstr(custom, "addr=");
+ if (pos == NULL) {
+ wpa_printf(MSG_DEBUG,
+ "MLME-MICHAELMICFAILURE.indication "
+ "without sender address ignored");
+ return;
+ }
+ pos += 5;
+ if (hwaddr_aton(pos, addr) == 0) {
+ ieee80211_michael_mic_failure(drv->hapd, addr, 1);
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "MLME-MICHAELMICFAILURE.indication "
+ "with invalid MAC address");
+ }
+ }
+}
+
+
+static void hostapd_wireless_event_wireless(struct hostap_driver_data *drv,
+ char *data, int len)
+{
+ struct iw_event iwe_buf, *iwe = &iwe_buf;
+ char *pos, *end, *custom, *buf;
+
+ pos = data;
+ end = data + len;
+
+ while (pos + IW_EV_LCP_LEN <= end) {
+ /* Event data may be unaligned, so make a local, aligned copy
+ * before processing. */
+ memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
+ wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
+ iwe->cmd, iwe->len);
+ if (iwe->len <= IW_EV_LCP_LEN)
+ return;
+
+ custom = pos + IW_EV_POINT_LEN;
+ if (drv->we_version > 18 &&
+ (iwe->cmd == IWEVMICHAELMICFAILURE ||
+ iwe->cmd == IWEVCUSTOM)) {
+ /* WE-19 removed the pointer from struct iw_point */
+ char *dpos = (char *) &iwe_buf.u.data.length;
+ int dlen = dpos - (char *) &iwe_buf;
+ memcpy(dpos, pos + IW_EV_LCP_LEN,
+ sizeof(struct iw_event) - dlen);
+ } else {
+ memcpy(&iwe_buf, pos, sizeof(struct iw_event));
+ custom += IW_EV_POINT_OFF;
+ }
+
+ switch (iwe->cmd) {
+ case IWEVCUSTOM:
+ if (custom + iwe->u.data.length > end)
+ return;
+ buf = malloc(iwe->u.data.length + 1);
+ if (buf == NULL)
+ return;
+ memcpy(buf, custom, iwe->u.data.length);
+ buf[iwe->u.data.length] = '\0';
+ hostapd_wireless_event_wireless_custom(drv, buf);
+ free(buf);
+ break;
+ }
+
+ pos += iwe->len;
+ }
+}
+
+
+static void hostapd_wireless_event_rtm_newlink(struct hostap_driver_data *drv,
+ struct nlmsghdr *h, int len)
+{
+ struct ifinfomsg *ifi;
+ int attrlen, nlmsg_len, rta_len;
+ struct rtattr * attr;
+
+ if (len < (int) sizeof(*ifi))
+ return;
+
+ ifi = NLMSG_DATA(h);
+
+ /* TODO: use ifi->ifi_index to filter out wireless events from other
+ * interfaces */
+
+ nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
+
+ attrlen = h->nlmsg_len - nlmsg_len;
+ if (attrlen < 0)
+ return;
+
+ attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
+
+ rta_len = RTA_ALIGN(sizeof(struct rtattr));
+ while (RTA_OK(attr, attrlen)) {
+ if (attr->rta_type == IFLA_WIRELESS) {
+ hostapd_wireless_event_wireless(
+ drv, ((char *) attr) + rta_len,
+ attr->rta_len - rta_len);
+ }
+ attr = RTA_NEXT(attr, attrlen);
+ }
+}
+
+
+static void hostapd_wireless_event_receive(int sock, void *eloop_ctx,
+ void *sock_ctx)
+{
+ char buf[256];
+ int left;
+ struct sockaddr_nl from;
+ socklen_t fromlen;
+ struct nlmsghdr *h;
+ struct hostap_driver_data *drv = eloop_ctx;
+
+ fromlen = sizeof(from);
+ left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
+ (struct sockaddr *) &from, &fromlen);
+ if (left < 0) {
+ if (errno != EINTR && errno != EAGAIN)
+ perror("recvfrom(netlink)");
+ return;
+ }
+
+ h = (struct nlmsghdr *) buf;
+ while (left >= (int) sizeof(*h)) {
+ int len, plen;
+
+ len = h->nlmsg_len;
+ plen = len - sizeof(*h);
+ if (len > left || plen < 0) {
+ printf("Malformed netlink message: "
+ "len=%d left=%d plen=%d\n",
+ len, left, plen);
+ break;
+ }
+
+ switch (h->nlmsg_type) {
+ case RTM_NEWLINK:
+ hostapd_wireless_event_rtm_newlink(drv, h, plen);
+ break;
+ }
+
+ len = NLMSG_ALIGN(len);
+ left -= len;
+ h = (struct nlmsghdr *) ((char *) h + len);
+ }
+
+ if (left > 0) {
+ printf("%d extra bytes in the end of netlink message\n", left);
+ }
+}
+
+
+static int hostap_get_we_version(struct hostap_driver_data *drv)
+{
+ struct iw_range *range;
+ struct iwreq iwr;
+ int minlen;
+ size_t buflen;
+
+ drv->we_version = 0;
+
+ /*
+ * Use larger buffer than struct iw_range in order to allow the
+ * structure to grow in the future.
+ */
+ buflen = sizeof(struct iw_range) + 500;
+ range = os_zalloc(buflen);
+ if (range == NULL)
+ return -1;
+
+ memset(&iwr, 0, sizeof(iwr));
+ os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
+ iwr.u.data.pointer = (caddr_t) range;
+ iwr.u.data.length = buflen;
+
+ minlen = ((char *) &range->enc_capa) - (char *) range +
+ sizeof(range->enc_capa);
+
+ if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
+ perror("ioctl[SIOCGIWRANGE]");
+ free(range);
+ return -1;
+ } else if (iwr.u.data.length >= minlen &&
+ range->we_version_compiled >= 18) {
+ wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
+ "WE(source)=%d enc_capa=0x%x",
+ range->we_version_compiled,
+ range->we_version_source,
+ range->enc_capa);
+ drv->we_version = range->we_version_compiled;
+ }
+
+ free(range);
+ return 0;
+}
+
+
+static int hostap_wireless_event_init(void *priv)
+{
+ struct hostap_driver_data *drv = priv;
+ int s;
+ struct sockaddr_nl local;
+
+ hostap_get_we_version(drv);
+
+ drv->wext_sock = -1;
+
+ s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (s < 0) {
+ perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
+ return -1;
+ }
+
+ memset(&local, 0, sizeof(local));
+ local.nl_family = AF_NETLINK;
+ local.nl_groups = RTMGRP_LINK;
+ if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
+ perror("bind(netlink)");
+ close(s);
+ return -1;
+ }
+
+ eloop_register_read_sock(s, hostapd_wireless_event_receive, drv,
+ NULL);
+ drv->wext_sock = s;
+
+ return 0;
+}
+
+
+static void hostap_wireless_event_deinit(void *priv)
+{
+ struct hostap_driver_data *drv = priv;
+ if (drv->wext_sock < 0)
+ return;
+ eloop_unregister_read_sock(drv->wext_sock);
+ close(drv->wext_sock);
+}
+
+
+static void * hostap_init(struct hostapd_data *hapd)
+{
+ struct hostap_driver_data *drv;
+
+ drv = os_zalloc(sizeof(struct hostap_driver_data));
+ if (drv == NULL) {
+ printf("Could not allocate memory for hostapd driver data\n");
+ return NULL;
+ }
+
+ drv->hapd = hapd;
+ drv->ioctl_sock = drv->sock = -1;
+ memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
+
+ drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
+ if (drv->ioctl_sock < 0) {
+ perror("socket[PF_INET,SOCK_DGRAM]");
+ free(drv);
+ return NULL;
+ }
+
+ if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 1)) {
+ printf("Could not enable hostapd mode for interface %s\n",
+ drv->iface);
+ close(drv->ioctl_sock);
+ free(drv);
+ return NULL;
+ }
+
+ if (hostap_init_sockets(drv)) {
+ close(drv->ioctl_sock);
+ free(drv);
+ return NULL;
+ }
+
+ return drv;
+}
+
+
+static void hostap_driver_deinit(void *priv)
+{
+ struct hostap_driver_data *drv = priv;
+
+ (void) hostap_set_iface_flags(drv, 0);
+ (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 0);
+ (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD_STA, 0);
+
+ if (drv->ioctl_sock >= 0)
+ close(drv->ioctl_sock);
+
+ if (drv->sock >= 0)
+ close(drv->sock);
+
+ os_free(drv->generic_ie);
+ os_free(drv->wps_ie);
+
+ free(drv);
+}
+
+
+static int hostap_sta_deauth(void *priv, const u8 *addr, int reason)
+{
+ struct hostap_driver_data *drv = priv;
+ struct ieee80211_mgmt mgmt;
+
+ memset(&mgmt, 0, sizeof(mgmt));
+ mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+ WLAN_FC_STYPE_DEAUTH);
+ memcpy(mgmt.da, addr, ETH_ALEN);
+ memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN);
+ memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN);
+ mgmt.u.deauth.reason_code = host_to_le16(reason);
+ return hostap_send_mgmt_frame(drv, &mgmt, IEEE80211_HDRLEN +
+ sizeof(mgmt.u.deauth), 0);
+}
+
+
+static int hostap_sta_disassoc(void *priv, const u8 *addr, int reason)
+{
+ struct hostap_driver_data *drv = priv;
+ struct ieee80211_mgmt mgmt;
+
+ memset(&mgmt, 0, sizeof(mgmt));
+ mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+ WLAN_FC_STYPE_DISASSOC);
+ memcpy(mgmt.da, addr, ETH_ALEN);
+ memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN);
+ memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN);
+ mgmt.u.disassoc.reason_code = host_to_le16(reason);
+ return hostap_send_mgmt_frame(drv, &mgmt, IEEE80211_HDRLEN +
+ sizeof(mgmt.u.disassoc), 0);
+}
+
+
+static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv,
+ u16 *num_modes,
+ u16 *flags)
+{
+ struct hostapd_hw_modes *mode;
+ int i, clen, rlen;
+ const short chan2freq[14] = {
+ 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+ 2447, 2452, 2457, 2462, 2467, 2472, 2484
+ };
+
+ mode = os_zalloc(sizeof(struct hostapd_hw_modes));
+ if (mode == NULL)
+ return NULL;
+
+ *num_modes = 1;
+ *flags = 0;
+
+ mode->mode = HOSTAPD_MODE_IEEE80211B;
+ mode->num_channels = 14;
+ mode->num_rates = 4;
+
+ clen = mode->num_channels * sizeof(struct hostapd_channel_data);
+ rlen = mode->num_rates * sizeof(struct hostapd_rate_data);
+
+ mode->channels = os_zalloc(clen);
+ mode->rates = os_zalloc(rlen);
+ if (mode->channels == NULL || mode->rates == NULL) {
+ hostapd_free_hw_features(mode, *num_modes);
+ return NULL;
+ }
+
+ for (i = 0; i < 14; i++) {
+ mode->channels[i].chan = i + 1;
+ mode->channels[i].freq = chan2freq[i];
+ /* TODO: Get allowed channel list from the driver */
+ if (i >= 11)
+ mode->channels[i].flag = HOSTAPD_CHAN_DISABLED;
+ }
+
+ mode->rates[0].rate = 10;
+ mode->rates[0].flags = HOSTAPD_RATE_CCK;
+ mode->rates[1].rate = 20;
+ mode->rates[1].flags = HOSTAPD_RATE_CCK;
+ mode->rates[2].rate = 55;
+ mode->rates[2].flags = HOSTAPD_RATE_CCK;
+ mode->rates[3].rate = 110;
+ mode->rates[3].flags = HOSTAPD_RATE_CCK;
+
+ return mode;
+}
+
+
+const struct wpa_driver_ops wpa_driver_hostap_ops = {
+ .name = "hostap",
+ .init = hostap_init,
+ .deinit = hostap_driver_deinit,
+ .wireless_event_init = hostap_wireless_event_init,
+ .wireless_event_deinit = hostap_wireless_event_deinit,
+ .set_ieee8021x = hostap_set_ieee8021x,
+ .set_privacy = hostap_set_privacy,
+ .set_encryption = hostap_set_encryption,
+ .get_seqnum = hostap_get_seqnum,
+ .flush = hostap_flush,
+ .set_generic_elem = hostap_set_generic_elem,
+ .read_sta_data = hostap_read_sta_data,
+ .send_eapol = hostap_send_eapol,
+ .sta_set_flags = hostap_sta_set_flags,
+ .sta_deauth = hostap_sta_deauth,
+ .sta_disassoc = hostap_sta_disassoc,
+ .sta_remove = hostap_sta_remove,
+ .set_ssid = hostap_set_ssid,
+ .send_mgmt_frame = hostap_send_mgmt_frame,
+ .set_assoc_ap = hostap_set_assoc_ap,
+ .sta_add = hostap_sta_add,
+ .get_inact_sec = hostap_get_inact_sec,
+ .sta_clear_stats = hostap_sta_clear_stats,
+ .get_hw_feature_data = hostap_get_hw_feature_data,
+ .set_wps_beacon_ie = hostap_set_wps_beacon_ie,
+ .set_wps_probe_resp_ie = hostap_set_wps_probe_resp_ie,
+};
diff --git a/contrib/wpa/hostapd/driver_wired.c b/contrib/wpa/hostapd/driver_wired.c
new file mode 100644
index 0000000..61cb667
--- /dev/null
+++ b/contrib/wpa/hostapd/driver_wired.c
@@ -0,0 +1,372 @@
+/*
+ * hostapd / Kernel driver communication for wired (Ethernet) drivers
+ * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004, Gunter Burchardt <tira@isx.de>
+ *
+ * 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.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+#include <sys/ioctl.h>
+
+#ifdef USE_KERNEL_HEADERS
+#include <asm/types.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h> /* The L2 protocols */
+#include <linux/if_arp.h>
+#include <linux/if.h>
+#else /* USE_KERNEL_HEADERS */
+#include <net/if_arp.h>
+#include <net/if.h>
+#include <netpacket/packet.h>
+#endif /* USE_KERNEL_HEADERS */
+
+#include "hostapd.h"
+#include "ieee802_1x.h"
+#include "eloop.h"
+#include "sta_info.h"
+#include "driver.h"
+#include "accounting.h"
+
+
+struct wired_driver_data {
+ struct hostapd_data *hapd;
+
+ int sock; /* raw packet socket for driver access */
+ int dhcp_sock; /* socket for dhcp packets */
+ int use_pae_group_addr;
+};
+
+
+#define WIRED_EAPOL_MULTICAST_GROUP {0x01,0x80,0xc2,0x00,0x00,0x03}
+
+
+/* TODO: detecting new devices should eventually be changed from using DHCP
+ * snooping to trigger on any packet from a new layer 2 MAC address, e.g.,
+ * based on ebtables, etc. */
+
+struct dhcp_message {
+ u_int8_t op;
+ u_int8_t htype;
+ u_int8_t hlen;
+ u_int8_t hops;
+ u_int32_t xid;
+ u_int16_t secs;
+ u_int16_t flags;
+ u_int32_t ciaddr;
+ u_int32_t yiaddr;
+ u_int32_t siaddr;
+ u_int32_t giaddr;
+ u_int8_t chaddr[16];
+ u_int8_t sname[64];
+ u_int8_t file[128];
+ u_int32_t cookie;
+ u_int8_t options[308]; /* 312 - cookie */
+};
+
+
+static void wired_possible_new_sta(struct hostapd_data *hapd, u8 *addr)
+{
+ struct sta_info *sta;
+
+ sta = ap_get_sta(hapd, addr);
+ if (sta)
+ return;
+
+ wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
+ " - adding a new STA", MAC2STR(addr));
+ sta = ap_sta_add(hapd, addr);
+ if (sta) {
+ hostapd_new_assoc_sta(hapd, sta, 0);
+ } else {
+ wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
+ MAC2STR(addr));
+ }
+}
+
+
+static void handle_data(struct hostapd_data *hapd, unsigned char *buf,
+ size_t len)
+{
+ struct ieee8023_hdr *hdr;
+ u8 *pos, *sa;
+ size_t left;
+
+ /* must contain at least ieee8023_hdr 6 byte source, 6 byte dest,
+ * 2 byte ethertype */
+ if (len < 14) {
+ wpa_printf(MSG_MSGDUMP, "handle_data: too short (%lu)",
+ (unsigned long) len);
+ return;
+ }
+
+ hdr = (struct ieee8023_hdr *) buf;
+
+ switch (ntohs(hdr->ethertype)) {
+ case ETH_P_PAE:
+ wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
+ sa = hdr->src;
+ wired_possible_new_sta(hapd, sa);
+
+ pos = (u8 *) (hdr + 1);
+ left = len - sizeof(*hdr);
+
+ ieee802_1x_receive(hapd, sa, pos, left);
+ break;
+
+ default:
+ wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame",
+ ntohs(hdr->ethertype));
+ break;
+ }
+}
+
+
+static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
+{
+ struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
+ int len;
+ unsigned char buf[3000];
+
+ len = recv(sock, buf, sizeof(buf), 0);
+ if (len < 0) {
+ perror("recv");
+ return;
+ }
+
+ handle_data(hapd, buf, len);
+}
+
+
+static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx)
+{
+ struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
+ int len;
+ unsigned char buf[3000];
+ struct dhcp_message *msg;
+ u8 *mac_address;
+
+ len = recv(sock, buf, sizeof(buf), 0);
+ if (len < 0) {
+ perror("recv");
+ return;
+ }
+
+ /* must contain at least dhcp_message->chaddr */
+ if (len < 44) {
+ wpa_printf(MSG_MSGDUMP, "handle_dhcp: too short (%d)", len);
+ return;
+ }
+
+ msg = (struct dhcp_message *) buf;
+ mac_address = (u8 *) &(msg->chaddr);
+
+ wpa_printf(MSG_MSGDUMP, "Got DHCP broadcast packet from " MACSTR,
+ MAC2STR(mac_address));
+
+ wired_possible_new_sta(hapd, mac_address);
+}
+
+
+static int wired_init_sockets(struct wired_driver_data *drv)
+{
+ struct hostapd_data *hapd = drv->hapd;
+ struct ifreq ifr;
+ struct sockaddr_ll addr;
+ struct sockaddr_in addr2;
+ struct packet_mreq mreq;
+ u8 multicastgroup_eapol[6] = WIRED_EAPOL_MULTICAST_GROUP;
+ int n = 1;
+
+ drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
+ if (drv->sock < 0) {
+ perror("socket[PF_PACKET,SOCK_RAW]");
+ return -1;
+ }
+
+ if (eloop_register_read_sock(drv->sock, handle_read, hapd, NULL)) {
+ printf("Could not register read socket\n");
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_name, hapd->conf->iface, sizeof(ifr.ifr_name));
+ if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
+ perror("ioctl(SIOCGIFINDEX)");
+ return -1;
+ }
+
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sll_family = AF_PACKET;
+ addr.sll_ifindex = ifr.ifr_ifindex;
+ wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
+ addr.sll_ifindex);
+
+ if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("bind");
+ return -1;
+ }
+
+ /* filter multicast address */
+ memset(&mreq, 0, sizeof(mreq));
+ mreq.mr_ifindex = ifr.ifr_ifindex;
+ mreq.mr_type = PACKET_MR_MULTICAST;
+ mreq.mr_alen = 6;
+ memcpy(mreq.mr_address, multicastgroup_eapol, mreq.mr_alen);
+
+ if (setsockopt(drv->sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq,
+ sizeof(mreq)) < 0) {
+ perror("setsockopt[SOL_SOCKET,PACKET_ADD_MEMBERSHIP]");
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_name, hapd->conf->iface, sizeof(ifr.ifr_name));
+ if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
+ perror("ioctl(SIOCGIFHWADDR)");
+ return -1;
+ }
+
+ if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
+ printf("Invalid HW-addr family 0x%04x\n",
+ ifr.ifr_hwaddr.sa_family);
+ return -1;
+ }
+ memcpy(hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+
+ /* setup dhcp listen socket for sta detection */
+ if ((drv->dhcp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ perror("socket call failed for dhcp");
+ return -1;
+ }
+
+ if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, hapd, NULL))
+ {
+ printf("Could not register read socket\n");
+ return -1;
+ }
+
+ memset(&addr2, 0, sizeof(addr2));
+ addr2.sin_family = AF_INET;
+ addr2.sin_port = htons(67);
+ addr2.sin_addr.s_addr = INADDR_ANY;
+
+ if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n,
+ sizeof(n)) == -1) {
+ perror("setsockopt[SOL_SOCKET,SO_REUSEADDR]");
+ return -1;
+ }
+ if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BROADCAST, (char *) &n,
+ sizeof(n)) == -1) {
+ perror("setsockopt[SOL_SOCKET,SO_BROADCAST]");
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_ifrn.ifrn_name, hapd->conf->iface, IFNAMSIZ);
+ if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE,
+ (char *) &ifr, sizeof(ifr)) < 0) {
+ perror("setsockopt[SOL_SOCKET,SO_BINDTODEVICE]");
+ return -1;
+ }
+
+ if (bind(drv->dhcp_sock, (struct sockaddr *) &addr2,
+ sizeof(struct sockaddr)) == -1) {
+ perror("bind");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int wired_send_eapol(void *priv, const u8 *addr,
+ const u8 *data, size_t data_len, int encrypt,
+ const u8 *own_addr)
+{
+ struct wired_driver_data *drv = priv;
+ u8 pae_group_addr[ETH_ALEN] = WIRED_EAPOL_MULTICAST_GROUP;
+ struct ieee8023_hdr *hdr;
+ size_t len;
+ u8 *pos;
+ int res;
+
+ len = sizeof(*hdr) + data_len;
+ hdr = os_zalloc(len);
+ if (hdr == NULL) {
+ printf("malloc() failed for wired_send_eapol(len=%lu)\n",
+ (unsigned long) len);
+ return -1;
+ }
+
+ memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr,
+ ETH_ALEN);
+ memcpy(hdr->src, own_addr, ETH_ALEN);
+ hdr->ethertype = htons(ETH_P_PAE);
+
+ pos = (u8 *) (hdr + 1);
+ memcpy(pos, data, data_len);
+
+ res = send(drv->sock, (u8 *) hdr, len, 0);
+ free(hdr);
+
+ if (res < 0) {
+ perror("wired_send_eapol: send");
+ printf("wired_send_eapol - packet len: %lu - failed\n",
+ (unsigned long) len);
+ }
+
+ return res;
+}
+
+
+static void * wired_driver_init(struct hostapd_data *hapd)
+{
+ struct wired_driver_data *drv;
+
+ drv = os_zalloc(sizeof(struct wired_driver_data));
+ if (drv == NULL) {
+ printf("Could not allocate memory for wired driver data\n");
+ return NULL;
+ }
+
+ drv->hapd = hapd;
+ drv->use_pae_group_addr = hapd->conf->use_pae_group_addr;
+
+ if (wired_init_sockets(drv)) {
+ free(drv);
+ return NULL;
+ }
+
+ return drv;
+}
+
+
+static void wired_driver_deinit(void *priv)
+{
+ struct wired_driver_data *drv = priv;
+
+ if (drv->sock >= 0)
+ close(drv->sock);
+
+ if (drv->dhcp_sock >= 0)
+ close(drv->dhcp_sock);
+
+ free(drv);
+}
+
+
+const struct wpa_driver_ops wpa_driver_wired_ops = {
+ .name = "wired",
+ .init = wired_driver_init,
+ .deinit = wired_driver_deinit,
+ .send_eapol = wired_send_eapol,
+};
diff --git a/contrib/wpa/hostapd/drivers.c b/contrib/wpa/hostapd/drivers.c
index 3006190..bde6e60 100644
--- a/contrib/wpa/hostapd/drivers.c
+++ b/contrib/wpa/hostapd/drivers.c
@@ -27,6 +27,9 @@ extern struct wpa_driver_ops wpa_driver_prism54_ops; /* driver_prism54.c */
#ifdef CONFIG_DRIVER_MADWIFI
extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */
#endif /* CONFIG_DRIVER_MADWIFI */
+#ifdef CONFIG_DRIVER_ATHEROS
+extern struct wpa_driver_ops wpa_driver_atheros_ops; /* driver_atheros.c */
+#endif /* CONFIG_DRIVER_ATHEROS */
#ifdef CONFIG_DRIVER_BSD
extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */
#endif /* CONFIG_DRIVER_BSD */
@@ -55,6 +58,9 @@ struct wpa_driver_ops *hostapd_drivers[] =
#ifdef CONFIG_DRIVER_MADWIFI
&wpa_driver_madwifi_ops,
#endif /* CONFIG_DRIVER_MADWIFI */
+#ifdef CONFIG_DRIVER_ATHEROS
+ &wpa_driver_atheros_ops,
+#endif /* CONFIG_DRIVER_ATHEROS */
#ifdef CONFIG_DRIVER_BSD
&wpa_driver_bsd_ops,
#endif /* CONFIG_DRIVER_BSD */
diff --git a/contrib/wpa/hostapd/hostapd.8 b/contrib/wpa/hostapd/hostapd.8
index 9258512..a67a1bc 100644
--- a/contrib/wpa/hostapd/hostapd.8
+++ b/contrib/wpa/hostapd/hostapd.8
@@ -3,7 +3,7 @@
hostapd \- IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator
.SH SYNOPSIS
.B hostapd
-[-hdBKtv] [-P <PID file>] <configuration file(s)>
+[\-hdBKtv] [\-P <PID file>] <configuration file(s)>
.SH DESCRIPTION
This manual page documents briefly the
.B hostapd
diff --git a/contrib/wpa/hostapd/hostapd.c b/contrib/wpa/hostapd/hostapd.c
index 065a5fd..b1c5a2c 100644
--- a/contrib/wpa/hostapd/hostapd.c
+++ b/contrib/wpa/hostapd/hostapd.c
@@ -249,7 +249,7 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
accounting_sta_start(hapd, sta);
- hostapd_wme_sta_config(hapd, sta);
+ hostapd_wmm_sta_config(hapd, sta);
/* Start IEEE 802.1X authentication process for new stations */
ieee802_1x_new_station(hapd, sta);
@@ -306,7 +306,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wconf->rsn_preauth = conf->rsn_preauth;
wconf->eapol_version = conf->eapol_version;
wconf->peerkey = conf->peerkey;
- wconf->wme_enabled = conf->wme_enabled;
+ wconf->wmm_enabled = conf->wmm_enabled;
wconf->okc = conf->okc;
#ifdef CONFIG_IEEE80211W
wconf->ieee80211w = conf->ieee80211w;
@@ -339,6 +339,7 @@ int hostapd_reload_config(struct hostapd_iface *iface)
struct hostapd_data *hapd = iface->bss[0];
struct hostapd_config *newconf, *oldconf;
struct wpa_auth_config wpa_auth_conf;
+ size_t j;
newconf = hostapd_config_read(iface->config_fname);
if (newconf == NULL)
@@ -348,7 +349,8 @@ int hostapd_reload_config(struct hostapd_iface *iface)
* Deauthenticate all stations since the new configuration may not
* allow them to use the BSS anymore.
*/
- hostapd_flush_old_stations(hapd);
+ for (j = 0; j < iface->num_bss; j++)
+ hostapd_flush_old_stations(iface->bss[j]);
/* TODO: update dynamic data based on changed configuration
* items (e.g., open/close sockets, etc.) */
@@ -378,6 +380,16 @@ int hostapd_reload_config(struct hostapd_iface *iface)
ieee802_11_set_beacon(hapd);
+ if (hapd->conf->ssid.ssid_set &&
+ hostapd_set_ssid(hapd, (u8 *) hapd->conf->ssid.ssid,
+ hapd->conf->ssid.ssid_len)) {
+ wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
+ /* try to continue */
+ }
+
+ if (hapd->conf->ieee802_1x || hapd->conf->wpa)
+ hostapd_set_ieee8021x(hapd->conf->iface, hapd, 1);
+
hostapd_config_free(oldconf);
wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
@@ -465,7 +477,7 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
(sta->flags & WLAN_STA_SHORT_PREAMBLE ?
"[SHORT_PREAMBLE]" : ""),
(sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""),
- (sta->flags & WLAN_STA_WME ? "[WME]" : ""),
+ (sta->flags & WLAN_STA_WMM ? "[WMM]" : ""),
(sta->flags & WLAN_STA_MFP ? "[MFP]" : ""),
(sta->flags & WLAN_STA_WPS ? "[WPS]" : ""),
(sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
@@ -1308,6 +1320,13 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
}
}
+ hostapd_flush_old_stations(hapd);
+ hostapd_set_privacy(hapd, 0);
+
+ hostapd_broadcast_wep_clear(hapd);
+ if (hostapd_setup_encryption(hapd->conf->iface, hapd))
+ return -1;
+
/*
* Fetch the SSID from the system and use it or,
* if one was specified in the config file, verify they
@@ -1510,7 +1529,6 @@ static int setup_interface(struct hostapd_iface *iface)
u8 *b = conf->bssid;
int freq;
size_t j;
- int ret = 0;
u8 *prev_addr;
/*
@@ -1582,9 +1600,6 @@ static int setup_interface(struct hostapd_iface *iface)
}
}
- hostapd_flush_old_stations(hapd);
- hostapd_set_privacy(hapd, 0);
-
if (hapd->iconf->channel) {
freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel);
wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d "
@@ -1601,12 +1616,7 @@ static int setup_interface(struct hostapd_iface *iface)
}
}
- hostapd_broadcast_wep_clear(hapd);
- if (hostapd_setup_encryption(hapd->conf->iface, hapd))
- return -1;
-
hostapd_set_beacon_int(hapd, hapd->iconf->beacon_int);
- ieee802_11_set_beacon(hapd);
if (hapd->iconf->rts_threshold > -1 &&
hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) {
@@ -1644,7 +1654,7 @@ static int setup_interface(struct hostapd_iface *iface)
return -1;
}
- return ret;
+ return 0;
}
@@ -1867,7 +1877,7 @@ int main(int argc, char *argv[])
int ret = 1, k;
size_t i, j;
int c, debug = 0, daemonize = 0, tnc = 0;
- const char *pid_file = NULL;
+ char *pid_file = NULL;
hostapd_logger_register_cb(hostapd_logger_cb);
@@ -1891,7 +1901,8 @@ int main(int argc, char *argv[])
wpa_debug_show_keys++;
break;
case 'P':
- pid_file = optarg;
+ os_free(pid_file);
+ pid_file = os_rel2abs_path(optarg);
break;
case 't':
wpa_debug_timestamp++;
@@ -2026,6 +2037,7 @@ int main(int argc, char *argv[])
#endif /* EAP_SERVER */
os_daemonize_terminate(pid_file);
+ os_free(pid_file);
return ret;
}
diff --git a/contrib/wpa/hostapd/hostapd.conf b/contrib/wpa/hostapd/hostapd.conf
index 0602cb0..703b646 100644
--- a/contrib/wpa/hostapd/hostapd.conf
+++ b/contrib/wpa/hostapd/hostapd.conf
@@ -245,14 +245,14 @@ ignore_broadcast_ssid=0
#tx_queue_beacon_cwmax=7
#tx_queue_beacon_burst=1.5
-# 802.1D Tag to AC mappings
+# 802.1D Tag (= UP) to AC mappings
# WMM specifies following mapping of data frames to different ACs. This mapping
# can be configured using Linux QoS/tc and sch_pktpri.o module.
# 802.1D Tag 802.1D Designation Access Category WMM Designation
# 1 BK AC_BK Background
# 2 - AC_BK Background
# 0 BE AC_BE Best Effort
-# 3 EE AC_VI Video
+# 3 EE AC_BE Best Effort
# 4 CL AC_VI Video
# 5 VI AC_VI Video
# 6 VO AC_VO Voice
@@ -273,38 +273,38 @@ ignore_broadcast_ssid=0
# note - here cwMin and cmMax are in exponent form. the actual cw value used
# will be (2^n)-1 where n is the value given here
#
-wme_enabled=1
+wmm_enabled=1
#
# Low priority / AC_BK = background
-wme_ac_bk_cwmin=4
-wme_ac_bk_cwmax=10
-wme_ac_bk_aifs=7
-wme_ac_bk_txop_limit=0
-wme_ac_bk_acm=0
+wmm_ac_bk_cwmin=4
+wmm_ac_bk_cwmax=10
+wmm_ac_bk_aifs=7
+wmm_ac_bk_txop_limit=0
+wmm_ac_bk_acm=0
# Note: for IEEE 802.11b mode: cWmin=5 cWmax=10
#
# Normal priority / AC_BE = best effort
-wme_ac_be_aifs=3
-wme_ac_be_cwmin=4
-wme_ac_be_cwmax=10
-wme_ac_be_txop_limit=0
-wme_ac_be_acm=0
+wmm_ac_be_aifs=3
+wmm_ac_be_cwmin=4
+wmm_ac_be_cwmax=10
+wmm_ac_be_txop_limit=0
+wmm_ac_be_acm=0
# Note: for IEEE 802.11b mode: cWmin=5 cWmax=7
#
# High priority / AC_VI = video
-wme_ac_vi_aifs=2
-wme_ac_vi_cwmin=3
-wme_ac_vi_cwmax=4
-wme_ac_vi_txop_limit=94
-wme_ac_vi_acm=0
+wmm_ac_vi_aifs=2
+wmm_ac_vi_cwmin=3
+wmm_ac_vi_cwmax=4
+wmm_ac_vi_txop_limit=94
+wmm_ac_vi_acm=0
# Note: for IEEE 802.11b mode: cWmin=4 cWmax=5 txop_limit=188
#
# Highest priority / AC_VO = voice
-wme_ac_vo_aifs=2
-wme_ac_vo_cwmin=2
-wme_ac_vo_cwmax=3
-wme_ac_vo_txop_limit=47
-wme_ac_vo_acm=0
+wmm_ac_vo_aifs=2
+wmm_ac_vo_cwmin=2
+wmm_ac_vo_cwmax=3
+wmm_ac_vo_txop_limit=47
+wmm_ac_vo_acm=0
# Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102
# Static WEP key configuration
@@ -375,6 +375,7 @@ wme_ac_vo_acm=0
# ieee80211n: Whether IEEE 802.11n (HT) is enabled
# 0 = disabled (default)
# 1 = enabled
+# Note: You will also need to enable WMM for full HT functionality.
#ieee80211n=1
# ht_capab: HT capabilities (list of flags)
diff --git a/contrib/wpa/hostapd/hostapd_cli.1 b/contrib/wpa/hostapd/hostapd_cli.1
index 8d6587f..2fe4907 100644
--- a/contrib/wpa/hostapd/hostapd_cli.1
+++ b/contrib/wpa/hostapd/hostapd_cli.1
@@ -3,7 +3,7 @@
hostapd_cli \- hostapd command-line interface
.SH SYNOPSIS
.B hostapd_cli
-[-p<path>] [-i<ifname>] [-hv] [command..]
+[\-p<path>] [\-i<ifname>] [\-hv] [command..]
.SH DESCRIPTION
This manual page documents briefly the
.B hostapd_cli
diff --git a/contrib/wpa/hostapd/hostapd_cli.c b/contrib/wpa/hostapd/hostapd_cli.c
index 2614113..c2ecd4e 100644
--- a/contrib/wpa/hostapd/hostapd_cli.c
+++ b/contrib/wpa/hostapd/hostapd_cli.c
@@ -87,7 +87,7 @@ static const char *commands_help =
" sa_query <addr> send SA Query to a station\n"
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_WPS
-" wps_pin <uuid> <pin> add WPS Enrollee PIN (Device Password)\n"
+" wps_pin <uuid> <pin> [timeout] add WPS Enrollee PIN (Device Password)\n"
" wps_pbc indicate button pushed to initiate PBC\n"
#endif /* CONFIG_WPS */
" help show this usage help\n"
@@ -260,12 +260,16 @@ static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
char buf[64];
- if (argc != 2) {
- printf("Invalid 'wps_pin' command - exactly two arguments, "
+ if (argc < 2) {
+ printf("Invalid 'wps_pin' command - at least two arguments, "
"UUID and PIN, are required.\n");
return -1;
}
- snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
+ if (argc > 2)
+ snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
+ argv[0], argv[1], argv[2]);
+ else
+ snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
return wpa_ctrl_command(ctrl, buf);
}
diff --git a/contrib/wpa/hostapd/hw_features.c b/contrib/wpa/hostapd/hw_features.c
index f1288e0..1d6299e 100644
--- a/contrib/wpa/hostapd/hw_features.c
+++ b/contrib/wpa/hostapd/hw_features.c
@@ -382,6 +382,13 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
break;
}
}
+ if (iface->conf->channel == 0) {
+ /* TODO: could request a scan of neighboring BSSes and select
+ * the channel automatically */
+ wpa_printf(MSG_ERROR, "Channel not configured "
+ "(hw_mode/channel in hostapd.conf)");
+ return -1;
+ }
if (ok == 0 && iface->conf->channel != 0) {
hostapd_logger(iface->bss[0], NULL,
HOSTAPD_MODULE_IEEE80211,
diff --git a/contrib/wpa/hostapd/ieee802_11.c b/contrib/wpa/hostapd/ieee802_11.c
index 8399d88..70491b4 100644
--- a/contrib/wpa/hostapd/ieee802_11.c
+++ b/contrib/wpa/hostapd/ieee802_11.c
@@ -384,8 +384,8 @@ static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
r = random();
os_memcpy(key, &now, 4);
os_memcpy(key + 4, &r, 4);
- rc4(sta->challenge, WLAN_AUTH_CHALLENGE_LEN,
- key, sizeof(key));
+ rc4_skip(key, sizeof(key), 0,
+ sta->challenge, WLAN_AUTH_CHALLENGE_LEN);
}
return 0;
}
@@ -585,7 +585,7 @@ static void handle_auth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
if (vlan_id > 0) {
if (hostapd_get_vlan_id_ifname(hapd->conf->vlan,
- sta->vlan_id) == NULL) {
+ vlan_id) == NULL) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO, "Invalid VLAN ID "
"%d received from RADIUS server",
@@ -766,16 +766,16 @@ static void handle_assoc(struct hostapd_data *hapd,
goto fail;
}
- sta->flags &= ~WLAN_STA_WME;
- if (elems.wme && hapd->conf->wme_enabled) {
- if (hostapd_eid_wme_valid(hapd, elems.wme, elems.wme_len))
+ sta->flags &= ~WLAN_STA_WMM;
+ if (elems.wmm && hapd->conf->wmm_enabled) {
+ if (hostapd_eid_wmm_valid(hapd, elems.wmm, elems.wmm_len))
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_WPA,
HOSTAPD_LEVEL_DEBUG,
- "invalid WME element in association "
+ "invalid WMM element in association "
"request");
else
- sta->flags |= WLAN_STA_WME;
+ sta->flags |= WLAN_STA_WMM;
}
if (!elems.supp_rates) {
@@ -1124,8 +1124,8 @@ static void handle_assoc(struct hostapd_data *hapd,
p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable);
/* Extended supported rates */
p = hostapd_eid_ext_supp_rates(hapd, p);
- if (sta->flags & WLAN_STA_WME)
- p = hostapd_eid_wme(hapd, p);
+ if (sta->flags & WLAN_STA_WMM)
+ p = hostapd_eid_wmm(hapd, p);
p = hostapd_eid_ht_capabilities_info(hapd, p);
p = hostapd_eid_ht_operation(hapd, p);
@@ -1265,6 +1265,11 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
struct ieee80211_mgmt mgmt;
u8 *end;
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to "
+ MACSTR, MAC2STR(addr));
+ wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
+ trans_id, WLAN_SA_QUERY_TR_ID_LEN);
+
os_memset(&mgmt, 0, sizeof(mgmt));
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_ACTION);
@@ -1302,6 +1307,12 @@ static void hostapd_sa_query_action(struct hostapd_data *hapd,
return;
}
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from "
+ MACSTR, MAC2STR(mgmt->sa));
+ wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
+ mgmt->u.action.u.sa_query_resp.trans_id,
+ WLAN_SA_QUERY_TR_ID_LEN);
+
/* MLME-SAQuery.confirm */
sta = ap_get_sta(hapd, mgmt->sa);
@@ -1330,12 +1341,21 @@ static void hostapd_sa_query_action(struct hostapd_data *hapd,
"Reply to pending SA Query received");
ap_sta_stop_sa_query(hapd, sta);
}
+
+
+static int robust_action_frame(u8 category)
+{
+ return category != WLAN_ACTION_PUBLIC &&
+ category != WLAN_ACTION_HT;
+}
#endif /* CONFIG_IEEE80211W */
static void handle_action(struct hostapd_data *hapd,
struct ieee80211_mgmt *mgmt, size_t len)
{
+ struct sta_info *sta;
+
if (len < IEEE80211_HDRLEN + 1) {
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
@@ -1344,13 +1364,23 @@ static void handle_action(struct hostapd_data *hapd,
return;
}
+ sta = ap_get_sta(hapd, mgmt->sa);
+#ifdef CONFIG_IEEE80211W
+ if (sta && (sta->flags & WLAN_STA_MFP) &&
+ !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP) &&
+ robust_action_frame(mgmt->u.action.category))) {
+ hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "Dropped unprotected Robust Action frame from "
+ "an MFP STA");
+ return;
+ }
+#endif /* CONFIG_IEEE80211W */
+
switch (mgmt->u.action.category) {
#ifdef CONFIG_IEEE80211R
case WLAN_ACTION_FT:
{
- struct sta_info *sta;
-
- sta = ap_get_sta(hapd, mgmt->sa);
if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored FT Action "
"frame from unassociated STA " MACSTR,
@@ -1366,7 +1396,7 @@ static void handle_action(struct hostapd_data *hapd,
}
#endif /* CONFIG_IEEE80211R */
case WLAN_ACTION_WMM:
- hostapd_wme_action(hapd, mgmt, len);
+ hostapd_wmm_action(hapd, mgmt, len);
return;
#ifdef CONFIG_IEEE80211W
case WLAN_ACTION_SA_QUERY:
@@ -1527,6 +1557,26 @@ static void handle_auth_cb(struct hostapd_data *hapd,
}
+#ifdef CONFIG_IEEE80211N
+static void
+hostapd_get_ht_capab(struct hostapd_data *hapd,
+ struct ht_cap_ie *ht_cap_ie,
+ struct ht_cap_ie *neg_ht_cap_ie)
+{
+ u16 cap;
+
+ os_memcpy(neg_ht_cap_ie, ht_cap_ie, sizeof(struct ht_cap_ie));
+ cap = le_to_host16(neg_ht_cap_ie->data.capabilities_info);
+ cap &= hapd->iconf->ht_capab;
+ cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED);
+
+ /* FIXME: Rx STBC needs to be handled specially */
+ cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_RX_STBC_MASK);
+ neg_ht_cap_ie->data.capabilities_info = host_to_le16(cap);
+}
+#endif /* CONFIG_IEEE80211N */
+
+
static void handle_assoc_cb(struct hostapd_data *hapd,
struct ieee80211_mgmt *mgmt,
size_t len, int reassoc, int ok)
@@ -1534,7 +1584,11 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
u16 status;
struct sta_info *sta;
int new_assoc = 1;
- struct ht_cap_ie *ht_cap = NULL;
+#ifdef CONFIG_IEEE80211N
+ struct ht_cap_ie ht_cap;
+#endif /* CONFIG_IEEE80211N */
+ struct ht_cap_ie *ht_cap_ptr = NULL;
+ int set_flags, flags_and, flags_or;
if (!ok) {
hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
@@ -1584,18 +1638,27 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
mlme_associate_indication(hapd, sta);
#ifdef CONFIG_IEEE80211N
- if (sta->flags & WLAN_STA_HT)
- ht_cap = &sta->ht_capabilities;
+ if (sta->flags & WLAN_STA_HT) {
+ ht_cap_ptr = &ht_cap;
+ hostapd_get_ht_capab(hapd, &sta->ht_capabilities, ht_cap_ptr);
+ }
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211W
sta->sa_query_timed_out = 0;
#endif /* CONFIG_IEEE80211W */
+ /*
+ * Remove the STA entry in order to make sure the STA PS state gets
+ * cleared and configuration gets updated in case of reassociation back
+ * to the same AP.
+ */
+ hostapd_sta_remove(hapd, sta->addr);
+
if (hostapd_sta_add(hapd->conf->iface, hapd, sta->addr, sta->aid,
sta->capability, sta->supported_rates,
sta->supported_rates_len, 0, sta->listen_interval,
- ht_cap))
+ ht_cap_ptr))
{
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_NOTICE,
@@ -1613,13 +1676,15 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
/* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
ap_sta_bind_vlan(hapd, sta, 0);
}
- if (sta->flags & WLAN_STA_SHORT_PREAMBLE) {
- hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
- WLAN_STA_SHORT_PREAMBLE, ~0);
- } else {
- hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
- 0, ~WLAN_STA_SHORT_PREAMBLE);
- }
+
+ set_flags = WLAN_STA_SHORT_PREAMBLE | WLAN_STA_WMM | WLAN_STA_MFP;
+ if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
+ sta->flags & WLAN_STA_AUTHORIZED)
+ set_flags |= WLAN_STA_AUTHORIZED;
+ flags_or = sta->flags & set_flags;
+ flags_and = sta->flags | ~set_flags;
+ hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
+ flags_or, flags_and);
if (sta->auth_alg == WLAN_AUTH_FT)
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
diff --git a/contrib/wpa/hostapd/ieee802_1x.c b/contrib/wpa/hostapd/ieee802_1x.c
index 9b096d4..7fd8028 100644
--- a/contrib/wpa/hostapd/ieee802_1x.c
+++ b/contrib/wpa/hostapd/ieee802_1x.c
@@ -164,7 +164,7 @@ static void ieee802_1x_tx_key_one(struct hostapd_data *hapd,
}
os_memcpy(ekey, key->key_iv, sizeof(key->key_iv));
os_memcpy(ekey + sizeof(key->key_iv), sm->eap_if->eapKeyData, 32);
- rc4((u8 *) (key + 1), key_len, ekey, ekey_len);
+ rc4_skip(ekey, ekey_len, 0, (u8 *) (key + 1), key_len);
os_free(ekey);
/* This header is needed here for HMAC-MD5, but it will be regenerated
diff --git a/contrib/wpa/hostapd/preauth.c b/contrib/wpa/hostapd/preauth.c
index 36af4e3..9ab41ed 100644
--- a/contrib/wpa/hostapd/preauth.c
+++ b/contrib/wpa/hostapd/preauth.c
@@ -171,6 +171,7 @@ int rsn_preauth_iface_init(struct hostapd_data *hapd)
if (rsn_preauth_iface_add(hapd, start)) {
rsn_preauth_iface_deinit(hapd);
+ os_free(tmp);
return -1;
}
diff --git a/contrib/wpa/hostapd/radiotap.c b/contrib/wpa/hostapd/radiotap.c
new file mode 100644
index 0000000..804473f
--- /dev/null
+++ b/contrib/wpa/hostapd/radiotap.c
@@ -0,0 +1,287 @@
+/*
+ * Radiotap parser
+ *
+ * Copyright 2007 Andy Green <andy@warmcat.com>
+ *
+ * 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.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ *
+ *
+ * Modified for userspace by Johannes Berg <johannes@sipsolutions.net>
+ * I only modified some things on top to ease syncing should bugs be found.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "radiotap_iter.h"
+
+#define le16_to_cpu le_to_host16
+#define le32_to_cpu le_to_host32
+#define __le32 uint32_t
+#define ulong unsigned long
+#define unlikely(cond) (cond)
+#define get_unaligned(p) \
+({ \
+ struct packed_dummy_struct { \
+ typeof(*(p)) __val; \
+ } __attribute__((packed)) *__ptr = (void *) (p); \
+ \
+ __ptr->__val; \
+})
+
+/* function prototypes and related defs are in radiotap_iter.h */
+
+/**
+ * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
+ * @iterator: radiotap_iterator to initialize
+ * @radiotap_header: radiotap header to parse
+ * @max_length: total length we can parse into (eg, whole packet length)
+ *
+ * Returns: 0 or a negative error code if there is a problem.
+ *
+ * This function initializes an opaque iterator struct which can then
+ * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
+ * argument which is present in the header. It knows about extended
+ * present headers and handles them.
+ *
+ * How to use:
+ * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
+ * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
+ * checking for a good 0 return code. Then loop calling
+ * __ieee80211_radiotap_iterator_next()... it returns either 0,
+ * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem.
+ * The iterator's @this_arg member points to the start of the argument
+ * associated with the current argument index that is present, which can be
+ * found in the iterator's @this_arg_index member. This arg index corresponds
+ * to the IEEE80211_RADIOTAP_... defines.
+ *
+ * Radiotap header length:
+ * You can find the CPU-endian total radiotap header length in
+ * iterator->max_length after executing ieee80211_radiotap_iterator_init()
+ * successfully.
+ *
+ * Alignment Gotcha:
+ * You must take care when dereferencing iterator.this_arg
+ * for multibyte types... the pointer is not aligned. Use
+ * get_unaligned((type *)iterator.this_arg) to dereference
+ * iterator.this_arg for type "type" safely on all arches.
+ *
+ * Example code:
+ * See Documentation/networking/radiotap-headers.txt
+ */
+
+int ieee80211_radiotap_iterator_init(
+ struct ieee80211_radiotap_iterator *iterator,
+ struct ieee80211_radiotap_header *radiotap_header,
+ int max_length)
+{
+ /* Linux only supports version 0 radiotap format */
+ if (radiotap_header->it_version)
+ return -EINVAL;
+
+ /* sanity check for allowed length and radiotap length field */
+ if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len)))
+ return -EINVAL;
+
+ iterator->rtheader = radiotap_header;
+ iterator->max_length = le16_to_cpu(get_unaligned(
+ &radiotap_header->it_len));
+ iterator->arg_index = 0;
+ iterator->bitmap_shifter = le32_to_cpu(get_unaligned(
+ &radiotap_header->it_present));
+ iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header);
+ iterator->this_arg = NULL;
+
+ /* find payload start allowing for extended bitmap(s) */
+
+ if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) {
+ while (le32_to_cpu(get_unaligned((__le32 *)iterator->arg)) &
+ (1<<IEEE80211_RADIOTAP_EXT)) {
+ iterator->arg += sizeof(u32);
+
+ /*
+ * check for insanity where the present bitmaps
+ * keep claiming to extend up to or even beyond the
+ * stated radiotap header length
+ */
+
+ if (((ulong)iterator->arg - (ulong)iterator->rtheader)
+ > (ulong)iterator->max_length)
+ return -EINVAL;
+ }
+
+ iterator->arg += sizeof(u32);
+
+ /*
+ * no need to check again for blowing past stated radiotap
+ * header length, because ieee80211_radiotap_iterator_next
+ * checks it before it is dereferenced
+ */
+ }
+
+ /* we are all initialized happily */
+
+ return 0;
+}
+
+
+/**
+ * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
+ * @iterator: radiotap_iterator to move to next arg (if any)
+ *
+ * Returns: 0 if there is an argument to handle,
+ * -ENOENT if there are no more args or -EINVAL
+ * if there is something else wrong.
+ *
+ * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*)
+ * in @this_arg_index and sets @this_arg to point to the
+ * payload for the field. It takes care of alignment handling and extended
+ * present fields. @this_arg can be changed by the caller (eg,
+ * incremented to move inside a compound argument like
+ * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in
+ * little-endian format whatever the endianess of your CPU.
+ *
+ * Alignment Gotcha:
+ * You must take care when dereferencing iterator.this_arg
+ * for multibyte types... the pointer is not aligned. Use
+ * get_unaligned((type *)iterator.this_arg) to dereference
+ * iterator.this_arg for type "type" safely on all arches.
+ */
+
+int ieee80211_radiotap_iterator_next(
+ struct ieee80211_radiotap_iterator *iterator)
+{
+
+ /*
+ * small length lookup table for all radiotap types we heard of
+ * starting from b0 in the bitmap, so we can walk the payload
+ * area of the radiotap header
+ *
+ * There is a requirement to pad args, so that args
+ * of a given length must begin at a boundary of that length
+ * -- but note that compound args are allowed (eg, 2 x u16
+ * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not
+ * a reliable indicator of alignment requirement.
+ *
+ * upper nybble: content alignment for arg
+ * lower nybble: content length for arg
+ */
+
+ static const u8 rt_sizes[] = {
+ [IEEE80211_RADIOTAP_TSFT] = 0x88,
+ [IEEE80211_RADIOTAP_FLAGS] = 0x11,
+ [IEEE80211_RADIOTAP_RATE] = 0x11,
+ [IEEE80211_RADIOTAP_CHANNEL] = 0x24,
+ [IEEE80211_RADIOTAP_FHSS] = 0x22,
+ [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11,
+ [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11,
+ [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22,
+ [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22,
+ [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22,
+ [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11,
+ [IEEE80211_RADIOTAP_ANTENNA] = 0x11,
+ [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11,
+ [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11,
+ [IEEE80211_RADIOTAP_RX_FLAGS] = 0x22,
+ [IEEE80211_RADIOTAP_TX_FLAGS] = 0x22,
+ [IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11,
+ [IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11,
+ /*
+ * add more here as they are defined in
+ * include/net/ieee80211_radiotap.h
+ */
+ };
+
+ /*
+ * for every radiotap entry we can at
+ * least skip (by knowing the length)...
+ */
+
+ while (iterator->arg_index < (int) sizeof(rt_sizes)) {
+ int hit = 0;
+ int pad;
+
+ if (!(iterator->bitmap_shifter & 1))
+ goto next_entry; /* arg not present */
+
+ /*
+ * arg is present, account for alignment padding
+ * 8-bit args can be at any alignment
+ * 16-bit args must start on 16-bit boundary
+ * 32-bit args must start on 32-bit boundary
+ * 64-bit args must start on 64-bit boundary
+ *
+ * note that total arg size can differ from alignment of
+ * elements inside arg, so we use upper nybble of length
+ * table to base alignment on
+ *
+ * also note: these alignments are ** relative to the
+ * start of the radiotap header **. There is no guarantee
+ * that the radiotap header itself is aligned on any
+ * kind of boundary.
+ *
+ * the above is why get_unaligned() is used to dereference
+ * multibyte elements from the radiotap area
+ */
+
+ pad = (((ulong)iterator->arg) -
+ ((ulong)iterator->rtheader)) &
+ ((rt_sizes[iterator->arg_index] >> 4) - 1);
+
+ if (pad)
+ iterator->arg +=
+ (rt_sizes[iterator->arg_index] >> 4) - pad;
+
+ /*
+ * this is what we will return to user, but we need to
+ * move on first so next call has something fresh to test
+ */
+ iterator->this_arg_index = iterator->arg_index;
+ iterator->this_arg = iterator->arg;
+ hit = 1;
+
+ /* internally move on the size of this arg */
+ iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
+
+ /*
+ * check for insanity where we are given a bitmap that
+ * claims to have more arg content than the length of the
+ * radiotap section. We will normally end up equalling this
+ * max_length on the last arg, never exceeding it.
+ */
+
+ if (((ulong)iterator->arg - (ulong)iterator->rtheader) >
+ (ulong) iterator->max_length)
+ return -EINVAL;
+
+ next_entry:
+ iterator->arg_index++;
+ if (unlikely((iterator->arg_index & 31) == 0)) {
+ /* completed current u32 bitmap */
+ if (iterator->bitmap_shifter & 1) {
+ /* b31 was set, there is more */
+ /* move to next u32 bitmap */
+ iterator->bitmap_shifter = le32_to_cpu(
+ get_unaligned(iterator->next_bitmap));
+ iterator->next_bitmap++;
+ } else
+ /* no more bitmaps: end */
+ iterator->arg_index = sizeof(rt_sizes);
+ } else /* just try the next bit */
+ iterator->bitmap_shifter >>= 1;
+
+ /* if we found a valid arg earlier, return it now */
+ if (hit)
+ return 0;
+ }
+
+ /* we don't know how to handle any more args, we're done */
+ return -ENOENT;
+}
diff --git a/contrib/wpa/hostapd/radiotap.h b/contrib/wpa/hostapd/radiotap.h
new file mode 100644
index 0000000..508264c
--- /dev/null
+++ b/contrib/wpa/hostapd/radiotap.h
@@ -0,0 +1,242 @@
+/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
+/* $NetBSD: ieee80211_radiotap.h,v 1.11 2005/06/22 06:16:02 dyoung Exp $ */
+
+/*-
+ * Copyright (c) 2003, 2004 David Young. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of David Young may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
+ * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+/*
+ * Modifications to fit into the linux IEEE 802.11 stack,
+ * Mike Kershaw (dragorn@kismetwireless.net)
+ */
+
+#ifndef IEEE80211RADIOTAP_H
+#define IEEE80211RADIOTAP_H
+
+#include <stdint.h>
+
+/* Base version of the radiotap packet header data */
+#define PKTHDR_RADIOTAP_VERSION 0
+
+/* A generic radio capture format is desirable. There is one for
+ * Linux, but it is neither rigidly defined (there were not even
+ * units given for some fields) nor easily extensible.
+ *
+ * I suggest the following extensible radio capture format. It is
+ * based on a bitmap indicating which fields are present.
+ *
+ * I am trying to describe precisely what the application programmer
+ * should expect in the following, and for that reason I tell the
+ * units and origin of each measurement (where it applies), or else I
+ * use sufficiently weaselly language ("is a monotonically nondecreasing
+ * function of...") that I cannot set false expectations for lawyerly
+ * readers.
+ */
+
+/* The radio capture header precedes the 802.11 header.
+ * All data in the header is little endian on all platforms.
+ */
+struct ieee80211_radiotap_header {
+ uint8_t it_version; /* Version 0. Only increases
+ * for drastic changes,
+ * introduction of compatible
+ * new fields does not count.
+ */
+ uint8_t it_pad;
+ uint16_t it_len; /* length of the whole
+ * header in bytes, including
+ * it_version, it_pad,
+ * it_len, and data fields.
+ */
+ uint32_t it_present; /* A bitmap telling which
+ * fields are present. Set bit 31
+ * (0x80000000) to extend the
+ * bitmap by another 32 bits.
+ * Additional extensions are made
+ * by setting bit 31.
+ */
+};
+
+/* Name Data type Units
+ * ---- --------- -----
+ *
+ * IEEE80211_RADIOTAP_TSFT __le64 microseconds
+ *
+ * Value in microseconds of the MAC's 64-bit 802.11 Time
+ * Synchronization Function timer when the first bit of the
+ * MPDU arrived at the MAC. For received frames, only.
+ *
+ * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap
+ *
+ * Tx/Rx frequency in MHz, followed by flags (see below).
+ *
+ * IEEE80211_RADIOTAP_FHSS uint16_t see below
+ *
+ * For frequency-hopping radios, the hop set (first byte)
+ * and pattern (second byte).
+ *
+ * IEEE80211_RADIOTAP_RATE u8 500kb/s
+ *
+ * Tx/Rx data rate
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from
+ * one milliwatt (dBm)
+ *
+ * RF signal power at the antenna, decibel difference from
+ * one milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from
+ * one milliwatt (dBm)
+ *
+ * RF noise power at the antenna, decibel difference from one
+ * milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB)
+ *
+ * RF signal power at the antenna, decibel difference from an
+ * arbitrary, fixed reference.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB)
+ *
+ * RF noise power at the antenna, decibel difference from an
+ * arbitrary, fixed reference point.
+ *
+ * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless
+ *
+ * Quality of Barker code lock. Unitless. Monotonically
+ * nondecreasing with "better" lock strength. Called "Signal
+ * Quality" in datasheets. (Is there a standard way to measure
+ * this?)
+ *
+ * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless
+ *
+ * Transmit power expressed as unitless distance from max
+ * power set at factory calibration. 0 is max power.
+ * Monotonically nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB)
+ *
+ * Transmit power expressed as decibel distance from max power
+ * set at factory calibration. 0 is max power. Monotonically
+ * nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from
+ * one milliwatt (dBm)
+ *
+ * Transmit power expressed as dBm (decibels from a 1 milliwatt
+ * reference). This is the absolute power level measured at
+ * the antenna port.
+ *
+ * IEEE80211_RADIOTAP_FLAGS u8 bitmap
+ *
+ * Properties of transmitted and received frames. See flags
+ * defined below.
+ *
+ * IEEE80211_RADIOTAP_ANTENNA u8 antenna index
+ *
+ * Unitless indication of the Rx/Tx antenna for this packet.
+ * The first antenna is antenna 0.
+ *
+ * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap
+ *
+ * Properties of received frames. See flags defined below.
+ *
+ * IEEE80211_RADIOTAP_TX_FLAGS uint16_t bitmap
+ *
+ * Properties of transmitted frames. See flags defined below.
+ *
+ * IEEE80211_RADIOTAP_RTS_RETRIES u8 data
+ *
+ * Number of rts retries a transmitted frame used.
+ *
+ * IEEE80211_RADIOTAP_DATA_RETRIES u8 data
+ *
+ * Number of unicast retries a transmitted frame used.
+ *
+ */
+enum ieee80211_radiotap_type {
+ IEEE80211_RADIOTAP_TSFT = 0,
+ IEEE80211_RADIOTAP_FLAGS = 1,
+ IEEE80211_RADIOTAP_RATE = 2,
+ IEEE80211_RADIOTAP_CHANNEL = 3,
+ IEEE80211_RADIOTAP_FHSS = 4,
+ IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+ IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+ IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+ IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+ IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+ IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+ IEEE80211_RADIOTAP_ANTENNA = 11,
+ IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+ IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+ IEEE80211_RADIOTAP_RX_FLAGS = 14,
+ IEEE80211_RADIOTAP_TX_FLAGS = 15,
+ IEEE80211_RADIOTAP_RTS_RETRIES = 16,
+ IEEE80211_RADIOTAP_DATA_RETRIES = 17,
+ IEEE80211_RADIOTAP_EXT = 31
+};
+
+/* Channel flags. */
+#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */
+#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */
+#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */
+#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */
+#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */
+#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */
+#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */
+#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */
+
+/* For IEEE80211_RADIOTAP_FLAGS */
+#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
+ * during CFP
+ */
+#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
+ * with short
+ * preamble
+ */
+#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
+ * with WEP encryption
+ */
+#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
+ * with fragmentation
+ */
+#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
+#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
+ * 802.11 header and payload
+ * (to 32-bit boundary)
+ */
+/* For IEEE80211_RADIOTAP_RX_FLAGS */
+#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
+
+/* For IEEE80211_RADIOTAP_TX_FLAGS */
+#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive
+ * retries */
+#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */
+#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
+
+#endif /* IEEE80211_RADIOTAP_H */
diff --git a/contrib/wpa/hostapd/radiotap_iter.h b/contrib/wpa/hostapd/radiotap_iter.h
new file mode 100644
index 0000000..92a798a
--- /dev/null
+++ b/contrib/wpa/hostapd/radiotap_iter.h
@@ -0,0 +1,41 @@
+#ifndef __RADIOTAP_ITER_H
+#define __RADIOTAP_ITER_H
+
+#include "radiotap.h"
+
+/* Radiotap header iteration
+ * implemented in radiotap.c
+ */
+/**
+ * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args
+ * @rtheader: pointer to the radiotap header we are walking through
+ * @max_length: length of radiotap header in cpu byte ordering
+ * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg
+ * @this_arg: pointer to current radiotap arg
+ * @arg_index: internal next argument index
+ * @arg: internal next argument pointer
+ * @next_bitmap: internal pointer to next present u32
+ * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present
+ */
+
+struct ieee80211_radiotap_iterator {
+ struct ieee80211_radiotap_header *rtheader;
+ int max_length;
+ int this_arg_index;
+ unsigned char *this_arg;
+
+ int arg_index;
+ unsigned char *arg;
+ uint32_t *next_bitmap;
+ uint32_t bitmap_shifter;
+};
+
+extern int ieee80211_radiotap_iterator_init(
+ struct ieee80211_radiotap_iterator *iterator,
+ struct ieee80211_radiotap_header *radiotap_header,
+ int max_length);
+
+extern int ieee80211_radiotap_iterator_next(
+ struct ieee80211_radiotap_iterator *iterator);
+
+#endif /* __RADIOTAP_ITER_H */
diff --git a/contrib/wpa/hostapd/wme.c b/contrib/wpa/hostapd/wme.c
index 727ee7e..f2bbbd9 100644
--- a/contrib/wpa/hostapd/wme.c
+++ b/contrib/wpa/hostapd/wme.c
@@ -24,47 +24,63 @@
/* TODO: maintain separate sequence and fragment numbers for each AC
* TODO: IGMP snooping to track which multicasts to forward - and use QOS-DATA
- * if only WME stations are receiving a certain group */
+ * if only WMM stations are receiving a certain group */
-static u8 wme_oui[3] = { 0x00, 0x50, 0xf2 };
+static inline u8 wmm_aci_aifsn(int aifsn, int acm, int aci)
+{
+ u8 ret;
+ ret = (aifsn << WMM_AC_AIFNS_SHIFT) & WMM_AC_AIFSN_MASK;
+ if (acm)
+ ret |= WMM_AC_ACM;
+ ret |= (aci << WMM_AC_ACI_SHIFT) & WMM_AC_ACI_MASK;
+ return ret;
+}
+
+
+static inline u8 wmm_ecw(int ecwmin, int ecwmax)
+{
+ return ((ecwmin << WMM_AC_ECWMIN_SHIFT) & WMM_AC_ECWMIN_MASK) |
+ ((ecwmax << WMM_AC_ECWMAX_SHIFT) & WMM_AC_ECWMAX_MASK);
+}
-/* Add WME Parameter Element to Beacon and Probe Response frames. */
-u8 * hostapd_eid_wme(struct hostapd_data *hapd, u8 *eid)
+/*
+ * Add WMM Parameter Element to Beacon, Probe Response, and (Re)Association
+ * Response frames.
+ */
+u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
{
u8 *pos = eid;
- struct wme_parameter_element *wme =
- (struct wme_parameter_element *) (pos + 2);
+ struct wmm_parameter_element *wmm =
+ (struct wmm_parameter_element *) (pos + 2);
int e;
- if (!hapd->conf->wme_enabled)
+ if (!hapd->conf->wmm_enabled)
return eid;
eid[0] = WLAN_EID_VENDOR_SPECIFIC;
- wme->oui[0] = 0x00;
- wme->oui[1] = 0x50;
- wme->oui[2] = 0xf2;
- wme->oui_type = WME_OUI_TYPE;
- wme->oui_subtype = WME_OUI_SUBTYPE_PARAMETER_ELEMENT;
- wme->version = WME_VERSION;
- wme->acInfo = hapd->parameter_set_count & 0xf;
+ wmm->oui[0] = 0x00;
+ wmm->oui[1] = 0x50;
+ wmm->oui[2] = 0xf2;
+ wmm->oui_type = WMM_OUI_TYPE;
+ wmm->oui_subtype = WMM_OUI_SUBTYPE_PARAMETER_ELEMENT;
+ wmm->version = WMM_VERSION;
+ wmm->qos_info = hapd->parameter_set_count & 0xf;
/* fill in a parameter set record for each AC */
for (e = 0; e < 4; e++) {
- struct wme_ac_parameter *ac = &wme->ac[e];
- struct hostapd_wme_ac_params *acp =
- &hapd->iconf->wme_ac_params[e];
-
- ac->aifsn = acp->aifs;
- ac->acm = acp->admission_control_mandatory;
- ac->aci = e;
- ac->reserved = 0;
- ac->eCWmin = acp->cwmin;
- ac->eCWmax = acp->cwmax;
- ac->txopLimit = host_to_le16(acp->txopLimit);
+ struct wmm_ac_parameter *ac = &wmm->ac[e];
+ struct hostapd_wmm_ac_params *acp =
+ &hapd->iconf->wmm_ac_params[e];
+
+ ac->aci_aifsn = wmm_aci_aifsn(acp->aifs,
+ acp->admission_control_mandatory,
+ e);
+ ac->cw = wmm_ecw(acp->cwmin, acp->cwmax);
+ ac->txop_limit = host_to_le16(acp->txop_limit);
}
- pos = (u8 *) (wme + 1);
+ pos = (u8 *) (wmm + 1);
eid[1] = pos - eid - 2; /* element length */
return pos;
@@ -72,31 +88,28 @@ u8 * hostapd_eid_wme(struct hostapd_data *hapd, u8 *eid)
/* This function is called when a station sends an association request with
- * WME info element. The function returns zero on success or non-zero on any
- * error in WME element. eid does not include Element ID and Length octets. */
-int hostapd_eid_wme_valid(struct hostapd_data *hapd, u8 *eid, size_t len)
+ * WMM info element. The function returns zero on success or non-zero on any
+ * error in WMM element. eid does not include Element ID and Length octets. */
+int hostapd_eid_wmm_valid(struct hostapd_data *hapd, u8 *eid, size_t len)
{
- struct wme_information_element *wme;
+ struct wmm_information_element *wmm;
- wpa_hexdump(MSG_MSGDUMP, "WME IE", eid, len);
+ wpa_hexdump(MSG_MSGDUMP, "WMM IE", eid, len);
- if (len < sizeof(struct wme_information_element)) {
- wpa_printf(MSG_DEBUG, "Too short WME IE (len=%lu)",
+ if (len < sizeof(struct wmm_information_element)) {
+ wpa_printf(MSG_DEBUG, "Too short WMM IE (len=%lu)",
(unsigned long) len);
return -1;
}
- wme = (struct wme_information_element *) eid;
- wpa_printf(MSG_DEBUG, "Validating WME IE: OUI %02x:%02x:%02x "
- "OUI type %d OUI sub-type %d version %d",
- wme->oui[0], wme->oui[1], wme->oui[2], wme->oui_type,
- wme->oui_subtype, wme->version);
- if (os_memcmp(wme->oui, wme_oui, sizeof(wme_oui)) != 0 ||
- wme->oui_type != WME_OUI_TYPE ||
- wme->oui_subtype != WME_OUI_SUBTYPE_INFORMATION_ELEMENT ||
- wme->version != WME_VERSION) {
- wpa_printf(MSG_DEBUG, "Unsupported WME IE OUI/Type/Subtype/"
- "Version");
+ wmm = (struct wmm_information_element *) eid;
+ wpa_printf(MSG_DEBUG, "Validating WMM IE: OUI %02x:%02x:%02x "
+ "OUI type %d OUI sub-type %d version %d QoS info 0x%x",
+ wmm->oui[0], wmm->oui[1], wmm->oui[2], wmm->oui_type,
+ wmm->oui_subtype, wmm->version, wmm->qos_info);
+ if (wmm->oui_subtype != WMM_OUI_SUBTYPE_INFORMATION_ELEMENT ||
+ wmm->version != WMM_VERSION) {
+ wpa_printf(MSG_DEBUG, "Unsupported WMM IE Subtype/Version");
return -1;
}
@@ -105,31 +118,30 @@ int hostapd_eid_wme_valid(struct hostapd_data *hapd, u8 *eid, size_t len)
/* This function is called when a station sends an ACK frame for an AssocResp
- * frame (status=success) and the matching AssocReq contained a WME element.
+ * frame (status=success) and the matching AssocReq contained a WMM element.
*/
-int hostapd_wme_sta_config(struct hostapd_data *hapd, struct sta_info *sta)
+int hostapd_wmm_sta_config(struct hostapd_data *hapd, struct sta_info *sta)
{
- /* update kernel STA data for WME related items (WLAN_STA_WPA flag) */
- if (sta->flags & WLAN_STA_WME)
+ /* update kernel STA data for WMM related items (WLAN_STA_WPA flag) */
+ if (sta->flags & WLAN_STA_WMM)
hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
- WLAN_STA_WME, ~0);
+ WLAN_STA_WMM, ~0);
else
hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
- 0, ~WLAN_STA_WME);
+ 0, ~WLAN_STA_WMM);
return 0;
}
-static void wme_send_action(struct hostapd_data *hapd, const u8 *addr,
- const struct wme_tspec_info_element *tspec,
+static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr,
+ const struct wmm_tspec_element *tspec,
u8 action_code, u8 dialogue_token, u8 status_code)
{
u8 buf[256];
struct ieee80211_mgmt *m = (struct ieee80211_mgmt *) buf;
- struct wme_tspec_info_element *t =
- (struct wme_tspec_info_element *)
- m->u.action.u.wme_action.variable;
+ struct wmm_tspec_element *t = (struct wmm_tspec_element *)
+ m->u.action.u.wmm_action.variable;
int len;
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
@@ -142,55 +154,117 @@ static void wme_send_action(struct hostapd_data *hapd, const u8 *addr,
os_memcpy(m->sa, hapd->own_addr, ETH_ALEN);
os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
m->u.action.category = WLAN_ACTION_WMM;
- m->u.action.u.wme_action.action_code = action_code;
- m->u.action.u.wme_action.dialog_token = dialogue_token;
- m->u.action.u.wme_action.status_code = status_code;
- os_memcpy(t, tspec, sizeof(struct wme_tspec_info_element));
+ m->u.action.u.wmm_action.action_code = action_code;
+ m->u.action.u.wmm_action.dialog_token = dialogue_token;
+ m->u.action.u.wmm_action.status_code = status_code;
+ os_memcpy(t, tspec, sizeof(struct wmm_tspec_element));
len = ((u8 *) (t + 1)) - buf;
if (hostapd_send_mgmt_frame(hapd, m, len, 0) < 0)
- perror("wme_send_action: send");
+ perror("wmm_send_action: send");
}
-/* given frame data payload size in bytes, and data_rate in bits per second
- * returns time to complete frame exchange */
-/* FIX: should not use floating point types */
-static double wme_frame_exchange_time(int bytes, int data_rate, int encryption,
- int cts_protection)
+static void wmm_addts_req(struct hostapd_data *hapd,
+ struct ieee80211_mgmt *mgmt,
+ struct wmm_tspec_element *tspec, size_t len)
{
- /* TODO: account for MAC/PHY headers correctly */
- /* TODO: account for encryption headers */
- /* TODO: account for WDS headers */
- /* TODO: account for CTS protection */
- /* TODO: account for SIFS + ACK at minimum PHY rate */
- return (bytes + 400) * 8.0 / data_rate;
-}
+ u8 *end = ((u8 *) mgmt) + len;
+ int medium_time, pps, duration;
+ int up, psb, dir, tid;
+ u16 val, surplus;
+ if ((u8 *) (tspec + 1) > end) {
+ wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request");
+ return;
+ }
-static void wme_setup_request(struct hostapd_data *hapd,
- struct ieee80211_mgmt *mgmt,
- struct wme_tspec_info_element *tspec, size_t len)
-{
- /* FIX: should not use floating point types */
- double medium_time, pps;
+ wpa_printf(MSG_DEBUG, "WMM: ADDTS Request (Dialog Token %d) for TSPEC "
+ "from " MACSTR,
+ mgmt->u.action.u.wmm_action.dialog_token,
+ MAC2STR(mgmt->sa));
+
+ up = (tspec->ts_info[1] >> 3) & 0x07;
+ psb = (tspec->ts_info[1] >> 2) & 0x01;
+ dir = (tspec->ts_info[0] >> 5) & 0x03;
+ tid = (tspec->ts_info[0] >> 1) & 0x0f;
+ wpa_printf(MSG_DEBUG, "WMM: TS Info: UP=%d PSB=%d Direction=%d TID=%d",
+ up, psb, dir, tid);
+ val = le_to_host16(tspec->nominal_msdu_size);
+ wpa_printf(MSG_DEBUG, "WMM: Nominal MSDU Size: %d%s",
+ val & 0x7fff, val & 0x8000 ? " (fixed)" : "");
+ wpa_printf(MSG_DEBUG, "WMM: Mean Data Rate: %u bps",
+ le_to_host32(tspec->mean_data_rate));
+ wpa_printf(MSG_DEBUG, "WMM: Minimum PHY Rate: %u bps",
+ le_to_host32(tspec->minimum_phy_rate));
+ val = le_to_host16(tspec->surplus_bandwidth_allowance);
+ wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance: %u.%04u",
+ val >> 13, 10000 * (val & 0x1fff) / 0x2000);
+
+ val = le_to_host16(tspec->nominal_msdu_size);
+ if (val == 0) {
+ wpa_printf(MSG_DEBUG, "WMM: Invalid Nominal MSDU Size (0)");
+ goto invalid;
+ }
+ /* pps = Ceiling((Mean Data Rate / 8) / Nominal MSDU Size) */
+ pps = ((le_to_host32(tspec->mean_data_rate) / 8) + val - 1) / val;
+ wpa_printf(MSG_DEBUG, "WMM: Packets-per-second estimate for TSPEC: %d",
+ pps);
+
+ if (le_to_host32(tspec->minimum_phy_rate) < 1000000) {
+ wpa_printf(MSG_DEBUG, "WMM: Too small Minimum PHY Rate");
+ goto invalid;
+ }
+
+ duration = (le_to_host16(tspec->nominal_msdu_size) & 0x7fff) * 8 /
+ (le_to_host32(tspec->minimum_phy_rate) / 1000000) +
+ 50 /* FIX: proper SIFS + ACK duration */;
+
+ /* unsigned binary number with an implicit binary point after the
+ * leftmost 3 bits, i.e., 0x2000 = 1.0 */
+ surplus = le_to_host16(tspec->surplus_bandwidth_allowance);
+ if (surplus <= 0x2000) {
+ wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance not "
+ "greater than unity");
+ goto invalid;
+ }
+
+ medium_time = surplus * pps * duration / 0x2000;
+ wpa_printf(MSG_DEBUG, "WMM: Estimated medium time: %u", medium_time);
+
+ /*
+ * TODO: store list of granted (and still active) TSPECs and check
+ * whether there is available medium time for this request. For now,
+ * just refuse requests that would by themselves take very large
+ * portion of the available bandwidth.
+ */
+ if (medium_time > 750000) {
+ wpa_printf(MSG_DEBUG, "WMM: Refuse TSPEC request for over "
+ "75%% of available bandwidth");
+ wmm_send_action(hapd, mgmt->sa, tspec,
+ WMM_ACTION_CODE_ADDTS_RESP,
+ mgmt->u.action.u.wmm_action.dialog_token,
+ WMM_ADDTS_STATUS_REFUSED);
+ return;
+ }
- /* TODO: account for airtime and answer no to tspec setup requests
- * when none left!! */
+ /* Convert to 32 microseconds per second unit */
+ tspec->medium_time = host_to_le16(medium_time / 32);
- pps = (tspec->mean_data_rate / 8.0) / tspec->nominal_msdu_size;
- medium_time = (tspec->surplus_bandwidth_allowance / 8) * pps *
- wme_frame_exchange_time(tspec->nominal_msdu_size,
- tspec->minimum_phy_rate, 0, 0);
- tspec->medium_time = medium_time * 1000000.0 / 32.0;
+ wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP,
+ mgmt->u.action.u.wmm_action.dialog_token,
+ WMM_ADDTS_STATUS_ADMISSION_ACCEPTED);
+ return;
- wme_send_action(hapd, mgmt->sa, tspec, WME_ACTION_CODE_SETUP_RESPONSE,
- mgmt->u.action.u.wme_action.dialog_token,
- WME_SETUP_RESPONSE_STATUS_ADMISSION_ACCEPTED);
+invalid:
+ wmm_send_action(hapd, mgmt->sa, tspec,
+ WMM_ACTION_CODE_ADDTS_RESP,
+ mgmt->u.action.u.wmm_action.dialog_token,
+ WMM_ADDTS_STATUS_INVALID_PARAMETERS);
}
-void hostapd_wme_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
+void hostapd_wmm_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
size_t len)
{
int action_code;
@@ -201,11 +275,11 @@ void hostapd_wme_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
/* check that the request comes from a valid station */
if (!sta ||
- (sta->flags & (WLAN_STA_ASSOC | WLAN_STA_WME)) !=
- (WLAN_STA_ASSOC | WLAN_STA_WME)) {
+ (sta->flags & (WLAN_STA_ASSOC | WLAN_STA_WMM)) !=
+ (WLAN_STA_ASSOC | WLAN_STA_WMM)) {
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
- "wme action received is not from associated wme"
+ "wmm action received is not from associated wmm"
" station");
/* TODO: respond with action frame refused status code */
return;
@@ -215,19 +289,18 @@ void hostapd_wme_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
if (ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) {
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
- "hostapd_wme_action - could not parse wme "
+ "hostapd_wmm_action - could not parse wmm "
"action");
/* TODO: respond with action frame invalid parameters status
* code */
return;
}
- if (!elems.wme_tspec ||
- elems.wme_tspec_len != (sizeof(struct wme_tspec_info_element) - 2))
- {
+ if (!elems.wmm_tspec ||
+ elems.wmm_tspec_len != (sizeof(struct wmm_tspec_element) - 2)) {
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
- "hostapd_wme_action - missing or wrong length "
+ "hostapd_wmm_action - missing or wrong length "
"tspec");
/* TODO: respond with action frame invalid parameters status
* code */
@@ -237,26 +310,26 @@ void hostapd_wme_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
/* TODO: check the request is for an AC with ACM set, if not, refuse
* request */
- action_code = mgmt->u.action.u.wme_action.action_code;
+ action_code = mgmt->u.action.u.wmm_action.action_code;
switch (action_code) {
- case WME_ACTION_CODE_SETUP_REQUEST:
- wme_setup_request(hapd, mgmt, (struct wme_tspec_info_element *)
- elems.wme_tspec, len);
+ case WMM_ACTION_CODE_ADDTS_REQ:
+ wmm_addts_req(hapd, mgmt, (struct wmm_tspec_element *)
+ (elems.wmm_tspec - 2), len);
return;
#if 0
/* TODO: needed for client implementation */
- case WME_ACTION_CODE_SETUP_RESPONSE:
- wme_setup_request(hapd, mgmt, len);
+ case WMM_ACTION_CODE_ADDTS_RESP:
+ wmm_setup_request(hapd, mgmt, len);
return;
/* TODO: handle station teardown requests */
- case WME_ACTION_CODE_TEARDOWN:
- wme_teardown(hapd, mgmt, len);
+ case WMM_ACTION_CODE_DELTS:
+ wmm_teardown(hapd, mgmt, len);
return;
#endif
}
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
- "hostapd_wme_action - unknown action code %d",
+ "hostapd_wmm_action - unknown action code %d",
action_code);
}
diff --git a/contrib/wpa/hostapd/wme.h b/contrib/wpa/hostapd/wme.h
index 3c80c01..9bc48cb 100644
--- a/contrib/wpa/hostapd/wme.h
+++ b/contrib/wpa/hostapd/wme.h
@@ -16,9 +16,19 @@
#ifndef WME_H
#define WME_H
-#ifdef __linux__
-#include <endian.h>
-#endif /* __linux__ */
+/*
+ * WMM Information Element (used in (Re)Association Request frames; may also be
+ * used in Beacon frames)
+ */
+struct wmm_information_element {
+ /* Element ID: 221 (0xdd); Length: 7 */
+ /* required fields for WMM version 1 */
+ u8 oui[3]; /* 00:50:f2 */
+ u8 oui_type; /* 2 */
+ u8 oui_subtype; /* 0 */
+ u8 version; /* 1 for WMM version 1.0 */
+ u8 qos_info; /* AP/STA specific QoS info */
+};
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
#include <sys/types.h>
@@ -44,86 +54,82 @@ struct wme_information_element {
} __attribute__ ((packed));
-struct wme_ac_parameter {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
- /* byte 1 */
- u8 aifsn:4,
- acm:1,
- aci:2,
- reserved:1;
-
- /* byte 2 */
- u8 eCWmin:4,
- eCWmax:4;
-#elif __BYTE_ORDER == __BIG_ENDIAN
- /* byte 1 */
- u8 reserved:1,
- aci:2,
- acm:1,
- aifsn:4;
-
- /* byte 2 */
- u8 eCWmax:4,
- eCWmin:4;
-#else
-#error "Please fix <endian.h>"
-#endif
-
- /* bytes 3 & 4 */
- le16 txopLimit;
+#define WMM_AC_AIFSN_MASK 0x0f
+#define WMM_AC_AIFNS_SHIFT 0
+#define WMM_AC_ACM 0x10
+#define WMM_AC_ACI_MASK 0x60
+#define WMM_AC_ACI_SHIFT 5
+
+#define WMM_AC_ECWMIN_MASK 0x0f
+#define WMM_AC_ECWMIN_SHIFT 0
+#define WMM_AC_ECWMAX_MASK 0xf0
+#define WMM_AC_ECWMAX_SHIFT 4
+
+struct wmm_ac_parameter {
+ u8 aci_aifsn; /* AIFSN, ACM, ACI */
+ u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */
+ le16 txop_limit;
} __attribute__ ((packed));
-struct wme_parameter_element {
- /* required fields for WME version 1 */
- u8 oui[3];
- u8 oui_type;
- u8 oui_subtype;
- u8 version;
- u8 acInfo;
- u8 reserved;
- struct wme_ac_parameter ac[4];
+/*
+ * WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association
+ * Response frmaes)
+ */
+struct wmm_parameter_element {
+ /* Element ID: 221 (0xdd); Length: 24 */
+ /* required fields for WMM version 1 */
+ u8 oui[3]; /* 00:50:f2 */
+ u8 oui_type; /* 2 */
+ u8 oui_subtype; /* 1 */
+ u8 version; /* 1 for WMM version 1.0 */
+ u8 qos_info; /* AP/STA specif QoS info */
+ u8 reserved; /* 0 */
+ struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */
} __attribute__ ((packed));
-struct wme_tspec_info_element {
- u8 eid;
- u8 length;
- u8 oui[3];
- u8 oui_type;
- u8 oui_subtype;
- u8 version;
- u16 ts_info;
- u16 nominal_msdu_size;
- u16 maximum_msdu_size;
- u32 minimum_service_interval;
- u32 maximum_service_interval;
- u32 inactivity_interval;
- u32 start_time;
- u32 minimum_data_rate;
- u32 mean_data_rate;
- u32 maximum_burst_size;
- u32 minimum_phy_rate;
- u32 peak_data_rate;
- u32 delay_bound;
- u16 surplus_bandwidth_allowance;
- u16 medium_time;
+/* WMM TSPEC Element */
+struct wmm_tspec_element {
+ u8 eid; /* 221 = 0xdd */
+ u8 length; /* 6 + 55 = 61 */
+ u8 oui[3]; /* 00:50:f2 */
+ u8 oui_type; /* 2 */
+ u8 oui_subtype; /* 2 */
+ u8 version; /* 1 */
+ /* WMM TSPEC body (55 octets): */
+ u8 ts_info[3];
+ le16 nominal_msdu_size;
+ le16 maximum_msdu_size;
+ le32 minimum_service_interval;
+ le32 maximum_service_interval;
+ le32 inactivity_interval;
+ le32 suspension_interval;
+ le32 service_start_time;
+ le32 minimum_data_rate;
+ le32 mean_data_rate;
+ le32 peak_data_rate;
+ le32 maximum_burst_size;
+ le32 delay_bound;
+ le32 minimum_phy_rate;
+ le16 surplus_bandwidth_allowance;
+ le16 medium_time;
} __attribute__ ((packed));
-/* Access Categories */
+/* Access Categories / ACI to AC coding */
enum {
- WME_AC_BK = 1,
- WME_AC_BE = 0,
- WME_AC_VI = 2,
- WME_AC_VO = 3
+ WMM_AC_BE = 0 /* Best Effort */,
+ WMM_AC_BK = 1 /* Background */,
+ WMM_AC_VI = 2 /* Video */,
+ WMM_AC_VO = 3 /* Voice */
};
struct ieee80211_mgmt;
-u8 * hostapd_eid_wme(struct hostapd_data *hapd, u8 *eid);
-int hostapd_eid_wme_valid(struct hostapd_data *hapd, u8 *eid, size_t len);
-int hostapd_wme_sta_config(struct hostapd_data *hapd, struct sta_info *sta);
-void hostapd_wme_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
+u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid);
+int hostapd_eid_wmm_valid(struct hostapd_data *hapd, u8 *eid, size_t len);
+int hostapd_wmm_sta_config(struct hostapd_data *hapd, struct sta_info *sta);
+void hostapd_wmm_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
size_t len);
#endif /* WME_H */
diff --git a/contrib/wpa/hostapd/wpa.c b/contrib/wpa/hostapd/wpa.c
index cf285b6..19b11d5 100644
--- a/contrib/wpa/hostapd/wpa.c
+++ b/contrib/wpa/hostapd/wpa.c
@@ -1,6 +1,6 @@
/*
* hostapd - IEEE 802.11i-2004 / WPA Authenticator
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* 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
@@ -44,6 +44,8 @@ static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx);
static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static void wpa_request_new_ptk(struct wpa_state_machine *sm);
+static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
+ struct wpa_group *group);
static const u32 dot11RSNAConfigGroupUpdateCount = 4;
static const u32 dot11RSNAConfigPairwiseUpdateCount = 4;
@@ -286,21 +288,9 @@ static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
}
-static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
- int vlan_id)
+static void wpa_group_set_key_len(struct wpa_group *group, int cipher)
{
- struct wpa_group *group;
- u8 buf[ETH_ALEN + 8 + sizeof(group)];
- u8 rkey[32];
-
- group = os_zalloc(sizeof(struct wpa_group));
- if (group == NULL)
- return NULL;
-
- group->GTKAuthenticator = TRUE;
- group->vlan_id = vlan_id;
-
- switch (wpa_auth->conf.wpa_group) {
+ switch (cipher) {
case WPA_CIPHER_CCMP:
group->GTK_len = 16;
break;
@@ -314,6 +304,24 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
group->GTK_len = 5;
break;
}
+}
+
+
+static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
+ int vlan_id)
+{
+ struct wpa_group *group;
+ u8 buf[ETH_ALEN + 8 + sizeof(group)];
+ u8 rkey[32];
+
+ group = os_zalloc(sizeof(struct wpa_group));
+ if (group == NULL)
+ return NULL;
+
+ group->GTKAuthenticator = TRUE;
+ group->vlan_id = vlan_id;
+
+ wpa_group_set_key_len(group, wpa_auth->conf.wpa_group);
/* Counter = PRF-256(Random number, "Init Counter",
* Local MAC Address || Time)
@@ -451,6 +459,7 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
int wpa_reconfig(struct wpa_authenticator *wpa_auth,
struct wpa_auth_config *conf)
{
+ struct wpa_group *group;
if (wpa_auth == NULL)
return 0;
@@ -460,6 +469,17 @@ int wpa_reconfig(struct wpa_authenticator *wpa_auth,
return -1;
}
+ /*
+ * Reinitialize GTK to make sure it is suitable for the new
+ * configuration.
+ */
+ group = wpa_auth->group;
+ wpa_group_set_key_len(group, wpa_auth->conf.wpa_group);
+ group->GInit = TRUE;
+ wpa_group_sm_step(wpa_auth, group);
+ group->GInit = FALSE;
+ wpa_group_sm_step(wpa_auth, group);
+
return 0;
}
@@ -619,6 +639,22 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
return;
}
+ if (sm->wpa == WPA_VERSION_WPA2) {
+ if (key->type != EAPOL_KEY_TYPE_RSN) {
+ wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with "
+ "unexpected type %d in RSN mode",
+ key->type);
+ return;
+ }
+ } else {
+ if (key->type != EAPOL_KEY_TYPE_WPA) {
+ wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with "
+ "unexpected type %d in WPA mode",
+ key->type);
+ return;
+ }
+ }
+
/* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys
* are set */
@@ -1403,14 +1439,15 @@ SM_STATE(WPA_PTK, PTKSTART)
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk,
struct wpa_ptk *ptk)
{
+ size_t ptk_len = sm->pairwise == WPA_CIPHER_CCMP ? 48 : 64;
#ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
- return wpa_auth_derive_ptk_ft(sm, pmk, ptk);
+ return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len);
#endif /* CONFIG_IEEE80211R */
wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion",
sm->wpa_auth->addr, sm->addr, sm->ANonce, sm->SNonce,
- (u8 *) ptk, sizeof(*ptk),
+ (u8 *) ptk, ptk_len,
wpa_key_mgmt_sha256(sm->wpa_key_mgmt));
return 0;
diff --git a/contrib/wpa/hostapd/wpa.h b/contrib/wpa/hostapd/wpa.h
index d353844..7d9b3d3 100644
--- a/contrib/wpa/hostapd/wpa.h
+++ b/contrib/wpa/hostapd/wpa.h
@@ -141,7 +141,7 @@ struct wpa_auth_config {
int rsn_preauth;
int eapol_version;
int peerkey;
- int wme_enabled;
+ int wmm_enabled;
int okc;
#ifdef CONFIG_IEEE80211W
enum {
diff --git a/contrib/wpa/hostapd/wpa_auth_i.h b/contrib/wpa/hostapd/wpa_auth_i.h
index bcaeda5..925d3ee 100644
--- a/contrib/wpa/hostapd/wpa_auth_i.h
+++ b/contrib/wpa/hostapd/wpa_auth_i.h
@@ -213,7 +213,7 @@ void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
#ifdef CONFIG_IEEE80211R
int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len);
int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
- struct wpa_ptk *ptk);
+ struct wpa_ptk *ptk, size_t ptk_len);
struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void);
void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache);
#endif /* CONFIG_IEEE80211R */
diff --git a/contrib/wpa/hostapd/wpa_auth_ie.c b/contrib/wpa/hostapd/wpa_auth_ie.c
index 3ac9d67..7e01635 100644
--- a/contrib/wpa/hostapd/wpa_auth_ie.c
+++ b/contrib/wpa/hostapd/wpa_auth_ie.c
@@ -215,8 +215,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
capab |= WPA_CAPABILITY_PREAUTH;
if (conf->peerkey)
capab |= WPA_CAPABILITY_PEERKEY_ENABLED;
- if (conf->wme_enabled) {
- /* 4 PTKSA replay counters when using WME */
+ if (conf->wmm_enabled) {
+ /* 4 PTKSA replay counters when using WMM */
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
}
#ifdef CONFIG_IEEE80211W
diff --git a/contrib/wpa/hostapd/wpa_ft.c b/contrib/wpa/hostapd/wpa_ft.c
index 9cf6713..3139105 100644
--- a/contrib/wpa/hostapd/wpa_ft.c
+++ b/contrib/wpa/hostapd/wpa_ft.c
@@ -321,7 +321,7 @@ static int wpa_ft_pull_pmk_r1(struct wpa_authenticator *wpa_auth,
int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
- struct wpa_ptk *ptk)
+ struct wpa_ptk *ptk, size_t ptk_len)
{
u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN];
u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN];
@@ -354,8 +354,8 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
sm->wpa_auth->addr, pmk_r1_name,
- (u8 *) ptk, sizeof(*ptk), ptk_name);
- wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, sizeof(*ptk));
+ (u8 *) ptk, ptk_len, ptk_name);
+ wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, ptk_len);
wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
return 0;
@@ -714,7 +714,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
u8 ptk_name[WPA_PMK_NAME_LEN];
struct wpa_auth_config *conf;
struct wpa_ft_ies parse;
- size_t buflen;
+ size_t buflen, ptk_len;
int ret;
u8 *pos, *end;
@@ -804,11 +804,12 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce",
sm->ANonce, WPA_NONCE_LEN);
+ ptk_len = sm->pairwise == WPA_CIPHER_CCMP ? 48 : 64;
wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
sm->wpa_auth->addr, pmk_r1_name,
- (u8 *) &sm->PTK, sizeof(sm->PTK), ptk_name);
+ (u8 *) &sm->PTK, ptk_len, ptk_name);
wpa_hexdump_key(MSG_DEBUG, "FT: PTK",
- (u8 *) &sm->PTK, sizeof(sm->PTK));
+ (u8 *) &sm->PTK, ptk_len);
wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
wpa_ft_install_ptk(sm);
diff --git a/contrib/wpa/hostapd/wps_hostapd.c b/contrib/wpa/hostapd/wps_hostapd.c
index a824c16..818767e 100644
--- a/contrib/wpa/hostapd/wps_hostapd.c
+++ b/contrib/wpa/hostapd/wps_hostapd.c
@@ -219,13 +219,13 @@ static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
if ((hapd->conf->wps_cred_processing == 1 ||
hapd->conf->wps_cred_processing == 2) && cred->cred_attr) {
size_t blen = cred->cred_attr_len * 2 + 1;
- char *buf = os_malloc(blen);
- if (buf) {
- wpa_snprintf_hex(buf, blen,
+ char *_buf = os_malloc(blen);
+ if (_buf) {
+ wpa_snprintf_hex(_buf, blen,
cred->cred_attr, cred->cred_attr_len);
wpa_msg(hapd, MSG_INFO, "%s%s",
- WPS_EVENT_NEW_AP_SETTINGS, buf);
- os_free(buf);
+ WPS_EVENT_NEW_AP_SETTINGS, _buf);
+ os_free(_buf);
}
} else
wpa_msg(hapd, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS);
@@ -233,6 +233,28 @@ static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
if (hapd->conf->wps_cred_processing == 1)
return 0;
+ os_memcpy(hapd->wps->ssid, cred->ssid, cred->ssid_len);
+ hapd->wps->ssid_len = cred->ssid_len;
+ hapd->wps->encr_types = cred->encr_type;
+ hapd->wps->auth_types = cred->auth_type;
+ if (cred->key_len == 0) {
+ os_free(hapd->wps->network_key);
+ hapd->wps->network_key = NULL;
+ hapd->wps->network_key_len = 0;
+ } else {
+ if (hapd->wps->network_key == NULL ||
+ hapd->wps->network_key_len < cred->key_len) {
+ hapd->wps->network_key_len = 0;
+ os_free(hapd->wps->network_key);
+ hapd->wps->network_key = os_malloc(cred->key_len);
+ if (hapd->wps->network_key == NULL)
+ return -1;
+ }
+ hapd->wps->network_key_len = cred->key_len;
+ os_memcpy(hapd->wps->network_key, cred->key, cred->key_len);
+ }
+ hapd->wps->wps_state = WPS_STATE_CONFIGURED;
+
len = os_strlen(hapd->iface->config_fname) + 5;
tmp_fname = os_malloc(len);
if (tmp_fname == NULL)
@@ -326,15 +348,21 @@ static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
else
fprintf(nconf, "auth_algs=1\n");
- if (cred->encr_type & WPS_ENCR_WEP && cred->key_idx < 4) {
- fprintf(nconf, "wep_default_key=%d\n", cred->key_idx);
- fprintf(nconf, "wep_key%d=", cred->key_idx);
- if (cred->key_len != 10 && cred->key_len != 26)
- fputc('"', nconf);
- for (i = 0; i < cred->key_len; i++)
- fputc(cred->key[i], nconf);
- if (cred->key_len != 10 && cred->key_len != 26)
- fputc('"', nconf);
+ if (cred->encr_type & WPS_ENCR_WEP && cred->key_idx <= 4) {
+ int key_idx = cred->key_idx;
+ if (key_idx)
+ key_idx--;
+ fprintf(nconf, "wep_default_key=%d\n", key_idx);
+ fprintf(nconf, "wep_key%d=", key_idx);
+ if (cred->key_len == 10 || cred->key_len == 26) {
+ /* WEP key as a hex string */
+ for (i = 0; i < cred->key_len; i++)
+ fputc(cred->key[i], nconf);
+ } else {
+ /* Raw WEP key; convert to hex */
+ for (i = 0; i < cred->key_len; i++)
+ fprintf(nconf, "%02x", cred->key[i]);
+ }
fprintf(nconf, "\n");
}
}
@@ -620,6 +648,8 @@ int hostapd_init_wps(struct hostapd_data *hapd,
cfg.extra_cred_len = conf->extra_cred_len;
cfg.disable_auto_conf = (hapd->conf->wps_cred_processing == 1) &&
conf->skip_cred_build;
+ if (conf->ssid.security_policy == SECURITY_STATIC_WEP)
+ cfg.static_wep_only = 1;
wps->registrar = wps_registrar_init(wps, &cfg);
if (wps->registrar == NULL) {
@@ -669,7 +699,7 @@ void hostapd_deinit_wps(struct hostapd_data *hapd)
int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
- const char *pin)
+ const char *pin, int timeout)
{
u8 u[UUID_LEN];
int any = 0;
@@ -681,7 +711,8 @@ int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
else if (uuid_str2bin(uuid, u))
return -1;
return wps_registrar_add_pin(hapd->wps->registrar, any ? NULL : u,
- (const u8 *) pin, os_strlen(pin));
+ (const u8 *) pin, os_strlen(pin),
+ timeout);
}
@@ -864,8 +895,8 @@ static int hostapd_rx_req_put_wlan_response(
wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse ev_type=%d mac_addr="
MACSTR, ev_type, MAC2STR(mac_addr));
- wpa_hexdump_ascii(MSG_MSGDUMP, "WPS UPnP: PutWLANResponse NewMessage",
- wpabuf_head(msg), wpabuf_len(msg));
+ wpa_hexdump(MSG_MSGDUMP, "WPS UPnP: PutWLANResponse NewMessage",
+ wpabuf_head(msg), wpabuf_len(msg));
if (ev_type != UPNP_WPS_WLANEVENT_TYPE_EAP) {
wpa_printf(MSG_DEBUG, "WPS UPnP: Ignored unexpected "
"PutWLANResponse WLANEventType %d", ev_type);
diff --git a/contrib/wpa/hostapd/wps_hostapd.h b/contrib/wpa/hostapd/wps_hostapd.h
index 6615c62a..e949bee 100644
--- a/contrib/wpa/hostapd/wps_hostapd.h
+++ b/contrib/wpa/hostapd/wps_hostapd.h
@@ -21,7 +21,7 @@ int hostapd_init_wps(struct hostapd_data *hapd,
struct hostapd_bss_config *conf);
void hostapd_deinit_wps(struct hostapd_data *hapd);
int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
- const char *pin);
+ const char *pin, int timeout);
int hostapd_wps_button_pushed(struct hostapd_data *hapd);
void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr,
const u8 *ie, size_t ie_len);
OpenPOWER on IntegriCloud