from hostap.epitest.fi

This commit is contained in:
christos 2012-10-07 23:46:57 +00:00
parent 320d4922ba
commit 111b9fd8ca
360 changed files with 65803 additions and 8755 deletions

View File

@ -1,19 +1,75 @@
wpa_supplicant and hostapd v0.6.x
---------------------------------
wpa_supplicant and hostapd
--------------------------
Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> and contributors
Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
These program is dual-licensed under both the GPL version 2 and BSD
license. Either license may be used at your option.
These programs are dual-licensed under both the GPL version 2 and BSD
license (the one with advertisement clause removed). Either license
may be used at your option.
If you are submitting changes to the project, please see CONTRIBUTIONS
file for more instructions.
This package may include either wpa_supplicant, hostapd, or both. See
README file respective subdirectories (wpa_supplicant/README or
hostapd/README) for more details.
Source code files have been moved around in v0.6.x releases and
compared to earlier releases, the programs are now build by first
going to a subdirectory (wpa_supplicant or hostapd) and creating
build configuration (.config) and running 'make' there (for
Linux/BSD/cygwin builds).
Source code files were moved around in v0.6.x releases and compared to
earlier releases, the programs are now built by first going to a
subdirectory (wpa_supplicant or hostapd) and creating build
configuration (.config) and running 'make' there (for Linux/BSD/cygwin
builds).
License
-------
GPL v2:
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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
(this copy of the license is in COPYING file)
Alternatively, this software may be distributed, used, and modified
under the terms of BSD license:
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. Neither the name(s) of the above-listed copyright holder(s) nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"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 THE COPYRIGHT
OWNER OR CONTRIBUTORS 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.

828
external/bsd/wpa/dist/hostapd/Android.mk vendored Normal file
View File

@ -0,0 +1,828 @@
LOCAL_PATH := $(call my-dir)
WPA_BUILD_HOSTAPD := false
ifneq ($(TARGET_SIMULATOR),true)
ifneq ($(BOARD_HOSTAPD_DRIVER),)
WPA_BUILD_HOSTAPD := true
CONFIG_DRIVER_$(BOARD_HOSTAPD_DRIVER) := y
endif
endif
include $(LOCAL_PATH)/.config
# To ignore possible wrong network configurations
L_CFLAGS = -DWPA_IGNORE_CONFIG_ERRORS
# Set Android log name
L_CFLAGS += -DANDROID_LOG_NAME=\"hostapd\"
# To force sizeof(enum) = 4
ifeq ($(TARGET_ARCH),arm)
L_CFLAGS += -mabi=aapcs-linux
endif
# To allow non-ASCII characters in SSID
L_CFLAGS += -DWPA_UNICODE_SSID
# OpenSSL is configured without engines on Android
L_CFLAGS += -DOPENSSL_NO_ENGINE
INCLUDES = $(LOCAL_PATH)
INCLUDES += $(LOCAL_PATH)/src
INCLUDES += $(LOCAL_PATH)/src/utils
INCLUDES += external/openssl/include
INCLUDES += frameworks/base/cmds/keystore
ifdef CONFIG_DRIVER_NL80211
INCLUDES += external/libnl-headers
endif
ifndef CONFIG_OS
ifdef CONFIG_NATIVE_WINDOWS
CONFIG_OS=win32
else
CONFIG_OS=unix
endif
endif
ifeq ($(CONFIG_OS), internal)
L_CFLAGS += -DOS_NO_C_LIB_DEFINES
endif
ifdef CONFIG_NATIVE_WINDOWS
L_CFLAGS += -DCONFIG_NATIVE_WINDOWS
LIBS += -lws2_32
endif
OBJS = main.c
OBJS += config_file.c
OBJS += src/ap/hostapd.c
OBJS += src/ap/wpa_auth_glue.c
OBJS += src/ap/drv_callbacks.c
OBJS += src/ap/ap_drv_ops.c
OBJS += src/ap/utils.c
OBJS += src/ap/authsrv.c
OBJS += src/ap/ieee802_1x.c
OBJS += src/ap/ap_config.c
OBJS += src/ap/ieee802_11_auth.c
OBJS += src/ap/sta_info.c
OBJS += src/ap/wpa_auth.c
OBJS += src/ap/tkip_countermeasures.c
OBJS += src/ap/ap_mlme.c
OBJS += src/ap/wpa_auth_ie.c
OBJS += src/ap/preauth_auth.c
OBJS += src/ap/pmksa_cache_auth.c
OBJS += src/ap/ieee802_11_shared.c
OBJS += src/ap/beacon.c
OBJS_d =
OBJS_p =
LIBS =
LIBS_c =
HOBJS =
LIBS_h =
NEED_RC4=y
NEED_AES=y
NEED_MD5=y
NEED_SHA1=y
OBJS += src/drivers/drivers.c
L_CFLAGS += -DHOSTAPD
ifdef CONFIG_WPA_TRACE
L_CFLAGS += -DWPA_TRACE
OBJS += src/utils/trace.c
HOBJS += src/utils/trace.c
LDFLAGS += -rdynamic
L_CFLAGS += -funwind-tables
ifdef CONFIG_WPA_TRACE_BFD
L_CFLAGS += -DWPA_TRACE_BFD
LIBS += -lbfd
LIBS_c += -lbfd
LIBS_h += -lbfd
endif
endif
OBJS += src/utils/eloop.c
OBJS += src/utils/common.c
OBJS += src/utils/wpa_debug.c
OBJS += src/utils/wpabuf.c
OBJS += src/utils/os_$(CONFIG_OS).c
OBJS += src/utils/ip_addr.c
OBJS += src/common/ieee802_11_common.c
OBJS += src/common/wpa_common.c
OBJS += src/eapol_auth/eapol_auth_sm.c
ifndef CONFIG_NO_DUMP_STATE
# define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to
# a file (undefine it, if you want to save in binary size)
L_CFLAGS += -DHOSTAPD_DUMP_STATE
OBJS += dump_state.c
OBJS += src/eapol_auth/eapol_auth_dump.c
endif
ifdef CONFIG_NO_RADIUS
L_CFLAGS += -DCONFIG_NO_RADIUS
CONFIG_NO_ACCOUNTING=y
else
OBJS += src/radius/radius.c
OBJS += src/radius/radius_client.c
endif
ifdef CONFIG_NO_ACCOUNTING
L_CFLAGS += -DCONFIG_NO_ACCOUNTING
else
OBJS += src/ap/accounting.c
endif
ifdef CONFIG_NO_VLAN
L_CFLAGS += -DCONFIG_NO_VLAN
else
OBJS += src/ap/vlan_init.c
endif
ifdef CONFIG_NO_CTRL_IFACE
L_CFLAGS += -DCONFIG_NO_CTRL_IFACE
else
OBJS += ctrl_iface.c
OBJS += src/ap/ctrl_iface_ap.c
endif
OBJS += src/crypto/md5.c
L_CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX
ifdef CONFIG_IAPP
L_CFLAGS += -DCONFIG_IAPP
OBJS += src/ap/iapp.c
endif
ifdef CONFIG_RSN_PREAUTH
L_CFLAGS += -DCONFIG_RSN_PREAUTH
CONFIG_L2_PACKET=y
endif
ifdef CONFIG_PEERKEY
L_CFLAGS += -DCONFIG_PEERKEY
OBJS += src/ap/peerkey_auth.c
endif
ifdef CONFIG_IEEE80211W
L_CFLAGS += -DCONFIG_IEEE80211W
NEED_SHA256=y
NEED_AES_OMAC1=y
endif
ifdef CONFIG_IEEE80211R
L_CFLAGS += -DCONFIG_IEEE80211R
OBJS += src/ap/wpa_auth_ft.c
NEED_SHA256=y
NEED_AES_OMAC1=y
NEED_AES_UNWRAP=y
endif
ifdef CONFIG_IEEE80211N
L_CFLAGS += -DCONFIG_IEEE80211N
endif
include $(LOCAL_PATH)/src/drivers/drivers.mk
OBJS += $(DRV_AP_OBJS)
L_CFLAGS += $(DRV_AP_CFLAGS)
LDFLAGS += $(DRV_AP_LDFLAGS)
LIBS += $(DRV_AP_LIBS)
ifdef CONFIG_L2_PACKET
ifdef CONFIG_DNET_PCAP
ifdef CONFIG_L2_FREEBSD
LIBS += -lpcap
OBJS += src/l2_packet/l2_packet_freebsd.c
else
LIBS += -ldnet -lpcap
OBJS += src/l2_packet/l2_packet_pcap.c
endif
else
OBJS += src/l2_packet/l2_packet_linux.c
endif
else
OBJS += src/l2_packet/l2_packet_none.c
endif
ifdef CONFIG_EAP_MD5
L_CFLAGS += -DEAP_SERVER_MD5
OBJS += src/eap_server/eap_server_md5.c
CHAP=y
endif
ifdef CONFIG_EAP_TLS
L_CFLAGS += -DEAP_SERVER_TLS
OBJS += src/eap_server/eap_server_tls.c
TLS_FUNCS=y
endif
ifdef CONFIG_EAP_PEAP
L_CFLAGS += -DEAP_SERVER_PEAP
OBJS += src/eap_server/eap_server_peap.c
OBJS += src/eap_common/eap_peap_common.c
TLS_FUNCS=y
CONFIG_EAP_MSCHAPV2=y
endif
ifdef CONFIG_EAP_TTLS
L_CFLAGS += -DEAP_SERVER_TTLS
OBJS += src/eap_server/eap_server_ttls.c
TLS_FUNCS=y
CHAP=y
endif
ifdef CONFIG_EAP_MSCHAPV2
L_CFLAGS += -DEAP_SERVER_MSCHAPV2
OBJS += src/eap_server/eap_server_mschapv2.c
MS_FUNCS=y
endif
ifdef CONFIG_EAP_GTC
L_CFLAGS += -DEAP_SERVER_GTC
OBJS += src/eap_server/eap_server_gtc.c
endif
ifdef CONFIG_EAP_SIM
L_CFLAGS += -DEAP_SERVER_SIM
OBJS += src/eap_server/eap_server_sim.c
CONFIG_EAP_SIM_COMMON=y
NEED_AES_CBC=y
endif
ifdef CONFIG_EAP_AKA
L_CFLAGS += -DEAP_SERVER_AKA
OBJS += src/eap_server/eap_server_aka.c
CONFIG_EAP_SIM_COMMON=y
NEED_SHA256=y
NEED_AES_CBC=y
endif
ifdef CONFIG_EAP_AKA_PRIME
L_CFLAGS += -DEAP_SERVER_AKA_PRIME
endif
ifdef CONFIG_EAP_SIM_COMMON
OBJS += src/eap_common/eap_sim_common.c
# 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.c
NEED_FIPS186_2_PRF=y
endif
ifdef CONFIG_EAP_PAX
L_CFLAGS += -DEAP_SERVER_PAX
OBJS += src/eap_server/eap_server_pax.c src/eap_common/eap_pax_common.c
endif
ifdef CONFIG_EAP_PSK
L_CFLAGS += -DEAP_SERVER_PSK
OBJS += src/eap_server/eap_server_psk.c src/eap_common/eap_psk_common.c
NEED_AES_OMAC1=y
NEED_AES_ENCBLOCK=y
NEED_AES_EAX=y
endif
ifdef CONFIG_EAP_SAKE
L_CFLAGS += -DEAP_SERVER_SAKE
OBJS += src/eap_server/eap_server_sake.c src/eap_common/eap_sake_common.c
endif
ifdef CONFIG_EAP_GPSK
L_CFLAGS += -DEAP_SERVER_GPSK
OBJS += src/eap_server/eap_server_gpsk.c src/eap_common/eap_gpsk_common.c
ifdef CONFIG_EAP_GPSK_SHA256
L_CFLAGS += -DEAP_SERVER_GPSK_SHA256
endif
NEED_SHA256=y
NEED_AES_OMAC1=y
endif
ifdef CONFIG_EAP_PWD
L_CFLAGS += -DEAP_SERVER_PWD
OBJS += src/eap_server/eap_server_pwd.c src/eap_common/eap_pwd_common.c
NEED_SHA256=y
endif
ifdef CONFIG_EAP_VENDOR_TEST
L_CFLAGS += -DEAP_SERVER_VENDOR_TEST
OBJS += src/eap_server/eap_server_vendor_test.c
endif
ifdef CONFIG_EAP_FAST
L_CFLAGS += -DEAP_SERVER_FAST
OBJS += src/eap_server/eap_server_fast.c
OBJS += src/eap_common/eap_fast_common.c
TLS_FUNCS=y
NEED_T_PRF=y
NEED_AES_UNWRAP=y
endif
ifdef CONFIG_WPS
ifdef CONFIG_WPS2
L_CFLAGS += -DCONFIG_WPS2
endif
L_CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC
OBJS += src/utils/uuid.c
OBJS += src/ap/wps_hostapd.c
OBJS += src/eap_server/eap_server_wsc.c src/eap_common/eap_wsc_common.c
OBJS += src/wps/wps.c
OBJS += src/wps/wps_common.c
OBJS += src/wps/wps_attr_parse.c
OBJS += src/wps/wps_attr_build.c
OBJS += src/wps/wps_attr_process.c
OBJS += src/wps/wps_dev_attr.c
OBJS += src/wps/wps_enrollee.c
OBJS += src/wps/wps_registrar.c
NEED_DH_GROUPS=y
NEED_SHA256=y
NEED_BASE64=y
NEED_AES_CBC=y
NEED_MODEXP=y
CONFIG_EAP=y
ifdef CONFIG_WPS_UFD
L_CFLAGS += -DCONFIG_WPS_UFD
OBJS += src/wps/wps_ufd.c
NEED_WPS_OOB=y
endif
ifdef CONFIG_WPS_NFC
L_CFLAGS += -DCONFIG_WPS_NFC
OBJS += src/wps/ndef.c
OBJS += src/wps/wps_nfc.c
NEED_WPS_OOB=y
ifdef CONFIG_WPS_NFC_PN531
PN531_PATH ?= /usr/local/src/nfc
L_CFLAGS += -DCONFIG_WPS_NFC_PN531
L_CFLAGS += -I${PN531_PATH}/inc
OBJS += src/wps/wps_nfc_pn531.c
LIBS += ${PN531_PATH}/lib/wpsnfc.dll
LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll
endif
endif
ifdef NEED_WPS_OOB
L_CFLAGS += -DCONFIG_WPS_OOB
endif
ifdef CONFIG_WPS_UPNP
L_CFLAGS += -DCONFIG_WPS_UPNP
OBJS += src/wps/wps_upnp.c
OBJS += src/wps/wps_upnp_ssdp.c
OBJS += src/wps/wps_upnp_web.c
OBJS += src/wps/wps_upnp_event.c
OBJS += src/wps/wps_upnp_ap.c
OBJS += src/wps/upnp_xml.c
OBJS += src/wps/httpread.c
OBJS += src/wps/http_client.c
OBJS += src/wps/http_server.c
endif
ifdef CONFIG_WPS_STRICT
L_CFLAGS += -DCONFIG_WPS_STRICT
OBJS += src/wps/wps_validate.c
endif
ifdef CONFIG_WPS_TESTING
L_CFLAGS += -DCONFIG_WPS_TESTING
endif
endif
ifdef CONFIG_EAP_IKEV2
L_CFLAGS += -DEAP_SERVER_IKEV2
OBJS += src/eap_server/eap_server_ikev2.c src/eap_server/ikev2.c
OBJS += src/eap_common/eap_ikev2_common.c src/eap_common/ikev2_common.c
NEED_DH_GROUPS=y
NEED_DH_GROUPS_ALL=y
NEED_MODEXP=y
NEED_CIPHER=y
endif
ifdef CONFIG_EAP_TNC
L_CFLAGS += -DEAP_SERVER_TNC
OBJS += src/eap_server/eap_server_tnc.c
OBJS += src/eap_server/tncs.c
NEED_BASE64=y
ifndef CONFIG_DRIVER_BSD
LIBS += -ldl
endif
endif
# Basic EAP functionality is needed for EAPOL
OBJS += eap_register.c
OBJS += src/eap_server/eap_server.c
OBJS += src/eap_common/eap_common.c
OBJS += src/eap_server/eap_server_methods.c
OBJS += src/eap_server/eap_server_identity.c
L_CFLAGS += -DEAP_SERVER_IDENTITY
ifdef CONFIG_EAP
L_CFLAGS += -DEAP_SERVER
endif
ifdef CONFIG_PKCS12
L_CFLAGS += -DPKCS12_FUNCS
endif
ifdef MS_FUNCS
OBJS += src/crypto/ms_funcs.c
NEED_DES=y
NEED_MD4=y
endif
ifdef CHAP
OBJS += src/eap_common/chap.c
endif
ifdef TLS_FUNCS
NEED_DES=y
# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
L_CFLAGS += -DEAP_TLS_FUNCS
OBJS += src/eap_server/eap_server_tls_common.c
NEED_TLS_PRF=y
endif
ifndef CONFIG_TLS
CONFIG_TLS=openssl
endif
ifeq ($(CONFIG_TLS), openssl)
ifdef TLS_FUNCS
OBJS += src/crypto/tls_openssl.c
LIBS += -lssl
endif
OBJS += src/crypto/crypto_openssl.c
HOBJS += src/crypto/crypto_openssl.c
ifdef NEED_FIPS186_2_PRF
OBJS += src/crypto/fips_prf_openssl.c
endif
LIBS += -lcrypto
LIBS_h += -lcrypto
endif
ifeq ($(CONFIG_TLS), gnutls)
ifdef TLS_FUNCS
OBJS += src/crypto/tls_gnutls.c
LIBS += -lgnutls -lgpg-error
ifdef CONFIG_GNUTLS_EXTRA
L_CFLAGS += -DCONFIG_GNUTLS_EXTRA
LIBS += -lgnutls-extra
endif
endif
OBJS += src/crypto/crypto_gnutls.c
HOBJS += src/crypto/crypto_gnutls.c
ifdef NEED_FIPS186_2_PRF
OBJS += src/crypto/fips_prf_gnutls.c
endif
LIBS += -lgcrypt
LIBS_h += -lgcrypt
CONFIG_INTERNAL_SHA256=y
CONFIG_INTERNAL_RC4=y
CONFIG_INTERNAL_DH_GROUP5=y
endif
ifeq ($(CONFIG_TLS), schannel)
ifdef TLS_FUNCS
OBJS += src/crypto/tls_schannel.c
endif
OBJS += src/crypto/crypto_cryptoapi.c
OBJS_p += src/crypto/crypto_cryptoapi.c
CONFIG_INTERNAL_SHA256=y
CONFIG_INTERNAL_RC4=y
CONFIG_INTERNAL_DH_GROUP5=y
endif
ifeq ($(CONFIG_TLS), nss)
ifdef TLS_FUNCS
OBJS += src/crypto/tls_nss.c
LIBS += -lssl3
endif
OBJS += src/crypto/crypto_nss.c
ifdef NEED_FIPS186_2_PRF
OBJS += src/crypto/fips_prf_nss.c
endif
LIBS += -lnss3
LIBS_h += -lnss3
CONFIG_INTERNAL_MD4=y
CONFIG_INTERNAL_DH_GROUP5=y
endif
ifeq ($(CONFIG_TLS), internal)
ifndef CONFIG_CRYPTO
CONFIG_CRYPTO=internal
endif
ifdef TLS_FUNCS
OBJS += src/crypto/crypto_internal-rsa.c
OBJS += src/crypto/tls_internal.c
OBJS += src/tls/tlsv1_common.c
OBJS += src/tls/tlsv1_record.c
OBJS += src/tls/tlsv1_cred.c
OBJS += src/tls/tlsv1_server.c
OBJS += src/tls/tlsv1_server_write.c
OBJS += src/tls/tlsv1_server_read.c
OBJS += src/tls/asn1.c
OBJS += src/tls/rsa.c
OBJS += src/tls/x509v3.c
OBJS += src/tls/pkcs1.c
OBJS += src/tls/pkcs5.c
OBJS += src/tls/pkcs8.c
NEED_SHA256=y
NEED_BASE64=y
NEED_TLS_PRF=y
NEED_MODEXP=y
NEED_CIPHER=y
L_CFLAGS += -DCONFIG_TLS_INTERNAL
L_CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
endif
ifdef NEED_CIPHER
NEED_DES=y
OBJS += src/crypto/crypto_internal-cipher.c
endif
ifdef NEED_MODEXP
OBJS += src/crypto/crypto_internal-modexp.c
OBJS += src/tls/bignum.c
endif
ifeq ($(CONFIG_CRYPTO), libtomcrypt)
OBJS += src/crypto/crypto_libtomcrypt.c
LIBS += -ltomcrypt -ltfm
LIBS_h += -ltomcrypt -ltfm
CONFIG_INTERNAL_SHA256=y
CONFIG_INTERNAL_RC4=y
CONFIG_INTERNAL_DH_GROUP5=y
endif
ifeq ($(CONFIG_CRYPTO), internal)
OBJS += src/crypto/crypto_internal.c
NEED_AES_DEC=y
L_CFLAGS += -DCONFIG_CRYPTO_INTERNAL
ifdef CONFIG_INTERNAL_LIBTOMMATH
L_CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
ifdef CONFIG_INTERNAL_LIBTOMMATH_FAST
L_CFLAGS += -DLTM_FAST
endif
else
LIBS += -ltommath
LIBS_h += -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
CONFIG_INTERNAL_RC4=y
CONFIG_INTERNAL_DH_GROUP5=y
endif
ifeq ($(CONFIG_CRYPTO), cryptoapi)
OBJS += src/crypto/crypto_cryptoapi.c
OBJS_p += src/crypto/crypto_cryptoapi.c
L_CFLAGS += -DCONFIG_CRYPTO_CRYPTOAPI
CONFIG_INTERNAL_SHA256=y
CONFIG_INTERNAL_RC4=y
endif
endif
ifeq ($(CONFIG_TLS), none)
ifdef TLS_FUNCS
OBJS += src/crypto/tls_none.c
L_CFLAGS += -DEAP_TLS_NONE
CONFIG_INTERNAL_AES=y
CONFIG_INTERNAL_SHA1=y
CONFIG_INTERNAL_MD5=y
endif
OBJS += src/crypto/crypto_none.c
OBJS_p += src/crypto/crypto_none.c
CONFIG_INTERNAL_SHA256=y
CONFIG_INTERNAL_RC4=y
endif
ifndef TLS_FUNCS
OBJS += src/crypto/tls_none.c
ifeq ($(CONFIG_TLS), internal)
CONFIG_INTERNAL_AES=y
CONFIG_INTERNAL_SHA1=y
CONFIG_INTERNAL_MD5=y
CONFIG_INTERNAL_RC4=y
endif
endif
AESOBJS = # none so far
ifdef CONFIG_INTERNAL_AES
AESOBJS += src/crypto/aes-internal.c src/crypto/aes-internal-enc.c
endif
AESOBJS += src/crypto/aes-wrap.c
ifdef NEED_AES_EAX
AESOBJS += src/crypto/aes-eax.c
NEED_AES_CTR=y
endif
ifdef NEED_AES_CTR
AESOBJS += src/crypto/aes-ctr.c
endif
ifdef NEED_AES_ENCBLOCK
AESOBJS += src/crypto/aes-encblock.c
endif
ifdef NEED_AES_OMAC1
AESOBJS += src/crypto/aes-omac1.c
endif
ifdef NEED_AES_UNWRAP
NEED_AES_DEC=y
AESOBJS += src/crypto/aes-unwrap.c
endif
ifdef NEED_AES_CBC
NEED_AES_DEC=y
AESOBJS += src/crypto/aes-cbc.c
endif
ifdef NEED_AES_DEC
ifdef CONFIG_INTERNAL_AES
AESOBJS += src/crypto/aes-internal-dec.c
endif
endif
ifdef NEED_AES
OBJS += $(AESOBJS)
endif
SHA1OBJS =
ifdef NEED_SHA1
SHA1OBJS += src/crypto/sha1.c
ifdef CONFIG_INTERNAL_SHA1
SHA1OBJS += src/crypto/sha1-internal.c
ifdef NEED_FIPS186_2_PRF
SHA1OBJS += src/crypto/fips_prf_internal.c
endif
endif
SHA1OBJS += src/crypto/sha1-pbkdf2.c
ifdef NEED_T_PRF
SHA1OBJS += src/crypto/sha1-tprf.c
endif
ifdef NEED_TLS_PRF
SHA1OBJS += src/crypto/sha1-tlsprf.c
endif
endif
ifdef NEED_SHA1
OBJS += $(SHA1OBJS)
endif
ifdef NEED_MD5
ifdef CONFIG_INTERNAL_MD5
OBJS += src/crypto/md5-internal.c
HOBJS += src/crypto/md5-internal.c
endif
endif
ifdef NEED_MD4
ifdef CONFIG_INTERNAL_MD4
OBJS += src/crypto/md4-internal.c
endif
endif
ifdef NEED_DES
ifdef CONFIG_INTERNAL_DES
OBJS += src/crypto/des-internal.c
endif
endif
ifdef NEED_RC4
ifdef CONFIG_INTERNAL_RC4
OBJS += src/crypto/rc4.c
endif
endif
ifdef NEED_SHA256
OBJS += src/crypto/sha256.c
ifdef CONFIG_INTERNAL_SHA256
OBJS += src/crypto/sha256-internal.c
endif
endif
ifdef NEED_DH_GROUPS
OBJS += src/crypto/dh_groups.c
endif
ifdef NEED_DH_GROUPS_ALL
L_CFLAGS += -DALL_DH_GROUPS
endif
ifdef CONFIG_INTERNAL_DH_GROUP5
ifdef NEED_DH_GROUPS
OBJS += src/crypto/dh_group5.c
endif
endif
ifdef CONFIG_NO_RANDOM_POOL
L_CFLAGS += -DCONFIG_NO_RANDOM_POOL
else
OBJS += src/crypto/random.c
HOBJS += src/crypto/random.c
HOBJS += $(SHA1OBJS)
HOBJS += src/crypto/md5.c
endif
ifdef CONFIG_RADIUS_SERVER
L_CFLAGS += -DRADIUS_SERVER
OBJS += src/radius/radius_server.c
endif
ifdef CONFIG_IPV6
L_CFLAGS += -DCONFIG_IPV6
endif
ifdef CONFIG_DRIVER_RADIUS_ACL
L_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.
L_CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN
endif
ifdef NEED_BASE64
OBJS += src/utils/base64.c
endif
ifdef NEED_AP_MLME
OBJS += src/ap/wmm.c
OBJS += src/ap/ap_list.c
OBJS += src/ap/ieee802_11.c
OBJS += src/ap/hw_features.c
L_CFLAGS += -DNEED_AP_MLME
endif
ifdef CONFIG_IEEE80211N
OBJS += src/ap/ieee802_11_ht.c
endif
ifdef CONFIG_P2P_MANAGER
L_CFLAGS += -DCONFIG_P2P_MANAGER
OBJS += src/ap/p2p_hostapd.c
endif
OBJS += src/drivers/driver_common.c
ifdef CONFIG_NO_STDOUT_DEBUG
L_CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
endif
ifdef CONFIG_DEBUG_FILE
L_CFLAGS += -DCONFIG_DEBUG_FILE
endif
ifdef CONFIG_ANDROID_LOG
L_CFLAGS += -DCONFIG_ANDROID_LOG
endif
OBJS_c = hostapd_cli.c src/common/wpa_ctrl.c src/utils/os_$(CONFIG_OS).c
OBJS_c += src/utils/eloop.c
ifdef CONFIG_WPA_TRACE
OBJS_c += src/utils/trace.c
endif
OBJS_c += src/utils/wpa_debug.c
ifdef CONFIG_WPA_CLI_EDIT
OBJS_c += src/utils/edit.c
else
OBJS_c += src/utils/edit_simple.c
endif
ifeq ($(WPA_BUILD_HOSTAPD),true)
########################
include $(CLEAR_VARS)
LOCAL_MODULE := hostapd_cli
LOCAL_MODULE_TAGS := debug
LOCAL_SHARED_LIBRARIES := libc libcutils
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := $(OBJS_c)
LOCAL_C_INCLUDES := $(INCLUDES)
include $(BUILD_EXECUTABLE)
########################
include $(CLEAR_VARS)
LOCAL_MODULE := hostapd
LOCAL_MODULE_TAGS := optional
ifdef CONFIG_DRIVER_CUSTOM
LOCAL_STATIC_LIBRARIES := libCustomWifi
endif
ifneq ($(BOARD_HOSTAPD_PRIVATE_LIB),)
LOCAL_STATIC_LIBRARIES += $(BOARD_HOSTAPD_PRIVATE_LIB)
endif
LOCAL_SHARED_LIBRARIES := libc libcutils libcrypto libssl
ifdef CONFIG_DRIVER_NL80211
LOCAL_STATIC_LIBRARIES += libnl_2
endif
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := $(OBJS)
LOCAL_C_INCLUDES := $(INCLUDES)
include $(BUILD_EXECUTABLE)
endif # ifeq ($(WPA_BUILD_HOSTAPD),true)

View File

@ -1,20 +1,111 @@
ChangeLog for hostapd
2010-09-07 - v0.7.3
* fixed re-association after WPS not initializing WPA state machine in
some cases
* fixed WPS IE update on reconfiguration
* fixed WPS code not to proxy Probe Request frames for foreign SSIDs
* added WPS workaround for open networks and some known interop issues
* fixed WPS Diffie-Hellman derivation to use correct public key length
* fixed FT RRB messages on big endian CPUs
* changed WPS protection for brute force AP PIN attacks to disable AP
PIN only temporarily (but with increasing time) to avoid usability
issues on Label-only devices
* added wps_ap_pin command for more secure handling of AP PIN
operations (e.g., to generate a random AP PIN and only use it for
short amount of time)
* fixed HT STBC negotiation
2012-04-18 - v1.0
* Add channel selection support in hostapd. See hostapd.conf.
* Add support for IEEE 802.11v Time Advertisement mechanism with UTC
TSF offset. See hostapd.conf for config info.
* Delay STA entry removal until Deauth/Disassoc TX status in AP mode.
This allows the driver to use PS buffering of Deauthentication and
Disassociation frames when the STA is in power save sleep. Only
available with drivers that provide TX status events for Deauth/
Disassoc frames (nl80211).
* Allow PMKSA caching to be disabled on the Authenticator. See
hostap.conf config parameter disable_pmksa_caching.
* atheros: Add support for IEEE 802.11w configuration.
* bsd: Add support for setting HT values in IFM_MMASK.
* Allow client isolation to be configured with ap_isolate. Client
isolation can be used to prevent low-level bridging of frames
between associated stations in the BSS. By default, this bridging
is allowed.
* Allow coexistance of HT BSSes with WEP/TKIP BSSes.
* Add require_ht config parameter, which can be used to configure
hostapd to reject association with any station that does not support
HT PHY.
* Add support for writing debug log to a file using "-f" option. Also
add relog CLI command to re-open the log file.
* Add bridge handling for WDS STA interfaces. By default they are
added to the configured bridge of the AP interface (if present),
but the user can also specify a separate bridge using cli command
wds_bridge.
* hostapd_cli:
- Add wds_bridge command for specifying bridge for WDS STA
interfaces.
- Add relog command for reopening log file.
- Send AP-STA-DISCONNECTED event when an AP disconnects a station
due to inactivity.
- Add wps_config ctrl_interface command for configuring AP. This
command can be used to configure the AP using the internal WPS
registrar. It works in the same way as new AP settings received
from an ER.
- Many WPS/WPS ER commands - see WPS/WPS ER sections for details.
- Add command get version, that returns hostapd version string.
* WNM: Add BSS Transition Management Request for ESS Disassoc Imminent.
Use hostapd_cli ess_disassoc (STA addr) (URL) to send the
notification to the STA.
* Allow AP mode to disconnect STAs based on low ACK condition (when
the data connection is not working properly, e.g., due to the STA
going outside the range of the AP). Disabled by default, enable by
config option disassoc_low_ack.
* Add WPA_IGNORE_CONFIG_ERRORS build option to continue in case of bad
config file.
* WPS:
- Send AP Settings as a wrapped Credential attribute to ctrl_iface
in WPS-NEW-AP-SETTINGS.
- Dispatch more WPS events through hostapd ctrl_iface.
- Add mechanism for indicating non-standard WPS errors.
- Change concurrent radio AP to use only one WPS UPnP instance.
- Add wps_check_pin command for processing PIN from user input.
UIs can use this command to process a PIN entered by a user and to
validate the checksum digit (if present).
- Add hostap_cli get_config command to display current AP config.
- Add new hostapd_cli command, wps_ap_pin, to manage AP PIN at
runtime and support dynamic AP PIN management.
- Disable AP PIN after 10 consecutive failures. Slow down attacks
on failures up to 10.
- Allow AP to start in Enrollee mode without AP PIN for probing,
to be compatible with Windows 7.
- Add Config Error into WPS-FAIL events to provide more info
to the user on how to resolve the issue.
- When controlling multiple interfaces:
- apply WPS commands to all interfaces configured to use WPS
- apply WPS config changes to all interfaces that use WPS
- when an attack is detected on any interface, disable AP PIN on
all interfaces
* WPS ER:
- Show SetSelectedRegistrar events as ctrl_iface events.
- Add special AP Setup Locked mode to allow read only ER.
ap_setup_locked=2 can now be used to enable a special mode where
WPS ER can learn the current AP settings, but cannot change them.
* WPS 2.0: Add support for WPS 2.0 (CONFIG_WPS2)
- Add build option CONFIG_WPS_EXTENSIBILITY_TESTING to enable tool
for testing protocol extensibility.
- Add build option CONFIG_WPS_STRICT to allow disabling of WPS
workarounds.
- Add support for AuthorizedMACs attribute.
* TDLS:
- Allow TDLS use or TDLS channel switching in the BSS to be
prohibited in the BSS, using config params tdls_prohibit and
tdls_prohibit_chan_switch.
* EAP server: Add support for configuring fragment size (see
fragment_size in hostapd.conf).
* wlantest: Add a tool wlantest for IEEE802.11 protocol testing.
wlantest can be used to capture frames from a monitor interface
for realtime capturing or from pcap files for offline analysis.
* Interworking: Support added for 802.11u. Enable in .config with
CONFIG_INTERWORKING. See hostapd.conf for config parameters for
interworking.
* Android: Add build and runtime support for Android hostapd.
* Add a new debug message level for excessive information. Use
-ddd to enable.
* TLS: Add support for tls_disable_time_checks=1 in client mode.
* Internal TLS:
- Add support for TLS v1.1 (RFC 4346). Enable with build parameter
CONFIG_TLSV11.
- Add domainComponent parser for X.509 names
* Reorder some IEs to get closer to IEEE 802.11 standard. Move
WMM into end of Beacon, Probe Resp and (Re)Assoc Resp frames.
Move HT IEs to be later in (Re)Assoc Resp.
* Many bugfixes.
2010-04-18 - v0.7.2
* fix WPS internal Registrar use when an external Registrar is also
@ -98,7 +189,7 @@ ChangeLog for hostapd
* updated management frame protection to use IEEE Std 802.11w-2009
* fixed number of small WPS issues and added workarounds to
interoperate with common deployed broken implementations
* added some IEEE 802.11n co-existance rules to disable 40 MHz channels
* added some IEEE 802.11n co-existence rules to disable 40 MHz channels
or modify primary/secondary channels if needed based on neighboring
networks
* added support for NFC out-of-band mechanism with WPS

View File

@ -51,6 +51,10 @@ OBJS += ../src/ap/ap_mlme.o
OBJS += ../src/ap/wpa_auth_ie.o
OBJS += ../src/ap/preauth_auth.o
OBJS += ../src/ap/pmksa_cache_auth.o
OBJS += ../src/ap/ieee802_11_shared.o
OBJS += ../src/ap/beacon.o
OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
NEED_RC4=y
NEED_AES=y
@ -63,18 +67,25 @@ CFLAGS += -DHOSTAPD
ifdef CONFIG_WPA_TRACE
CFLAGS += -DWPA_TRACE
OBJS += ../src/utils/trace.o
HOBJS += ../src/utils/trace.o
LDFLAGS += -rdynamic
CFLAGS += -funwind-tables
ifdef CONFIG_WPA_TRACE_BFD
CFLAGS += -DWPA_TRACE_BFD
LIBS += -lbfd
LIBS_c += -lbfd
LIBS_h += -lbfd
endif
endif
OBJS += ../src/utils/eloop.o
ifndef CONFIG_ELOOP
CONFIG_ELOOP=eloop
endif
OBJS += ../src/utils/$(CONFIG_ELOOP).o
OBJS_c += ../src/utils/$(CONFIG_ELOOP).o
OBJS += ../src/utils/common.o
OBJS += ../src/utils/wpa_debug.o
OBJS_c += ../src/utils/wpa_debug.o
OBJS += ../src/utils/wpabuf.o
OBJS += ../src/utils/os_$(CONFIG_OS).o
OBJS += ../src/utils/ip_addr.o
@ -274,6 +285,12 @@ NEED_SHA256=y
NEED_AES_OMAC1=y
endif
ifdef CONFIG_EAP_PWD
CFLAGS += -DEAP_SERVER_PWD
OBJS += ../src/eap_server/eap_server_pwd.o ../src/eap_common/eap_pwd_common.o
NEED_SHA256=y
endif
ifdef CONFIG_EAP_VENDOR_TEST
CFLAGS += -DEAP_SERVER_VENDOR_TEST
OBJS += ../src/eap_server/eap_server_vendor_test.o
@ -289,6 +306,10 @@ NEED_AES_UNWRAP=y
endif
ifdef CONFIG_WPS
ifdef CONFIG_WPS2
CFLAGS += -DCONFIG_WPS2
endif
CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC
OBJS += ../src/utils/uuid.o
OBJS += ../src/ap/wps_hostapd.o
@ -346,6 +367,15 @@ OBJS += ../src/wps/http_client.o
OBJS += ../src/wps/http_server.o
endif
ifdef CONFIG_WPS_STRICT
CFLAGS += -DCONFIG_WPS_STRICT
OBJS += ../src/wps/wps_validate.o
endif
ifdef CONFIG_WPS_TESTING
CFLAGS += -DCONFIG_WPS_TESTING
endif
endif
ifdef CONFIG_EAP_IKEV2
@ -406,6 +436,10 @@ ifndef CONFIG_TLS
CONFIG_TLS=openssl
endif
ifdef CONFIG_TLSV11
CFLAGS += -DCONFIG_TLSV11
endif
ifeq ($(CONFIG_TLS), openssl)
ifdef TLS_FUNCS
OBJS += ../src/crypto/tls_openssl.o
@ -424,10 +458,6 @@ ifeq ($(CONFIG_TLS), gnutls)
ifdef TLS_FUNCS
OBJS += ../src/crypto/tls_gnutls.o
LIBS += -lgnutls -lgpg-error
ifdef CONFIG_GNUTLS_EXTRA
CFLAGS += -DCONFIG_GNUTLS_EXTRA
LIBS += -lgnutls-extra
endif
endif
OBJS += ../src/crypto/crypto_gnutls.o
HOBJS += ../src/crypto/crypto_gnutls.o
@ -625,6 +655,7 @@ endif
ifdef NEED_MD5
ifdef CONFIG_INTERNAL_MD5
OBJS += ../src/crypto/md5-internal.o
HOBJS += ../src/crypto/md5-internal.o
endif
endif
@ -665,6 +696,16 @@ OBJS += ../src/crypto/dh_group5.o
endif
endif
ifdef CONFIG_NO_RANDOM_POOL
CFLAGS += -DCONFIG_NO_RANDOM_POOL
else
OBJS += ../src/crypto/random.o
HOBJS += ../src/crypto/random.o
HOBJS += ../src/utils/eloop.o
HOBJS += $(SHA1OBJS)
HOBJS += ../src/crypto/md5.o
endif
ifdef CONFIG_RADIUS_SERVER
CFLAGS += -DRADIUS_SERVER
OBJS += ../src/radius/radius_server.o
@ -689,7 +730,6 @@ OBJS += ../src/utils/base64.o
endif
ifdef NEED_AP_MLME
OBJS += ../src/ap/beacon.o
OBJS += ../src/ap/wmm.o
OBJS += ../src/ap/ap_list.o
OBJS += ../src/ap/ieee802_11.o
@ -700,10 +740,31 @@ ifdef CONFIG_IEEE80211N
OBJS += ../src/ap/ieee802_11_ht.o
endif
ifdef CONFIG_P2P_MANAGER
CFLAGS += -DCONFIG_P2P_MANAGER
OBJS += ../src/ap/p2p_hostapd.o
endif
ifdef CONFIG_INTERWORKING
CFLAGS += -DCONFIG_INTERWORKING
endif
OBJS += ../src/drivers/driver_common.o
ifdef CONFIG_WPA_CLI_EDIT
OBJS_c += ../src/utils/edit.o
else
OBJS_c += ../src/utils/edit_simple.o
endif
ifdef CONFIG_NO_STDOUT_DEBUG
CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
endif
ifdef CONFIG_DEBUG_FILE
CFLAGS += -DCONFIG_DEBUG_FILE
endif
ALL=hostapd hostapd_cli
all: verify_config $(ALL)
@ -729,7 +790,8 @@ verify_config:
fi
install: all
for i in $(ALL); do cp -f $$i /usr/local/bin/$$i; done
mkdir -p $(DESTDIR)/usr/local/bin
for i in $(ALL); do cp -f $$i $(DESTDIR)/usr/local/bin/$$i; done
../src/drivers/build.hostapd:
@if [ -f ../src/drivers/build.wpa_supplicant ]; then \
@ -740,15 +802,15 @@ install: all
BCHECK=../src/drivers/build.hostapd
hostapd: $(BCHECK) $(OBJS)
$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
@$(E) " LD " $@
OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
ifdef CONFIG_WPA_TRACE
OBJS_c += ../src/utils/trace.o
OBJS_c += ../src/utils/wpa_debug.o
endif
hostapd_cli: $(OBJS_c)
$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
@$(E) " LD " $@
NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) ../src/crypto/md5.o
ifdef NEED_RC4
@ -778,10 +840,12 @@ HOBJS += ../src/crypto/aes-internal-enc.o
endif
nt_password_hash: $(NOBJS)
$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
$(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
@$(E) " LD " $@
hlr_auc_gw: $(HOBJS)
$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
$(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
@$(E) " LD " $@
clean:
$(MAKE) -C ../src clean

View File

@ -2,7 +2,7 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
Authenticator and RADIUS authentication server
================================================================
Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi> and contributors
Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
This program is dual-licensed under both the GPL version 2 and BSD

View File

@ -63,6 +63,7 @@ includes WPS support and uses madwifi driver interface:
CONFIG_DRIVER_MADWIFI=y
CFLAGS += -I/usr/src/madwifi-0.9.3
CONFIG_WPS=y
CONFIG_WPS2=y
CONFIG_WPS_UPNP=y
@ -119,6 +120,13 @@ pushbutton event (for PBC) to allow a new WPS Enrollee to join the
network. hostapd uses the control interface as an input channel for
these events.
The PIN value used in the commands must be processed by an UI to
remove non-digit characters and potentially, to verify the checksum
digit. "hostapd_cli wps_check_pin <PIN>" can be used to do such
processing. It returns FAIL if the PIN is invalid, or FAIL-CHECKSUM if
the checksum digit is incorrect, or the processed PIN (non-digit
characters removed) if the PIN is valid.
When a client device (WPS Enrollee) connects to hostapd (WPS
Registrar) in order to start PIN mode negotiation for WPS, an
identifier (Enrollee UUID) is sent. hostapd will need to be configured
@ -171,10 +179,17 @@ 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:
time in seconds can be set for the new PIN (value 0 indicates no
expiration):
hostapd_cli wps_pin any 12345670 300
If the MAC address of the enrollee is known, it should be configured
to allow the AP to advertise list of authorized enrollees:
hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c \
12345670 300 00:11:22:33:44:55
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
@ -221,6 +236,17 @@ hostapd_cli wps_ap_pin set <PIN> [timeout]
- if the optional timeout parameter is given, the AP PIN will be enabled
for the specified number of seconds
hostapd_cli get_config
- display the current configuration
hostapd_cli wps_config <new SSID> <auth> <encr> <new key>
examples:
hostapd_cli wps_config testing WPA2PSK CCMP 12345678
hostapd_cli wps_config "no security" OPEN NONE ""
<auth> must be one of the following: OPEN WPAPSK WPA2PSK
<encr> must be one of the following: NONE WEP TKIP CCMP
Credential generation and configuration changes
-----------------------------------------------
@ -251,7 +277,7 @@ WPS-REG-SUCCESS <Enrollee MAC address <UUID-E>
For example:
<2>WPS-REG-SUCCESS 02:66:a0:ee:17:27 2b7093f1-d6fb-5108-adbb-bea66bb87333
This can be used to tricker change from unconfigured to configured
This can be used to trigger change from unconfigured to configured
state (random configuration based on the first successful WPS
registration). In addition, this can be used to update AP UI about the
status of WPS registration progress.

View File

@ -752,10 +752,7 @@ enum {
IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */
IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */
IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */
IEEE80211_TX_QUEUE_DATA3 = 3, /* used for EDCA AC_BK data */
IEEE80211_TX_QUEUE_DATA4 = 4,
IEEE80211_TX_QUEUE_AFTER_BEACON = 6,
IEEE80211_TX_QUEUE_BEACON = 7
IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */
};
static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name,
@ -771,17 +768,21 @@ static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name,
pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') {
num = pos[4] - '0';
pos += 6;
} else if (os_strncmp(pos, "after_beacon_", 13) == 0) {
num = IEEE80211_TX_QUEUE_AFTER_BEACON;
pos += 13;
} else if (os_strncmp(pos, "beacon_", 7) == 0) {
num = IEEE80211_TX_QUEUE_BEACON;
pos += 7;
} else if (os_strncmp(pos, "after_beacon_", 13) == 0 ||
os_strncmp(pos, "beacon_", 7) == 0) {
wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
return 0;
} else {
wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos);
return -1;
}
if (num >= NUM_TX_QUEUES) {
/* for backwards compatibility, do not trigger failure */
wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
return 0;
}
queue = &conf->tx_queue[num];
if (os_strcmp(pos, "aifs") == 0) {
@ -812,8 +813,6 @@ static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name,
return -1;
}
queue->configured = 1;
return 0;
}
@ -1089,15 +1088,37 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211N
if (conf->ieee80211n &&
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
bss->disable_11n = 1;
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
"allowed, disabling HT capabilities");
}
if (conf->ieee80211n && bss->wpa &&
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
!(bss->rsn_pairwise & WPA_CIPHER_CCMP)) {
bss->disable_11n = 1;
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 "
"requires CCMP to be enabled");
return -1;
"requires CCMP to be enabled, disabling HT "
"capabilities");
}
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_WPS2
if (bss->wps_state && bss->ignore_broadcast_ssid) {
wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
"configuration forced WPS to be disabled");
bss->wps_state = 0;
}
if (bss->wps_state && bss->ssid.wep.keys_set && bss->wpa == 0) {
wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
"disabled");
bss->wps_state = 0;
}
#endif /* CONFIG_WPS2 */
return 0;
}
@ -1121,6 +1142,40 @@ static int hostapd_config_check(struct hostapd_config *conf)
}
#ifdef CONFIG_INTERWORKING
static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos,
int line)
{
size_t len = os_strlen(pos);
u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
struct hostapd_roaming_consortium *rc;
if ((len & 1) || len < 2 * 3 || len / 2 > MAX_ROAMING_CONSORTIUM_LEN ||
hexstr2bin(pos, oi, len / 2)) {
wpa_printf(MSG_ERROR, "Line %d: invalid roaming_consortium "
"'%s'", line, pos);
return -1;
}
len /= 2;
rc = os_realloc(bss->roaming_consortium,
sizeof(struct hostapd_roaming_consortium) *
(bss->roaming_consortium_count + 1));
if (rc == NULL)
return -1;
os_memcpy(rc[bss->roaming_consortium_count].oi, oi, len);
rc[bss->roaming_consortium_count].len = len;
bss->roaming_consortium = rc;
bss->roaming_consortium_count++;
return 0;
}
#endif /* CONFIG_INTERWORKING */
/**
* hostapd_config_read - Read and parse a configuration file
* @fname: Configuration file name (including path, if needed)
@ -1193,6 +1248,9 @@ struct hostapd_config * hostapd_config_read(const char *fname)
sizeof(conf->bss[0].iface));
} else if (os_strcmp(buf, "bridge") == 0) {
os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
} else if (os_strcmp(buf, "wds_bridge") == 0) {
os_strlcpy(bss->wds_bridge, pos,
sizeof(bss->wds_bridge));
} else if (os_strcmp(buf, "driver") == 0) {
int j;
/* clear to get error below if setting is invalid */
@ -1264,6 +1322,8 @@ struct hostapd_config * hostapd_config_read(const char *fname)
}
} else if (os_strcmp(buf, "wds_sta") == 0) {
bss->wds_sta = atoi(pos);
} else if (os_strcmp(buf, "ap_isolate") == 0) {
bss->isolate = atoi(pos);
} else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
bss->ap_max_inactivity = atoi(pos);
} else if (os_strcmp(buf, "country_code") == 0) {
@ -1313,6 +1373,8 @@ struct hostapd_config * hostapd_config_read(const char *fname)
} else if (os_strcmp(buf, "dh_file") == 0) {
os_free(bss->dh_file);
bss->dh_file = os_strdup(pos);
} else if (os_strcmp(buf, "fragment_size") == 0) {
bss->fragment_size = atoi(pos);
#ifdef EAP_SERVER_FAST
} else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) {
os_free(bss->pac_opaque_encr_key);
@ -1367,6 +1429,10 @@ struct hostapd_config * hostapd_config_read(const char *fname)
} else if (os_strcmp(buf, "tnc") == 0) {
bss->tnc = atoi(pos);
#endif /* EAP_SERVER_TNC */
#ifdef EAP_SERVER_PWD
} else if (os_strcmp(buf, "pwd_group") == 0) {
bss->pwd_group = atoi(pos);
#endif /* EAP_SERVER_PWD */
#endif /* EAP_SERVER */
} else if (os_strcmp(buf, "eap_message") == 0) {
char *term;
@ -1641,6 +1707,8 @@ struct hostapd_config * hostapd_config_read(const char *fname)
}
} else if (os_strcmp(buf, "pmk_r1_push") == 0) {
bss->pmk_r1_push = atoi(pos);
} else if (os_strcmp(buf, "ft_over_ds") == 0) {
bss->ft_over_ds = atoi(pos);
#endif /* CONFIG_IEEE80211R */
#ifndef CONFIG_NO_CTRL_IFACE
} else if (os_strcmp(buf, "ctrl_interface") == 0) {
@ -1865,9 +1933,13 @@ struct hostapd_config * hostapd_config_read(const char *fname)
"ht_capab", line);
errors++;
}
} else if (os_strcmp(buf, "require_ht") == 0) {
conf->require_ht = atoi(pos);
#endif /* CONFIG_IEEE80211N */
} else if (os_strcmp(buf, "max_listen_interval") == 0) {
bss->max_listen_interval = atoi(pos);
} else if (os_strcmp(buf, "disable_pmksa_caching") == 0) {
bss->disable_pmksa_caching = atoi(pos);
} else if (os_strcmp(buf, "okc") == 0) {
bss->okc = atoi(pos);
#ifdef CONFIG_WPS
@ -1930,8 +2002,8 @@ struct hostapd_config * hostapd_config_read(const char *fname)
os_free(bss->serial_number);
bss->serial_number = os_strdup(pos);
} else if (os_strcmp(buf, "device_type") == 0) {
os_free(bss->device_type);
bss->device_type = os_strdup(pos);
if (wps_dev_type_str2bin(pos, bss->device_type))
errors++;
} else if (os_strcmp(buf, "config_methods") == 0) {
os_free(bss->config_methods);
bss->config_methods = os_strdup(pos);
@ -1985,7 +2057,90 @@ struct hostapd_config * hostapd_config_read(const char *fname)
} else if (os_strcmp(buf, "upc") == 0) {
os_free(bss->upc);
bss->upc = os_strdup(pos);
} else if (os_strcmp(buf, "pbc_in_m1") == 0) {
bss->pbc_in_m1 = atoi(pos);
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P_MANAGER
} else if (os_strcmp(buf, "manage_p2p") == 0) {
int manage = atoi(pos);
if (manage)
bss->p2p |= P2P_MANAGE;
else
bss->p2p &= ~P2P_MANAGE;
} else if (os_strcmp(buf, "allow_cross_connection") == 0) {
if (atoi(pos))
bss->p2p |= P2P_ALLOW_CROSS_CONNECTION;
else
bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION;
#endif /* CONFIG_P2P_MANAGER */
} else if (os_strcmp(buf, "disassoc_low_ack") == 0) {
bss->disassoc_low_ack = atoi(pos);
} else if (os_strcmp(buf, "tdls_prohibit") == 0) {
int val = atoi(pos);
if (val)
bss->tdls |= TDLS_PROHIBIT;
else
bss->tdls &= ~TDLS_PROHIBIT;
} else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) {
int val = atoi(pos);
if (val)
bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH;
else
bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH;
#ifdef CONFIG_RSN_TESTING
} else if (os_strcmp(buf, "rsn_testing") == 0) {
extern int rsn_testing;
rsn_testing = atoi(pos);
#endif /* CONFIG_RSN_TESTING */
} else if (os_strcmp(buf, "time_advertisement") == 0) {
bss->time_advertisement = atoi(pos);
} else if (os_strcmp(buf, "time_zone") == 0) {
size_t tz_len = os_strlen(pos);
if (tz_len < 4 || tz_len > 255) {
wpa_printf(MSG_DEBUG, "Line %d: invalid "
"time_zone", line);
errors++;
continue;
}
os_free(bss->time_zone);
bss->time_zone = os_strdup(pos);
if (bss->time_zone == NULL)
errors++;
#ifdef CONFIG_INTERWORKING
} else if (os_strcmp(buf, "interworking") == 0) {
bss->interworking = atoi(pos);
} else if (os_strcmp(buf, "access_network_type") == 0) {
bss->access_network_type = atoi(pos);
if (bss->access_network_type < 0 ||
bss->access_network_type > 15) {
wpa_printf(MSG_ERROR, "Line %d: invalid "
"access_network_type", line);
errors++;
}
} else if (os_strcmp(buf, "internet") == 0) {
bss->internet = atoi(pos);
} else if (os_strcmp(buf, "asra") == 0) {
bss->asra = atoi(pos);
} else if (os_strcmp(buf, "esr") == 0) {
bss->esr = atoi(pos);
} else if (os_strcmp(buf, "uesa") == 0) {
bss->uesa = atoi(pos);
} else if (os_strcmp(buf, "venue_group") == 0) {
bss->venue_group = atoi(pos);
bss->venue_info_set = 1;
} else if (os_strcmp(buf, "venue_type") == 0) {
bss->venue_type = atoi(pos);
bss->venue_info_set = 1;
} else if (os_strcmp(buf, "hessid") == 0) {
if (hwaddr_aton(pos, bss->hessid)) {
wpa_printf(MSG_ERROR, "Line %d: invalid "
"hessid", line);
errors++;
}
} else if (os_strcmp(buf, "roaming_consortium") == 0) {
if (parse_roaming_consortium(bss, pos, line) < 0)
errors++;
#endif /* CONFIG_INTERWORKING */
} else {
wpa_printf(MSG_ERROR, "Line %d: unknown configuration "
"item '%s'", line, buf);
@ -2027,23 +2182,42 @@ struct hostapd_config * hostapd_config_read(const char *fname)
} else if (bss->wpa) {
bss->ssid.security_policy = SECURITY_WPA_PSK;
} else if (bss->ieee802_1x) {
int cipher = WPA_CIPHER_NONE;
bss->ssid.security_policy = SECURITY_IEEE_802_1X;
bss->ssid.wep.default_len = bss->default_wep_key_len;
} else if (bss->ssid.wep.keys_set)
if (bss->default_wep_key_len)
cipher = bss->default_wep_key_len >= 13 ?
WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
bss->wpa_group = cipher;
bss->wpa_pairwise = cipher;
bss->rsn_pairwise = cipher;
} else if (bss->ssid.wep.keys_set) {
int cipher = WPA_CIPHER_WEP40;
if (bss->ssid.wep.len[0] >= 13)
cipher = WPA_CIPHER_WEP104;
bss->ssid.security_policy = SECURITY_STATIC_WEP;
else
bss->wpa_group = cipher;
bss->wpa_pairwise = cipher;
bss->rsn_pairwise = cipher;
} else {
bss->ssid.security_policy = SECURITY_PLAINTEXT;
bss->wpa_group = WPA_CIPHER_NONE;
bss->wpa_pairwise = WPA_CIPHER_NONE;
bss->rsn_pairwise = WPA_CIPHER_NONE;
}
}
if (hostapd_config_check(conf))
errors++;
#ifndef WPA_IGNORE_CONFIG_ERRORS
if (errors) {
wpa_printf(MSG_ERROR, "%d errors found in configuration file "
"'%s'", errors, fname);
hostapd_config_free(conf);
conf = NULL;
}
#endif /* WPA_IGNORE_CONFIG_ERRORS */
return conf;
}

View File

@ -1,6 +1,6 @@
/*
* hostapd / UNIX domain socket -based control interface
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2010, 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
@ -22,6 +22,7 @@
#include "utils/common.h"
#include "utils/eloop.h"
#include "common/version.h"
#include "common/ieee802_11_defs.h"
#include "drivers/driver.h"
#include "radius/radius_client.h"
@ -34,6 +35,9 @@
#include "ap/accounting.h"
#include "ap/wps_hostapd.h"
#include "ap/ctrl_iface_ap.h"
#include "ap/ap_drv_ops.h"
#include "wps/wps_defs.h"
#include "wps/wps.h"
#include "ctrl_iface.h"
@ -155,6 +159,59 @@ static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
}
#ifdef CONFIG_P2P_MANAGER
static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
u8 minor_reason_code, const u8 *addr)
{
struct ieee80211_mgmt *mgmt;
int ret;
u8 *pos;
if (hapd->driver->send_frame == NULL)
return -1;
mgmt = os_zalloc(sizeof(*mgmt) + 100);
if (mgmt == NULL)
return -1;
wpa_printf(MSG_DEBUG, "P2P: Disconnect STA " MACSTR " with minor "
"reason code %u (stype=%u)",
MAC2STR(addr), minor_reason_code, stype);
mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
os_memcpy(mgmt->da, addr, ETH_ALEN);
os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
if (stype == WLAN_FC_STYPE_DEAUTH) {
mgmt->u.deauth.reason_code =
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
pos = (u8 *) (&mgmt->u.deauth.reason_code + 1);
} else {
mgmt->u.disassoc.reason_code =
host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1);
}
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 4 + 3 + 1;
WPA_PUT_BE24(pos, OUI_WFA);
pos += 3;
*pos++ = P2P_OUI_TYPE;
*pos++ = P2P_ATTR_MINOR_REASON_CODE;
WPA_PUT_LE16(pos, 1);
pos += 2;
*pos++ = minor_reason_code;
ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
pos - (u8 *) mgmt, 1);
os_free(mgmt);
return ret < 0 ? -1 : 0;
}
#endif /* CONFIG_P2P_MANAGER */
static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
const char *txtaddr)
{
@ -191,11 +248,21 @@ static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
return 0;
}
hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
#ifdef CONFIG_P2P_MANAGER
pos = os_strstr(txtaddr, " p2p=");
if (pos) {
return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH,
atoi(pos + 5), addr);
}
#endif /* CONFIG_P2P_MANAGER */
hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
sta = ap_get_sta(hapd, addr);
if (sta)
ap_sta_deauthenticate(hapd, sta,
WLAN_REASON_PREV_AUTH_NOT_VALID);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
return 0;
}
@ -237,11 +304,21 @@ static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
return 0;
}
hapd->drv.sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
#ifdef CONFIG_P2P_MANAGER
pos = os_strstr(txtaddr, " p2p=");
if (pos) {
return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC,
atoi(pos + 5), addr);
}
#endif /* CONFIG_P2P_MANAGER */
hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
sta = ap_get_sta(hapd, addr);
if (sta)
ap_sta_disassociate(hapd, sta,
WLAN_REASON_PREV_AUTH_NOT_VALID);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
return 0;
}
@ -275,6 +352,8 @@ static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
char *pin = os_strchr(txt, ' ');
char *timeout_txt;
int timeout;
u8 addr_buf[ETH_ALEN], *addr = NULL;
char *pos;
if (pin == NULL)
return -1;
@ -284,10 +363,61 @@ static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
if (timeout_txt) {
*timeout_txt++ = '\0';
timeout = atoi(timeout_txt);
pos = os_strchr(timeout_txt, ' ');
if (pos) {
*pos++ = '\0';
if (hwaddr_aton(pos, addr_buf) == 0)
addr = addr_buf;
}
} else
timeout = 0;
return hostapd_wps_add_pin(hapd, txt, pin, timeout);
return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
}
static int hostapd_ctrl_iface_wps_check_pin(
struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
{
char pin[9];
size_t len;
char *pos;
int ret;
wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
(u8 *) cmd, os_strlen(cmd));
for (pos = cmd, len = 0; *pos != '\0'; pos++) {
if (*pos < '0' || *pos > '9')
continue;
pin[len++] = *pos;
if (len == 9) {
wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
return -1;
}
}
if (len != 4 && len != 8) {
wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
return -1;
}
pin[len] = '\0';
if (len == 8) {
unsigned int pin_val;
pin_val = atoi(pin);
if (!wps_pin_valid(pin_val)) {
wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
if (ret < 0 || (size_t) ret >= buflen)
return -1;
return ret;
}
}
ret = os_snprintf(buf, buflen, "%s", pin);
if (ret < 0 || (size_t) ret >= buflen)
return -1;
return ret;
}
@ -366,9 +496,314 @@ static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
return -1;
}
static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
{
char *pos;
char *ssid, *auth, *encr = NULL, *key = NULL;
ssid = txt;
pos = os_strchr(txt, ' ');
if (!pos)
return -1;
*pos++ = '\0';
auth = pos;
pos = os_strchr(pos, ' ');
if (pos) {
*pos++ = '\0';
encr = pos;
pos = os_strchr(pos, ' ');
if (pos) {
*pos++ = '\0';
key = pos;
}
}
return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
}
#endif /* CONFIG_WPS */
static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
const char *cmd)
{
u8 addr[ETH_ALEN];
const char *url;
u8 buf[1000], *pos;
struct ieee80211_mgmt *mgmt;
size_t url_len;
if (hwaddr_aton(cmd, addr))
return -1;
url = cmd + 17;
if (*url != ' ')
return -1;
url++;
url_len = os_strlen(url);
if (url_len > 255)
return -1;
os_memset(buf, 0, sizeof(buf));
mgmt = (struct ieee80211_mgmt *) buf;
mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_ACTION);
os_memcpy(mgmt->da, addr, ETH_ALEN);
os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
mgmt->u.action.category = WLAN_ACTION_WNM;
mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
mgmt->u.action.u.bss_tm_req.dialog_token = 1;
mgmt->u.action.u.bss_tm_req.req_mode =
WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0);
mgmt->u.action.u.bss_tm_req.validity_interval = 0;
pos = mgmt->u.action.u.bss_tm_req.variable;
/* Session Information URL */
*pos++ = url_len;
os_memcpy(pos, url, url_len);
pos += url_len;
if (hostapd_drv_send_mlme(hapd, buf, pos - buf) < 0) {
wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
"Management Request frame");
return -1;
}
return 0;
}
static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
char *buf, size_t buflen)
{
int ret;
char *pos, *end;
pos = buf;
end = buf + buflen;
ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
"ssid=%s\n",
MAC2STR(hapd->own_addr),
hapd->conf->ssid.ssid);
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
#ifdef CONFIG_WPS
ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
hapd->conf->wps_state == 0 ? "disabled" :
(hapd->conf->wps_state == 1 ? "not configured" :
"configured"));
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
if (hapd->conf->wps_state && hapd->conf->wpa &&
hapd->conf->ssid.wpa_passphrase) {
ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
hapd->conf->ssid.wpa_passphrase);
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
if (hapd->conf->wps_state && hapd->conf->wpa &&
hapd->conf->ssid.wpa_psk &&
hapd->conf->ssid.wpa_psk->group) {
char hex[PMK_LEN * 2 + 1];
wpa_snprintf_hex(hex, sizeof(hex),
hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
#endif /* CONFIG_WPS */
if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
ret = os_snprintf(pos, end - pos, "key_mgmt=");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
ret = os_snprintf(pos, end - pos, "WPA-PSK ");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
ret = os_snprintf(pos, end - pos, "WPA-EAP ");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
#ifdef CONFIG_IEEE80211R
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
ret = os_snprintf(pos, end - pos, "FT-PSK ");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
ret = os_snprintf(pos, end - pos, "FT-EAP ");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
#endif /* CONFIG_IEEE80211W */
ret = os_snprintf(pos, end - pos, "\n");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
if (hapd->conf->wpa && hapd->conf->wpa_group == WPA_CIPHER_CCMP) {
ret = os_snprintf(pos, end - pos, "group_cipher=CCMP\n");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
} else if (hapd->conf->wpa &&
hapd->conf->wpa_group == WPA_CIPHER_TKIP) {
ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
if (hapd->conf->rsn_pairwise & WPA_CIPHER_CCMP) {
ret = os_snprintf(pos, end - pos, "CCMP ");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) {
ret = os_snprintf(pos, end - pos, "TKIP ");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
ret = os_snprintf(pos, end - pos, "\n");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
if (hapd->conf->wpa_pairwise & WPA_CIPHER_CCMP) {
ret = os_snprintf(pos, end - pos, "CCMP ");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) {
ret = os_snprintf(pos, end - pos, "TKIP ");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
ret = os_snprintf(pos, end - pos, "\n");
if (ret < 0 || ret >= end - pos)
return pos - buf;
pos += ret;
}
return pos - buf;
}
static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
{
char *value;
int ret = 0;
value = os_strchr(cmd, ' ');
if (value == NULL)
return -1;
*value++ = '\0';
wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
if (0) {
#ifdef CONFIG_WPS_TESTING
} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
long int val;
val = strtol(value, NULL, 0);
if (val < 0 || val > 0xff) {
ret = -1;
wpa_printf(MSG_DEBUG, "WPS: Invalid "
"wps_version_number %ld", val);
} else {
wps_version_number = val;
wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
"version %u.%u",
(wps_version_number & 0xf0) >> 4,
wps_version_number & 0x0f);
hostapd_wps_update_ie(hapd);
}
} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
wps_testing_dummy_cred = atoi(value);
wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
wps_testing_dummy_cred);
#endif /* CONFIG_WPS_TESTING */
} else {
ret = -1;
}
return ret;
}
static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
char *buf, size_t buflen)
{
int res;
wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
if (os_strcmp(cmd, "version") == 0) {
res = os_snprintf(buf, buflen, "%s", VERSION_STR);
if (res < 0 || (unsigned int) res >= buflen)
return -1;
return res;
}
return -1;
}
static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
@ -380,6 +815,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
char *reply;
const int reply_size = 4096;
int reply_len;
int level = MSG_DEBUG;
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
(struct sockaddr *) &from, &fromlen);
@ -388,7 +824,9 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
return;
}
buf[res] = '\0';
wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) buf, res);
if (os_strcmp(buf, "PING") == 0)
level = MSG_EXCESSIVE;
wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
reply = os_malloc(reply_size);
if (reply == NULL) {
@ -403,6 +841,9 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
if (os_strcmp(buf, "PING") == 0) {
os_memcpy(reply, "PONG\n", 5);
reply_len = 5;
} else if (os_strncmp(buf, "RELOG", 5) == 0) {
if (wpa_debug_reopen_file() < 0)
reply_len = -1;
} else if (os_strcmp(buf, "MIB") == 0) {
reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
if (reply_len >= 0) {
@ -471,8 +912,11 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
reply_len = -1;
} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
reply_len = hostapd_ctrl_iface_wps_check_pin(
hapd, buf + 14, reply, reply_size);
} else if (os_strcmp(buf, "WPS_PBC") == 0) {
if (hostapd_wps_button_pushed(hapd))
if (hostapd_wps_button_pushed(hapd, NULL))
reply_len = -1;
#ifdef CONFIG_WPS_OOB
} else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
@ -482,7 +926,22 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
reply, reply_size);
} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
reply_len = -1;
#endif /* CONFIG_WPS */
} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
reply_len = -1;
} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
reply_size);
} else if (os_strncmp(buf, "SET ", 4) == 0) {
if (hostapd_ctrl_iface_set(hapd, buf + 4))
reply_len = -1;
} else if (os_strncmp(buf, "GET ", 4) == 0) {
reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
reply_size);
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;

View File

@ -20,13 +20,7 @@ CONFIG_DRIVER_HOSTAP=y
#CFLAGS += -I../../madwifi # change to the madwifi source directory
# Driver interface for drivers using the nl80211 kernel interface
#CONFIG_DRIVER_NL80211=y
# driver_nl80211.c requires a rather new libnl (version 1.1) which may not be
# shipped with your distribution yet. If that is the case, you need to build
# newer libnl version and point the hostapd build to use it.
#LIBNL=/usr/src/libnl
#CFLAGS += -I$(LIBNL)/include
#LIBS += -L$(LIBNL)/lib
CONFIG_DRIVER_NL80211=y
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
#CONFIG_DRIVER_BSD=y
@ -90,6 +84,9 @@ CONFIG_EAP_TTLS=y
# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
#CONFIG_EAP_PSK=y
# EAP-pwd for the integrated EAP server (secure authentication with a password)
#CONFIG_EAP_PWD=y
# EAP-SAKE for the integrated EAP server
#CONFIG_EAP_SAKE=y
@ -107,6 +104,8 @@ CONFIG_EAP_TTLS=y
# Wi-Fi Protected Setup (WPS)
#CONFIG_WPS=y
# Enable WSC 2.0 support
#CONFIG_WPS2=y
# Enable UPnP support for external WPS Registrars
#CONFIG_WPS_UPNP=y
@ -142,6 +141,10 @@ CONFIG_IPV6=y
# code is not needed.
#CONFIG_NO_STDOUT_DEBUG=y
# Add support for writing debug log to a file: -f /tmp/hostapd.log
# Disabled by default.
#CONFIG_DEBUG_FILE=y
# Remove support for RADIUS accounting
#CONFIG_NO_ACCOUNTING=y
@ -151,6 +154,10 @@ CONFIG_IPV6=y
# Remove support for VLANs
#CONFIG_NO_VLAN=y
# Enable support for fully dynamic VLANs. This enables hostapd to
# automatically create bridge and VLAN interfaces if necessary.
#CONFIG_FULL_DYNAMIC_VLAN=y
# Remove support for dumping state into a file on SIGUSR1 signal
# This can be used to reduce binary size at the cost of disabling a debugging
# option.
@ -173,3 +180,67 @@ CONFIG_IPV6=y
#LIBS += -lbfd -liberty -lz
#LIBS_p += -lbfd -liberty -lz
#LIBS_c += -lbfd -liberty -lz
# hostapd depends on strong random number generation being available from the
# operating system. os_get_random() function is used to fetch random data when
# needed, e.g., for key generation. On Linux and BSD systems, this works by
# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
# properly initialized before hostapd is started. This is important especially
# on embedded devices that do not have a hardware random number generator and
# may by default start up with minimal entropy available for random number
# generation.
#
# As a safety net, hostapd is by default trying to internally collect
# additional entropy for generating random data to mix in with the data
# fetched from the OS. This by itself is not considered to be very strong, but
# it may help in cases where the system pool is not initialized properly.
# However, it is very strongly recommended that the system pool is initialized
# with enough entropy either by using hardware assisted random number
# generator or by storing state over device reboots.
#
# hostapd can be configured to maintain its own entropy store over restarts to
# enhance random number generation. This is not perfect, but it is much more
# secure than using the same sequence of random numbers after every reboot.
# This can be enabled with -e<entropy file> command line option. The specified
# file needs to be readable and writable by hostapd.
#
# If the os_get_random() is known to provide strong random data (e.g., on
# Linux/BSD, the board in question is known to have reliable source of random
# data from /dev/urandom), the internal hostapd random pool can be disabled.
# This will save some in binary size and CPU use. However, this should only be
# considered for builds that are known to be used on devices that meet the
# requirements described above.
#CONFIG_NO_RANDOM_POOL=y
# Select TLS implementation
# openssl = OpenSSL (default)
# gnutls = GnuTLS
# internal = Internal TLSv1 implementation (experimental)
# none = Empty template
#CONFIG_TLS=openssl
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
# can be enabled to get a stronger construction of messages when block ciphers
# are used.
#CONFIG_TLSV11=y
# If CONFIG_TLS=internal is used, additional library and include paths are
# needed for LibTomMath. Alternatively, an integrated, minimal version of
# LibTomMath can be used. See beginning of libtommath.c for details on benefits
# and drawbacks of this option.
#CONFIG_INTERNAL_LIBTOMMATH=y
#ifndef CONFIG_INTERNAL_LIBTOMMATH
#LTM_PATH=/usr/src/libtommath-0.39
#CFLAGS += -I$(LTM_PATH)
#LIBS += -L$(LTM_PATH)
#LIBS_p += -L$(LTM_PATH)
#endif
# At the cost of about 4 kB of additional binary size, the internal LibTomMath
# can be configured to include faster routines for exptmod, sqr, and div to
# speed up DH and RSA calculation considerably
#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
# Interworking (IEEE 802.11u)
# This can be used to enable functionality to improve interworking with
# external networks.
#CONFIG_INTERWORKING=y

View File

@ -13,6 +13,7 @@
*/
#include "utils/includes.h"
#include <time.h>
#include "utils/common.h"
#include "radius/radius_client.h"
@ -106,7 +107,8 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
fprintf(f,
" AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
" AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
"\n"
" capability=0x%x listen_interval=%d\n",
sta->aid,
sta->flags,
@ -115,8 +117,7 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
(sta->flags & WLAN_STA_PS ? "[PS]" : ""),
(sta->flags & WLAN_STA_TIM ? "[TIM]" : ""),
(sta->flags & WLAN_STA_PERM ? "[PERM]" : ""),
(sta->flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" :
""),
(ap_sta_is_authorized(sta) ? "[AUTHORIZED]" : ""),
(sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" :
""),
(sta->flags & WLAN_STA_SHORT_PREAMBLE ?
@ -128,6 +129,7 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
(sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
(sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
(sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
(sta->flags & WLAN_STA_WPS2 ? "[WPS2]" : ""),
sta->capability,
sta->listen_interval);

View File

@ -130,5 +130,10 @@ int eap_server_register_methods(void)
ret = eap_server_tnc_register();
#endif /* EAP_SERVER_TNC */
#ifdef EAP_SERVER_PWD
if (ret == 0)
ret = eap_server_pwd_register();
#endif /* EAP_SERVER_PWD */
return ret;
}

View File

@ -48,6 +48,7 @@
#include "common.h"
#include "crypto/milenage.h"
#include "crypto/random.h"
static const char *default_socket_path = "/tmp/hlr_auc_gw.sock";
static const char *socket_path;
@ -418,7 +419,7 @@ static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
if (m) {
u8 _rand[16], sres[4], kc[8];
for (count = 0; count < max_chal; count++) {
if (os_get_random(_rand, 16) < 0)
if (random_get_bytes(_rand, 16) < 0)
return;
gsm_milenage(m->opc, m->ki, _rand, sres, kc);
*rpos++ = ' ';
@ -481,7 +482,7 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
m = get_milenage(imsi);
if (m) {
if (os_get_random(_rand, EAP_AKA_RAND_LEN) < 0)
if (random_get_bytes(_rand, EAP_AKA_RAND_LEN) < 0)
return;
res_len = EAP_AKA_RES_MAX_LEN;
inc_byte_array(m->sqn, 6);

View File

@ -99,19 +99,18 @@ ssid=test
# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,
# Default: IEEE 802.11b
hw_mode=a
hw_mode=g
# Channel number (IEEE 802.11)
# (default: 0, i.e., not set)
# Please note that some drivers (e.g., madwifi) do not use this value from
# hostapd and the channel will need to be configuration separately with
# iwconfig.
channel=60
# Please note that some drivers do not use this value from hostapd and the
# channel will need to be configured separately with iwconfig.
channel=1
# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
beacon_int=100
# DTIM (delivery trafic information message) period (range 1..255):
# DTIM (delivery traffic information message) period (range 1..255):
# number of beacons between DTIMs (1 = every beacon includes DTIM element)
# (default: 2)
dtim_period=2
@ -198,7 +197,6 @@ auth_algs=3
ignore_broadcast_ssid=0
# TX queue parameters (EDCF / bursting)
# default for all these fields: not set, use hardware defaults
# tx_queue_<queue name>_<param>
# queues: data0, data1, data2, data3, after_beacon, beacon
# (data0 is the highest priority queue)
@ -240,18 +238,6 @@ ignore_broadcast_ssid=0
#tx_queue_data0_cwmax=7
#tx_queue_data0_burst=1.5
# Note: for IEEE 802.11b mode: cWmin=7 cWmax=15 burst=3.3
#
# Special queues; normally not user configurable
#
#tx_queue_after_beacon_aifs=2
#tx_queue_after_beacon_cwmin=15
#tx_queue_after_beacon_cwmax=1023
#tx_queue_after_beacon_burst=0
#
#tx_queue_beacon_aifs=2
#tx_queue_beacon_cwmin=3
#tx_queue_beacon_cwmax=7
#tx_queue_beacon_burst=1.5
# 802.1D Tag (= UP) to AC mappings
# WMM specifies following mapping of data frames to different ACs. This mapping
@ -354,6 +340,11 @@ wmm_ac_vo_acm=0
# default: 300 (i.e., 5 minutes)
#ap_max_inactivity=300
# Disassociate stations based on excessive transmission failures or other
# indications of connection loss. This depends on the driver capabilities and
# may not be available with all drivers.
#disassoc_low_ack=1
# Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to
# remain asleep). Default: 65535 (no limit apart from field size)
#max_listen_interval=100
@ -364,6 +355,15 @@ wmm_ac_vo_acm=0
# bridging to be used.
#wds_sta=1
# If bridge parameter is set, the WDS STA interface will be added to the same
# bridge by default. This can be overridden with the wds_bridge parameter to
# use a separate bridge.
#wds_bridge=wds-br0
# Client isolation can be used to prevent low-level bridging of frames between
# associated stations in the BSS. By default, this bridging is allowed.
#ap_isolate=1
##### IEEE 802.11n related configuration ######################################
# ieee80211n: Whether IEEE 802.11n (HT) is enabled
@ -407,6 +407,9 @@ wmm_ac_vo_acm=0
# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set)
#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40]
# Require stations to support HT PHY (reject association if they do not)
#require_ht=1
##### IEEE 802.1X-2004 related configuration ##################################
# Require IEEE 802.1X authorization
@ -504,6 +507,9 @@ eap_server=0
# "openssl dhparam -out /etc/hostapd.dh.pem 1024"
#dh_file=/etc/hostapd.dh.pem
# Fragment size for EAP methods
#fragment_size=1400
# Configuration data for EAP-SIM database/authentication gateway interface.
# This is a text string in implementation specific format. The example
# implementation in eap_sim_db.c uses this as the UNIX domain socket name for
@ -763,6 +769,13 @@ own_ip_addr=127.0.0.1
# dot11AssociationSAQueryRetryTimeout, 1...4294967295
#assoc_sa_query_retry_timeout=201
# disable_pmksa_caching: Disable PMKSA caching
# This parameter can be used to disable caching of PMKSA created through EAP
# authentication. RSN preauthentication may still end up using PMKSA caching if
# it is enabled (rsn_preauth=1).
# 0 = PMKSA caching enabled (default)
# 1 = PMKSA caching disabled
#disable_pmksa_caching=0
# okc: Opportunistic Key Caching (aka Proactive Key Caching)
# Allow PMK cache to be shared opportunistically among configured interfaces
@ -910,8 +923,21 @@ own_ip_addr=127.0.0.1
# Config Methods
# List of the supported configuration methods
# Available methods: usba ethernet label display ext_nfc_token int_nfc_token
# nfc_interface push_button keypad
#config_methods=label display push_button keypad
# nfc_interface push_button keypad virtual_display physical_display
# virtual_push_button physical_push_button
#config_methods=label virtual_display virtual_push_button keypad
# WPS capability discovery workaround for PBC with Windows 7
# Windows 7 uses incorrect way of figuring out AP's WPS capabilities by acting
# as a Registrar and using M1 from the AP. The config methods attribute in that
# message is supposed to indicate only the configuration method supported by
# the AP in Enrollee role, i.e., to add an external Registrar. For that case,
# PBC shall not be used and as such, the PushButton config method is removed
# from M1 by default. If pbc_in_m1=1 is included in the configuration file,
# the PushButton config method is left in M1 (if included in config_methods
# parameter) to allow Windows 7 to use PBC instead of PIN (e.g., from a label
# in the AP).
#pbc_in_m1=1
# Static access point PIN for initial configuration and adding Registrars
# If not set, hostapd will not allow external WPS Registrars to control the
@ -981,6 +1007,91 @@ own_ip_addr=127.0.0.1
# 12-digit, all-numeric code that identifies the consumer package.
#upc=123456789012
##### Wi-Fi Direct (P2P) ######################################################
# Enable P2P Device management
#manage_p2p=1
# Allow cross connection
#allow_cross_connection=1
#### TDLS (IEEE 802.11z-2010) #################################################
# Prohibit use of TDLS in this BSS
#tdls_prohibit=1
# Prohibit use of TDLS Channel Switching in this BSS
#tdls_prohibit_chan_switch=1
##### IEEE 802.11v-2011 #######################################################
# Time advertisement
# 0 = disabled (default)
# 2 = UTC time at which the TSF timer is 0
#time_advertisement=2
# Local time zone as specified in 8.3 of IEEE Std 1003.1-2004:
# stdoffset[dst[offset][,start[/time],end[/time]]]
#time_zone=EST5
##### IEEE 802.11u-2011 #######################################################
# Enable Interworking service
#interworking=1
# Access Network Type
# 0 = Private network
# 1 = Private network with guest access
# 2 = Chargeable public network
# 3 = Free public network
# 4 = Personal device network
# 5 = Emergency services only network
# 14 = Test or experimental
# 15 = Wildcard
#access_network_type=0
# Whether the network provides connectivity to the Internet
# 0 = Unspecified
# 1 = Network provides connectivity to the Internet
#internet=1
# Additional Step Required for Access
# Note: This is only used with open network, i.e., ASRA shall ne set to 0 if
# RSN is used.
#asra=0
# Emergency services reachable
#esr=0
# Unauthenticated emergency service accessible
#uesa=0
# Venue Info (optional)
# The available values are defined in IEEE Std 802.11u-2011, 7.3.1.34.
# Example values (group,type):
# 0,0 = Unspecified
# 1,7 = Convention Center
# 1,13 = Coffee Shop
# 2,0 = Unspecified Business
# 7,1 Private Residence
#venue_group=7
#venue_type=1
# Homogeneous ESS identifier (optional; dot11HESSID)
# If set, this shall be identifical to one of the BSSIDs in the homogeneous
# ESS and this shall be set to the same value across all BSSs in homogeneous
# ESS.
#hessid=02:03:04:05:06:07
# Roaming Consortium List
# Arbitrary number of Roaming Consortium OIs can be configured with each line
# adding a new OI to the list. The first three entries are available through
# Beacon and Probe Response frames. Any additional entry will be available only
# through ANQP queries. Each OI is between 3 and 15 octets and is configured a
# a hexstring.
#roaming_consortium=021122
#roaming_consortium=2233445566
##### Multiple BSSID support ##################################################
#
# Above configuration is using the default interface (wlan#, or multi-SSID VLAN

View File

@ -1,6 +1,6 @@
/*
* hostapd / main()
* Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2011, 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
@ -19,6 +19,7 @@
#include "utils/common.h"
#include "utils/eloop.h"
#include "crypto/random.h"
#include "crypto/tls.h"
#include "common/version.h"
#include "drivers/driver.h"
@ -36,6 +37,16 @@ extern int wpa_debug_level;
extern int wpa_debug_show_keys;
extern int wpa_debug_timestamp;
extern struct wpa_driver_ops *wpa_drivers[];
struct hapd_global {
void **drv_priv;
size_t drv_count;
};
static struct hapd_global global;
struct hapd_interfaces {
size_t count;
@ -233,6 +244,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
struct hostapd_data *hapd = iface->bss[0];
struct hostapd_bss_config *conf = hapd->conf;
u8 *b = conf->bssid;
struct wpa_driver_capa capa;
if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
@ -244,6 +256,24 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
b = NULL;
os_memset(&params, 0, sizeof(params));
for (i = 0; wpa_drivers[i]; i++) {
if (wpa_drivers[i] != hapd->driver)
continue;
if (global.drv_priv[i] == NULL &&
wpa_drivers[i]->global_init) {
global.drv_priv[i] = wpa_drivers[i]->global_init();
if (global.drv_priv[i] == NULL) {
wpa_printf(MSG_ERROR, "Failed to initialize "
"driver '%s'",
wpa_drivers[i]->name);
return -1;
}
}
params.global_priv = global.drv_priv[i];
break;
}
params.bssid = b;
params.ifname = hapd->conf->iface;
params.ssid = (const u8 *) hapd->conf->ssid.ssid;
@ -272,6 +302,10 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
return -1;
}
if (hapd->driver->get_capa &&
hapd->driver->get_capa(hapd->drv_priv, &capa) == 0)
iface->drv_flags = capa.flags;
return 0;
}
@ -363,8 +397,13 @@ static void handle_dump_state(int sig, void *signal_ctx)
#endif /* CONFIG_NATIVE_WINDOWS */
static int hostapd_global_init(struct hapd_interfaces *interfaces)
static int hostapd_global_init(struct hapd_interfaces *interfaces,
const char *entropy_file)
{
int i;
os_memset(&global, 0, sizeof(global));
hostapd_logger_register_cb(hostapd_logger_cb);
if (eap_server_register_methods()) {
@ -377,6 +416,8 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces)
return -1;
}
random_init(entropy_file);
#ifndef CONFIG_NATIVE_WINDOWS
eloop_register_signal(SIGHUP, handle_reload, interfaces);
eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
@ -387,16 +428,38 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces)
openlog("hostapd", 0, LOG_DAEMON);
#endif /* CONFIG_NATIVE_WINDOWS */
for (i = 0; wpa_drivers[i]; i++)
global.drv_count++;
if (global.drv_count == 0) {
wpa_printf(MSG_ERROR, "No drivers enabled");
return -1;
}
global.drv_priv = os_zalloc(global.drv_count * sizeof(void *));
if (global.drv_priv == NULL)
return -1;
return 0;
}
static void hostapd_global_deinit(const char *pid_file)
{
int i;
for (i = 0; wpa_drivers[i] && global.drv_priv; i++) {
if (!global.drv_priv[i])
continue;
wpa_drivers[i]->global_deinit(global.drv_priv[i]);
}
os_free(global.drv_priv);
global.drv_priv = NULL;
#ifdef EAP_SERVER_TNC
tncs_global_deinit();
#endif /* EAP_SERVER_TNC */
random_deinit();
eloop_destroy();
#ifndef CONFIG_NATIVE_WINDOWS
@ -448,7 +511,7 @@ static void show_version(void)
"hostapd v" VERSION_STR "\n"
"User space daemon for IEEE 802.11 AP management,\n"
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
"Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi> "
"Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> "
"and contributors\n");
}
@ -458,15 +521,19 @@ static void usage(void)
show_version();
fprintf(stderr,
"\n"
"usage: hostapd [-hdBKtv] [-P <PID file>] "
"usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
"<configuration file(s)>\n"
"\n"
"options:\n"
" -h show this usage\n"
" -d show more debug messages (-dd for even more)\n"
" -B run daemon in the background\n"
" -e entropy file\n"
" -P PID file\n"
" -K include key data in debug messages\n"
#ifdef CONFIG_DEBUG_FILE
" -f log output to debug file instead of stdout\n"
#endif /* CONFIG_DEBUG_FILE */
" -t include timestamps in some debug messages\n"
" -v show hostapd version\n");
@ -474,6 +541,15 @@ static void usage(void)
}
static const char * hostapd_msg_ifname_cb(void *ctx)
{
struct hostapd_data *hapd = ctx;
if (hapd && hapd->iconf && hapd->iconf->bss)
return hapd->iconf->bss->iface;
return NULL;
}
int main(int argc, char *argv[])
{
struct hapd_interfaces interfaces;
@ -481,12 +557,14 @@ int main(int argc, char *argv[])
size_t i;
int c, debug = 0, daemonize = 0;
char *pid_file = NULL;
const char *log_file = NULL;
const char *entropy_file = NULL;
if (os_program_init())
return -1;
for (;;) {
c = getopt(argc, argv, "BdhKP:tv");
c = getopt(argc, argv, "Bde:f:hKP:tv");
if (c < 0)
break;
switch (c) {
@ -501,6 +579,12 @@ int main(int argc, char *argv[])
case 'B':
daemonize++;
break;
case 'e':
entropy_file = optarg;
break;
case 'f':
log_file = optarg;
break;
case 'K':
wpa_debug_show_keys++;
break;
@ -525,15 +609,20 @@ int main(int argc, char *argv[])
if (optind == argc)
usage();
wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
if (log_file)
wpa_debug_open_file(log_file);
interfaces.count = argc - optind;
interfaces.iface = os_malloc(interfaces.count *
interfaces.iface = os_zalloc(interfaces.count *
sizeof(struct hostapd_iface *));
if (interfaces.iface == NULL) {
wpa_printf(MSG_ERROR, "malloc failed\n");
wpa_printf(MSG_ERROR, "malloc failed");
return -1;
}
if (hostapd_global_init(&interfaces))
if (hostapd_global_init(&interfaces, entropy_file))
return -1;
/* Initialize interfaces */
@ -559,6 +648,9 @@ int main(int argc, char *argv[])
hostapd_global_deinit(pid_file);
os_free(pid_file);
if (log_file)
wpa_debug_close_file();
os_program_deinit();
return ret;

View File

@ -1,4 +1,4 @@
SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet radius rsn_supp tls utils wps
SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet p2p radius rsn_supp tls utils wps
all:
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done

View File

@ -23,6 +23,7 @@
#include "ieee802_1x.h"
#include "ap_config.h"
#include "sta_info.h"
#include "ap_drv_ops.h"
#include "accounting.h"
@ -186,7 +187,7 @@ static int accounting_sta_update_stats(struct hostapd_data *hapd,
struct sta_info *sta,
struct hostap_sta_driver_data *data)
{
if (hapd->drv.read_sta_data(hapd, data, sta->addr))
if (hostapd_drv_read_sta_data(hapd, data, sta->addr))
return -1;
if (sta->last_rx_bytes > data->rx_bytes)
@ -235,6 +236,7 @@ static void accounting_interim_update(void *eloop_ctx, void *timeout_ctx)
void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
{
struct radius_msg *msg;
struct os_time t;
int interval;
if (sta->acct_session_started)
@ -246,10 +248,11 @@ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
"starting accounting session %08X-%08X",
sta->acct_session_id_hi, sta->acct_session_id_lo);
time(&sta->acct_session_start);
os_get_time(&t);
sta->acct_session_start = t.sec;
sta->last_rx_bytes = sta->last_tx_bytes = 0;
sta->acct_input_gigawords = sta->acct_output_gigawords = 0;
hapd->drv.sta_clear_stats(hapd, sta->addr);
hostapd_drv_sta_clear_stats(hapd, sta->addr);
if (!hapd->conf->radius->acct_server)
return;
@ -262,8 +265,9 @@ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
hapd, sta);
msg = accounting_msg(hapd, sta, RADIUS_ACCT_STATUS_TYPE_START);
if (msg)
radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr);
if (msg &&
radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr) < 0)
radius_msg_free(msg);
sta->acct_session_started = 1;
}
@ -275,6 +279,7 @@ static void accounting_sta_report(struct hostapd_data *hapd,
struct radius_msg *msg;
int cause = sta->acct_terminate_cause;
struct hostap_sta_driver_data data;
struct os_time now;
u32 gigawords;
if (!hapd->conf->radius->acct_server)
@ -288,8 +293,9 @@ static void accounting_sta_report(struct hostapd_data *hapd,
return;
}
os_get_time(&now);
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME,
time(NULL) - sta->acct_session_start)) {
now.sec - sta->acct_session_start)) {
printf("Could not add Acct-Session-Time\n");
goto fail;
}
@ -344,7 +350,7 @@ static void accounting_sta_report(struct hostapd_data *hapd,
}
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP,
time(NULL))) {
now.sec)) {
printf("Could not add Event-Timestamp\n");
goto fail;
}
@ -359,9 +365,10 @@ static void accounting_sta_report(struct hostapd_data *hapd,
goto fail;
}
radius_client_send(hapd->radius, msg,
stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM,
sta->addr);
if (radius_client_send(hapd->radius, msg,
stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM,
sta->addr) < 0)
goto fail;
return;
fail:
@ -464,7 +471,8 @@ static void accounting_report_state(struct hostapd_data *hapd, int on)
return;
}
radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL);
if (radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL) < 0)
radius_msg_free(msg);
}
@ -475,9 +483,12 @@ static void accounting_report_state(struct hostapd_data *hapd, int on)
*/
int accounting_init(struct hostapd_data *hapd)
{
struct os_time now;
/* Acct-Session-Id should be unique over reboots. If reliable clock is
* not available, this could be replaced with reboot counter, etc. */
hapd->acct_session_id_hi = time(NULL);
os_get_time(&now);
hapd->acct_session_id_hi = now.sec;
if (radius_client_register(hapd->radius, RADIUS_ACCT,
accounting_receive, hapd))

View File

@ -74,6 +74,8 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
bss->max_listen_interval = 65535;
bss->pwd_group = 19; /* ECC: GF(p=256) */
#ifdef CONFIG_IEEE80211W
bss->assoc_sa_query_max_timeout = 1000;
bss->assoc_sa_query_retry_timeout = 201;
@ -84,14 +86,22 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
bss->pac_key_lifetime = 7 * 24 * 60 * 60;
bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
#endif /* EAP_SERVER_FAST */
/* Set to -1 as defaults depends on HT in setup */
bss->wmm_enabled = -1;
#ifdef CONFIG_IEEE80211R
bss->ft_over_ds = 1;
#endif /* CONFIG_IEEE80211R */
}
struct hostapd_config * hostapd_config_defaults(void)
{
#define ecw2cw(ecw) ((1 << (ecw)) - 1)
struct hostapd_config *conf;
struct hostapd_bss_config *bss;
int i;
const int aCWmin = 4, aCWmax = 10;
const struct hostapd_wmm_ac_params ac_bk =
{ aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
@ -101,6 +111,17 @@ struct hostapd_config * hostapd_config_defaults(void)
{ 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 };
const struct hostapd_tx_queue_params txq_bk =
{ 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 };
const struct hostapd_tx_queue_params txq_be =
{ 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0};
const struct hostapd_tx_queue_params txq_vi =
{ 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30};
const struct hostapd_tx_queue_params txq_vo =
{ 1, (ecw2cw(aCWmin) + 1) / 4 - 1,
(ecw2cw(aCWmin) + 1) / 2 - 1, 15};
#undef ecw2cw
conf = os_zalloc(sizeof(*conf));
bss = os_zalloc(sizeof(*bss));
@ -129,14 +150,16 @@ struct hostapd_config * hostapd_config_defaults(void)
conf->fragm_threshold = -1; /* user driver default: 2346 */
conf->send_probe_response = 1;
for (i = 0; i < NUM_TX_QUEUES; i++)
conf->tx_queue[i].aifs = -1; /* use hw default */
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;
conf->tx_queue[0] = txq_vo;
conf->tx_queue[1] = txq_vi;
conf->tx_queue[2] = txq_be;
conf->tx_queue[3] = txq_bk;
conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
return conf;
@ -403,6 +426,8 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
ssid->dyn_vlan_keys = NULL;
}
os_free(conf->time_zone);
#ifdef CONFIG_IEEE80211R
{
struct ft_remote_r0kh *r0kh, *r0kh_prev;
@ -433,7 +458,6 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
os_free(conf->model_name);
os_free(conf->model_number);
os_free(conf->serial_number);
os_free(conf->device_type);
os_free(conf->config_methods);
os_free(conf->ap_pin);
os_free(conf->extra_cred);
@ -445,6 +469,8 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
os_free(conf->model_url);
os_free(conf->upc);
#endif /* CONFIG_WPS */
os_free(conf->roaming_consortium);
}

View File

@ -18,6 +18,7 @@
#include "common/defs.h"
#include "ip_addr.h"
#include "common/wpa_common.h"
#include "wps/wps.h"
#define MAX_STA_COUNT 2007
#define MAX_VLAN_ID 4094
@ -123,14 +124,13 @@ struct hostapd_eap_user {
};
#define NUM_TX_QUEUES 8
#define NUM_TX_QUEUES 4
struct hostapd_tx_queue_params {
int aifs;
int cwmin;
int cwmax;
int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */
int configured;
};
struct hostapd_wmm_ac_params {
@ -142,12 +142,20 @@ struct hostapd_wmm_ac_params {
};
#define MAX_ROAMING_CONSORTIUM_LEN 15
struct hostapd_roaming_consortium {
u8 len;
u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
};
/**
* struct hostapd_bss_config - Per-BSS configuration
*/
struct hostapd_bss_config {
char iface[IFNAMSIZ + 1];
char bridge[IFNAMSIZ + 1];
char wds_bridge[IFNAMSIZ + 1];
enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
@ -198,6 +206,7 @@ struct hostapd_bss_config {
struct mac_acl_entry *deny_mac;
int num_deny_mac;
int wds_sta;
int isolate;
int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
@ -231,6 +240,7 @@ struct hostapd_bss_config {
struct ft_remote_r0kh *r0kh_list;
struct ft_remote_r1kh *r1kh_list;
int pmk_r1_push;
int ft_over_ds;
#endif /* CONFIG_IEEE80211R */
char *ctrl_interface; /* directory for UNIX domain sockets */
@ -254,6 +264,8 @@ struct hostapd_bss_config {
int pac_key_refresh_time;
int eap_sim_aka_result_ind;
int tnc;
int fragment_size;
u16 pwd_group;
char *radius_server_clients;
int radius_server_auth_port;
@ -283,6 +295,7 @@ struct hostapd_bss_config {
*/
u16 max_listen_interval;
int disable_pmksa_caching;
int okc; /* Opportunistic Key Caching */
int wps_state;
@ -295,7 +308,7 @@ struct hostapd_bss_config {
char *model_name;
char *model_number;
char *serial_number;
char *device_type;
u8 device_type[WPS_DEV_TYPE_LEN];
char *config_methods;
u8 os_version[4];
char *ap_pin;
@ -311,7 +324,43 @@ struct hostapd_bss_config {
char *model_description;
char *model_url;
char *upc;
struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
#endif /* CONFIG_WPS */
int pbc_in_m1;
#define P2P_ENABLED BIT(0)
#define P2P_GROUP_OWNER BIT(1)
#define P2P_GROUP_FORMATION BIT(2)
#define P2P_MANAGE BIT(3)
#define P2P_ALLOW_CROSS_CONNECTION BIT(4)
int p2p;
int disassoc_low_ack;
#define TDLS_PROHIBIT BIT(0)
#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1)
int tdls;
int disable_11n;
/* IEEE 802.11v */
int time_advertisement;
char *time_zone;
/* IEEE 802.11u - Interworking */
int interworking;
int access_network_type;
int internet;
int asra;
int esr;
int uesa;
int venue_info_set;
u8 venue_group;
u8 venue_type;
u8 hessid[ETH_ALEN];
/* IEEE 802.11u - Roaming Consortium list */
unsigned int roaming_consortium_count;
struct hostapd_roaming_consortium *roaming_consortium;
};
@ -332,12 +381,6 @@ struct hostapd_config {
LONG_PREAMBLE = 0,
SHORT_PREAMBLE = 1
} preamble;
enum {
CTS_PROTECTION_AUTOMATIC = 0,
CTS_PROTECTION_FORCE_ENABLED = 1,
CTS_PROTECTION_FORCE_DISABLED = 2,
CTS_PROTECTION_AUTOMATIC_NO_OLBC = 3,
} cts_protection_type;
int *supported_rates;
int *basic_rates;
@ -371,6 +414,7 @@ struct hostapd_config {
u16 ht_capab;
int ieee80211n;
int secondary_channel;
int require_ht;
};

View File

@ -17,14 +17,16 @@
#include "utils/common.h"
#include "drivers/driver.h"
#include "common/ieee802_11_defs.h"
#include "wps/wps.h"
#include "hostapd.h"
#include "ieee802_11.h"
#include "sta_info.h"
#include "ap_config.h"
#include "p2p_hostapd.h"
#include "ap_drv_ops.h"
static int hostapd_sta_flags_to_drv(int flags)
u32 hostapd_sta_flags_to_drv(u32 flags)
{
int res = 0;
if (flags & WLAN_STA_AUTHORIZED)
@ -39,45 +41,166 @@ static int hostapd_sta_flags_to_drv(int flags)
}
static int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
struct wpabuf **beacon_ret,
struct wpabuf **proberesp_ret,
struct wpabuf **assocresp_ret)
{
struct wpabuf *beacon, *proberesp;
struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL;
u8 buf[200], *pos;
*beacon_ret = *proberesp_ret = *assocresp_ret = NULL;
pos = buf;
pos = hostapd_eid_time_adv(hapd, pos);
if (pos != buf) {
if (wpabuf_resize(&beacon, pos - buf) != 0)
goto fail;
wpabuf_put_data(beacon, buf, pos - buf);
}
pos = hostapd_eid_time_zone(hapd, pos);
if (pos != buf) {
if (wpabuf_resize(&proberesp, pos - buf) != 0)
goto fail;
wpabuf_put_data(proberesp, buf, pos - buf);
}
pos = buf;
pos = hostapd_eid_ext_capab(hapd, pos);
if (pos != buf) {
if (wpabuf_resize(&assocresp, pos - buf) != 0)
goto fail;
wpabuf_put_data(assocresp, buf, pos - buf);
}
pos = hostapd_eid_interworking(hapd, pos);
pos = hostapd_eid_adv_proto(hapd, pos);
pos = hostapd_eid_roaming_consortium(hapd, pos);
if (pos != buf) {
if (wpabuf_resize(&beacon, pos - buf) != 0)
goto fail;
wpabuf_put_data(beacon, buf, pos - buf);
if (wpabuf_resize(&proberesp, pos - buf) != 0)
goto fail;
wpabuf_put_data(proberesp, buf, pos - buf);
}
if (hapd->wps_beacon_ie) {
if (wpabuf_resize(&beacon, wpabuf_len(hapd->wps_beacon_ie)) <
0)
goto fail;
wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
}
if (hapd->wps_probe_resp_ie) {
if (wpabuf_resize(&proberesp,
wpabuf_len(hapd->wps_probe_resp_ie)) < 0)
goto fail;
wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
}
#ifdef CONFIG_P2P
if (hapd->p2p_beacon_ie) {
if (wpabuf_resize(&beacon, wpabuf_len(hapd->p2p_beacon_ie)) <
0)
goto fail;
wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
}
if (hapd->p2p_probe_resp_ie) {
if (wpabuf_resize(&proberesp,
wpabuf_len(hapd->p2p_probe_resp_ie)) < 0)
goto fail;
wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
}
#endif /* CONFIG_P2P */
#ifdef CONFIG_P2P_MANAGER
if (hapd->conf->p2p & P2P_MANAGE) {
if (wpabuf_resize(&beacon, 100) == 0) {
u8 *start, *p;
start = wpabuf_put(beacon, 0);
p = hostapd_eid_p2p_manage(hapd, start);
wpabuf_put(beacon, p - start);
}
if (wpabuf_resize(&proberesp, 100) == 0) {
u8 *start, *p;
start = wpabuf_put(proberesp, 0);
p = hostapd_eid_p2p_manage(hapd, start);
wpabuf_put(proberesp, p - start);
}
}
#endif /* CONFIG_P2P_MANAGER */
#ifdef CONFIG_WPS2
if (hapd->conf->wps_state) {
struct wpabuf *a = wps_build_assoc_resp_ie();
if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
wpabuf_put_buf(assocresp, a);
wpabuf_free(a);
}
#endif /* CONFIG_WPS2 */
#ifdef CONFIG_P2P_MANAGER
if (hapd->conf->p2p & P2P_MANAGE) {
if (wpabuf_resize(&assocresp, 100) == 0) {
u8 *start, *p;
start = wpabuf_put(assocresp, 0);
p = hostapd_eid_p2p_manage(hapd, start);
wpabuf_put(assocresp, p - start);
}
}
#endif /* CONFIG_P2P_MANAGER */
*beacon_ret = beacon;
*proberesp_ret = proberesp;
*assocresp_ret = assocresp;
return 0;
fail:
wpabuf_free(beacon);
wpabuf_free(proberesp);
wpabuf_free(assocresp);
return -1;
}
void hostapd_free_ap_extra_ies(struct hostapd_data *hapd,
struct wpabuf *beacon,
struct wpabuf *proberesp,
struct wpabuf *assocresp)
{
wpabuf_free(beacon);
wpabuf_free(proberesp);
wpabuf_free(assocresp);
}
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
{
struct wpabuf *beacon, *proberesp, *assocresp;
int ret;
if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
return 0;
beacon = hapd->wps_beacon_ie;
proberesp = hapd->wps_probe_resp_ie;
if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
0)
return -1;
ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp);
ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
assocresp);
hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
return ret;
}
static int hostapd_send_mgmt_frame(struct hostapd_data *hapd, const void *msg,
size_t len)
{
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
return 0;
return hapd->driver->send_mlme(hapd->drv_priv, msg, len);
}
static int hostapd_send_eapol(struct hostapd_data *hapd, const u8 *addr,
const u8 *data, size_t data_len, int encrypt)
{
if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
return 0;
return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
data_len, encrypt,
hapd->own_addr);
}
static int hostapd_set_authorized(struct hostapd_data *hapd,
struct sta_info *sta, int authorized)
int hostapd_set_authorized(struct hostapd_data *hapd,
struct sta_info *sta, int authorized)
{
if (authorized) {
return hostapd_sta_set_flags(hapd, sta->addr,
@ -92,39 +215,7 @@ static int hostapd_set_authorized(struct hostapd_data *hapd,
}
static int hostapd_set_key(const char *ifname, struct hostapd_data *hapd,
enum wpa_alg alg, const u8 *addr, int key_idx,
int set_tx, const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
if (hapd->driver == NULL || hapd->driver->set_key == NULL)
return 0;
return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
key_idx, set_tx, seq, seq_len, key,
key_len);
}
static int hostapd_read_sta_data(struct hostapd_data *hapd,
struct hostap_sta_driver_data *data,
const u8 *addr)
{
if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL)
return -1;
return hapd->driver->read_sta_data(hapd->drv_priv, data, addr);
}
static int hostapd_sta_clear_stats(struct hostapd_data *hapd, const u8 *addr)
{
if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL)
return 0;
return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
}
static int hostapd_set_sta_flags(struct hostapd_data *hapd,
struct sta_info *sta)
int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta)
{
int set_flags, total_flags, flags_and, flags_or;
total_flags = hostapd_sta_flags_to_drv(sta->flags);
@ -140,8 +231,8 @@ static int hostapd_set_sta_flags(struct hostapd_data *hapd,
}
static int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd,
const char *ifname, int enabled)
int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
int enabled)
{
struct wpa_bss_params params;
os_memset(&params, 0, sizeof(params));
@ -154,166 +245,80 @@ static int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd,
params.wpa_pairwise = hapd->conf->wpa_pairwise;
params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
params.rsn_preauth = hapd->conf->rsn_preauth;
#ifdef CONFIG_IEEE80211W
params.ieee80211w = hapd->conf->ieee80211w;
#endif /* CONFIG_IEEE80211W */
}
return hostapd_set_ieee8021x(hapd, &params);
}
static int hostapd_set_radius_acl_auth(struct hostapd_data *hapd,
const u8 *mac, int accepted,
u32 session_timeout)
{
if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL)
return 0;
return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted,
session_timeout);
}
static int hostapd_set_radius_acl_expire(struct hostapd_data *hapd,
const u8 *mac)
{
if (hapd->driver == NULL ||
hapd->driver->set_radius_acl_expire == NULL)
return 0;
return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac);
}
static int hostapd_set_bss_params(struct hostapd_data *hapd,
int use_protection)
{
int ret = 0;
int preamble;
#ifdef CONFIG_IEEE80211N
u8 buf[60], *ht_capab, *ht_oper, *pos;
pos = buf;
ht_capab = pos;
pos = hostapd_eid_ht_capabilities(hapd, pos);
ht_oper = pos;
pos = hostapd_eid_ht_operation(hapd, pos);
if (pos > ht_oper && ht_oper > ht_capab &&
hostapd_set_ht_params(hapd, ht_capab + 2, ht_capab[1],
ht_oper + 2, ht_oper[1])) {
wpa_printf(MSG_ERROR, "Could not set HT capabilities "
"for kernel driver");
ret = -1;
}
#endif /* CONFIG_IEEE80211N */
if (hostapd_set_cts_protect(hapd, use_protection)) {
wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel "
"driver");
ret = -1;
}
if (hapd->iface->current_mode &&
hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
hostapd_set_short_slot_time(hapd,
hapd->iface->num_sta_no_short_slot_time
> 0 ? 0 : 1)) {
wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option "
"in kernel driver");
ret = -1;
}
if (hapd->iface->num_sta_no_short_preamble == 0 &&
hapd->iconf->preamble == SHORT_PREAMBLE)
preamble = SHORT_PREAMBLE;
else
preamble = LONG_PREAMBLE;
if (hostapd_set_preamble(hapd, preamble)) {
wpa_printf(MSG_ERROR, "Could not set preamble for kernel "
"driver");
ret = -1;
}
return ret;
}
static int hostapd_set_beacon(struct hostapd_data *hapd,
const u8 *head, size_t head_len,
const u8 *tail, size_t tail_len, int dtim_period,
int beacon_int)
{
if (hapd->driver == NULL || hapd->driver->set_beacon == NULL)
return 0;
return hapd->driver->set_beacon(hapd->drv_priv,
head, head_len, tail, tail_len,
dtim_period, beacon_int);
}
static int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
{
char force_ifname[IFNAMSIZ];
u8 if_addr[ETH_ALEN];
return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL, NULL,
force_ifname, if_addr);
return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
NULL, NULL, force_ifname, if_addr, NULL);
}
static int hostapd_vlan_if_remove(struct hostapd_data *hapd,
const char *ifname)
int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname)
{
return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname);
}
static int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr,
int aid, int val)
int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
int val)
{
const char *bridge = NULL;
if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
return 0;
return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val);
if (hapd->conf->wds_bridge[0])
bridge = hapd->conf->wds_bridge;
else if (hapd->conf->bridge[0])
bridge = hapd->conf->bridge;
return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
bridge);
}
static int hostapd_set_sta_vlan(const char *ifname, struct hostapd_data *hapd,
const u8 *addr, int vlan_id)
int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
u16 auth_alg)
{
if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL)
if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
return 0;
return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname,
vlan_id);
return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
}
static int hostapd_get_inact_sec(struct hostapd_data *hapd, const u8 *addr)
int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
u16 seq, u16 status, const u8 *ie, size_t len)
{
if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL)
if (hapd->driver == NULL || hapd->driver->sta_auth == NULL)
return 0;
return hapd->driver->get_inact_sec(hapd->drv_priv, addr);
return hapd->driver->sta_auth(hapd->drv_priv, hapd->own_addr, addr,
seq, status, ie, len);
}
static int hostapd_sta_deauth(struct hostapd_data *hapd, const u8 *addr,
int reason)
int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
int reassoc, u16 status, const u8 *ie, size_t len)
{
if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL)
return 0;
return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
reason);
return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr,
reassoc, status, ie, len);
}
static int hostapd_sta_disassoc(struct hostapd_data *hapd, const u8 *addr,
int reason)
{
if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
return 0;
return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
reason);
}
static int hostapd_sta_add(struct hostapd_data *hapd,
const u8 *addr, u16 aid, u16 capability,
const u8 *supp_rates, size_t supp_rates_len,
u16 listen_interval,
const struct ieee80211_ht_capabilities *ht_capab)
int hostapd_sta_add(struct hostapd_data *hapd,
const u8 *addr, u16 aid, u16 capability,
const u8 *supp_rates, size_t supp_rates_len,
u16 listen_interval,
const struct ieee80211_ht_capabilities *ht_capab,
u32 flags)
{
struct hostapd_sta_add_params params;
@ -330,52 +335,18 @@ static int hostapd_sta_add(struct hostapd_data *hapd,
params.supp_rates_len = supp_rates_len;
params.listen_interval = listen_interval;
params.ht_capabilities = ht_capab;
params.flags = hostapd_sta_flags_to_drv(flags);
return hapd->driver->sta_add(hapd->drv_priv, &params);
}
static int hostapd_sta_remove(struct hostapd_data *hapd, const u8 *addr)
int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
u8 *tspec_ie, size_t tspec_ielen)
{
if (hapd->driver == NULL || hapd->driver->sta_remove == NULL)
if (hapd->driver == NULL || hapd->driver->add_tspec == NULL)
return 0;
return hapd->driver->sta_remove(hapd->drv_priv, addr);
}
static int hostapd_set_countermeasures(struct hostapd_data *hapd, int enabled)
{
if (hapd->driver == NULL ||
hapd->driver->hapd_set_countermeasures == NULL)
return 0;
return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled);
}
void hostapd_set_driver_ops(struct hostapd_driver_ops *ops)
{
ops->set_ap_wps_ie = hostapd_set_ap_wps_ie;
ops->send_mgmt_frame = hostapd_send_mgmt_frame;
ops->send_eapol = hostapd_send_eapol;
ops->set_authorized = hostapd_set_authorized;
ops->set_key = hostapd_set_key;
ops->read_sta_data = hostapd_read_sta_data;
ops->sta_clear_stats = hostapd_sta_clear_stats;
ops->set_sta_flags = hostapd_set_sta_flags;
ops->set_drv_ieee8021x = hostapd_set_drv_ieee8021x;
ops->set_radius_acl_auth = hostapd_set_radius_acl_auth;
ops->set_radius_acl_expire = hostapd_set_radius_acl_expire;
ops->set_bss_params = hostapd_set_bss_params;
ops->set_beacon = hostapd_set_beacon;
ops->vlan_if_add = hostapd_vlan_if_add;
ops->vlan_if_remove = hostapd_vlan_if_remove;
ops->set_wds_sta = hostapd_set_wds_sta;
ops->set_sta_vlan = hostapd_set_sta_vlan;
ops->get_inact_sec = hostapd_get_inact_sec;
ops->sta_deauth = hostapd_sta_deauth;
ops->sta_disassoc = hostapd_sta_disassoc;
ops->sta_add = hostapd_sta_add;
ops->sta_remove = hostapd_sta_remove;
ops->set_countermeasures = hostapd_set_countermeasures;
return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie,
tspec_ielen);
}
@ -414,12 +385,14 @@ int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
const char *ifname, const u8 *addr, void *bss_ctx,
void **drv_priv, char *force_ifname, u8 *if_addr)
void **drv_priv, char *force_ifname, u8 *if_addr,
const char *bridge)
{
if (hapd->driver == NULL || hapd->driver->if_add == NULL)
return -1;
return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
bss_ctx, drv_priv, force_ifname, if_addr);
bss_ctx, drv_priv, force_ifname, if_addr,
bridge);
}
@ -521,30 +494,6 @@ int hostapd_set_country(struct hostapd_data *hapd, const char *country)
}
int hostapd_set_cts_protect(struct hostapd_data *hapd, int value)
{
if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL)
return 0;
return hapd->driver->set_cts_protect(hapd->drv_priv, value);
}
int hostapd_set_preamble(struct hostapd_data *hapd, int value)
{
if (hapd->driver == NULL || hapd->driver->set_preamble == NULL)
return 0;
return hapd->driver->set_preamble(hapd->drv_priv, value);
}
int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value)
{
if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL)
return 0;
return hapd->driver->set_short_slot_time(hapd->drv_priv, value);
}
int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
int cw_min, int cw_max, int burst_time)
{
@ -555,15 +504,6 @@ int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
}
int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
const u8 *mask)
{
if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL)
return 1;
return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask);
}
struct hostapd_hw_modes *
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
u16 *flags)
@ -584,19 +524,6 @@ int hostapd_driver_commit(struct hostapd_data *hapd)
}
int hostapd_set_ht_params(struct hostapd_data *hapd,
const u8 *ht_capab, size_t ht_capab_len,
const u8 *ht_oper, size_t ht_oper_len)
{
if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL ||
ht_capab == NULL || ht_oper == NULL)
return 0;
return hapd->driver->set_ht_params(hapd->drv_priv,
ht_capab, ht_capab_len,
ht_oper, ht_oper_len);
}
int hostapd_drv_none(struct hostapd_data *hapd)
{
return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
@ -619,3 +546,56 @@ struct wpa_scan_results * hostapd_driver_get_scan_results(
return hapd->driver->get_scan_results2(hapd->drv_priv);
return NULL;
}
int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
int duration)
{
if (hapd->driver && hapd->driver->set_noa)
return hapd->driver->set_noa(hapd->drv_priv, count, start,
duration);
return -1;
}
int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
enum wpa_alg alg, const u8 *addr,
int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
if (hapd->driver == NULL || hapd->driver->set_key == NULL)
return 0;
return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
key_idx, set_tx, seq, seq_len, key,
key_len);
}
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
const void *msg, size_t len)
{
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
return 0;
return hapd->driver->send_mlme(hapd->drv_priv, msg, len);
}
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
const u8 *addr, int reason)
{
if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
return 0;
return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
reason);
}
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
const u8 *addr, int reason)
{
if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
return 0;
return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
reason);
}

View File

@ -18,8 +18,32 @@
enum wpa_driver_if_type;
struct wpa_bss_params;
struct wpa_driver_scan_params;
struct ieee80211_ht_capabilities;
void hostapd_set_driver_ops(struct hostapd_driver_ops *ops);
u32 hostapd_sta_flags_to_drv(u32 flags);
int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
struct wpabuf **beacon,
struct wpabuf **proberesp,
struct wpabuf **assocresp);
void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon,
struct wpabuf *proberesp,
struct wpabuf *assocresp);
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
int hostapd_set_authorized(struct hostapd_data *hapd,
struct sta_info *sta, int authorized);
int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta);
int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
int enabled);
int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname);
int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname);
int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
int val);
int hostapd_sta_add(struct hostapd_data *hapd,
const u8 *addr, u16 aid, u16 capability,
const u8 *supp_rates, size_t supp_rates_len,
u16 listen_interval,
const struct ieee80211_ht_capabilities *ht_capab,
u32 flags);
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
size_t elem_len);
@ -27,7 +51,8 @@ int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len);
int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len);
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
const char *ifname, const u8 *addr, void *bss_ctx,
void **drv_priv, char *force_ifname, u8 *if_addr);
void **drv_priv, char *force_ifname, u8 *if_addr,
const char *bridge);
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
const char *ifname);
int hostapd_set_ieee8021x(struct hostapd_data *hapd,
@ -44,24 +69,149 @@ int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
int *basic_rates, int mode);
int hostapd_set_country(struct hostapd_data *hapd, const char *country);
int hostapd_set_cts_protect(struct hostapd_data *hapd, int value);
int hostapd_set_preamble(struct hostapd_data *hapd, int value);
int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value);
int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
int cw_min, int cw_max, int burst_time);
int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
const u8 *mask);
struct hostapd_hw_modes *
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
u16 *flags);
int hostapd_driver_commit(struct hostapd_data *hapd);
int hostapd_set_ht_params(struct hostapd_data *hapd,
const u8 *ht_capab, size_t ht_capab_len,
const u8 *ht_oper, size_t ht_oper_len);
int hostapd_drv_none(struct hostapd_data *hapd);
int hostapd_driver_scan(struct hostapd_data *hapd,
struct wpa_driver_scan_params *params);
struct wpa_scan_results * hostapd_driver_get_scan_results(
struct hostapd_data *hapd);
int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
int duration);
int hostapd_drv_set_key(const char *ifname,
struct hostapd_data *hapd,
enum wpa_alg alg, const u8 *addr,
int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len);
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
const void *msg, size_t len);
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
const u8 *addr, int reason);
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
const u8 *addr, int reason);
int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
u16 auth_alg);
int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
u16 seq, u16 status, const u8 *ie, size_t len);
int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
int reassoc, u16 status, const u8 *ie, size_t len);
int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
u8 *tspec_ie, size_t tspec_ielen);
#include "drivers/driver.h"
static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd,
int enabled)
{
if (hapd->driver == NULL ||
hapd->driver->hapd_set_countermeasures == NULL)
return 0;
return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled);
}
static inline int hostapd_drv_set_sta_vlan(const char *ifname,
struct hostapd_data *hapd,
const u8 *addr, int vlan_id)
{
if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL)
return 0;
return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname,
vlan_id);
}
static inline int hostapd_drv_get_inact_sec(struct hostapd_data *hapd,
const u8 *addr)
{
if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL)
return 0;
return hapd->driver->get_inact_sec(hapd->drv_priv, addr);
}
static inline int hostapd_drv_sta_remove(struct hostapd_data *hapd,
const u8 *addr)
{
if (hapd->driver == NULL || hapd->driver->sta_remove == NULL)
return 0;
return hapd->driver->sta_remove(hapd->drv_priv, addr);
}
static inline int hostapd_drv_hapd_send_eapol(struct hostapd_data *hapd,
const u8 *addr, const u8 *data,
size_t data_len, int encrypt,
u32 flags)
{
if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
return 0;
return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
data_len, encrypt,
hapd->own_addr, flags);
}
static inline int hostapd_drv_read_sta_data(
struct hostapd_data *hapd, struct hostap_sta_driver_data *data,
const u8 *addr)
{
if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL)
return -1;
return hapd->driver->read_sta_data(hapd->drv_priv, data, addr);
}
static inline int hostapd_drv_sta_clear_stats(struct hostapd_data *hapd,
const u8 *addr)
{
if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL)
return 0;
return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
}
static inline int hostapd_drv_set_ap(struct hostapd_data *hapd,
struct wpa_driver_ap_params *params)
{
if (hapd->driver == NULL || hapd->driver->set_ap == NULL)
return 0;
return hapd->driver->set_ap(hapd->drv_priv, params);
}
static inline int hostapd_drv_set_radius_acl_auth(struct hostapd_data *hapd,
const u8 *mac, int accepted,
u32 session_timeout)
{
if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL)
return 0;
return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted,
session_timeout);
}
static inline int hostapd_drv_set_radius_acl_expire(struct hostapd_data *hapd,
const u8 *mac)
{
if (hapd->driver == NULL ||
hapd->driver->set_radius_acl_expire == NULL)
return 0;
return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac);
}
static inline int hostapd_drv_set_authmode(struct hostapd_data *hapd,
int auth_algs)
{
if (hapd->driver == NULL || hapd->driver->set_authmode == NULL)
return 0;
return hapd->driver->set_authmode(hapd->drv_priv, auth_algs);
}
static inline void hostapd_drv_poll_client(struct hostapd_data *hapd,
const u8 *own_addr, const u8 *addr,
int qos)
{
if (hapd->driver == NULL || hapd->driver->poll_client == NULL)
return;
hapd->driver->poll_client(hapd->drv_priv, own_addr, addr, qos);
}
#endif /* AP_DRV_OPS */

View File

@ -227,6 +227,7 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
struct hostapd_frame_info *fi)
{
struct ap_info *ap;
struct os_time now;
int new_ap = 0;
size_t len;
int set_beacon = 0;
@ -292,7 +293,8 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
ap->ht_support = 0;
ap->num_beacons++;
time(&ap->last_beacon);
os_get_time(&now);
ap->last_beacon = now.sec;
if (fi) {
ap->ssi_signal = fi->ssi_signal;
ap->datarate = fi->datarate;
@ -331,7 +333,7 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
{
struct hostapd_iface *iface = eloop_ctx;
time_t now;
struct os_time now;
struct ap_info *ap;
int set_beacon = 0;
@ -340,12 +342,12 @@ static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
if (!iface->ap_list)
return;
time(&now);
os_get_time(&now);
while (iface->ap_list) {
ap = iface->ap_list->prev;
if (ap->last_beacon + iface->conf->ap_table_expiration_time >=
now)
now.sec)
break;
ap_free_ap(iface, ap);

View File

@ -45,7 +45,7 @@ struct ap_info {
int ht_support;
unsigned int num_beacons; /* number of beacon frames received */
time_t last_beacon;
os_time_t last_beacon;
int already_seen; /* whether API call AP-NEW has already fetched
* information about this AP */

View File

@ -119,6 +119,7 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
srv.get_eap_user = hostapd_radius_get_eap_user;
srv.eap_req_id_text = conf->eap_req_id_text;
srv.eap_req_id_text_len = conf->eap_req_id_text_len;
srv.pwd_group = conf->pwd_group;
hapd->radius_srv = radius_server_init(&srv);
if (hapd->radius_srv == NULL) {

View File

@ -22,15 +22,21 @@
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "drivers/driver.h"
#include "wps/wps_defs.h"
#include "p2p/p2p.h"
#include "hostapd.h"
#include "ieee802_11.h"
#include "wpa_auth.h"
#include "wmm.h"
#include "ap_config.h"
#include "sta_info.h"
#include "p2p_hostapd.h"
#include "ap_drv_ops.h"
#include "beacon.h"
#ifdef NEED_AP_MLME
static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
{
u8 erp = 0;
@ -39,23 +45,11 @@ static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
return 0;
switch (hapd->iconf->cts_protection_type) {
case CTS_PROTECTION_FORCE_ENABLED:
erp |= ERP_INFO_NON_ERP_PRESENT | ERP_INFO_USE_PROTECTION;
break;
case CTS_PROTECTION_FORCE_DISABLED:
erp = 0;
break;
case CTS_PROTECTION_AUTOMATIC:
if (hapd->iface->olbc)
erp |= ERP_INFO_USE_PROTECTION;
/* continue */
case CTS_PROTECTION_AUTOMATIC_NO_OLBC:
if (hapd->iface->num_sta_non_erp > 0) {
erp |= ERP_INFO_NON_ERP_PRESENT |
ERP_INFO_USE_PROTECTION;
}
break;
if (hapd->iface->olbc)
erp |= ERP_INFO_USE_PROTECTION;
if (hapd->iface->num_sta_non_erp > 0) {
erp |= ERP_INFO_NON_ERP_PRESENT |
ERP_INFO_USE_PROTECTION;
}
if (hapd->iface->num_sta_no_short_preamble > 0 ||
hapd->iconf->preamble == LONG_PREAMBLE)
@ -178,8 +172,7 @@ static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
}
static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len,
struct sta_info *sta)
static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
{
const u8 *ie;
size_t ielen;
@ -207,11 +200,14 @@ void handle_probe_req(struct hostapd_data *hapd,
size_t i;
ie = mgmt->u.probe_req.variable;
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
return;
ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
mgmt->sa, ie, ie_len) > 0)
mgmt->sa, mgmt->da, mgmt->bssid,
ie, ie_len) > 0)
return;
if (!hapd->iconf->send_probe_response)
@ -233,6 +229,33 @@ void handle_probe_req(struct hostapd_data *hapd,
return;
}
#ifdef CONFIG_P2P
if (hapd->p2p && elems.wps_ie) {
struct wpabuf *wps;
wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) {
wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
"due to mismatch with Requested Device "
"Type");
wpabuf_free(wps);
return;
}
wpabuf_free(wps);
}
if (hapd->p2p && elems.p2p) {
struct wpabuf *p2p;
p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE);
if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) {
wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
"due to mismatch with Device ID");
wpabuf_free(p2p);
return;
}
wpabuf_free(p2p);
}
#endif /* CONFIG_P2P */
if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) {
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
"broadcast SSID ignored", MAC2STR(mgmt->sa));
@ -241,6 +264,16 @@ void handle_probe_req(struct hostapd_data *hapd,
sta = ap_get_sta(hapd, mgmt->sa);
#ifdef CONFIG_P2P
if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
elems.ssid_len == P2P_WILDCARD_SSID_LEN &&
os_memcmp(elems.ssid, P2P_WILDCARD_SSID,
P2P_WILDCARD_SSID_LEN) == 0) {
/* Process P2P Wildcard SSID like Wildcard SSID */
elems.ssid_len = 0;
}
#endif /* CONFIG_P2P */
if (elems.ssid_len == 0 ||
(elems.ssid_len == hapd->conf->ssid.ssid_len &&
os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) ==
@ -257,12 +290,43 @@ void handle_probe_req(struct hostapd_data *hapd,
ieee802_11_print_ssid(ssid_txt, elems.ssid,
elems.ssid_len);
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
" for foreign SSID '%s'",
MAC2STR(mgmt->sa), ssid_txt);
" for foreign SSID '%s' (DA " MACSTR ")",
MAC2STR(mgmt->sa), ssid_txt,
MAC2STR(mgmt->da));
}
return;
}
#ifdef CONFIG_INTERWORKING
if (elems.interworking && elems.interworking_len >= 1) {
u8 ant = elems.interworking[0] & 0x0f;
if (ant != INTERWORKING_ANT_WILDCARD &&
ant != hapd->conf->access_network_type) {
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
" for mismatching ANT %u ignored",
MAC2STR(mgmt->sa), ant);
return;
}
}
if (elems.interworking &&
(elems.interworking_len == 7 || elems.interworking_len == 9)) {
const u8 *hessid;
if (elems.interworking_len == 7)
hessid = elems.interworking + 1;
else
hessid = elems.interworking + 1 + 2;
if (!is_broadcast_ether_addr(hessid) &&
os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) {
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
" for mismatching HESSID " MACSTR
" ignored",
MAC2STR(mgmt->sa), MAC2STR(hessid));
return;
}
}
#endif /* CONFIG_INTERWORKING */
/* TODO: verify that supp_rates contains at least one matching rate
* with AP configuration */
#define MAX_PROBERESP_LEN 768
@ -271,6 +335,10 @@ void handle_probe_req(struct hostapd_data *hapd,
if (hapd->wps_probe_resp_ie)
buflen += wpabuf_len(hapd->wps_probe_resp_ie);
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
if (hapd->p2p_probe_resp_ie)
buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
#endif /* CONFIG_P2P */
resp = os_zalloc(buflen);
if (resp == NULL)
return;
@ -310,13 +378,22 @@ void handle_probe_req(struct hostapd_data *hapd,
pos = hostapd_eid_ext_supp_rates(hapd, pos);
/* RSN, MDIE, WPA */
pos = hostapd_eid_wpa(hapd, pos, epos - pos, sta);
pos = hostapd_eid_wpa(hapd, pos, epos - pos);
#ifdef CONFIG_IEEE80211N
pos = hostapd_eid_ht_capabilities(hapd, pos);
pos = hostapd_eid_ht_operation(hapd, pos);
#endif /* CONFIG_IEEE80211N */
pos = hostapd_eid_ext_capab(hapd, pos);
pos = hostapd_eid_time_adv(hapd, pos);
pos = hostapd_eid_time_zone(hapd, pos);
pos = hostapd_eid_interworking(hapd, pos);
pos = hostapd_eid_adv_proto(hapd, pos);
pos = hostapd_eid_roaming_consortium(hapd, pos);
/* Wi-Fi Alliance WMM */
pos = hostapd_eid_wmm(hapd, pos);
@ -328,23 +405,48 @@ void handle_probe_req(struct hostapd_data *hapd,
}
#endif /* CONFIG_WPS */
if (hapd->drv.send_mgmt_frame(hapd, resp, pos - (u8 *) resp) < 0)
#ifdef CONFIG_P2P
if ((hapd->conf->p2p & P2P_ENABLED) && elems.p2p &&
hapd->p2p_probe_resp_ie) {
os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
wpabuf_len(hapd->p2p_probe_resp_ie));
pos += wpabuf_len(hapd->p2p_probe_resp_ie);
}
#endif /* CONFIG_P2P */
#ifdef CONFIG_P2P_MANAGER
if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
P2P_MANAGE)
pos = hostapd_eid_p2p_manage(hapd, pos);
#endif /* CONFIG_P2P_MANAGER */
if (hostapd_drv_send_mlme(hapd, resp, pos - (u8 *) resp) < 0)
perror("handle_probe_req: send");
os_free(resp);
wpa_printf(MSG_MSGDUMP, "STA " MACSTR " sent probe request for %s "
wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s "
"SSID", MAC2STR(mgmt->sa),
elems.ssid_len == 0 ? "broadcast" : "our");
}
#endif /* NEED_AP_MLME */
void ieee802_11_set_beacon(struct hostapd_data *hapd)
{
struct ieee80211_mgmt *head;
u8 *pos, *tail, *tailpos;
struct ieee80211_mgmt *head = NULL;
u8 *tail = NULL;
size_t head_len = 0, tail_len = 0;
struct wpa_driver_ap_params params;
struct wpabuf *beacon, *proberesp, *assocresp;
#ifdef NEED_AP_MLME
u16 capab_info;
size_t head_len, tail_len;
u8 *pos, *tailpos;
#endif /* NEED_AP_MLME */
hapd->beacon_set_done = 1;
#ifdef NEED_AP_MLME
#define BEACON_HEAD_BUF_SIZE 256
#define BEACON_TAIL_BUF_SIZE 512
@ -354,6 +456,10 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
if (hapd->conf->wps_state && hapd->wps_beacon_ie)
tail_len += wpabuf_len(hapd->wps_beacon_ie);
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
if (hapd->p2p_beacon_ie)
tail_len += wpabuf_len(hapd->p2p_beacon_ie);
#endif /* CONFIG_P2P */
tailpos = tail = os_malloc(tail_len);
if (head == NULL || tail == NULL) {
wpa_printf(MSG_ERROR, "Failed to set beacon data");
@ -412,13 +518,25 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
/* RSN, MDIE, WPA */
tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
tailpos, NULL);
tailpos);
#ifdef CONFIG_IEEE80211N
tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
tailpos = hostapd_eid_ht_operation(hapd, tailpos);
#endif /* CONFIG_IEEE80211N */
tailpos = hostapd_eid_ext_capab(hapd, tailpos);
/*
* TODO: Time Advertisement element should only be included in some
* DTIM Beacon frames.
*/
tailpos = hostapd_eid_time_adv(hapd, tailpos);
tailpos = hostapd_eid_interworking(hapd, tailpos);
tailpos = hostapd_eid_adv_proto(hapd, tailpos);
tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
/* Wi-Fi Alliance WMM */
tailpos = hostapd_eid_wmm(hapd, tailpos);
@ -430,19 +548,85 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
}
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) {
os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie),
wpabuf_len(hapd->p2p_beacon_ie));
tailpos += wpabuf_len(hapd->p2p_beacon_ie);
}
#endif /* CONFIG_P2P */
#ifdef CONFIG_P2P_MANAGER
if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
P2P_MANAGE)
tailpos = hostapd_eid_p2p_manage(hapd, tailpos);
#endif /* CONFIG_P2P_MANAGER */
tail_len = tailpos > tail ? tailpos - tail : 0;
if (hapd->drv.set_beacon(hapd, (u8 *) head, head_len,
tail, tail_len, hapd->conf->dtim_period,
hapd->iconf->beacon_int))
wpa_printf(MSG_ERROR, "Failed to set beacon head/tail or DTIM "
"period");
#endif /* NEED_AP_MLME */
os_memset(&params, 0, sizeof(params));
params.head = (u8 *) head;
params.head_len = head_len;
params.tail = tail;
params.tail_len = tail_len;
params.dtim_period = hapd->conf->dtim_period;
params.beacon_int = hapd->iconf->beacon_int;
params.ssid = (u8 *) hapd->conf->ssid.ssid;
params.ssid_len = hapd->conf->ssid.ssid_len;
params.pairwise_ciphers = hapd->conf->rsn_pairwise ?
hapd->conf->rsn_pairwise : hapd->conf->wpa_pairwise;
params.group_cipher = hapd->conf->wpa_group;
params.key_mgmt_suites = hapd->conf->wpa_key_mgmt;
params.auth_algs = hapd->conf->auth_algs;
params.wpa_version = hapd->conf->wpa;
params.privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa ||
(hapd->conf->ieee802_1x &&
(hapd->conf->default_wep_key_len ||
hapd->conf->individual_wep_key_len));
switch (hapd->conf->ignore_broadcast_ssid) {
case 0:
params.hide_ssid = NO_SSID_HIDING;
break;
case 1:
params.hide_ssid = HIDDEN_SSID_ZERO_LEN;
break;
case 2:
params.hide_ssid = HIDDEN_SSID_ZERO_CONTENTS;
break;
}
hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp);
params.beacon_ies = beacon;
params.proberesp_ies = proberesp;
params.assocresp_ies = assocresp;
params.isolate = hapd->conf->isolate;
#ifdef NEED_AP_MLME
params.cts_protect = !!(ieee802_11_erp_info(hapd) &
ERP_INFO_USE_PROTECTION);
params.preamble = hapd->iface->num_sta_no_short_preamble == 0 &&
hapd->iconf->preamble == SHORT_PREAMBLE;
if (hapd->iface->current_mode &&
hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
params.short_slot_time =
hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1;
else
params.short_slot_time = -1;
if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
params.ht_opmode = -1;
else
params.ht_opmode = hapd->iface->ht_op_mode;
#endif /* NEED_AP_MLME */
params.interworking = hapd->conf->interworking;
if (hapd->conf->interworking &&
!is_zero_ether_addr(hapd->conf->hessid))
params.hessid = hapd->conf->hessid;
params.access_network_type = hapd->conf->access_network_type;
if (hostapd_drv_set_ap(hapd, &params))
wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
os_free(tail);
os_free(head);
hapd->drv.set_bss_params(hapd, !!(ieee802_11_erp_info(hapd) &
ERP_INFO_USE_PROTECTION));
}

View File

@ -20,17 +20,7 @@ struct ieee80211_mgmt;
void handle_probe_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len);
#ifdef NEED_AP_MLME
void ieee802_11_set_beacon(struct hostapd_data *hapd);
void ieee802_11_set_beacons(struct hostapd_iface *iface);
#else /* NEED_AP_MLME */
static inline void ieee802_11_set_beacon(struct hostapd_data *hapd)
{
}
static inline void ieee802_11_set_beacons(struct hostapd_iface *iface)
{
}
#endif /* NEED_AP_MLME */
#endif /* BEACON_H */

View File

@ -21,6 +21,7 @@
#include "ieee802_11.h"
#include "sta_info.h"
#include "wps_hostapd.h"
#include "p2p_hostapd.h"
#include "ctrl_iface_ap.h"
@ -57,6 +58,9 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
buflen - len);
if (res >= 0)
len += res;
res = hostapd_p2p_get_mib_sta(hapd, sta, buf + len, buflen - len);
if (res >= 0)
len += res;
return len;
}

View File

@ -20,6 +20,9 @@
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/wpa_ctrl.h"
#include "crypto/random.h"
#include "p2p/p2p.h"
#include "wps/wps.h"
#include "hostapd.h"
#include "ieee802_11.h"
#include "sta_info.h"
@ -30,15 +33,19 @@
#include "wpa_auth.h"
#include "wmm.h"
#include "wps_hostapd.h"
#include "ap_drv_ops.h"
#include "ap_config.h"
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
const u8 *ie, size_t ielen)
const u8 *req_ies, size_t req_ies_len, int reassoc)
{
struct sta_info *sta;
int new_assoc, res;
struct ieee802_11_elems elems;
const u8 *ie;
size_t ielen;
u16 reason = WLAN_REASON_UNSPECIFIED;
if (addr == NULL) {
/*
@ -52,11 +59,12 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
"no address");
return -1;
}
random_add_randomness(addr, ETH_ALEN);
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "associated");
ieee802_11_parse_elems(ie, ielen, &elems, 0);
ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0);
if (elems.wps_ie) {
ie = elems.wps_ie - 2;
ielen = elems.wps_ie_len + 2;
@ -79,15 +87,30 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
sta = ap_get_sta(hapd, addr);
if (sta) {
accounting_sta_stop(hapd, sta);
/*
* Make sure that the previously registered inactivity timer
* will not remove the STA immediately.
*/
sta->timeout_next = STA_NULLFUNC;
} else {
sta = ap_sta_add(hapd, addr);
if (sta == NULL)
return -1;
}
sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
#ifdef CONFIG_P2P
if (elems.p2p) {
wpabuf_free(sta->p2p_ie);
sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
P2P_IE_VENDOR_TYPE);
}
#endif /* CONFIG_P2P */
if (hapd->conf->wpa) {
if (ie == NULL || ielen == 0) {
#ifdef CONFIG_WPS
if (hapd->conf->wps_state) {
wpa_printf(MSG_DEBUG, "STA did not include "
"WPA/RSN IE in (Re)Association "
@ -95,15 +118,29 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
sta->flags |= WLAN_STA_MAYBE_WPS;
goto skip_wpa_check;
}
#endif /* CONFIG_WPS */
wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
return -1;
}
#ifdef CONFIG_WPS
if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
struct wpabuf *wps;
sta->flags |= WLAN_STA_WPS;
wps = ieee802_11_vendor_ie_concat(ie, ielen,
WPS_IE_VENDOR_TYPE);
if (wps) {
if (wps_is_20(wps)) {
wpa_printf(MSG_DEBUG, "WPS: STA "
"supports WPS 2.0");
sta->flags |= WLAN_STA_WPS2;
}
wpabuf_free(wps);
}
goto skip_wpa_check;
}
#endif /* CONFIG_WPS */
if (sta->wpa_sm == NULL)
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
@ -116,36 +153,55 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
ie, ielen, NULL, 0);
if (res != WPA_IE_OK) {
int resp;
wpa_printf(MSG_DEBUG, "WPA/RSN information element "
"rejected? (res %u)", res);
wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
if (res == WPA_INVALID_GROUP)
resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
else if (res == WPA_INVALID_PAIRWISE)
resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
else if (res == WPA_INVALID_AKMP)
resp = WLAN_REASON_AKMP_NOT_VALID;
reason = WLAN_REASON_AKMP_NOT_VALID;
#ifdef CONFIG_IEEE80211W
else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
resp = WLAN_REASON_INVALID_IE;
reason = WLAN_REASON_INVALID_IE;
else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
#endif /* CONFIG_IEEE80211W */
else
resp = WLAN_REASON_INVALID_IE;
hapd->drv.sta_disassoc(hapd, sta->addr, resp);
ap_free_sta(hapd, sta);
return -1;
reason = WLAN_REASON_INVALID_IE;
goto fail;
}
} else if (hapd->conf->wps_state) {
if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
#ifdef CONFIG_WPS
struct wpabuf *wps;
if (req_ies)
wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
WPS_IE_VENDOR_TYPE);
else
wps = NULL;
#ifdef CONFIG_WPS_STRICT
if (wps && wps_validate_assoc_req(wps) < 0) {
reason = WLAN_REASON_INVALID_IE;
wpabuf_free(wps);
goto fail;
}
#endif /* CONFIG_WPS_STRICT */
if (wps) {
sta->flags |= WLAN_STA_WPS;
if (wps_is_20(wps)) {
wpa_printf(MSG_DEBUG, "WPS: STA supports "
"WPS 2.0");
sta->flags |= WLAN_STA_WPS2;
}
} else
sta->flags |= WLAN_STA_MAYBE_WPS;
wpabuf_free(wps);
#endif /* CONFIG_WPS */
}
#ifdef CONFIG_WPS
skip_wpa_check:
#endif /* CONFIG_WPS */
new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
@ -155,7 +211,19 @@ skip_wpa_check:
ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
#ifdef CONFIG_P2P
if (req_ies) {
p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
req_ies, req_ies_len);
}
#endif /* CONFIG_P2P */
return 0;
fail:
hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
ap_free_sta(hapd, sta);
return -1;
}
@ -163,6 +231,19 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
{
struct sta_info *sta;
if (addr == NULL) {
/*
* This could potentially happen with unexpected event from the
* driver wrapper. This was seen at least in one case where the
* driver ended up reporting a station mode event while hostapd
* was running, so better make sure we stop processing such an
* event here.
*/
wpa_printf(MSG_DEBUG, "hostapd_notif_disassoc: Skip event "
"with no address");
return;
}
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "disassociated");
@ -173,9 +254,8 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
return;
}
ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
MAC2STR(sta->addr));
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);
@ -183,50 +263,47 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
}
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
{
struct sta_info *sta = ap_get_sta(hapd, addr);
if (!sta || !hapd->conf->disassoc_low_ack)
return;
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "disconnected due to excessive "
"missing ACKs");
hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK);
if (sta)
ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK);
}
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
const u8 *bssid, const u8 *ie, size_t ie_len)
{
size_t i;
int ret = 0;
if (sa == NULL || ie == NULL)
return -1;
random_add_randomness(sa, ETH_ALEN);
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
sa, da, bssid, ie, ie_len) > 0) {
ret = 1;
break;
}
}
return ret;
}
#ifdef HOSTAPD
#ifdef NEED_AP_MLME
static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
{
u16 fc, type, stype;
/*
* PS-Poll frames are 16 bytes. All other frames are
* 24 bytes or longer.
*/
if (len < 16)
return NULL;
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_DATA:
if (len < 24)
return NULL;
switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
case WLAN_FC_FROMDS | WLAN_FC_TODS:
case WLAN_FC_TODS:
return hdr->addr1;
case WLAN_FC_FROMDS:
return hdr->addr2;
default:
return NULL;
}
case WLAN_FC_TYPE_CTRL:
if (stype != WLAN_FC_STYPE_PSPOLL)
return NULL;
return hdr->addr1;
case WLAN_FC_TYPE_MGMT:
return hdr->addr3;
default:
return NULL;
}
}
#define HAPD_BROADCAST ((struct hostapd_data *) -1)
static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
@ -250,17 +327,14 @@ static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
const u8 *frame, size_t len)
const u8 *bssid, const u8 *addr,
int wds)
{
const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame;
u16 fc = le_to_host16(hdr->frame_control);
hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
hapd = get_hapd_bssid(hapd->iface, bssid);
if (hapd == NULL || hapd == HAPD_BROADCAST)
return;
ieee802_11_rx_from_unknown(hapd, hdr->addr2,
(fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
(WLAN_FC_TODS | WLAN_FC_FROMDS));
ieee802_11_rx_from_unknown(hapd, addr, wds);
}
@ -303,6 +377,48 @@ static void hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
rx_mgmt->frame_len, &fi);
} else
ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi);
random_add_randomness(&fi, sizeof(fi));
}
static void hostapd_rx_action(struct hostapd_data *hapd,
struct rx_action *rx_action)
{
struct rx_mgmt rx_mgmt;
u8 *buf;
struct ieee80211_hdr *hdr;
wpa_printf(MSG_DEBUG, "EVENT_RX_ACTION DA=" MACSTR " SA=" MACSTR
" BSSID=" MACSTR " category=%u",
MAC2STR(rx_action->da), MAC2STR(rx_action->sa),
MAC2STR(rx_action->bssid), rx_action->category);
wpa_hexdump(MSG_MSGDUMP, "Received action frame contents",
rx_action->data, rx_action->len);
buf = os_zalloc(24 + 1 + rx_action->len);
if (buf == NULL)
return;
hdr = (struct ieee80211_hdr *) buf;
hdr->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_ACTION);
if (rx_action->category == WLAN_ACTION_SA_QUERY) {
/*
* Assume frame was protected; it would have been dropped if
* not.
*/
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
}
os_memcpy(hdr->addr1, rx_action->da, ETH_ALEN);
os_memcpy(hdr->addr2, rx_action->sa, ETH_ALEN);
os_memcpy(hdr->addr3, rx_action->bssid, ETH_ALEN);
buf[24] = rx_action->category;
os_memcpy(buf + 24 + 1, rx_action->data, rx_action->len);
os_memset(&rx_mgmt, 0, sizeof(rx_mgmt));
rx_mgmt.frame = buf;
rx_mgmt.frame_len = 24 + 1 + rx_action->len;
hostapd_mgmt_rx(hapd, &rx_mgmt);
os_free(buf);
}
@ -320,23 +436,6 @@ static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
#endif /* NEED_AP_MLME */
static int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
const u8 *ie, size_t ie_len)
{
size_t i;
int ret = 0;
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
sa, ie, ie_len) > 0) {
ret = 1;
break;
}
}
return ret;
}
static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
{
struct sta_info *sta = ap_get_sta(hapd, addr);
@ -395,7 +494,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
#endif /* CONFIG_IEEE80211R */
case EVENT_WPS_BUTTON_PUSHED:
hostapd_wps_button_pushed(hapd);
hostapd_wps_button_pushed(hapd, NULL);
break;
#ifdef NEED_AP_MLME
case EVENT_TX_STATUS:
@ -414,16 +513,25 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
}
break;
case EVENT_DRIVER_CLIENT_POLL_OK:
hostapd_client_poll_ok(hapd, data->client_poll.addr);
break;
case EVENT_RX_FROM_UNKNOWN:
hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.frame,
data->rx_from_unknown.len);
hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid,
data->rx_from_unknown.addr,
data->rx_from_unknown.wds);
break;
case EVENT_RX_MGMT:
hostapd_mgmt_rx(hapd, &data->rx_mgmt);
break;
#endif /* NEED_AP_MLME */
case EVENT_RX_PROBE_REQ:
if (data->rx_probe_req.sa == NULL ||
data->rx_probe_req.ie == NULL)
break;
hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
data->rx_probe_req.da,
data->rx_probe_req.bssid,
data->rx_probe_req.ie,
data->rx_probe_req.ie_len);
break;
@ -438,7 +546,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
case EVENT_ASSOC:
hostapd_notif_assoc(hapd, data->assoc_info.addr,
data->assoc_info.req_ies,
data->assoc_info.req_ies_len);
data->assoc_info.req_ies_len,
data->assoc_info.reassoc);
break;
case EVENT_DISASSOC:
if (data)
@ -448,6 +557,19 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
if (data)
hostapd_notif_disassoc(hapd, data->deauth_info.addr);
break;
case EVENT_STATION_LOW_ACK:
if (!data)
break;
hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
break;
#ifdef NEED_AP_MLME
case EVENT_RX_ACTION:
if (data->rx_action.da == NULL || data->rx_action.sa == NULL ||
data->rx_action.bssid == NULL)
break;
hostapd_rx_action(hapd, &data->rx_action);
break;
#endif /* NEED_AP_MLME */
default:
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
break;

View File

@ -35,57 +35,37 @@
#include "wpa_auth_glue.h"
#include "ap_drv_ops.h"
#include "ap_config.h"
#include "p2p_hostapd.h"
static int hostapd_flush_old_stations(struct hostapd_data *hapd);
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd);
extern int wpa_debug_level;
int hostapd_reload_config(struct hostapd_iface *iface)
static void hostapd_reload_bss(struct hostapd_data *hapd)
{
struct hostapd_data *hapd = iface->bss[0];
struct hostapd_config *newconf, *oldconf;
size_t j;
if (iface->config_read_cb == NULL)
return -1;
newconf = iface->config_read_cb(iface->config_fname);
if (newconf == NULL)
return -1;
/*
* Deauthenticate all stations since the new configuration may not
* allow them to use the BSS anymore.
*/
for (j = 0; j < iface->num_bss; j++)
hostapd_flush_old_stations(iface->bss[j]);
#ifndef CONFIG_NO_RADIUS
/* TODO: update dynamic data based on changed configuration
* items (e.g., open/close sockets, etc.) */
radius_client_flush(hapd->radius, 0);
radius_client_reconfig(hapd->radius, hapd->conf->radius);
#endif /* CONFIG_NO_RADIUS */
oldconf = hapd->iconf;
hapd->iconf = newconf;
hapd->conf = &newconf->bss[0];
iface->conf = newconf;
if (hostapd_setup_wpa_psk(hapd->conf)) {
wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK "
"after reloading configuration");
}
if (hapd->conf->ieee802_1x || hapd->conf->wpa)
hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 1);
hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1);
else
hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
if (hapd->conf->wpa && hapd->wpa_auth == NULL)
if (hapd->conf->wpa && hapd->wpa_auth == NULL) {
hostapd_setup_wpa(hapd);
else if (hapd->conf->wpa) {
if (hapd->wpa_auth)
wpa_init_keys(hapd->wpa_auth);
} else if (hapd->conf->wpa) {
const u8 *wpa_ie;
size_t wpa_ie_len;
hostapd_reconfig_wpa(hapd);
@ -110,10 +90,50 @@ int hostapd_reload_config(struct hostapd_iface *iface)
wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
/* try to continue */
}
wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
}
int hostapd_reload_config(struct hostapd_iface *iface)
{
struct hostapd_data *hapd = iface->bss[0];
struct hostapd_config *newconf, *oldconf;
size_t j;
if (iface->config_read_cb == NULL)
return -1;
newconf = iface->config_read_cb(iface->config_fname);
if (newconf == NULL)
return -1;
/*
* Deauthenticate all stations since the new configuration may not
* allow them to use the BSS anymore.
*/
for (j = 0; j < iface->num_bss; j++) {
hostapd_flush_old_stations(iface->bss[j],
WLAN_REASON_PREV_AUTH_NOT_VALID);
hostapd_broadcast_wep_clear(iface->bss[j]);
#ifndef CONFIG_NO_RADIUS
/* TODO: update dynamic data based on changed configuration
* items (e.g., open/close sockets, etc.) */
radius_client_flush(iface->bss[j]->radius, 0);
#endif /* CONFIG_NO_RADIUS */
}
oldconf = hapd->iconf;
iface->conf = newconf;
for (j = 0; j < iface->num_bss; j++) {
hapd = iface->bss[j];
hapd->iconf = newconf;
hapd->conf = &newconf->bss[j];
hostapd_reload_bss(hapd);
}
hostapd_config_free(oldconf);
wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
return 0;
}
@ -125,8 +145,8 @@ static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
int i;
for (i = 0; i < NUM_WEP_KEYS; i++) {
if (hapd->drv.set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
i == 0 ? 1 : 0, NULL, 0, NULL, 0)) {
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
0, NULL, 0, NULL, 0)) {
wpa_printf(MSG_DEBUG, "Failed to clear default "
"encryption keys (ifname=%s keyidx=%d)",
ifname, i);
@ -135,9 +155,9 @@ static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
#ifdef CONFIG_IEEE80211W
if (hapd->conf->ieee80211w) {
for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
if (hapd->drv.set_key(ifname, hapd, WPA_ALG_NONE, NULL,
i, i == 0 ? 1 : 0, NULL, 0,
NULL, 0)) {
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE,
NULL, i, 0, NULL,
0, NULL, 0)) {
wpa_printf(MSG_DEBUG, "Failed to clear "
"default mgmt encryption keys "
"(ifname=%s keyidx=%d)", ifname, i);
@ -162,11 +182,10 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
idx = ssid->wep.idx;
if (ssid->wep.default_len &&
hapd->drv.set_key(hapd->conf->iface,
hapd, WPA_ALG_WEP, NULL, idx,
idx == ssid->wep.idx,
NULL, 0, ssid->wep.key[idx],
ssid->wep.len[idx])) {
hostapd_drv_set_key(hapd->conf->iface,
hapd, WPA_ALG_WEP, broadcast_ether_addr, idx,
1, NULL, 0, ssid->wep.key[idx],
ssid->wep.len[idx])) {
wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
errors++;
}
@ -184,9 +203,10 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
continue;
idx = key->idx;
if (hapd->drv.set_key(ifname, hapd, WPA_ALG_WEP, NULL,
idx, idx == key->idx, NULL, 0,
key->key[idx], key->len[idx])) {
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_WEP,
broadcast_ether_addr, idx, 1,
NULL, 0, key->key[idx],
key->len[idx])) {
wpa_printf(MSG_WARNING, "Could not set "
"dynamic VLAN WEP encryption.");
errors++;
@ -235,6 +255,15 @@ static void hostapd_cleanup(struct hostapd_data *hapd)
os_free(hapd->probereq_cb);
hapd->probereq_cb = NULL;
#ifdef CONFIG_P2P
wpabuf_free(hapd->p2p_beacon_ie);
hapd->p2p_beacon_ie = NULL;
wpabuf_free(hapd->p2p_probe_resp_ie);
hapd->p2p_probe_resp_ie = NULL;
#endif /* CONFIG_P2P */
wpabuf_free(hapd->time_adv);
}
@ -284,12 +313,18 @@ static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
return 0;
}
/*
* When IEEE 802.1X is not enabled, the driver may need to know how to
* set authentication algorithms for static WEP.
*/
hostapd_drv_set_authmode(hapd, hapd->conf->auth_algs);
for (i = 0; i < 4; i++) {
if (hapd->conf->ssid.wep.key[i] &&
hapd->drv.set_key(iface, hapd, WPA_ALG_WEP, NULL, i,
i == hapd->conf->ssid.wep.idx, NULL, 0,
hapd->conf->ssid.wep.key[i],
hapd->conf->ssid.wep.len[i])) {
hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i,
i == hapd->conf->ssid.wep.idx, NULL, 0,
hapd->conf->ssid.wep.key[i],
hapd->conf->ssid.wep.len[i])) {
wpa_printf(MSG_WARNING, "Could not set WEP "
"encryption.");
return -1;
@ -303,9 +338,10 @@ static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
}
static int hostapd_flush_old_stations(struct hostapd_data *hapd)
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
{
int ret = 0;
u8 addr[ETH_ALEN];
if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL)
return 0;
@ -316,17 +352,9 @@ static int hostapd_flush_old_stations(struct hostapd_data *hapd)
ret = -1;
}
wpa_printf(MSG_DEBUG, "Deauthenticate all stations");
/* New Prism2.5/3 STA firmware versions seem to have issues with this
* broadcast deauth frame. This gets the firmware in odd state where
* nothing works correctly, so let's skip sending this for the hostap
* driver. */
if (hapd->driver && os_strcmp(hapd->driver->name, "hostap") != 0) {
u8 addr[ETH_ALEN];
os_memset(addr, 0xff, ETH_ALEN);
hapd->drv.sta_deauth(hapd, addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
}
os_memset(addr, 0xff, ETH_ALEN);
hostapd_drv_sta_deauth(hapd, addr, reason);
hostapd_free_stas(hapd);
return ret;
}
@ -344,7 +372,6 @@ static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface)
u8 mask[ETH_ALEN] = { 0 };
struct hostapd_data *hapd = iface->bss[0];
unsigned int i = iface->conf->num_bss, bits = 0, j;
int res;
int auto_addr = 0;
if (hostapd_drv_none(hapd))
@ -408,17 +435,6 @@ skip_mask_ext:
wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)",
(unsigned long) iface->conf->num_bss, MAC2STR(mask), bits);
res = hostapd_valid_bss_mask(hapd, hapd->own_addr, mask);
if (res == 0)
return 0;
if (res < 0) {
wpa_printf(MSG_ERROR, "Driver did not accept BSSID mask "
MACSTR " for start address " MACSTR ".",
MAC2STR(mask), MAC2STR(hapd->own_addr));
return -1;
}
if (!auto_addr)
return 0;
@ -495,14 +511,19 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
hapd->interface_added = 1;
if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
hapd->conf->iface, hapd->own_addr, hapd,
&hapd->drv_priv, force_ifname, if_addr)) {
&hapd->drv_priv, force_ifname, if_addr,
hapd->conf->bridge[0] ? hapd->conf->bridge :
NULL)) {
wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
MACSTR ")", MAC2STR(hapd->own_addr));
return -1;
}
}
hostapd_flush_old_stations(hapd);
if (conf->wmm_enabled < 0)
conf->wmm_enabled = hapd->iconf->ieee80211n;
hostapd_flush_old_stations(hapd, WLAN_REASON_PREV_AUTH_NOT_VALID);
hostapd_set_privacy(hapd, 0);
hostapd_broadcast_wep_clear(hapd);
@ -611,6 +632,12 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
ieee802_11_set_beacon(hapd);
if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
return -1;
if (hapd->driver && hapd->driver->set_operstate)
hapd->driver->set_operstate(hapd->drv_priv, 1);
return 0;
}
@ -624,9 +651,6 @@ static void hostapd_tx_queue_params(struct hostapd_iface *iface)
for (i = 0; i < NUM_TX_QUEUES; i++) {
p = &iface->conf->tx_queue[i];
if (!p->configured)
continue;
if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin,
p->cwmax, p->burst)) {
wpa_printf(MSG_DEBUG, "Failed to set TX queue "
@ -717,6 +741,17 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
}
}
if (iface->current_mode) {
if (hostapd_prepare_rates(hapd, iface->current_mode)) {
wpa_printf(MSG_ERROR, "Failed to prepare rates "
"table.");
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"Failed to prepare rates table.");
return -1;
}
}
if (hapd->iconf->rts_threshold > -1 &&
hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) {
wpa_printf(MSG_ERROR, "Could not set RTS threshold for "
@ -753,6 +788,20 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
return -1;
}
/*
* WPS UPnP module can be initialized only when the "upnp_iface" is up.
* If "interface" and "upnp_iface" are the same (e.g., non-bridge
* mode), the interface is up only after driver_commit, so initialize
* WPS after driver_commit.
*/
for (j = 0; j < iface->num_bss; j++) {
if (hostapd_init_wps_complete(iface->bss[j]))
return -1;
}
if (hapd->setup_complete_cb)
hapd->setup_complete_cb(hapd->setup_complete_cb_ctx);
wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
iface->bss[0]->conf->iface);
@ -807,7 +856,6 @@ hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
if (hapd == NULL)
return NULL;
hostapd_set_driver_ops(&hapd->drv);
hapd->new_assoc_sta_cb = hostapd_new_assoc_sta;
hapd->iconf = conf;
hapd->conf = bss;
@ -829,7 +877,7 @@ void hostapd_interface_deinit(struct hostapd_iface *iface)
for (j = 0; j < iface->num_bss; j++) {
struct hostapd_data *hapd = iface->bss[j];
hostapd_free_stas(hapd);
hostapd_flush_old_stations(hapd);
hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
hostapd_cleanup(hapd);
}
}
@ -859,8 +907,8 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
int reassoc)
{
if (hapd->tkip_countermeasures) {
hapd->drv.sta_deauth(hapd, sta->addr,
WLAN_REASON_MICHAEL_MIC_FAILURE);
hostapd_drv_sta_deauth(hapd, sta->addr,
WLAN_REASON_MICHAEL_MIC_FAILURE);
return;
}
@ -870,6 +918,15 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
if (hapd->conf->ieee802_11f)
iapp_new_station(hapd->iapp, sta);
#ifdef CONFIG_P2P
if (sta->p2p_ie == NULL && !sta->no_p2p_set) {
sta->no_p2p_set = 1;
hapd->num_sta_no_p2p++;
if (hapd->num_sta_no_p2p == 1)
hostapd_p2p_non_p2p_sta_connected(hapd);
}
#endif /* CONFIG_P2P */
/* Start accounting here, if IEEE 802.1X and WPA are not used.
* IEEE 802.1X/WPA code will start accounting after the station has
* been authorized. */

View File

@ -27,9 +27,12 @@ struct sta_info;
struct hostap_sta_driver_data;
struct ieee80211_ht_capabilities;
struct full_dynamic_vlan;
enum wps_event;
union wps_event_data;
struct hostapd_probereq_cb {
int (*cb)(void *ctx, const u8 *sa, const u8 *ie, size_t ie_len);
int (*cb)(void *ctx, const u8 *sa, const u8 *da, const u8 *bssid,
const u8 *ie, size_t ie_len);
void *ctx;
};
@ -47,55 +50,6 @@ struct hostapd_frame_info {
};
struct hostapd_driver_ops {
int (*set_ap_wps_ie)(struct hostapd_data *hapd);
int (*send_mgmt_frame)(struct hostapd_data *hapd, const void *msg,
size_t len);
int (*send_eapol)(struct hostapd_data *hapd, const u8 *addr,
const u8 *data, size_t data_len, int encrypt);
int (*set_authorized)(struct hostapd_data *hapd, struct sta_info *sta,
int authorized);
int (*set_key)(const char *ifname, struct hostapd_data *hapd,
enum wpa_alg alg, const u8 *addr, int key_idx,
int set_tx, const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len);
int (*read_sta_data)(struct hostapd_data *hapd,
struct hostap_sta_driver_data *data,
const u8 *addr);
int (*sta_clear_stats)(struct hostapd_data *hapd, const u8 *addr);
int (*set_sta_flags)(struct hostapd_data *hapd, struct sta_info *sta);
int (*set_drv_ieee8021x)(struct hostapd_data *hapd, const char *ifname,
int enabled);
int (*set_radius_acl_auth)(struct hostapd_data *hapd,
const u8 *mac, int accepted,
u32 session_timeout);
int (*set_radius_acl_expire)(struct hostapd_data *hapd,
const u8 *mac);
int (*set_bss_params)(struct hostapd_data *hapd, int use_protection);
int (*set_beacon)(struct hostapd_data *hapd,
const u8 *head, size_t head_len,
const u8 *tail, size_t tail_len, int dtim_period,
int beacon_int);
int (*vlan_if_add)(struct hostapd_data *hapd, const char *ifname);
int (*vlan_if_remove)(struct hostapd_data *hapd, const char *ifname);
int (*set_wds_sta)(struct hostapd_data *hapd, const u8 *addr, int aid,
int val);
int (*set_sta_vlan)(const char *ifname, struct hostapd_data *hapd,
const u8 *addr, int vlan_id);
int (*get_inact_sec)(struct hostapd_data *hapd, const u8 *addr);
int (*sta_deauth)(struct hostapd_data *hapd, const u8 *addr,
int reason);
int (*sta_disassoc)(struct hostapd_data *hapd, const u8 *addr,
int reason);
int (*sta_add)(struct hostapd_data *hapd,
const u8 *addr, u16 aid, u16 capability,
const u8 *supp_rates, size_t supp_rates_len,
u16 listen_interval,
const struct ieee80211_ht_capabilities *ht_capab);
int (*sta_remove)(struct hostapd_data *hapd, const u8 *addr);
int (*set_countermeasures)(struct hostapd_data *hapd, int enabled);
};
/**
* struct hostapd_data - hostapd per-BSS data structure
*/
@ -123,12 +77,12 @@ struct hostapd_data {
const struct wpa_driver_ops *driver;
void *drv_priv;
struct hostapd_driver_ops drv;
void (*new_assoc_sta_cb)(struct hostapd_data *hapd,
struct sta_info *sta, int reassoc);
void *msg_ctx; /* ctx for wpa_msg() calls */
void *msg_ctx_parent; /* parent interface ctx for wpa_msg() calls */
struct radius_client_data *radius;
u32 acct_session_id_hi, acct_session_id_lo;
@ -155,6 +109,10 @@ struct hostapd_data {
int parameter_set_count;
/* Time Advertisement */
u8 time_update_counter;
struct wpabuf *time_adv;
#ifdef CONFIG_FULL_DYNAMIC_VLAN
struct full_dynamic_vlan *full_dynamic_vlan;
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
@ -162,10 +120,12 @@ struct hostapd_data {
struct l2_packet_data *l2;
struct wps_context *wps;
int beacon_set_done;
struct wpabuf *wps_beacon_ie;
struct wpabuf *wps_probe_resp_ie;
#ifdef CONFIG_WPS
unsigned int ap_pin_failures;
unsigned int ap_pin_failures_consecutive;
struct upnp_wps_device_sm *wps_upnp;
unsigned int ap_pin_lockout_time;
#endif /* CONFIG_WPS */
@ -177,9 +137,39 @@ struct hostapd_data {
int freq);
void *public_action_cb_ctx;
int (*vendor_action_cb)(void *ctx, const u8 *buf, size_t len,
int freq);
void *vendor_action_cb_ctx;
void (*wps_reg_success_cb)(void *ctx, const u8 *mac_addr,
const u8 *uuid_e);
void *wps_reg_success_cb_ctx;
void (*wps_event_cb)(void *ctx, enum wps_event event,
union wps_event_data *data);
void *wps_event_cb_ctx;
void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr,
int authorized, const u8 *p2p_dev_addr);
void *sta_authorized_cb_ctx;
void (*setup_complete_cb)(void *ctx);
void *setup_complete_cb_ctx;
#ifdef CONFIG_P2P
struct p2p_data *p2p;
struct p2p_group *p2p_group;
struct wpabuf *p2p_beacon_ie;
struct wpabuf *p2p_probe_resp_ie;
/* Number of non-P2P association stations */
int num_sta_no_p2p;
/* Periodic NoA (used only when no non-P2P clients in the group) */
int noa_enabled;
int noa_start;
int noa_duration;
#endif /* CONFIG_P2P */
};
@ -202,6 +192,7 @@ struct hostapd_iface {
struct ap_info *ap_hash[STA_HASH_SIZE];
struct ap_info *ap_iter_list;
unsigned int drv_flags;
struct hostapd_hw_modes *hw_features;
int num_hw_features;
struct hostapd_hw_modes *current_mode;
@ -264,13 +255,17 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
/* utils.c */
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
int (*cb)(void *ctx, const u8 *sa,
const u8 *da, const u8 *bssid,
const u8 *ie, size_t ie_len),
void *ctx);
void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
/* drv_callbacks.c (TODO: move to somewhere else?) */
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
const u8 *ie, size_t ielen);
const u8 *ie, size_t ielen, int reassoc);
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr);
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
const u8 *bssid, const u8 *ie, size_t ie_len);
#endif /* HOSTAPD_H */

View File

@ -101,8 +101,8 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
}
static int hostapd_prepare_rates(struct hostapd_data *hapd,
struct hostapd_hw_modes *mode)
int hostapd_prepare_rates(struct hostapd_data *hapd,
struct hostapd_hw_modes *mode)
{
int i, num_basic_rates = 0;
int basic_rates_a[] = { 60, 120, 240, -1 };
@ -162,7 +162,8 @@ static int hostapd_prepare_rates(struct hostapd_data *hapd,
hapd->iface->num_rates++;
}
if (hapd->iface->num_rates == 0 || num_basic_rates == 0) {
if ((hapd->iface->num_rates == 0 || num_basic_rates == 0) &&
(!hapd->iconf->ieee80211n || !hapd->iconf->require_ht)) {
wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
"rate sets (%d,%d).",
hapd->iface->num_rates, num_basic_rates);
@ -265,11 +266,11 @@ static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss,
oper = (struct ieee80211_ht_operation *) elems.ht_operation;
*pri_chan = oper->control_chan;
if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) {
if (oper->ht_param &
HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
int sec = oper->ht_param &
HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
*sec_chan = *pri_chan + 4;
else if (oper->ht_param &
HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
*sec_chan = *pri_chan - 4;
}
}
@ -406,24 +407,11 @@ static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface,
}
static void wpa_scan_results_free(struct wpa_scan_results *res)
{
size_t i;
if (res == NULL)
return;
for (i = 0; i < res->num; i++)
os_free(res->res[i]);
os_free(res->res);
os_free(res);
}
static void ieee80211n_check_scan(struct hostapd_iface *iface)
{
struct wpa_scan_results *scan_res;
int oper40;
int res;
/* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
* allowed per IEEE 802.11n/D7.0, 11.14.3.2 */
@ -452,7 +440,8 @@ static void ieee80211n_check_scan(struct hostapd_iface *iface)
iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
}
hostapd_setup_interface_complete(iface, 0);
res = ieee80211n_allowed_ht40_channel_pair(iface);
hostapd_setup_interface_complete(iface, !res);
}
@ -483,9 +472,6 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
u16 hw = iface->current_mode->ht_capab;
u16 conf = iface->conf->ht_capab;
if (!iface->conf->ieee80211n)
return 1;
if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) &&
!(hw & HT_CAP_INFO_LDPC_CODING_CAP)) {
wpa_printf(MSG_ERROR, "Driver does not support configured "
@ -585,13 +571,15 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
{
#ifdef CONFIG_IEEE80211N
int ret;
if (!iface->conf->ieee80211n)
return 0;
if (!ieee80211n_supported_ht_capab(iface))
return -1;
ret = ieee80211n_check_40mhz(iface);
if (ret)
return ret;
if (!ieee80211n_allowed_ht40_channel_pair(iface))
return -1;
if (!ieee80211n_supported_ht_capab(iface))
return -1;
#endif /* CONFIG_IEEE80211N */
return 0;
@ -601,7 +589,7 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
/**
* hostapd_select_hw_mode - Select the hardware mode
* @iface: Pointer to interface data.
* Returns: 0 on success, -1 on failure
* Returns: 0 on success, < 0 on failure
*
* Sets up the hardware mode, channel, rates, and passive scanning
* based on the configuration.
@ -628,18 +616,51 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"Hardware does not support configured mode "
"(%d)", (int) iface->conf->hw_mode);
return -1;
"(%d) (hw_mode in hostapd.conf)",
(int) iface->conf->hw_mode);
return -2;
}
ok = 0;
for (j = 0; j < iface->current_mode->num_channels; j++) {
struct hostapd_channel_data *chan =
&iface->current_mode->channels[j];
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
(chan->chan == iface->conf->channel)) {
ok = 1;
break;
if (chan->chan == iface->conf->channel) {
if (chan->flag & HOSTAPD_CHAN_DISABLED) {
wpa_printf(MSG_ERROR,
"channel [%i] (%i) is disabled for "
"use in AP mode, flags: 0x%x",
j, chan->chan, chan->flag);
} else {
ok = 1;
break;
}
}
}
if (ok && iface->conf->secondary_channel) {
int sec_ok = 0;
int sec_chan = iface->conf->channel +
iface->conf->secondary_channel * 4;
for (j = 0; j < iface->current_mode->num_channels; j++) {
struct hostapd_channel_data *chan =
&iface->current_mode->channels[j];
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
(chan->chan == sec_chan)) {
sec_ok = 1;
break;
}
}
if (!sec_ok) {
hostapd_logger(iface->bss[0], NULL,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"Configured HT40 secondary channel "
"(%d) not found from the channel list "
"of current mode (%d) %s",
sec_chan, iface->current_mode->mode,
hostapd_hw_mode_txt(
iface->current_mode->mode));
ok = 0;
}
}
if (iface->conf->channel == 0) {
@ -647,7 +668,7 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
* the channel automatically */
wpa_printf(MSG_ERROR, "Channel not configured "
"(hw_mode/channel in hostapd.conf)");
return -1;
return -3;
}
if (ok == 0 && iface->conf->channel != 0) {
hostapd_logger(iface->bss[0], NULL,
@ -665,15 +686,7 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"Hardware does not support configured channel");
return -1;
}
if (hostapd_prepare_rates(iface->bss[0], iface->current_mode)) {
wpa_printf(MSG_ERROR, "Failed to prepare rates table.");
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"Failed to prepare rates table.");
return -1;
return -4;
}
return 0;

View File

@ -25,6 +25,8 @@ const char * hostapd_hw_mode_txt(int mode);
int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
int hostapd_check_ht_capab(struct hostapd_iface *iface);
int hostapd_prepare_rates(struct hostapd_data *hapd,
struct hostapd_hw_modes *mode);
#else /* NEED_AP_MLME */
static inline void
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
@ -39,7 +41,7 @@ static inline int hostapd_get_hw_features(struct hostapd_iface *iface)
static inline int hostapd_select_hw_mode(struct hostapd_iface *iface)
{
return -1;
return -100;
}
static inline const char * hostapd_hw_mode_txt(int mode)
@ -57,6 +59,12 @@ static inline int hostapd_check_ht_capab(struct hostapd_iface *iface)
return 0;
}
static inline int hostapd_prepare_rates(struct hostapd_data *hapd,
struct hostapd_hw_modes *mode)
{
return 0;
}
#endif /* NEED_AP_MLME */
#endif /* HW_FEATURES_H */

View File

@ -1,6 +1,6 @@
/*
* hostapd / IEEE 802.11 Management
* Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2011, 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
@ -25,6 +25,7 @@
#include "common/wpa_ctrl.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
#include "p2p/p2p.h"
#include "wps/wps.h"
#include "hostapd.h"
#include "beacon.h"
@ -37,6 +38,8 @@
#include "accounting.h"
#include "ap_config.h"
#include "ap_mlme.h"
#include "p2p_hostapd.h"
#include "ap_drv_ops.h"
#include "ieee802_11.h"
@ -50,6 +53,8 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
*pos++ = WLAN_EID_SUPP_RATES;
num = hapd->iface->num_rates;
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
num++;
if (num > 8) {
/* rest of the rates are encoded in Extended supported
* rates element */
@ -67,6 +72,10 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
pos++;
}
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
hapd->iface->num_rates < 8)
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
return pos;
}
@ -80,6 +89,8 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
return eid;
num = hapd->iface->num_rates;
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
num++;
if (num <= 8)
return eid;
num -= 8;
@ -98,6 +109,10 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
pos++;
}
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
hapd->iface->num_rates >= 8)
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
return pos;
}
@ -148,34 +163,6 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
}
#ifdef CONFIG_IEEE80211W
static u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
struct sta_info *sta, u8 *eid)
{
u8 *pos = eid;
u32 timeout, tu;
struct os_time now, passed;
*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
*pos++ = 5;
*pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK;
os_get_time(&now);
os_time_sub(&now, &sta->sa_query_start, &passed);
tu = (passed.sec * 1000000 + passed.usec) / 1024;
if (hapd->conf->assoc_sa_query_max_timeout > tu)
timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
else
timeout = 0;
if (timeout < hapd->conf->assoc_sa_query_max_timeout)
timeout++; /* add some extra time for local timers */
WPA_PUT_LE32(pos, timeout);
pos += 4;
return pos;
}
#endif /* CONFIG_IEEE80211W */
void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len)
{
int i;
@ -204,15 +191,15 @@ static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
if (!sta->challenge) {
/* Generate a pseudo-random challenge */
u8 key[8];
time_t now;
struct os_time now;
int r;
sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN);
if (sta->challenge == NULL)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
now = time(NULL);
r = random();
os_memcpy(key, &now, 4);
os_get_time(&now);
r = os_random();
os_memcpy(key, &now.sec, 4);
os_memcpy(key + 4, &r, 4);
rc4_skip(key, sizeof(key), 0,
sta->challenge, WLAN_AUTH_CHALLENGE_LEN);
@ -282,7 +269,7 @@ static void send_auth_reply(struct hostapd_data *hapd,
" auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)",
MAC2STR(dst), auth_alg, auth_transaction,
resp, (unsigned long) ies_len);
if (hapd->drv.send_mgmt_frame(hapd, reply, rlen) < 0)
if (hostapd_drv_send_mlme(hapd, reply, rlen) < 0)
perror("send_auth_reply: send");
os_free(buf);
@ -553,7 +540,7 @@ static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
{
sta->flags &= ~WLAN_STA_WMM;
if (wmm_ie && hapd->conf->wmm_enabled) {
if (hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len))
if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len))
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_WPA,
HOSTAPD_LEVEL_DEBUG,
@ -635,10 +622,17 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
if (resp != WLAN_STATUS_SUCCESS)
return resp;
#ifdef CONFIG_IEEE80211N
resp = copy_sta_ht_capab(sta, elems.ht_capabilities,
resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities,
elems.ht_capabilities_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
!(sta->flags & WLAN_STA_HT)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "Station does not support "
"mandatory HT PHY - reject association");
return WLAN_STATUS_ASSOC_DENIED_NO_HT;
}
#endif /* CONFIG_IEEE80211N */
if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
@ -654,7 +648,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
}
#ifdef CONFIG_WPS
sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
if (hapd->conf->wps_state && elems.wps_ie) {
wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
"Request - assume WPS is used");
@ -662,8 +656,17 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
wpabuf_free(sta->wps_ie);
sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
WPS_IE_VENDOR_TYPE);
if (sta->wps_ie && wps_is_20(sta->wps_ie)) {
wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0");
sta->flags |= WLAN_STA_WPS2;
}
wpa_ie = NULL;
wpa_ie_len = 0;
if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) {
wpa_printf(MSG_DEBUG, "WPS: Invalid WPS IE in "
"(Re)Association Request - reject");
return WLAN_STATUS_INVALID_IE;
}
} else if (hapd->conf->wps_state && wpa_ie == NULL) {
wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in "
"(Re)Association Request - possible WPS use");
@ -768,6 +771,20 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
} else
wpa_auth_sta_no_wpa(sta->wpa_sm);
#ifdef CONFIG_P2P
if (elems.p2p) {
wpabuf_free(sta->p2p_ie);
sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
P2P_IE_VENDOR_TYPE);
} else {
wpabuf_free(sta->p2p_ie);
sta->p2p_ie = NULL;
}
p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len);
#endif /* CONFIG_P2P */
return WLAN_STATUS_SUCCESS;
}
@ -788,7 +805,7 @@ static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
reply.u.deauth.reason_code = host_to_le16(reason_code);
if (hapd->drv.send_mgmt_frame(hapd, &reply, send_len) < 0)
if (hostapd_drv_send_mlme(hapd, &reply, send_len) < 0)
wpa_printf(MSG_INFO, "Failed to send deauth: %s",
strerror(errno));
}
@ -845,11 +862,14 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
p = hostapd_eid_ht_operation(hapd, p);
#endif /* CONFIG_IEEE80211N */
p = hostapd_eid_ext_capab(hapd, p);
if (sta->flags & WLAN_STA_WMM)
p = hostapd_eid_wmm(hapd, p);
#ifdef CONFIG_WPS
if (sta->flags & WLAN_STA_WPS) {
if ((sta->flags & WLAN_STA_WPS) ||
((sta->flags & WLAN_STA_MAYBE_WPS) && hapd->conf->wpa)) {
struct wpabuf *wps = wps_build_assoc_resp_ie();
if (wps) {
os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps));
@ -859,9 +879,39 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
}
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
if (sta->p2p_ie) {
struct wpabuf *p2p_resp_ie;
enum p2p_status_code status;
switch (status_code) {
case WLAN_STATUS_SUCCESS:
status = P2P_SC_SUCCESS;
break;
case WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA:
status = P2P_SC_FAIL_LIMIT_REACHED;
break;
default:
status = P2P_SC_FAIL_INVALID_PARAMS;
break;
}
p2p_resp_ie = p2p_group_assoc_resp_ie(hapd->p2p_group, status);
if (p2p_resp_ie) {
os_memcpy(p, wpabuf_head(p2p_resp_ie),
wpabuf_len(p2p_resp_ie));
p += wpabuf_len(p2p_resp_ie);
wpabuf_free(p2p_resp_ie);
}
}
#endif /* CONFIG_P2P */
#ifdef CONFIG_P2P_MANAGER
if (hapd->conf->p2p & P2P_MANAGE)
p = hostapd_eid_p2p_manage(hapd, p);
#endif /* CONFIG_P2P_MANAGER */
send_len += p - reply->u.assoc_resp.variable;
if (hapd->drv.send_mgmt_frame(hapd, reply, send_len) < 0)
if (hostapd_drv_send_mlme(hapd, reply, send_len) < 0)
wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
strerror(errno));
}
@ -1005,6 +1055,7 @@ static void handle_assoc(struct hostapd_data *hapd,
"association OK (aid %d)", sta->aid);
/* Station will be marked associated, after it acknowledges AssocResp
*/
sta->flags |= WLAN_STA_ASSOC_REQ_OK;
#ifdef CONFIG_IEEE80211W
if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) {
@ -1061,9 +1112,8 @@ static void handle_disassoc(struct hostapd_data *hapd,
return;
}
sta->flags &= ~WLAN_STA_ASSOC;
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
MAC2STR(sta->addr));
ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "disassociated");
@ -1073,7 +1123,7 @@ static void handle_disassoc(struct hostapd_data *hapd,
* authenticated. */
accounting_sta_stop(hapd, sta);
ieee802_1x_free_station(sta);
hapd->drv.sta_remove(hapd, sta->addr);
hostapd_drv_sta_remove(hapd, sta->addr);
if (sta->timeout_next == STA_NULLFUNC ||
sta->timeout_next == STA_DISASSOC) {
@ -1094,26 +1144,26 @@ static void handle_deauth(struct hostapd_data *hapd,
struct sta_info *sta;
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) {
printf("handle_deauth - too short payload (len=%lu)\n",
(unsigned long) len);
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "handle_deauth - too short "
"payload (len=%lu)", (unsigned long) len);
return;
}
wpa_printf(MSG_DEBUG, "deauthentication: STA=" MACSTR
" reason_code=%d",
MAC2STR(mgmt->sa),
le_to_host16(mgmt->u.deauth.reason_code));
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "deauthentication: STA=" MACSTR
" reason_code=%d",
MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
sta = ap_get_sta(hapd, mgmt->sa);
if (sta == NULL) {
printf("Station " MACSTR " trying to deauthenticate, but it "
"is not authenticated.\n", MAC2STR(mgmt->sa));
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
"to deauthenticate, but it is not authenticated",
MAC2STR(mgmt->sa));
return;
}
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
MAC2STR(sta->addr));
ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
WLAN_STA_ASSOC_REQ_OK);
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "deauthenticated");
@ -1148,81 +1198,11 @@ static void handle_beacon(struct hostapd_data *hapd,
#ifdef CONFIG_IEEE80211W
/* MLME-SAQuery.request */
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
const u8 *addr, const u8 *trans_id)
{
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);
os_memcpy(mgmt.da, addr, ETH_ALEN);
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
mgmt.u.action.category = WLAN_ACTION_SA_QUERY;
mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id,
WLAN_SA_QUERY_TR_ID_LEN);
end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
if (hapd->drv.send_mgmt_frame(hapd, &mgmt, end - (u8 *) &mgmt) < 0)
perror("ieee802_11_send_sa_query_req: send");
}
static void hostapd_sa_query_request(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt)
{
struct sta_info *sta;
struct ieee80211_mgmt resp;
u8 *end;
wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request 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);
sta = ap_get_sta(hapd, mgmt->sa);
if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request "
"from unassociated STA " MACSTR, MAC2STR(mgmt->sa));
return;
}
wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to "
MACSTR, MAC2STR(mgmt->sa));
os_memset(&resp, 0, sizeof(resp));
resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_ACTION);
os_memcpy(resp.da, mgmt->sa, ETH_ALEN);
os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN);
resp.u.action.category = WLAN_ACTION_SA_QUERY;
resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE;
os_memcpy(resp.u.action.u.sa_query_req.trans_id,
mgmt->u.action.u.sa_query_req.trans_id,
WLAN_SA_QUERY_TR_ID_LEN);
end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
if (hapd->drv.send_mgmt_frame(hapd, &resp, end - (u8 *) &resp) < 0)
perror("hostapd_sa_query_request: send");
}
static void hostapd_sa_query_action(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt,
size_t len)
{
struct sta_info *sta;
const u8 *end;
int i;
end = mgmt->u.action.u.sa_query_resp.trans_id +
WLAN_SA_QUERY_TR_ID_LEN;
@ -1232,50 +1212,9 @@ static void hostapd_sa_query_action(struct hostapd_data *hapd,
return;
}
if (mgmt->u.action.u.sa_query_resp.action == WLAN_SA_QUERY_REQUEST) {
hostapd_sa_query_request(hapd, mgmt);
return;
}
if (mgmt->u.action.u.sa_query_resp.action != WLAN_SA_QUERY_RESPONSE) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query "
"Action %d", mgmt->u.action.u.sa_query_resp.action);
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);
if (sta == NULL || sta->sa_query_trans_id == NULL) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with "
"pending SA Query request found");
return;
}
for (i = 0; i < sta->sa_query_count; i++) {
if (os_memcmp(sta->sa_query_trans_id +
i * WLAN_SA_QUERY_TR_ID_LEN,
mgmt->u.action.u.sa_query_resp.trans_id,
WLAN_SA_QUERY_TR_ID_LEN) == 0)
break;
}
if (i >= sta->sa_query_count) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query "
"transaction identifier found");
return;
}
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"Reply to pending SA Query received");
ap_sta_stop_sa_query(hapd, sta);
ieee802_11_sa_query_action(hapd, mgmt->sa,
mgmt->u.action.u.sa_query_resp.action,
mgmt->u.action.u.sa_query_resp.trans_id);
}
@ -1290,7 +1229,10 @@ static int robust_action_frame(u8 category)
static void handle_action(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len)
{
#if defined(CONFIG_IEEE80211W) || defined(CONFIG_IEEE80211R)
struct sta_info *sta;
sta = ap_get_sta(hapd, mgmt->sa);
#endif /* CONFIG_IEEE80211W || CONFIG_IEEE80211R */
if (len < IEEE80211_HDRLEN + 1) {
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
@ -1300,7 +1242,6 @@ 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) &&
@ -1347,6 +1288,14 @@ static void handle_action(struct hostapd_data *hapd,
return;
}
break;
case WLAN_ACTION_VENDOR_SPECIFIC:
if (hapd->vendor_action_cb) {
if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx,
(u8 *) mgmt, len,
hapd->iface->freq) == 0)
return;
}
break;
}
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
@ -1374,7 +1323,7 @@ static void handle_action(struct hostapd_data *hapd,
os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
resp->u.action.category |= 0x80;
hapd->drv.send_mgmt_frame(hapd, resp, len);
hostapd_drv_send_mlme(hapd, resp, len);
os_free(resp);
}
}
@ -1400,6 +1349,9 @@ void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
int broadcast;
u16 fc, stype;
if (len < 24)
return;
mgmt = (struct ieee80211_mgmt *) buf;
fc = le_to_host16(mgmt->frame_control);
stype = WLAN_FC_GET_STYPE(fc);
@ -1414,6 +1366,11 @@ void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
mgmt->bssid[4] == 0xff && mgmt->bssid[5] == 0xff;
if (!broadcast &&
#ifdef CONFIG_P2P
/* Invitation responses can be sent with the peer MAC as BSSID */
!((hapd->conf->p2p & P2P_GROUP_OWNER) &&
stype == WLAN_FC_STYPE_ACTION) &&
#endif /* CONFIG_P2P */
os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) {
printf("MGMT: BSSID=" MACSTR " not our address\n",
MAC2STR(mgmt->bssid));
@ -1452,7 +1409,7 @@ void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
handle_disassoc(hapd, mgmt, len);
break;
case WLAN_FC_STYPE_DEAUTH:
wpa_printf(MSG_DEBUG, "mgmt::deauth");
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "mgmt::deauth");
handle_deauth(hapd, mgmt, len);
break;
case WLAN_FC_STYPE_ACTION:
@ -1565,9 +1522,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
* Open, static WEP, or FT protocol; no separate authorization
* step.
*/
sta->flags |= WLAN_STA_AUTHORIZED;
wpa_msg(hapd->msg_ctx, MSG_INFO,
AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
ap_sta_set_authorized(hapd, sta, 1);
}
if (reassoc)
@ -1584,22 +1539,31 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
* cleared and configuration gets updated in case of reassociation back
* to the same AP.
*/
hapd->drv.sta_remove(hapd, sta->addr);
hostapd_drv_sta_remove(hapd, sta->addr);
#ifdef CONFIG_IEEE80211N
if (sta->flags & WLAN_STA_HT)
hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
#endif /* CONFIG_IEEE80211N */
if (hapd->drv.sta_add(hapd, sta->addr, sta->aid, sta->capability,
sta->supported_rates, sta->supported_rates_len,
sta->listen_interval,
sta->flags & WLAN_STA_HT ? &ht_cap : NULL)) {
if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
sta->supported_rates, sta->supported_rates_len,
sta->listen_interval,
sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
sta->flags)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_NOTICE,
"Could not add STA to kernel driver");
ap_sta_disconnect(hapd, sta, sta->addr,
WLAN_REASON_DISASSOC_AP_BUSY);
goto fail;
}
if (sta->flags & WLAN_STA_WDS)
hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 1);
if (sta->eapol_sm == NULL) {
/*
* This STA does not use RADIUS server for EAP authentication,
@ -1614,7 +1578,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
goto fail;
}
hapd->drv.set_sta_flags(hapd, sta);
hostapd_set_sta_flags(hapd, sta);
if (sta->auth_alg == WLAN_AUTH_FT)
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
@ -1633,6 +1597,54 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
}
static void handle_deauth_cb(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt,
size_t len, int ok)
{
struct sta_info *sta;
if (mgmt->da[0] & 0x01)
return;
sta = ap_get_sta(hapd, mgmt->da);
if (!sta) {
wpa_printf(MSG_DEBUG, "handle_deauth_cb: STA " MACSTR
" not found", MAC2STR(mgmt->da));
return;
}
if (ok)
wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged deauth",
MAC2STR(sta->addr));
else
wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
"deauth", MAC2STR(sta->addr));
ap_sta_deauth_cb(hapd, sta);
}
static void handle_disassoc_cb(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt,
size_t len, int ok)
{
struct sta_info *sta;
if (mgmt->da[0] & 0x01)
return;
sta = ap_get_sta(hapd, mgmt->da);
if (!sta) {
wpa_printf(MSG_DEBUG, "handle_disassoc_cb: STA " MACSTR
" not found", MAC2STR(mgmt->da));
return;
}
if (ok)
wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged disassoc",
MAC2STR(sta->addr));
else
wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
"disassoc", MAC2STR(sta->addr));
ap_sta_disassoc_cb(hapd, sta);
}
/**
* ieee802_11_mgmt_cb - Process management frame TX status callback
* @hapd: hostapd BSS data structure (the BSS from which the management frame
@ -1662,10 +1674,15 @@ void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
handle_assoc_cb(hapd, mgmt, len, 1, ok);
break;
case WLAN_FC_STYPE_PROBE_RESP:
wpa_printf(MSG_DEBUG, "mgmt::proberesp cb");
wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb");
break;
case WLAN_FC_STYPE_DEAUTH:
/* ignore */
wpa_printf(MSG_DEBUG, "mgmt::deauth cb");
handle_deauth_cb(hapd, mgmt, len, ok);
break;
case WLAN_FC_STYPE_DISASSOC:
wpa_printf(MSG_DEBUG, "mgmt::disassoc cb");
handle_disassoc_cb(hapd, mgmt, len, ok);
break;
case WLAN_FC_STYPE_ACTION:
wpa_printf(MSG_DEBUG, "mgmt::action cb");
@ -1708,7 +1725,7 @@ void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
break;
}
}
if (sta == NULL)
if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))
return;
if (sta->flags & WLAN_STA_PENDING_POLL) {
wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending "
@ -1722,6 +1739,32 @@ void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
}
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr)
{
struct sta_info *sta;
struct hostapd_iface *iface = hapd->iface;
sta = ap_get_sta(hapd, addr);
if (sta == NULL && iface->num_bss > 1) {
size_t j;
for (j = 0; j < iface->num_bss; j++) {
hapd = iface->bss[j];
sta = ap_get_sta(hapd, addr);
if (sta)
break;
}
}
if (sta == NULL)
return;
if (!(sta->flags & WLAN_STA_PENDING_POLL))
return;
wpa_printf(MSG_DEBUG, "STA " MACSTR " ACKed pending "
"activity poll", MAC2STR(sta->addr));
sta->flags &= ~WLAN_STA_PENDING_POLL;
}
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
int wds)
{
@ -1734,19 +1777,32 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
"STA " MACSTR " (aid %u)",
MAC2STR(sta->addr), sta->aid);
sta->flags |= WLAN_STA_WDS;
hapd->drv.set_wds_sta(hapd, sta->addr, sta->aid, 1);
hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 1);
}
return;
}
wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
MACSTR, MAC2STR(src));
if (src[0] & 0x01) {
/* Broadcast bit set in SA?! Ignore the frame silently. */
return;
}
if (sta && (sta->flags & WLAN_STA_ASSOC_REQ_OK)) {
wpa_printf(MSG_DEBUG, "Association Response to the STA has "
"already been sent, but no TX status yet known - "
"ignore Class 3 frame issue with " MACSTR,
MAC2STR(src));
return;
}
if (sta && (sta->flags & WLAN_STA_AUTH))
hapd->drv.sta_disassoc(
hostapd_drv_sta_disassoc(
hapd, src,
WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
else
hapd->drv.sta_deauth(
hostapd_drv_sta_deauth(
hapd, src,
WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
}

View File

@ -46,6 +46,7 @@ static inline int ieee802_11_get_mib_sta(struct hostapd_data *hapd,
#endif /* NEED_AP_MLME */
u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
int probe);
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
@ -56,12 +57,24 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
void hostapd_get_ht_capab(struct hostapd_data *hapd,
struct ieee80211_ht_capabilities *ht_cap,
struct ieee80211_ht_capabilities *neg_ht_cap);
u16 copy_sta_ht_capab(struct sta_info *sta, const u8 *ht_capab,
size_t ht_capab_len);
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ht_capab, size_t ht_capab_len);
void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta);
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
const u8 *buf, size_t len, int ack);
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
int wds);
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
struct sta_info *sta, u8 *eid);
void ieee802_11_sa_query_action(struct hostapd_data *hapd,
const u8 *sa, const u8 action_type,
const u8 *trans_id);
u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid);
int hostapd_update_time_adv(struct hostapd_data *hapd);
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);
#endif /* IEEE802_11_H */

View File

@ -25,6 +25,7 @@
#include "radius/radius_client.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
#include "ieee802_11.h"
#include "ieee802_11_auth.h"
@ -32,7 +33,7 @@
struct hostapd_cached_radius_acl {
time_t timestamp;
os_time_t timestamp;
macaddr addr;
int accepted; /* HOSTAPD_ACL_* */
struct hostapd_cached_radius_acl *next;
@ -43,7 +44,7 @@ struct hostapd_cached_radius_acl {
struct hostapd_acl_query_data {
time_t timestamp;
os_time_t timestamp;
u8 radius_id;
macaddr addr;
u8 *auth_msg; /* IEEE 802.11 authentication frame from station */
@ -70,14 +71,14 @@ static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
u32 *acct_interim_interval, int *vlan_id)
{
struct hostapd_cached_radius_acl *entry;
time_t now;
struct os_time now;
time(&now);
os_get_time(&now);
entry = hapd->acl_cache;
while (entry) {
if (os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
if (now - entry->timestamp > RADIUS_ACL_TIMEOUT)
if (now.sec - entry->timestamp > RADIUS_ACL_TIMEOUT)
return -1; /* entry has expired */
if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
if (session_timeout)
@ -190,7 +191,8 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
goto fail;
}
radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr);
if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr) < 0)
goto fail;
return 0;
fail:
@ -240,6 +242,7 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
return HOSTAPD_ACL_REJECT;
#else /* CONFIG_NO_RADIUS */
struct hostapd_acl_query_data *query;
struct os_time t;
/* Check whether ACL cache has an entry for this station */
int res = hostapd_acl_cache_get(hapd, addr, session_timeout,
@ -270,7 +273,8 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
wpa_printf(MSG_ERROR, "malloc for query data failed");
return HOSTAPD_ACL_REJECT;
}
time(&query->timestamp);
os_get_time(&t);
query->timestamp = t.sec;
os_memcpy(query->addr, addr, ETH_ALEN);
if (hostapd_radius_acl_query(hapd, addr, query)) {
wpa_printf(MSG_DEBUG, "Failed to send Access-Request "
@ -302,7 +306,7 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
#ifndef CONFIG_NO_RADIUS
static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now)
static void hostapd_acl_expire_cache(struct hostapd_data *hapd, os_time_t now)
{
struct hostapd_cached_radius_acl *prev, *entry, *tmp;
@ -317,9 +321,7 @@ static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now)
prev->next = entry->next;
else
hapd->acl_cache = entry->next;
#ifdef CONFIG_DRIVER_RADIUS_ACL
hapd->drv.set_radius_acl_expire(hapd, entry->addr);
#endif /* CONFIG_DRIVER_RADIUS_ACL */
hostapd_drv_set_radius_acl_expire(hapd, entry->addr);
tmp = entry;
entry = entry->next;
os_free(tmp);
@ -332,7 +334,8 @@ static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now)
}
static void hostapd_acl_expire_queries(struct hostapd_data *hapd, time_t now)
static void hostapd_acl_expire_queries(struct hostapd_data *hapd,
os_time_t now)
{
struct hostapd_acl_query_data *prev, *entry, *tmp;
@ -368,11 +371,11 @@ static void hostapd_acl_expire_queries(struct hostapd_data *hapd, time_t now)
static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx)
{
struct hostapd_data *hapd = eloop_ctx;
time_t now;
struct os_time now;
time(&now);
hostapd_acl_expire_cache(hapd, now);
hostapd_acl_expire_queries(hapd, now);
os_get_time(&now);
hostapd_acl_expire_cache(hapd, now.sec);
hostapd_acl_expire_queries(hapd, now.sec);
eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
}
@ -397,6 +400,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
struct hostapd_acl_query_data *query, *prev;
struct hostapd_cached_radius_acl *cache;
struct radius_hdr *hdr = radius_msg_get_hdr(msg);
struct os_time t;
query = hapd->acl_queries;
prev = NULL;
@ -431,7 +435,8 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry");
goto done;
}
time(&cache->timestamp);
os_get_time(&t);
cache->timestamp = t.sec;
os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
@ -458,8 +463,8 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
hapd->acl_cache = cache;
#ifdef CONFIG_DRIVER_RADIUS_ACL
hapd->drv.set_radius_acl_auth(hapd, query->addr, cache->accepted,
cache->session_timeout);
hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
cache->session_timeout);
#else /* CONFIG_DRIVER_RADIUS_ACL */
#ifdef NEED_AP_MLME
/* Re-send original authentication frame for 802.11 processing */

View File

@ -30,7 +30,8 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
struct ieee80211_ht_capabilities *cap;
u8 *pos = eid;
if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode)
if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode ||
hapd->conf->disable_11n)
return eid;
*pos++ = WLAN_EID_HT_CAP;
@ -58,7 +59,7 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
struct ieee80211_ht_operation *oper;
u8 *pos = eid;
if (!hapd->iconf->ieee80211n)
if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
return eid;
*pos++ = WLAN_EID_HT_OPERATION;
@ -92,7 +93,6 @@ Set to 1 (HT non-member protection) if there may be non-HT STAs
Set to 2 if only HT STAs are associated in BSS,
however and at least one 20 MHz HT STA is associated
Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
(currently non-GF HT station is considered as non-HT STA also)
*/
int hostapd_ht_operation_update(struct hostapd_iface *iface)
{
@ -130,13 +130,8 @@ int hostapd_ht_operation_update(struct hostapd_iface *iface)
op_mode_changes++;
}
/* Note: currently we switch to the MIXED op mode if HT non-greenfield
* station is associated. Probably it's a theoretical case, since
* it looks like all known HT STAs support greenfield.
*/
new_op_mode = 0;
if (iface->num_sta_no_ht ||
(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
if (iface->num_sta_no_ht)
new_op_mode = OP_MODE_MIXED;
else if ((iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
&& iface->num_sta_ht_20mhz)
@ -160,11 +155,13 @@ int hostapd_ht_operation_update(struct hostapd_iface *iface)
}
u16 copy_sta_ht_capab(struct sta_info *sta, const u8 *ht_capab,
size_t ht_capab_len)
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ht_capab, size_t ht_capab_len)
{
/* Disable HT caps for STAs associated to no-HT BSSes. */
if (!ht_capab ||
ht_capab_len < sizeof(struct ieee80211_ht_capabilities)) {
ht_capab_len < sizeof(struct ieee80211_ht_capabilities) ||
hapd->conf->disable_11n) {
sta->flags &= ~WLAN_STA_HT;
os_free(sta->ht_capabilities);
sta->ht_capabilities = NULL;
@ -253,8 +250,14 @@ void hostapd_get_ht_capab(struct hostapd_data *hapd,
return;
os_memcpy(neg_ht_cap, ht_cap, sizeof(*neg_ht_cap));
cap = le_to_host16(neg_ht_cap->ht_capabilities_info);
cap &= hapd->iconf->ht_capab;
cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED);
/*
* Mask out HT features we don't support, but don't overwrite
* non-symmetric features like STBC and SMPS. Just because
* we're not in dynamic SMPS mode the STA might still be.
*/
cap &= (hapd->iconf->ht_capab | HT_CAP_INFO_RX_STBC_MASK |
HT_CAP_INFO_TX_STBC | HT_CAP_INFO_SMPS_MASK);
/*
* STBC needs to be handled specially

View File

@ -0,0 +1,405 @@
/*
* hostapd / IEEE 802.11 Management
* Copyright (c) 2002-2010, 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 "utils/includes.h"
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
#include "hostapd.h"
#include "sta_info.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
#include "ieee802_11.h"
#ifdef CONFIG_IEEE80211W
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
struct sta_info *sta, u8 *eid)
{
u8 *pos = eid;
u32 timeout, tu;
struct os_time now, passed;
*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
*pos++ = 5;
*pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK;
os_get_time(&now);
os_time_sub(&now, &sta->sa_query_start, &passed);
tu = (passed.sec * 1000000 + passed.usec) / 1024;
if (hapd->conf->assoc_sa_query_max_timeout > tu)
timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
else
timeout = 0;
if (timeout < hapd->conf->assoc_sa_query_max_timeout)
timeout++; /* add some extra time for local timers */
WPA_PUT_LE32(pos, timeout);
pos += 4;
return pos;
}
/* MLME-SAQuery.request */
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
const u8 *addr, const u8 *trans_id)
{
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);
os_memcpy(mgmt.da, addr, ETH_ALEN);
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
mgmt.u.action.category = WLAN_ACTION_SA_QUERY;
mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id,
WLAN_SA_QUERY_TR_ID_LEN);
end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt) < 0)
perror("ieee802_11_send_sa_query_req: send");
}
void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
const u8 *sa, const u8 *trans_id)
{
struct sta_info *sta;
struct ieee80211_mgmt resp;
u8 *end;
wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from "
MACSTR, MAC2STR(sa));
wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
trans_id, WLAN_SA_QUERY_TR_ID_LEN);
sta = ap_get_sta(hapd, sa);
if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request "
"from unassociated STA " MACSTR, MAC2STR(sa));
return;
}
wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to "
MACSTR, MAC2STR(sa));
os_memset(&resp, 0, sizeof(resp));
resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_ACTION);
os_memcpy(resp.da, sa, ETH_ALEN);
os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN);
os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN);
resp.u.action.category = WLAN_ACTION_SA_QUERY;
resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE;
os_memcpy(resp.u.action.u.sa_query_req.trans_id, trans_id,
WLAN_SA_QUERY_TR_ID_LEN);
end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp) < 0)
perror("ieee80211_mgmt_sa_query_request: send");
}
void ieee802_11_sa_query_action(struct hostapd_data *hapd, const u8 *sa,
const u8 action_type, const u8 *trans_id)
{
struct sta_info *sta;
int i;
if (action_type == WLAN_SA_QUERY_REQUEST) {
ieee802_11_send_sa_query_resp(hapd, sa, trans_id);
return;
}
if (action_type != WLAN_SA_QUERY_RESPONSE) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query "
"Action %d", action_type);
return;
}
wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from "
MACSTR, MAC2STR(sa));
wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
trans_id, WLAN_SA_QUERY_TR_ID_LEN);
/* MLME-SAQuery.confirm */
sta = ap_get_sta(hapd, sa);
if (sta == NULL || sta->sa_query_trans_id == NULL) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with "
"pending SA Query request found");
return;
}
for (i = 0; i < sta->sa_query_count; i++) {
if (os_memcmp(sta->sa_query_trans_id +
i * WLAN_SA_QUERY_TR_ID_LEN,
trans_id, WLAN_SA_QUERY_TR_ID_LEN) == 0)
break;
}
if (i >= sta->sa_query_count) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query "
"transaction identifier found");
return;
}
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"Reply to pending SA Query received");
ap_sta_stop_sa_query(hapd, sta);
}
#endif /* CONFIG_IEEE80211W */
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
{
u8 *pos = eid;
u8 len = 0;
if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH))
len = 5;
if (len < 4 && hapd->conf->interworking)
len = 4;
if (len == 0)
return eid;
*pos++ = WLAN_EID_EXT_CAPAB;
*pos++ = len;
*pos++ = 0x00;
*pos++ = 0x00;
*pos++ = 0x00;
*pos = 0x00;
if (hapd->conf->time_advertisement == 2)
*pos |= 0x08; /* Bit 27 - UTC TSF Offset */
if (hapd->conf->interworking)
*pos |= 0x80; /* Bit 31 - Interworking */
pos++;
if (len < 5)
return pos;
*pos = 0x00;
if (hapd->conf->tdls & TDLS_PROHIBIT)
*pos |= 0x40; /* Bit 38 - TDLS Prohibited */
if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH)
*pos |= 0x80; /* Bit 39 - TDLS Channel Switching Prohibited */
pos++;
return pos;
}
u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid)
{
u8 *pos = eid;
#ifdef CONFIG_INTERWORKING
u8 *len;
if (!hapd->conf->interworking)
return eid;
*pos++ = WLAN_EID_INTERWORKING;
len = pos++;
*pos = hapd->conf->access_network_type;
if (hapd->conf->internet)
*pos |= INTERWORKING_ANO_INTERNET;
if (hapd->conf->asra)
*pos |= INTERWORKING_ANO_ASRA;
if (hapd->conf->esr)
*pos |= INTERWORKING_ANO_ESR;
if (hapd->conf->uesa)
*pos |= INTERWORKING_ANO_UESA;
pos++;
if (hapd->conf->venue_info_set) {
*pos++ = hapd->conf->venue_group;
*pos++ = hapd->conf->venue_type;
}
if (!is_zero_ether_addr(hapd->conf->hessid)) {
os_memcpy(pos, hapd->conf->hessid, ETH_ALEN);
pos += ETH_ALEN;
}
*len = pos - len - 1;
#endif /* CONFIG_INTERWORKING */
return pos;
}
u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid)
{
u8 *pos = eid;
#ifdef CONFIG_INTERWORKING
/* TODO: Separate configuration for ANQP? */
if (!hapd->conf->interworking)
return eid;
*pos++ = WLAN_EID_ADV_PROTO;
*pos++ = 2;
*pos++ = 0x7F; /* Query Response Length Limit | PAME-BI */
*pos++ = ACCESS_NETWORK_QUERY_PROTOCOL;
#endif /* CONFIG_INTERWORKING */
return pos;
}
u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid)
{
u8 *pos = eid;
#ifdef CONFIG_INTERWORKING
u8 *len;
unsigned int i, count;
if (!hapd->conf->interworking ||
hapd->conf->roaming_consortium == NULL ||
hapd->conf->roaming_consortium_count == 0)
return eid;
*pos++ = WLAN_EID_ROAMING_CONSORTIUM;
len = pos++;
/* Number of ANQP OIs (in addition to the max 3 listed here) */
if (hapd->conf->roaming_consortium_count > 3 + 255)
*pos++ = 255;
else if (hapd->conf->roaming_consortium_count > 3)
*pos++ = hapd->conf->roaming_consortium_count - 3;
else
*pos++ = 0;
/* OU #1 and #2 Lengths */
*pos = hapd->conf->roaming_consortium[0].len;
if (hapd->conf->roaming_consortium_count > 1)
*pos |= hapd->conf->roaming_consortium[1].len << 4;
pos++;
if (hapd->conf->roaming_consortium_count > 3)
count = 3;
else
count = hapd->conf->roaming_consortium_count;
for (i = 0; i < count; i++) {
os_memcpy(pos, hapd->conf->roaming_consortium[i].oi,
hapd->conf->roaming_consortium[i].len);
pos += hapd->conf->roaming_consortium[i].len;
}
*len = pos - len - 1;
#endif /* CONFIG_INTERWORKING */
return pos;
}
u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid)
{
if (hapd->conf->time_advertisement != 2)
return eid;
if (hapd->time_adv == NULL &&
hostapd_update_time_adv(hapd) < 0)
return eid;
if (hapd->time_adv == NULL)
return eid;
os_memcpy(eid, wpabuf_head(hapd->time_adv),
wpabuf_len(hapd->time_adv));
eid += wpabuf_len(hapd->time_adv);
return eid;
}
u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid)
{
size_t len;
if (hapd->conf->time_advertisement != 2)
return eid;
len = os_strlen(hapd->conf->time_zone);
*eid++ = WLAN_EID_TIME_ZONE;
*eid++ = len;
os_memcpy(eid, hapd->conf->time_zone, len);
eid += len;
return eid;
}
int hostapd_update_time_adv(struct hostapd_data *hapd)
{
const int elen = 2 + 1 + 10 + 5 + 1;
struct os_time t;
struct os_tm tm;
u8 *pos;
if (hapd->conf->time_advertisement != 2)
return 0;
if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0)
return -1;
if (!hapd->time_adv) {
hapd->time_adv = wpabuf_alloc(elen);
if (hapd->time_adv == NULL)
return -1;
pos = wpabuf_put(hapd->time_adv, elen);
} else
pos = wpabuf_mhead_u8(hapd->time_adv);
*pos++ = WLAN_EID_TIME_ADVERTISEMENT;
*pos++ = 1 + 10 + 5 + 1;
*pos++ = 2; /* UTC time at which the TSF timer is 0 */
/* Time Value at TSF 0 */
/* FIX: need to calculate this based on the current TSF value */
WPA_PUT_LE16(pos, tm.year); /* Year */
pos += 2;
*pos++ = tm.month; /* Month */
*pos++ = tm.day; /* Day of month */
*pos++ = tm.hour; /* Hours */
*pos++ = tm.min; /* Minutes */
*pos++ = tm.sec; /* Seconds */
WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */
pos += 2;
*pos++ = 0; /* Reserved */
/* Time Error */
/* TODO: fill in an estimate on the error */
*pos++ = 0;
*pos++ = 0;
*pos++ = 0;
*pos++ = 0;
*pos++ = 0;
*pos++ = hapd->time_update_counter++;
return 0;
}

View File

@ -1,6 +1,6 @@
/*
* hostapd / IEEE 802.1X-2004 Authenticator
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2012, 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
@ -18,6 +18,7 @@
#include "utils/eloop.h"
#include "crypto/md5.h"
#include "crypto/crypto.h"
#include "crypto/random.h"
#include "common/ieee802_11_defs.h"
#include "common/wpa_ctrl.h"
#include "radius/radius.h"
@ -26,6 +27,7 @@
#include "eap_common/eap_wsc_common.h"
#include "eapol_auth/eapol_auth_sm.h"
#include "eapol_auth/eapol_auth_sm_i.h"
#include "p2p/p2p.h"
#include "hostapd.h"
#include "accounting.h"
#include "sta_info.h"
@ -33,6 +35,7 @@
#include "preauth_auth.h"
#include "pmksa_cache_auth.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
#include "ieee802_1x.h"
@ -70,7 +73,8 @@ static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
if (sta->flags & WLAN_STA_PREAUTH) {
rsn_preauth_send(hapd, sta, buf, len);
} else {
hapd->drv.send_eapol(hapd, sta->addr, buf, len, encrypt);
hostapd_drv_hapd_send_eapol(hapd, sta->addr, buf, len,
encrypt, sta->flags);
}
os_free(buf);
@ -86,21 +90,13 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
return;
if (authorized) {
if (!(sta->flags & WLAN_STA_AUTHORIZED))
wpa_msg(hapd->msg_ctx, MSG_INFO,
AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
sta->flags |= WLAN_STA_AUTHORIZED;
res = hapd->drv.set_authorized(hapd, sta, 1);
ap_sta_set_authorized(hapd, sta, 1);
res = hostapd_set_authorized(hapd, sta, 1);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "authorizing port");
} else {
if ((sta->flags & (WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC)) ==
(WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC))
wpa_msg(hapd->msg_ctx, MSG_INFO,
AP_STA_DISCONNECTED MACSTR,
MAC2STR(sta->addr));
sta->flags &= ~WLAN_STA_AUTHORIZED;
res = hapd->drv.set_authorized(hapd, sta, 0);
ap_sta_set_authorized(hapd, sta, 0);
res = hostapd_set_authorized(hapd, sta, 0);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "unauthorizing port");
}
@ -140,7 +136,7 @@ static void ieee802_1x_tx_key_one(struct hostapd_data *hapd,
key->key_length = htons(key_len);
wpa_get_ntp_timestamp(key->replay_counter);
if (os_get_random(key->key_iv, sizeof(key->key_iv))) {
if (random_get_bytes(key->key_iv, sizeof(key->key_iv))) {
wpa_printf(MSG_ERROR, "Could not get random numbers");
os_free(buf);
return;
@ -215,7 +211,7 @@ ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname)
if (!key->key[key->idx])
key->key[key->idx] = os_malloc(key->default_len);
if (key->key[key->idx] == NULL ||
os_get_random(key->key[key->idx], key->default_len)) {
random_get_bytes(key->key[key->idx], key->default_len)) {
printf("Could not generate random WEP key (dynamic VLAN).\n");
os_free(key->key[key->idx]);
key->key[key->idx] = NULL;
@ -229,11 +225,13 @@ ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname)
wpa_hexdump_key(MSG_DEBUG, "Default WEP key (dynamic VLAN)",
key->key[key->idx], key->len[key->idx]);
if (hapd->drv.set_key(ifname, hapd, WPA_ALG_WEP, NULL, key->idx, 1,
NULL, 0, key->key[key->idx], key->len[key->idx]))
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_WEP,
broadcast_ether_addr, key->idx, 1,
NULL, 0, key->key[key->idx],
key->len[key->idx]))
printf("Could not set dynamic VLAN WEP encryption key.\n");
hapd->drv.set_drv_ieee8021x(hapd, ifname, 1);
hostapd_set_drv_ieee8021x(hapd, ifname, 1);
return key;
}
@ -330,7 +328,8 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
u8 *ikey;
ikey = os_malloc(hapd->conf->individual_wep_key_len);
if (ikey == NULL ||
os_get_random(ikey, hapd->conf->individual_wep_key_len)) {
random_get_bytes(ikey, hapd->conf->individual_wep_key_len))
{
wpa_printf(MSG_ERROR, "Could not generate random "
"individual WEP key.");
os_free(ikey);
@ -345,9 +344,9 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
/* TODO: set encryption in TX callback, i.e., only after STA
* has ACKed EAPOL-Key frame */
if (hapd->drv.set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
sta->addr, 0, 1, NULL, 0, ikey,
hapd->conf->individual_wep_key_len)) {
if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
sta->addr, 0, 1, NULL, 0, ikey,
hapd->conf->individual_wep_key_len)) {
wpa_printf(MSG_ERROR, "Could not set individual WEP "
"encryption.");
}
@ -549,7 +548,9 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
}
}
radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr);
if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr) < 0)
goto fail;
return;
fail:
@ -652,7 +653,7 @@ ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta)
flags |= EAPOL_SM_FROM_PMKSA_CACHE;
}
return eapol_auth_alloc(hapd->eapol_auth, sta->addr, flags,
sta->wps_ie, sta);
sta->wps_ie, sta->p2p_ie, sta);
}
@ -673,6 +674,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
struct ieee802_1x_eapol_key *key;
u16 datalen;
struct rsn_pmksa_cache_entry *pmksa;
int key_mgmt;
if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
!hapd->conf->wps_state)
@ -681,9 +683,10 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR,
(unsigned long) len, MAC2STR(sa));
sta = ap_get_sta(hapd, sa);
if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
if (!sta || (!(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH)) &&
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) {
wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not "
"associated STA");
"associated/Pre-authenticating STA");
return;
}
@ -724,10 +727,19 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
return;
}
if ((!hapd->conf->ieee802_1x &&
!(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) ||
wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm)))
if (!hapd->conf->ieee802_1x &&
!(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - "
"802.1X not enabled and WPS not used");
return;
}
key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm);
if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) {
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - "
"STA is using PSK");
return;
}
if (!sta->eapol_sm) {
sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta);
@ -735,14 +747,24 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
return;
#ifdef CONFIG_WPS
if (!hapd->conf->ieee802_1x &&
((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) ==
WLAN_STA_MAYBE_WPS)) {
/*
* Delay EAPOL frame transmission until a possible WPS
* STA initiates the handshake with EAPOL-Start.
*/
sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
if (!hapd->conf->ieee802_1x) {
u32 wflags = sta->flags & (WLAN_STA_WPS |
WLAN_STA_WPS2 |
WLAN_STA_MAYBE_WPS);
if (wflags == WLAN_STA_MAYBE_WPS ||
wflags == (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) {
/*
* Delay EAPOL frame transmission until a
* possible WPS STA initiates the handshake
* with EAPOL-Start. Only allow the wait to be
* skipped if the STA is known to support WPS
* 2.0.
*/
wpa_printf(MSG_DEBUG, "WPS: Do not start "
"EAPOL until EAPOL-Start is "
"received");
sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
}
}
#endif /* CONFIG_WPS */
@ -776,6 +798,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
}
sta->eapol_sm->eapolStart = TRUE;
sta->eapol_sm->dot1xAuthEapolStartFramesRx++;
eap_server_clear_identity(sta->eapol_sm->eap);
wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL);
break;
@ -788,11 +811,12 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
accounting_sta_stop(hapd, sta);
sta->eapol_sm->eapolLogoff = TRUE;
sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++;
eap_server_clear_identity(sta->eapol_sm->eap);
break;
case IEEE802_1X_TYPE_EAPOL_KEY:
wpa_printf(MSG_DEBUG, " EAPOL-Key");
if (!(sta->flags & WLAN_STA_AUTHORIZED)) {
if (!ap_sta_is_authorized(sta)) {
wpa_printf(MSG_DEBUG, " Dropped key data from "
"unauthorized Supplicant");
break;
@ -827,6 +851,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
struct rsn_pmksa_cache_entry *pmksa;
int reassoc = 1;
int force_1x = 0;
int key_mgmt;
#ifdef CONFIG_WPS
if (hapd->conf->wps_state && hapd->conf->wpa &&
@ -840,9 +865,27 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
}
#endif /* CONFIG_WPS */
if ((!force_1x && !hapd->conf->ieee802_1x) ||
wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm)))
if (!force_1x && !hapd->conf->ieee802_1x) {
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - "
"802.1X not enabled or forced for WPS");
/*
* Clear any possible EAPOL authenticator state to support
* reassociation change from WPS to PSK.
*/
ieee802_1x_free_station(sta);
return;
}
key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm);
if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) {
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - using PSK");
/*
* Clear any possible EAPOL authenticator state to support
* reassociation change from WPA-EAP to PSK.
*/
ieee802_1x_free_station(sta);
return;
}
if (sta->eapol_sm == NULL) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
@ -860,17 +903,40 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
#ifdef CONFIG_WPS
sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS)) {
if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS2)) {
/*
* Delay EAPOL frame transmission until a possible WPS
* initiates the handshake with EAPOL-Start.
* Delay EAPOL frame transmission until a possible WPS STA
* initiates the handshake with EAPOL-Start. Only allow the
* wait to be skipped if the STA is known to support WPS 2.0.
*/
wpa_printf(MSG_DEBUG, "WPS: Do not start EAPOL until "
"EAPOL-Start is received");
sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
}
#endif /* CONFIG_WPS */
sta->eapol_sm->eap_if->portEnabled = TRUE;
#ifdef CONFIG_IEEE80211R
if (sta->auth_alg == WLAN_AUTH_FT) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG,
"PMK from FT - skip IEEE 802.1X/EAP");
/* Setup EAPOL state machines to already authenticated state
* because of existing FT information from R0KH. */
sta->eapol_sm->keyRun = TRUE;
sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
sta->eapol_sm->authSuccess = TRUE;
sta->eapol_sm->authFail = FALSE;
if (sta->eapol_sm->eap)
eap_sm_notify_cached(sta->eapol_sm->eap);
/* TODO: get vlan_id from R0KH using RRB message */
return;
}
#endif /* CONFIG_IEEE80211R */
pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
if (pmksa) {
int old_vlanid;
@ -885,6 +951,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
sta->eapol_sm->authSuccess = TRUE;
sta->eapol_sm->authFail = FALSE;
if (sta->eapol_sm->eap)
eap_sm_notify_cached(sta->eapol_sm->eap);
old_vlanid = sta->vlan_id;
@ -1380,8 +1447,8 @@ static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd)
os_free(eapol->default_wep_key);
eapol->default_wep_key = os_malloc(hapd->conf->default_wep_key_len);
if (eapol->default_wep_key == NULL ||
os_get_random(eapol->default_wep_key,
hapd->conf->default_wep_key_len)) {
random_get_bytes(eapol->default_wep_key,
hapd->conf->default_wep_key_len)) {
printf("Could not generate random WEP key.\n");
os_free(eapol->default_wep_key);
eapol->default_wep_key = NULL;
@ -1432,10 +1499,11 @@ static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
/* TODO: Could setup key for RX here, but change default TX keyid only
* after new broadcast key has been sent to all stations. */
if (hapd->drv.set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, NULL,
eapol->default_wep_key_idx, 1, NULL, 0,
eapol->default_wep_key,
hapd->conf->default_wep_key_len)) {
if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
broadcast_ether_addr,
eapol->default_wep_key_idx, 1, NULL, 0,
eapol->default_wep_key,
hapd->conf->default_wep_key_len)) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_WARNING, "failed to configure a "
"new broadcast key");
@ -1538,6 +1606,7 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
os_memcpy(user->password, eap_user->password,
eap_user->password_len);
user->password_len = eap_user->password_len;
user->password_hash = eap_user->password_hash;
}
user->force_version = eap_user->force_version;
user->ttls_auth = eap_user->ttls_auth;
@ -1651,6 +1720,9 @@ int ieee802_1x_init(struct hostapd_data *hapd)
conf.eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind;
conf.tnc = hapd->conf->tnc;
conf.wps = hapd->wps;
conf.fragment_size = hapd->conf->fragment_size;
conf.pwd_group = hapd->conf->pwd_group;
conf.pbc_in_m1 = hapd->conf->pbc_in_m1;
os_memset(&cb, 0, sizeof(cb));
cb.eapol_send = ieee802_1x_eapol_send;
@ -1669,7 +1741,7 @@ int ieee802_1x_init(struct hostapd_data *hapd)
return -1;
if ((hapd->conf->ieee802_1x || hapd->conf->wpa) &&
hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 1))
hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1))
return -1;
#ifndef CONFIG_NO_RADIUS
@ -1680,9 +1752,9 @@ int ieee802_1x_init(struct hostapd_data *hapd)
if (hapd->conf->default_wep_key_len) {
for (i = 0; i < 4; i++)
hapd->drv.set_key(hapd->conf->iface, hapd,
WPA_ALG_NONE, NULL, i, 0, NULL, 0,
NULL, 0);
hostapd_drv_set_key(hapd->conf->iface, hapd,
WPA_ALG_NONE, NULL, i, 0, NULL, 0,
NULL, 0);
ieee802_1x_rekey(hapd, NULL);
@ -1700,7 +1772,7 @@ void ieee802_1x_deinit(struct hostapd_data *hapd)
if (hapd->driver != NULL &&
(hapd->conf->ieee802_1x || hapd->conf->wpa))
hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
eapol_auth_deinit(hapd->eapol_auth);
hapd->eapol_auth = NULL;
@ -1739,9 +1811,19 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
MAC2STR(sta->addr), xhdr->version, xhdr->type,
be_to_host16(xhdr->length), ack);
if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY &&
pos + sizeof(struct wpa_eapol_key) <= buf + len) {
const struct wpa_eapol_key *wpa;
wpa = (const struct wpa_eapol_key *) pos;
if (wpa->type == EAPOL_KEY_TYPE_RSN ||
wpa->type == EAPOL_KEY_TYPE_WPA)
wpa_auth_eapol_key_tx_status(hapd->wpa_auth,
sta->wpa_sm, ack);
}
/* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant
* or Authenticator state machines, but EAPOL-Key packets are not
* retransmitted in case of failure. Try to re-sent failed EAPOL-Key
* retransmitted in case of failure. Try to re-send failed EAPOL-Key
* packets couple of times because otherwise STA keys become
* unsynchronized with AP. */
if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && !ack &&
@ -1791,6 +1873,7 @@ u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len)
{
*len = 0;
if (sm == NULL)
return NULL;
@ -1848,6 +1931,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
{
int len = 0, ret;
struct eapol_state_machine *sm = sta->eapol_sm;
struct os_time t;
if (sm == NULL)
return 0;
@ -1962,6 +2046,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
len += ret;
/* dot1xAuthSessionStatsTable */
os_get_time(&t);
ret = os_snprintf(buf + len, buflen - len,
/* TODO: dot1xAuthSessionOctetsRx */
/* TODO: dot1xAuthSessionOctetsTx */
@ -1976,8 +2061,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
(wpa_key_mgmt_wpa_ieee8021x(
wpa_auth_sta_key_mgmt(sta->wpa_sm))) ?
1 : 2,
(unsigned int) (time(NULL) -
sta->acct_session_start),
(unsigned int) (t.sec - sta->acct_session_start),
sm->identity);
if (ret < 0 || (size_t) ret >= buflen - len)
return len;
@ -2004,14 +2088,18 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
"Added PMKSA cache entry (IEEE 802.1X)");
}
#ifdef CONFIG_WPS
if (!success && (sta->flags & WLAN_STA_WPS)) {
if (!success) {
/*
* Many devices require deauthentication after WPS provisioning
* and some may not be be able to do that themselves, so
* disconnect the client here.
* disconnect the client here. In addition, this may also
* benefit IEEE 802.1X/EAPOL authentication cases, too since
* the EAPOL PAE state machine would remain in HELD state for
* considerable amount of time and some EAP methods, like
* EAP-FAST with anonymous provisioning, may require another
* EAPOL authentication to be started to complete connection.
*/
wpa_printf(MSG_DEBUG, "WPS: Force disconnection after "
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Force disconnection after "
"EAP-Failure");
/* Add a small sleep to increase likelihood of previously
* requested EAP-Failure TX getting out before this should the
@ -2019,7 +2107,6 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
*/
os_sleep(0, 10000);
ap_sta_disconnect(hapd, sta, sta->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
WLAN_REASON_IEEE_802_1X_AUTH_FAILED);
}
#endif /* CONFIG_WPS */
}

View File

@ -0,0 +1,120 @@
/*
* hostapd / P2P integration
* Copyright (c) 2009-2010, Atheros Communications
*
* 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 "utils/includes.h"
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
#include "p2p/p2p.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
#include "sta_info.h"
#include "p2p_hostapd.h"
#ifdef CONFIG_P2P
int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
char *buf, size_t buflen)
{
if (sta->p2p_ie == NULL)
return 0;
return p2p_ie_text(sta->p2p_ie, buf, buf + buflen);
}
int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start,
int duration)
{
wpa_printf(MSG_DEBUG, "P2P: Set NoA parameters: count=%u start=%d "
"duration=%d", count, start, duration);
if (count == 0) {
hapd->noa_enabled = 0;
hapd->noa_start = 0;
hapd->noa_duration = 0;
}
if (count != 255) {
wpa_printf(MSG_DEBUG, "P2P: Non-periodic NoA - set "
"NoA parameters");
return hostapd_driver_set_noa(hapd, count, start, duration);
}
hapd->noa_enabled = 1;
hapd->noa_start = start;
hapd->noa_duration = duration;
if (hapd->num_sta_no_p2p == 0) {
wpa_printf(MSG_DEBUG, "P2P: No legacy STAs connected - update "
"periodic NoA parameters");
return hostapd_driver_set_noa(hapd, count, start, duration);
}
wpa_printf(MSG_DEBUG, "P2P: Legacy STA(s) connected - do not enable "
"periodic NoA");
return 0;
}
void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd)
{
wpa_printf(MSG_DEBUG, "P2P: First non-P2P device connected");
if (hapd->noa_enabled) {
wpa_printf(MSG_DEBUG, "P2P: Disable periodic NoA");
hostapd_driver_set_noa(hapd, 0, 0, 0);
}
}
void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd)
{
wpa_printf(MSG_DEBUG, "P2P: Last non-P2P device disconnected");
if (hapd->noa_enabled) {
wpa_printf(MSG_DEBUG, "P2P: Enable periodic NoA");
hostapd_driver_set_noa(hapd, 255, hapd->noa_start,
hapd->noa_duration);
}
}
#endif /* CONFIG_P2P */
#ifdef CONFIG_P2P_MANAGER
u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid)
{
u8 bitmap;
*eid++ = WLAN_EID_VENDOR_SPECIFIC;
*eid++ = 4 + 3 + 1;
WPA_PUT_BE24(eid, OUI_WFA);
eid += 3;
*eid++ = P2P_OUI_TYPE;
*eid++ = P2P_ATTR_MANAGEABILITY;
WPA_PUT_LE16(eid, 1);
eid += 2;
bitmap = P2P_MAN_DEVICE_MANAGEMENT;
if (hapd->conf->p2p & P2P_ALLOW_CROSS_CONNECTION)
bitmap |= P2P_MAN_CROSS_CONNECTION_PERMITTED;
bitmap |= P2P_MAN_COEXISTENCE_OPTIONAL;
*eid++ = bitmap;
return eid;
}
#endif /* CONFIG_P2P_MANAGER */

View File

@ -0,0 +1,41 @@
/*
* hostapd / P2P integration
* Copyright (c) 2009-2010, Atheros Communications
*
* 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.
*/
#ifndef P2P_HOSTAPD_H
#define P2P_HOSTAPD_H
#ifdef CONFIG_P2P
int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
char *buf, size_t buflen);
int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start,
int duration);
void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd);
void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd);
#else /* CONFIG_P2P */
static inline int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd,
struct sta_info *sta,
char *buf, size_t buflen)
{
return 0;
}
#endif /* CONFIG_P2P */
u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid);
#endif /* P2P_HOSTAPD_H */

View File

@ -18,6 +18,7 @@
#include "utils/eloop.h"
#include "crypto/sha1.h"
#include "crypto/sha256.h"
#include "crypto/random.h"
#include "wpa_auth.h"
#include "wpa_auth_i.h"
#include "wpa_auth_ie.h"
@ -294,7 +295,7 @@ void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
return;
}
if (os_get_random(smk, PMK_LEN)) {
if (random_get_bytes(smk, PMK_LEN)) {
wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK");
return;
}

View File

@ -1,6 +1,6 @@
/*
* hostapd / Station table
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2011, 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
@ -17,9 +17,11 @@
#include "utils/common.h"
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "common/wpa_ctrl.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
#include "drivers/driver.h"
#include "p2p/p2p.h"
#include "hostapd.h"
#include "accounting.h"
#include "ieee802_1x.h"
@ -30,14 +32,19 @@
#include "beacon.h"
#include "ap_mlme.h"
#include "vlan_init.h"
#include "p2p_hostapd.h"
#include "ap_drv_ops.h"
#include "sta_info.h"
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
struct sta_info *sta);
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx);
static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx);
#ifdef CONFIG_IEEE80211W
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);
#endif /* CONFIG_IEEE80211W */
static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta);
int ap_for_each_sta(struct hostapd_data *hapd,
int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
@ -121,11 +128,14 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
accounting_sta_stop(hapd, sta);
/* just in case */
ap_sta_set_authorized(hapd, sta, 0);
if (sta->flags & WLAN_STA_WDS)
hapd->drv.set_wds_sta(hapd, sta->addr, sta->aid, 0);
hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0);
if (!(sta->flags & WLAN_STA_PREAUTH))
hapd->drv.sta_remove(hapd, sta->addr);
hostapd_drv_sta_remove(hapd, sta->addr);
ap_sta_hash_del(hapd, sta);
ap_sta_list_del(hapd, sta);
@ -173,6 +183,15 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
hapd->iface->num_sta_ht_20mhz--;
}
#ifdef CONFIG_P2P
if (sta->no_p2p_set) {
sta->no_p2p_set = 0;
hapd->num_sta_no_p2p--;
if (hapd->num_sta_no_p2p == 0)
hostapd_p2p_non_p2p_sta_disconnected(hapd);
}
#endif /* CONFIG_P2P */
#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
if (hostapd_ht_operation_update(hapd->iface) > 0)
set_beacon++;
@ -183,6 +202,8 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
ieee802_1x_free_station(sta);
wpa_auth_sta_deinit(sta->wpa_sm);
@ -199,7 +220,12 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_P2P
p2p_group_notif_disassoc(hapd->p2p_group, sta->addr);
#endif /* CONFIG_P2P */
wpabuf_free(sta->wps_ie);
wpabuf_free(sta->p2p_ie);
os_free(sta->ht_capabilities);
@ -253,27 +279,41 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
(sta->timeout_next == STA_NULLFUNC ||
sta->timeout_next == STA_DISASSOC)) {
int inactive_sec;
wpa_printf(MSG_DEBUG, "Checking STA " MACSTR " inactivity:",
MAC2STR(sta->addr));
inactive_sec = hapd->drv.get_inact_sec(hapd, sta->addr);
inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr);
if (inactive_sec == -1) {
wpa_printf(MSG_DEBUG, "Could not get station info "
"from kernel driver for " MACSTR ".",
MAC2STR(sta->addr));
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
"Check inactivity: Could not "
"get station info from kernel driver for "
MACSTR, MAC2STR(sta->addr));
/*
* The driver may not support this functionality.
* Anyway, try again after the next inactivity timeout,
* but do not disconnect the station now.
*/
next_time = hapd->conf->ap_max_inactivity;
} else if (inactive_sec < hapd->conf->ap_max_inactivity &&
sta->flags & WLAN_STA_ASSOC) {
/* station activity detected; reset timeout state */
wpa_printf(MSG_DEBUG, " Station has been active");
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
"Station " MACSTR " has been active %is ago",
MAC2STR(sta->addr), inactive_sec);
sta->timeout_next = STA_NULLFUNC;
next_time = hapd->conf->ap_max_inactivity -
inactive_sec;
} else {
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
"Station " MACSTR " has been "
"inactive too long: %d sec, max allowed: %d",
MAC2STR(sta->addr), inactive_sec,
hapd->conf->ap_max_inactivity);
}
}
if ((sta->flags & WLAN_STA_ASSOC) &&
sta->timeout_next == STA_DISASSOC &&
!(sta->flags & WLAN_STA_PENDING_POLL)) {
wpa_printf(MSG_DEBUG, " Station has ACKed data poll");
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR
" has ACKed data poll", MAC2STR(sta->addr));
/* data nullfunc frame poll did not produce TX errors; assume
* station ACKed it */
sta->timeout_next = STA_NULLFUNC;
@ -288,40 +328,10 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
if (sta->timeout_next == STA_NULLFUNC &&
(sta->flags & WLAN_STA_ASSOC)) {
#ifndef CONFIG_NATIVE_WINDOWS
/* send data frame to poll STA and check whether this frame
* is ACKed */
struct ieee80211_hdr hdr;
wpa_printf(MSG_DEBUG, " Polling STA with data frame");
wpa_printf(MSG_DEBUG, " Polling STA");
sta->flags |= WLAN_STA_PENDING_POLL;
os_memset(&hdr, 0, sizeof(hdr));
if (hapd->driver &&
os_strcmp(hapd->driver->name, "hostap") == 0) {
/*
* WLAN_FC_STYPE_NULLFUNC would be more appropriate,
* but it is apparently not retried so TX Exc events
* are not received for it.
*/
hdr.frame_control =
IEEE80211_FC(WLAN_FC_TYPE_DATA,
WLAN_FC_STYPE_DATA);
} else {
hdr.frame_control =
IEEE80211_FC(WLAN_FC_TYPE_DATA,
WLAN_FC_STYPE_NULLFUNC);
}
hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN);
os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr,
ETH_ALEN);
os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN);
if (hapd->drv.send_mgmt_frame(hapd, &hdr, sizeof(hdr)) < 0)
perror("ap_handle_timer: send");
#endif /* CONFIG_NATIVE_WINDOWS */
hostapd_drv_poll_client(hapd, hapd->own_addr, sta->addr,
sta->flags & WLAN_STA_WMM);
} else if (sta->timeout_next != STA_REMOVE) {
int deauth = sta->timeout_next == STA_DEAUTH;
@ -330,10 +340,11 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
MAC2STR(sta->addr));
if (deauth) {
hapd->drv.sta_deauth(hapd, sta->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
hostapd_drv_sta_deauth(
hapd, sta->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
} else {
hapd->drv.sta_disassoc(
hostapd_drv_sta_disassoc(
hapd, sta->addr,
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
}
@ -346,6 +357,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
hapd, sta);
break;
case STA_DISASSOC:
ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~WLAN_STA_ASSOC;
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
if (!sta->acct_terminate_cause)
@ -397,7 +409,7 @@ static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT;
os_memcpy(addr, sta->addr, ETH_ALEN);
ap_free_sta(hapd, sta);
hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
}
@ -463,7 +475,7 @@ static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta)
wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
MAC2STR(sta->addr));
if (hapd->drv.sta_remove(hapd, sta->addr) &&
if (hostapd_drv_sta_remove(hapd, sta->addr) &&
sta->flags & WLAN_STA_ASSOC) {
wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR
" from kernel driver.", MAC2STR(sta->addr));
@ -498,13 +510,23 @@ static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
}
static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
ap_sta_remove(hapd, sta);
mlme_disassociate_indication(hapd, sta, sta->disassoc_reason);
}
void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
u16 reason)
{
wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
hapd->conf->iface, MAC2STR(sta->addr));
sta->flags &= ~WLAN_STA_ASSOC;
ap_sta_remove(hapd, sta);
ap_sta_set_authorized(hapd, sta, 0);
sta->timeout_next = STA_DEAUTH;
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
@ -512,7 +534,22 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
accounting_sta_stop(hapd, sta);
ieee802_1x_free_station(sta);
mlme_disassociate_indication(hapd, sta, reason);
sta->disassoc_reason = reason;
sta->flags |= WLAN_STA_PENDING_DISASSOC_CB;
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
eloop_register_timeout(hapd->iface->drv_flags &
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
ap_sta_disassoc_cb_timeout, hapd, sta);
}
static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
ap_sta_remove(hapd, sta);
mlme_deauthenticate_indication(hapd, sta, sta->deauth_reason);
}
@ -522,7 +559,7 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
hapd->conf->iface, MAC2STR(sta->addr));
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
ap_sta_remove(hapd, sta);
ap_sta_set_authorized(hapd, sta, 0);
sta->timeout_next = STA_REMOVE;
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
@ -530,7 +567,12 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
accounting_sta_stop(hapd, sta);
ieee802_1x_free_station(sta);
mlme_deauthenticate_indication(hapd, sta, reason);
sta->deauth_reason = reason;
sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
eloop_register_timeout(hapd->iface->drv_flags &
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
ap_sta_deauth_cb_timeout, hapd, sta);
}
@ -636,7 +678,7 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0)
wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA");
ret = hapd->drv.set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
ret = hostapd_drv_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
if (ret < 0) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "could not bind the STA "
@ -732,6 +774,64 @@ void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
#endif /* CONFIG_IEEE80211W */
void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
int authorized)
{
const u8 *dev_addr = NULL;
if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
return;
#ifdef CONFIG_P2P
dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr);
#endif /* CONFIG_P2P */
if (authorized) {
if (dev_addr)
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED
MACSTR " p2p_dev_addr=" MACSTR,
MAC2STR(sta->addr), MAC2STR(dev_addr));
else
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED
MACSTR, MAC2STR(sta->addr));
if (hapd->msg_ctx_parent &&
hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr)
wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_CONNECTED MACSTR " p2p_dev_addr="
MACSTR,
MAC2STR(sta->addr), MAC2STR(dev_addr));
else if (hapd->msg_ctx_parent &&
hapd->msg_ctx_parent != hapd->msg_ctx)
wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
sta->flags |= WLAN_STA_AUTHORIZED;
} else {
if (dev_addr)
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED
MACSTR " p2p_dev_addr=" MACSTR,
MAC2STR(sta->addr), MAC2STR(dev_addr));
else
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED
MACSTR, MAC2STR(sta->addr));
if (hapd->msg_ctx_parent &&
hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr)
wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_DISCONNECTED MACSTR " p2p_dev_addr="
MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr));
else if (hapd->msg_ctx_parent &&
hapd->msg_ctx_parent != hapd->msg_ctx)
wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_DISCONNECTED MACSTR,
MAC2STR(sta->addr));
sta->flags &= ~WLAN_STA_AUTHORIZED;
}
if (hapd->sta_authorized_cb)
hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
sta->addr, authorized, dev_addr);
}
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *addr, u16 reason)
{
@ -740,12 +840,47 @@ void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
sta = ap_get_sta(hapd, addr);
if (addr)
hapd->drv.sta_deauth(hapd, addr, reason);
hostapd_drv_sta_deauth(hapd, addr, reason);
if (sta == NULL)
return;
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED);
ap_sta_set_authorized(hapd, sta, 0);
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
ap_handle_timer, hapd, sta);
sta->timeout_next = STA_REMOVE;
sta->deauth_reason = reason;
sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
eloop_register_timeout(hapd->iface->drv_flags &
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
ap_sta_deauth_cb_timeout, hapd, sta);
}
void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta)
{
if (!(sta->flags & WLAN_STA_PENDING_DEAUTH_CB)) {
wpa_printf(MSG_DEBUG, "Ignore deauth cb for test frame");
return;
}
sta->flags &= ~WLAN_STA_PENDING_DEAUTH_CB;
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
ap_sta_deauth_cb_timeout(hapd, sta);
}
void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta)
{
if (!(sta->flags & WLAN_STA_PENDING_DISASSOC_CB)) {
wpa_printf(MSG_DEBUG, "Ignore disassoc cb for test frame");
return;
}
sta->flags &= ~WLAN_STA_PENDING_DISASSOC_CB;
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
ap_sta_disassoc_cb_timeout(hapd, sta);
}

View File

@ -1,6 +1,6 @@
/*
* hostapd / Station table
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2011, 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
@ -31,6 +31,10 @@
#define WLAN_STA_WPS BIT(12)
#define WLAN_STA_MAYBE_WPS BIT(13)
#define WLAN_STA_WDS BIT(14)
#define WLAN_STA_ASSOC_REQ_OK BIT(15)
#define WLAN_STA_WPS2 BIT(16)
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
#define WLAN_STA_NONERP BIT(31)
/* Maximum number of supported rates (from both Supported Rates and Extended
@ -55,6 +59,7 @@ struct sta_info {
unsigned int no_ht_gf_set:1;
unsigned int no_ht_set:1;
unsigned int ht_20mhz_set:1;
unsigned int no_p2p_set:1;
u16 auth_alg;
u8 previous_ap[6];
@ -63,6 +68,9 @@ struct sta_info {
STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE
} timeout_next;
u16 deauth_reason;
u16 disassoc_reason;
/* IEEE 802.1X related data */
struct eapol_state_machine *eapol_sm;
@ -104,6 +112,7 @@ struct sta_info {
#endif /* CONFIG_IEEE80211W */
struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */
struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */
};
@ -111,7 +120,7 @@ struct sta_info {
* passed since last received frame from the station, a nullfunc data frame is
* sent to the station. If this frame is not acknowledged and no other frames
* have been received, the station will be disassociated after
* AP_DISASSOC_DELAY seconds. Similarily, the station will be deauthenticated
* AP_DISASSOC_DELAY seconds. Similarly, the station will be deauthenticated
* after AP_DEAUTH_DELAY seconds has passed after disassociation. */
#define AP_MAX_INACTIVITY (5 * 60)
#define AP_DISASSOC_DELAY (1)
@ -152,4 +161,14 @@ int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *addr, u16 reason);
void ap_sta_set_authorized(struct hostapd_data *hapd,
struct sta_info *sta, int authorized);
static inline int ap_sta_is_authorized(struct sta_info *sta)
{
return sta->flags & WLAN_STA_AUTHORIZED;
}
void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta);
void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta);
#endif /* STA_INFO_H */

View File

@ -1,6 +1,6 @@
/*
* hostapd / TKIP countermeasures
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2011, 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
@ -21,6 +21,7 @@
#include "sta_info.h"
#include "ap_mlme.h"
#include "wpa_auth.h"
#include "ap_drv_ops.h"
#include "tkip_countermeasures.h"
@ -29,7 +30,7 @@ static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
{
struct hostapd_data *hapd = eloop_ctx;
hapd->tkip_countermeasures = 0;
hapd->drv.set_countermeasures(hapd, 0);
hostapd_drv_set_countermeasures(hapd, 0);
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
}
@ -44,24 +45,30 @@ static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
wpa_auth_countermeasures_start(hapd->wpa_auth);
hapd->tkip_countermeasures = 1;
hapd->drv.set_countermeasures(hapd, 1);
hostapd_drv_set_countermeasures(hapd, 1);
wpa_gtk_rekey(hapd->wpa_auth);
eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
hapd, NULL);
for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
hapd->drv.sta_deauth(hapd, sta->addr,
WLAN_REASON_MICHAEL_MIC_FAILURE);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
WLAN_STA_AUTHORIZED);
hapd->drv.sta_remove(hapd, sta->addr);
hostapd_drv_sta_deauth(hapd, sta->addr,
WLAN_REASON_MICHAEL_MIC_FAILURE);
ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
hostapd_drv_sta_remove(hapd, sta->addr);
}
}
void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
{
eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
}
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
{
time_t now;
struct os_time now;
if (addr && local) {
struct sta_info *sta = ap_get_sta(hapd, addr);
@ -81,13 +88,13 @@ void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
}
}
time(&now);
if (now > hapd->michael_mic_failure + 60) {
os_get_time(&now);
if (now.sec > hapd->michael_mic_failure + 60) {
hapd->michael_mic_failures = 1;
} else {
hapd->michael_mic_failures++;
if (hapd->michael_mic_failures > 1)
ieee80211_tkip_countermeasures_start(hapd);
}
hapd->michael_mic_failure = now;
hapd->michael_mic_failure = now.sec;
}

View File

@ -1,6 +1,6 @@
/*
* hostapd / TKIP countermeasures
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2011, 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
@ -16,5 +16,6 @@
#define TKIP_COUNTERMEASURES_H
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local);
void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd);
#endif /* TKIP_COUNTERMEASURES_H */

View File

@ -22,6 +22,7 @@
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
int (*cb)(void *ctx, const u8 *sa,
const u8 *da, const u8 *bssid,
const u8 *ie, size_t ie_len),
void *ctx)
{

View File

@ -19,6 +19,7 @@
#include "utils/common.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
#include "vlan_init.h"
@ -737,9 +738,10 @@ int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
* functions for setting up dynamic broadcast keys. */
for (i = 0; i < 4; i++) {
if (mssid->wep.key[i] &&
hapd->drv.set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i,
i == mssid->wep.idx, NULL, 0,
mssid->wep.key[i], mssid->wep.len[i])) {
hostapd_drv_set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i,
i == mssid->wep.idx, NULL, 0,
mssid->wep.key[i], mssid->wep.len[i]))
{
wpa_printf(MSG_ERROR, "VLAN: Could not set WEP "
"encryption for dynamic VLAN");
return -1;
@ -755,7 +757,7 @@ static int vlan_dynamic_add(struct hostapd_data *hapd,
{
while (vlan) {
if (vlan->vlan_id != VLAN_ID_WILDCARD) {
if (hapd->drv.vlan_if_add(hapd, vlan->ifname)) {
if (hostapd_vlan_if_add(hapd, vlan->ifname)) {
if (errno != EEXIST) {
wpa_printf(MSG_ERROR, "VLAN: Could "
"not add VLAN %s: %s",
@ -785,7 +787,7 @@ static void vlan_dynamic_remove(struct hostapd_data *hapd,
next = vlan->next;
if (vlan->vlan_id != VLAN_ID_WILDCARD &&
hapd->drv.vlan_if_remove(hapd, vlan->ifname)) {
hostapd_vlan_if_remove(hapd, vlan->ifname)) {
wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
"iface: %s: %s",
vlan->ifname, strerror(errno));
@ -859,7 +861,7 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
pos);
os_free(ifname);
if (hapd->drv.vlan_if_add(hapd, n->ifname)) {
if (hostapd_vlan_if_add(hapd, n->ifname)) {
os_free(n);
return NULL;
}
@ -897,7 +899,7 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
return 1;
if (vlan->dynamic_vlan == 0)
hapd->drv.vlan_if_remove(hapd, vlan->ifname);
hostapd_vlan_if_remove(hapd, vlan->ifname);
return 0;
}

View File

@ -23,6 +23,7 @@
#include "ieee802_11.h"
#include "sta_info.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
#include "wmm.h"
@ -74,6 +75,8 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
if (hapd->conf->wmm_uapsd)
wmm->qos_info |= 0x80;
wmm->reserved = 0;
/* fill in a parameter set record for each AC */
for (e = 0; e < 4; e++) {
struct wmm_ac_parameter *ac = &wmm->ac[e];
@ -94,9 +97,11 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
}
/* This function is called when a station sends an association request with
* 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. */
/*
* This function is called when a station sends an association request with
* WMM info element. The function returns 1 on success or 0 on any error in WMM
* element. eid does not include Element ID and Length octets.
*/
int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
{
struct wmm_information_element *wmm;
@ -106,7 +111,7 @@ int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
if (len < sizeof(struct wmm_information_element)) {
wpa_printf(MSG_DEBUG, "Too short WMM IE (len=%lu)",
(unsigned long) len);
return -1;
return 0;
}
wmm = (struct wmm_information_element *) eid;
@ -117,10 +122,10 @@ int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
if (wmm->oui_subtype != WMM_OUI_SUBTYPE_INFORMATION_ELEMENT ||
wmm->version != WMM_VERSION) {
wpa_printf(MSG_DEBUG, "Unsupported WMM IE Subtype/Version");
return -1;
return 0;
}
return 0;
return 1;
}
@ -150,7 +155,7 @@ static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr,
os_memcpy(t, tspec, sizeof(struct wmm_tspec_element));
len = ((u8 *) (t + 1)) - buf;
if (hapd->drv.send_mgmt_frame(hapd, m, len) < 0)
if (hostapd_drv_send_mlme(hapd, m, len) < 0)
perror("wmm_send_action: send");
}

View File

@ -143,7 +143,9 @@ struct wpa_auth_config {
int peerkey;
int wmm_enabled;
int wmm_uapsd;
int disable_pmksa_caching;
int okc;
int tx_status;
#ifdef CONFIG_IEEE80211W
enum mfp_options ieee80211w;
#endif /* CONFIG_IEEE80211W */
@ -160,6 +162,7 @@ struct wpa_auth_config {
struct ft_remote_r0kh *r0kh_list;
struct ft_remote_r1kh *r1kh_list;
int pmk_r1_push;
int ft_over_ds;
#endif /* CONFIG_IEEE80211R */
};
@ -205,6 +208,7 @@ struct wpa_auth_callbacks {
struct wpa_authenticator * wpa_init(const u8 *addr,
struct wpa_auth_config *conf,
struct wpa_auth_callbacks *cb);
int wpa_init_keys(struct wpa_authenticator *wpa_auth);
void wpa_deinit(struct wpa_authenticator *wpa_auth);
int wpa_reconfig(struct wpa_authenticator *wpa_auth,
struct wpa_auth_config *conf);
@ -259,6 +263,8 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
int session_timeout,
struct eapol_state_machine *eapol);
int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm, int ack);
#ifdef CONFIG_IEEE80211R
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,

View File

@ -18,6 +18,7 @@
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "crypto/aes_wrap.h"
#include "crypto/random.h"
#include "ap_config.h"
#include "ieee802_11.h"
#include "wmm.h"
@ -28,28 +29,6 @@
#ifdef CONFIG_IEEE80211R
struct wpa_ft_ies {
const u8 *mdie;
size_t mdie_len;
const u8 *ftie;
size_t ftie_len;
const u8 *r1kh_id;
const u8 *gtk;
size_t gtk_len;
const u8 *r0kh_id;
size_t r0kh_id_len;
const u8 *rsn;
size_t rsn_len;
const u8 *rsn_pmkid;
const u8 *ric;
size_t ric_len;
};
static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
struct wpa_ft_ies *parse);
static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
const u8 *data, size_t data_len)
{
@ -91,7 +70,9 @@ int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len)
*pos++ = MOBILITY_DOMAIN_ID_LEN + 1;
os_memcpy(pos, conf->mobility_domain, MOBILITY_DOMAIN_ID_LEN);
pos += MOBILITY_DOMAIN_ID_LEN;
capab = RSN_FT_CAPAB_FT_OVER_DS;
capab = 0;
if (conf->ft_over_ds)
capab |= RSN_FT_CAPAB_FT_OVER_DS;
*pos++ = capab;
return pos - buf;
@ -334,7 +315,7 @@ static int wpa_ft_pull_pmk_r1(struct wpa_authenticator *wpa_auth,
/* aes_wrap() does not support inplace encryption, so use a temporary
* buffer for the data. */
if (os_get_random(f.nonce, sizeof(f.nonce))) {
if (random_get_bytes(f.nonce, sizeof(f.nonce))) {
wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
"nonce");
return -1;
@ -725,143 +706,6 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
}
static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
struct wpa_ft_ies *parse)
{
const u8 *end, *pos;
parse->ftie = ie;
parse->ftie_len = ie_len;
pos = ie + sizeof(struct rsn_ftie);
end = ie + ie_len;
while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
switch (pos[0]) {
case FTIE_SUBELEM_R1KH_ID:
if (pos[1] != FT_R1KH_ID_LEN) {
wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "
"length in FTIE: %d", pos[1]);
return -1;
}
parse->r1kh_id = pos + 2;
break;
case FTIE_SUBELEM_GTK:
parse->gtk = pos + 2;
parse->gtk_len = pos[1];
break;
case FTIE_SUBELEM_R0KH_ID:
if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {
wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "
"length in FTIE: %d", pos[1]);
return -1;
}
parse->r0kh_id = pos + 2;
parse->r0kh_id_len = pos[1];
break;
}
pos += 2 + pos[1];
}
return 0;
}
static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
struct wpa_ft_ies *parse)
{
const u8 *end, *pos;
struct wpa_ie_data data;
int ret;
const struct rsn_ftie *ftie;
int prot_ie_count = 0;
os_memset(parse, 0, sizeof(*parse));
if (ies == NULL)
return 0;
pos = ies;
end = ies + ies_len;
while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
switch (pos[0]) {
case WLAN_EID_RSN:
parse->rsn = pos + 2;
parse->rsn_len = pos[1];
ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
parse->rsn_len + 2,
&data);
if (ret < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse "
"RSN IE: %d", ret);
return -1;
}
if (data.num_pmkid == 1 && data.pmkid)
parse->rsn_pmkid = data.pmkid;
break;
case WLAN_EID_MOBILITY_DOMAIN:
parse->mdie = pos + 2;
parse->mdie_len = pos[1];
break;
case WLAN_EID_FAST_BSS_TRANSITION:
if (pos[1] < sizeof(*ftie))
return -1;
ftie = (const struct rsn_ftie *) (pos + 2);
prot_ie_count = ftie->mic_control[1];
if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
return -1;
break;
case WLAN_EID_RIC_DATA:
if (parse->ric == NULL)
parse->ric = pos;
}
pos += 2 + pos[1];
}
if (prot_ie_count == 0)
return 0; /* no MIC */
/*
* Check that the protected IE count matches with IEs included in the
* frame.
*/
if (parse->rsn)
prot_ie_count--;
if (parse->mdie)
prot_ie_count--;
if (parse->ftie)
prot_ie_count--;
if (prot_ie_count < 0) {
wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
"the protected IE count");
return -1;
}
if (prot_ie_count == 0 && parse->ric) {
wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
"included in protected IE count");
return -1;
}
/* Determine the end of the RIC IE(s) */
pos = parse->ric;
while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
prot_ie_count) {
prot_ie_count--;
pos += 2 + pos[1];
}
parse->ric_len = pos - parse->ric;
if (prot_ie_count) {
wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
"frame", (int) prot_ie_count);
return -1;
}
return 0;
}
static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
int vlan_id,
enum wpa_alg alg, const u8 *addr, int idx,
@ -997,7 +841,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
sm->pmk_r1_name_valid = 1;
os_memcpy(sm->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN);
if (os_get_random(sm->ANonce, WPA_NONCE_LEN)) {
if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
"ANonce");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
@ -1204,7 +1048,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
count = 3;
if (parse.ric)
count++;
count += ieee802_11_ie_count(parse.ric, parse.ric_len);
if (ftie->mic_control[1] != count) {
wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
"Control: received %u expected %u",

View File

@ -1,6 +1,6 @@
/*
* hostapd / WPA authenticator glue code
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2011, 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
@ -31,15 +31,10 @@
#include "wpa_auth.h"
#ifdef CONFIG_IEEE80211R
static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
size_t len);
#endif /* CONFIG_IEEE80211R */
static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
struct wpa_auth_config *wconf)
{
os_memset(wconf, 0, sizeof(*wconf));
wconf->wpa = conf->wpa;
wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
wconf->wpa_pairwise = conf->wpa_pairwise;
@ -54,6 +49,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wconf->peerkey = conf->peerkey;
wconf->wmm_enabled = conf->wmm_enabled;
wconf->wmm_uapsd = conf->wmm_uapsd;
wconf->disable_pmksa_caching = conf->disable_pmksa_caching;
wconf->okc = conf->okc;
#ifdef CONFIG_IEEE80211W
wconf->ieee80211w = conf->ieee80211w;
@ -77,6 +73,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wconf->r0kh_list = conf->r0kh_list;
wconf->r1kh_list = conf->r1kh_list;
wconf->pmk_r1_push = conf->pmk_r1_push;
wconf->ft_over_ds = conf->ft_over_ds;
#endif /* CONFIG_IEEE80211R */
}
@ -230,8 +227,8 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
return -1;
}
return hapd->drv.set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0,
key, key_len);
return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0,
key, key_len);
}
@ -248,7 +245,15 @@ static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
int encrypt)
{
struct hostapd_data *hapd = ctx;
return hapd->drv.send_eapol(hapd, addr, data, data_len, encrypt);
struct sta_info *sta;
u32 flags = 0;
sta = ap_get_sta(hapd, addr);
if (sta)
flags = hostapd_sta_flags_to_drv(sta->flags);
return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len,
encrypt, flags);
}
@ -327,8 +332,9 @@ static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx)
MAC2STR(idata->src_hapd->own_addr),
idata->src_hapd->conf->iface,
MAC2STR(hapd->own_addr), hapd->conf->iface);
hostapd_rrb_receive(hapd, idata->src_hapd->own_addr,
idata->data, idata->data_len);
wpa_ft_rrb_rx(hapd->wpa_auth,
idata->src_hapd->own_addr,
idata->data, idata->data_len);
return 1;
}
}
@ -343,6 +349,8 @@ static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
const u8 *data, size_t data_len)
{
struct hostapd_data *hapd = ctx;
struct l2_ethhdr *buf;
int ret;
#ifdef CONFIG_IEEE80211R
if (proto == ETH_P_RRB && hapd->iface->for_each_interface) {
@ -366,7 +374,18 @@ static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
data, data_len);
if (hapd->l2 == NULL)
return -1;
return l2_packet_send(hapd->l2, dst, proto, data, data_len);
buf = os_malloc(sizeof(*buf) + data_len);
if (buf == NULL)
return -1;
os_memcpy(buf->h_dest, dst, ETH_ALEN);
os_memcpy(buf->h_source, hapd->own_addr, ETH_ALEN);
buf->h_proto = host_to_be16(proto);
os_memcpy(buf + 1, data, data_len);
ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf,
sizeof(*buf) + data_len);
os_free(buf);
return ret;
}
@ -396,7 +415,7 @@ static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
os_memcpy(&m->u, data, data_len);
res = hapd->drv.send_mgmt_frame(hapd, (u8 *) m, mlen);
res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen);
os_free(m);
return res;
}
@ -431,7 +450,14 @@ static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
size_t len)
{
struct hostapd_data *hapd = ctx;
wpa_ft_rrb_rx(hapd->wpa_auth, src_addr, buf, len);
struct l2_ethhdr *ethhdr;
if (len < sizeof(*ethhdr))
return;
ethhdr = (struct l2_ethhdr *) buf;
wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> "
MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest));
wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr),
len - sizeof(*ethhdr));
}
#endif /* CONFIG_IEEE80211R */
@ -445,6 +471,8 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
size_t wpa_ie_len;
hostapd_wpa_auth_conf(hapd->conf, &_conf);
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
_conf.tx_status = 1;
os_memset(&cb, 0, sizeof(cb));
cb.ctx = hapd;
cb.logger = hostapd_wpa_auth_logger;
@ -494,7 +522,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ?
hapd->conf->bridge :
hapd->conf->iface, NULL, ETH_P_RRB,
hostapd_rrb_receive, hapd, 0);
hostapd_rrb_receive, hapd, 1);
if (hapd->l2 == NULL &&
(hapd->driver == NULL ||
hapd->driver->send_ether == NULL)) {
@ -520,6 +548,7 @@ void hostapd_reconfig_wpa(struct hostapd_data *hapd)
void hostapd_deinit_wpa(struct hostapd_data *hapd)
{
ieee80211_tkip_countermeasures_deinit(hapd);
rsn_preauth_iface_deinit(hapd);
if (hapd->wpa_auth) {
wpa_deinit(hapd->wpa_auth);

View File

@ -86,6 +86,7 @@ struct wpa_state_machine {
unsigned int pending_deinit:1;
unsigned int started:1;
unsigned int mgmt_frame_prot:1;
unsigned int rx_eapol_key_secure:1;
#ifdef CONFIG_IEEE80211R
unsigned int ft_completed:1;
unsigned int pmk_r1_name_valid:1;
@ -120,6 +121,8 @@ struct wpa_state_machine {
* message 2/4 */
u8 *assoc_resp_ftie;
#endif /* CONFIG_IEEE80211R */
int pending_1_of_4_timeout;
};
@ -145,6 +148,8 @@ struct wpa_group {
u8 GTK[2][WPA_GTK_MAX_LEN];
u8 GNonce[WPA_NONCE_LEN];
Boolean changed;
Boolean first_sta_seen;
Boolean reject_4way_hs_for_entropy;
#ifdef CONFIG_IEEE80211W
u8 IGTK[2][WPA_IGTK_LEN];
int GN_igtk, GM_igtk;

View File

@ -25,6 +25,11 @@
#include "wpa_auth_i.h"
#ifdef CONFIG_RSN_TESTING
int rsn_testing = 0;
#endif /* CONFIG_RSN_TESTING */
static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
{
struct wpa_ie_hdr *hdr;
@ -141,6 +146,14 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
count = pos;
pos += 2;
#ifdef CONFIG_RSN_TESTING
if (rsn_testing) {
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_RSN_TESTING */
if (conf->rsn_pairwise & WPA_CIPHER_CCMP) {
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
pos += RSN_SELECTOR_LEN;
@ -157,6 +170,14 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
num_suites++;
}
#ifdef CONFIG_RSN_TESTING
if (rsn_testing) {
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_RSN_TESTING */
if (num_suites == 0) {
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
conf->rsn_pairwise);
@ -168,6 +189,14 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
count = pos;
pos += 2;
#ifdef CONFIG_RSN_TESTING
if (rsn_testing) {
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_RSN_TESTING */
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
pos += RSN_SELECTOR_LEN;
@ -203,6 +232,14 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
}
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_RSN_TESTING
if (rsn_testing) {
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_RSN_TESTING */
if (num_suites == 0) {
wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
conf->wpa_key_mgmt);
@ -227,6 +264,10 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
capab |= WPA_CAPABILITY_MFPR;
}
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_RSN_TESTING
if (rsn_testing)
capab |= BIT(8) | BIT(14) | BIT(15);
#endif /* CONFIG_RSN_TESTING */
WPA_PUT_LE16(pos, capab);
pos += 2;
@ -256,6 +297,29 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
}
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_RSN_TESTING
if (rsn_testing) {
/*
* Fill in any defined fields and add extra data to the end of
* the element.
*/
int pmkid_count_set = pmkid != NULL;
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
pmkid_count_set = 1;
/* PMKID Count */
WPA_PUT_LE16(pos, 0);
pos += 2;
if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
/* Management Group Cipher Suite */
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
pos += RSN_SELECTOR_LEN;
}
os_memset(pos, 0x12, 17);
pos += 17;
}
#endif /* CONFIG_RSN_TESTING */
hdr->len = (pos - buf) - 2;
return pos - buf;
@ -322,114 +386,6 @@ u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
}
static int wpa_selector_to_bitfield(const u8 *s)
{
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
return WPA_CIPHER_NONE;
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40)
return WPA_CIPHER_WEP40;
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
return WPA_CIPHER_TKIP;
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
return WPA_CIPHER_CCMP;
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104)
return WPA_CIPHER_WEP104;
return 0;
}
static int wpa_key_mgmt_to_bitfield(const u8 *s)
{
if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
return WPA_KEY_MGMT_IEEE8021X;
if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
return WPA_KEY_MGMT_PSK;
if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
return WPA_KEY_MGMT_WPA_NONE;
return 0;
}
static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
struct wpa_ie_data *data)
{
const struct wpa_ie_hdr *hdr;
const u8 *pos;
int left;
int i, count;
os_memset(data, 0, sizeof(*data));
data->pairwise_cipher = WPA_CIPHER_TKIP;
data->group_cipher = WPA_CIPHER_TKIP;
data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
data->mgmt_group_cipher = 0;
if (wpa_ie_len < sizeof(struct wpa_ie_hdr))
return -1;
hdr = (const struct wpa_ie_hdr *) wpa_ie;
if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
hdr->len != wpa_ie_len - 2 ||
RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
WPA_GET_LE16(hdr->version) != WPA_VERSION) {
return -2;
}
pos = (const u8 *) (hdr + 1);
left = wpa_ie_len - sizeof(*hdr);
if (left >= WPA_SELECTOR_LEN) {
data->group_cipher = wpa_selector_to_bitfield(pos);
pos += WPA_SELECTOR_LEN;
left -= WPA_SELECTOR_LEN;
} else if (left > 0)
return -3;
if (left >= 2) {
data->pairwise_cipher = 0;
count = WPA_GET_LE16(pos);
pos += 2;
left -= 2;
if (count == 0 || left < count * WPA_SELECTOR_LEN)
return -4;
for (i = 0; i < count; i++) {
data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
pos += WPA_SELECTOR_LEN;
left -= WPA_SELECTOR_LEN;
}
} else if (left == 1)
return -5;
if (left >= 2) {
data->key_mgmt = 0;
count = WPA_GET_LE16(pos);
pos += 2;
left -= 2;
if (count == 0 || left < count * WPA_SELECTOR_LEN)
return -6;
for (i = 0; i < count; i++) {
data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
pos += WPA_SELECTOR_LEN;
left -= WPA_SELECTOR_LEN;
}
} else if (left == 1)
return -7;
if (left >= 2) {
data->capabilities = WPA_GET_LE16(pos);
pos += 2;
left -= 2;
}
if (left > 0) {
return -8;
}
return 0;
}
struct wpa_auth_okc_iter_data {
struct rsn_pmksa_cache_entry *pmksa;
const u8 *aa;

View File

@ -28,6 +28,7 @@
#include "wps/wps_dev_attr.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
#include "beacon.h"
#include "sta_info.h"
#include "wps_hostapd.h"
@ -40,11 +41,51 @@ static int hostapd_wps_upnp_init(struct hostapd_data *hapd,
static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd);
#endif /* CONFIG_WPS_UPNP */
static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr,
static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
const u8 *bssid,
const u8 *ie, size_t ie_len);
static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
struct wps_for_each_data {
int (*func)(struct hostapd_data *h, void *ctx);
void *ctx;
};
static int wps_for_each(struct hostapd_iface *iface, void *ctx)
{
struct wps_for_each_data *data = ctx;
size_t j;
if (iface == NULL)
return 0;
for (j = 0; j < iface->num_bss; j++) {
struct hostapd_data *hapd = iface->bss[j];
int ret = data->func(hapd, data->ctx);
if (ret)
return ret;
}
return 0;
}
static int hostapd_wps_for_each(struct hostapd_data *hapd,
int (*func)(struct hostapd_data *h, void *ctx),
void *ctx)
{
struct hostapd_iface *iface = hapd->iface;
struct wps_for_each_data data;
data.func = func;
data.ctx = ctx;
if (iface->for_each_interface == NULL)
return wps_for_each(iface, &data);
return iface->for_each_interface(iface->interfaces, wps_for_each,
&data);
}
static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk,
size_t psk_len)
{
@ -100,8 +141,9 @@ static int hostapd_wps_set_ie_cb(void *ctx, struct wpabuf *beacon_ie,
hapd->wps_beacon_ie = beacon_ie;
wpabuf_free(hapd->wps_probe_resp_ie);
hapd->wps_probe_resp_ie = probe_resp_ie;
ieee802_11_set_beacon(hapd);
return hapd->drv.set_ap_wps_ie(hapd);
if (hapd->beacon_set_done)
ieee802_11_set_beacon(hapd);
return hostapd_set_ap_wps_ie(hapd);
}
@ -144,11 +186,26 @@ static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
}
struct wps_stop_reg_data {
struct hostapd_data *current_hapd;
const u8 *uuid_e;
};
static int wps_stop_registrar(struct hostapd_data *hapd, void *ctx)
{
struct wps_stop_reg_data *data = ctx;
if (hapd != data->current_hapd && hapd->wps != NULL)
wps_registrar_complete(hapd->wps->registrar, data->uuid_e);
return 0;
}
static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
const u8 *uuid_e)
{
struct hostapd_data *hapd = ctx;
char uuid[40];
struct wps_stop_reg_data data;
if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
return;
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_REG_SUCCESS MACSTR " %s",
@ -156,6 +213,9 @@ static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
if (hapd->wps_reg_success_cb)
hapd->wps_reg_success_cb(hapd->wps_reg_success_cb_ctx,
mac_addr, uuid_e);
data.current_hapd = hapd;
data.uuid_e = uuid_e;
hostapd_wps_for_each(hapd, wps_stop_registrar, &data);
}
@ -200,9 +260,23 @@ static void wps_reload_config(void *eloop_data, void *user_ctx)
}
static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
static void hapd_new_ap_event(struct hostapd_data *hapd, const u8 *attr,
size_t attr_len)
{
struct hostapd_data *hapd = ctx;
size_t blen = attr_len * 2 + 1;
char *buf = os_malloc(blen);
if (buf) {
wpa_snprintf_hex(buf, blen, attr, attr_len);
wpa_msg(hapd->msg_ctx, MSG_INFO,
WPS_EVENT_NEW_AP_SETTINGS "%s", buf);
os_free(buf);
}
}
static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
{
const struct wps_credential *cred = ctx;
FILE *oconf, *nconf;
size_t len, i;
char *tmp_fname;
@ -210,6 +284,9 @@ static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
int multi_bss;
int wpa;
if (hapd->wps == NULL)
return 0;
wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
cred->cred_attr, cred->cred_attr_len);
@ -226,15 +303,15 @@ 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,
cred->cred_attr, cred->cred_attr_len);
wpa_msg(hapd->msg_ctx, MSG_INFO, "%s%s",
WPS_EVENT_NEW_AP_SETTINGS, _buf);
os_free(_buf);
}
hapd_new_ap_event(hapd, cred->cred_attr, cred->cred_attr_len);
} else if (hapd->conf->wps_cred_processing == 1 ||
hapd->conf->wps_cred_processing == 2) {
struct wpabuf *attr;
attr = wpabuf_alloc(200);
if (attr && wps_build_credential_wrap(attr, cred) == 0)
hapd_new_ap_event(hapd, wpabuf_head_u8(attr),
wpabuf_len(attr));
wpabuf_free(attr);
} else
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS);
@ -384,6 +461,8 @@ static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
if (!multi_bss &&
(str_starts(buf, "ssid=") ||
str_starts(buf, "auth_algs=") ||
str_starts(buf, "wep_default_key=") ||
str_starts(buf, "wep_key") ||
str_starts(buf, "wps_state=") ||
str_starts(buf, "wpa=") ||
str_starts(buf, "wpa_psk=") ||
@ -414,20 +493,27 @@ static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface,
NULL);
/* TODO: dualband AP may need to update multiple configuration files */
wpa_printf(MSG_DEBUG, "WPS: AP configuration updated");
return 0;
}
static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
{
struct hostapd_data *hapd = ctx;
return hostapd_wps_for_each(hapd, hapd_wps_cred_cb, (void *) cred);
}
static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx)
{
struct hostapd_data *hapd = eloop_data;
if (hapd->conf->ap_setup_locked)
return;
if (hapd->ap_pin_failures_consecutive >= 10)
return;
wpa_printf(MSG_DEBUG, "WPS: Re-enable AP PIN");
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED);
@ -436,11 +522,12 @@ static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx)
}
static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
struct wps_event_pwd_auth_fail *data)
static int wps_pwd_auth_fail(struct hostapd_data *hapd, void *ctx)
{
if (!data->enrollee || hapd->conf->ap_pin == NULL)
return;
struct wps_event_pwd_auth_fail *data = ctx;
if (!data->enrollee || hapd->conf->ap_pin == NULL || hapd->wps == NULL)
return 0;
/*
* Registrar failed to prove its knowledge of the AP PIN. Lock AP setup
@ -448,17 +535,27 @@ static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
* force attacks.
*/
hapd->ap_pin_failures++;
wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u",
hapd->ap_pin_failures);
hapd->ap_pin_failures_consecutive++;
wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u "
"(%u consecutive)",
hapd->ap_pin_failures, hapd->ap_pin_failures_consecutive);
if (hapd->ap_pin_failures < 3)
return;
return 0;
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED);
hapd->wps->ap_setup_locked = 1;
wps_registrar_update_ie(hapd->wps->registrar);
if (!hapd->conf->ap_setup_locked) {
if (!hapd->conf->ap_setup_locked &&
hapd->ap_pin_failures_consecutive >= 10) {
/*
* In indefinite lockdown - disable automatic AP PIN
* reenablement.
*/
eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
wpa_printf(MSG_DEBUG, "WPS: AP PIN disabled indefinitely");
} else if (!hapd->conf->ap_setup_locked) {
if (hapd->ap_pin_lockout_time == 0)
hapd->ap_pin_lockout_time = 60;
else if (hapd->ap_pin_lockout_time < 365 * 24 * 60 * 60 &&
@ -473,7 +570,60 @@ static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
NULL);
}
/* TODO: dualband AP may need to update other interfaces */
return 0;
}
static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
struct wps_event_pwd_auth_fail *data)
{
hostapd_wps_for_each(hapd, wps_pwd_auth_fail, data);
}
static int wps_ap_pin_success(struct hostapd_data *hapd, void *ctx)
{
if (hapd->conf->ap_pin == NULL || hapd->wps == NULL)
return 0;
if (hapd->ap_pin_failures_consecutive == 0)
return 0;
wpa_printf(MSG_DEBUG, "WPS: Clear consecutive AP PIN failure counter "
"- total validation failures %u (%u consecutive)",
hapd->ap_pin_failures, hapd->ap_pin_failures_consecutive);
hapd->ap_pin_failures_consecutive = 0;
return 0;
}
static void hostapd_wps_ap_pin_success(struct hostapd_data *hapd)
{
hostapd_wps_for_each(hapd, wps_ap_pin_success, NULL);
}
static const char * wps_event_fail_reason[NUM_WPS_EI_VALUES] = {
"No Error", /* WPS_EI_NO_ERROR */
"TKIP Only Prohibited", /* WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED */
"WEP Prohibited" /* WPS_EI_SECURITY_WEP_PROHIBITED */
};
static void hostapd_wps_event_fail(struct hostapd_data *hapd,
struct wps_event_fail *fail)
{
if (fail->error_indication > 0 &&
fail->error_indication < NUM_WPS_EI_VALUES) {
wpa_msg(hapd->msg_ctx, MSG_INFO,
WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)",
fail->msg, fail->config_error, fail->error_indication,
wps_event_fail_reason[fail->error_indication]);
} else {
wpa_msg(hapd->msg_ctx, MSG_INFO,
WPS_EVENT_FAIL "msg=%d config_error=%d",
fail->msg, fail->config_error);
}
}
@ -482,8 +632,43 @@ static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
{
struct hostapd_data *hapd = ctx;
if (event == WPS_EV_PWD_AUTH_FAIL)
switch (event) {
case WPS_EV_M2D:
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_M2D);
break;
case WPS_EV_FAIL:
hostapd_wps_event_fail(hapd, &data->fail);
break;
case WPS_EV_SUCCESS:
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_SUCCESS);
break;
case WPS_EV_PWD_AUTH_FAIL:
hostapd_pwd_auth_fail(hapd, &data->pwd_auth_fail);
break;
case WPS_EV_PBC_OVERLAP:
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_OVERLAP);
break;
case WPS_EV_PBC_TIMEOUT:
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_TIMEOUT);
break;
case WPS_EV_ER_AP_ADD:
break;
case WPS_EV_ER_AP_REMOVE:
break;
case WPS_EV_ER_ENROLLEE_ADD:
break;
case WPS_EV_ER_ENROLLEE_REMOVE:
break;
case WPS_EV_ER_AP_SETTINGS:
break;
case WPS_EV_ER_SET_SELECTED_REGISTRAR:
break;
case WPS_EV_AP_PIN_SUCCESS:
hostapd_wps_ap_pin_success(hapd);
break;
}
if (hapd->wps_event_cb)
hapd->wps_event_cb(hapd->wps_event_cb_ctx, event, data);
}
@ -495,7 +680,81 @@ static void hostapd_wps_clear_ies(struct hostapd_data *hapd)
wpabuf_free(hapd->wps_probe_resp_ie);
hapd->wps_probe_resp_ie = NULL;
hapd->drv.set_ap_wps_ie(hapd);
hostapd_set_ap_wps_ie(hapd);
}
static int get_uuid_cb(struct hostapd_iface *iface, void *ctx)
{
const u8 **uuid = ctx;
size_t j;
if (iface == NULL)
return 0;
for (j = 0; j < iface->num_bss; j++) {
struct hostapd_data *hapd = iface->bss[j];
if (hapd->wps && !is_nil_uuid(hapd->wps->uuid)) {
*uuid = hapd->wps->uuid;
return 1;
}
}
return 0;
}
static const u8 * get_own_uuid(struct hostapd_iface *iface)
{
const u8 *uuid;
if (iface->for_each_interface == NULL)
return NULL;
uuid = NULL;
iface->for_each_interface(iface->interfaces, get_uuid_cb, &uuid);
return uuid;
}
static int count_interface_cb(struct hostapd_iface *iface, void *ctx)
{
int *count= ctx;
(*count)++;
return 0;
}
static int interface_count(struct hostapd_iface *iface)
{
int count = 0;
if (iface->for_each_interface == NULL)
return 0;
iface->for_each_interface(iface->interfaces, count_interface_cb,
&count);
return count;
}
static int hostapd_wps_set_vendor_ext(struct hostapd_data *hapd,
struct wps_context *wps)
{
int i;
for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
wpabuf_free(wps->dev.vendor_ext[i]);
wps->dev.vendor_ext[i] = NULL;
if (hapd->conf->wps_vendor_ext[i] == NULL)
continue;
wps->dev.vendor_ext[i] =
wpabuf_dup(hapd->conf->wps_vendor_ext[i]);
if (wps->dev.vendor_ext[i] == NULL) {
while (--i >= 0)
wpabuf_free(wps->dev.vendor_ext[i]);
return -1;
}
}
return 0;
}
@ -522,11 +781,22 @@ int hostapd_init_wps(struct hostapd_data *hapd,
wps->wps_state = hapd->conf->wps_state;
wps->ap_setup_locked = hapd->conf->ap_setup_locked;
if (is_nil_uuid(hapd->conf->uuid)) {
uuid_gen_mac_addr(hapd->own_addr, wps->uuid);
wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC address",
wps->uuid, UUID_LEN);
} else
const u8 *uuid;
uuid = get_own_uuid(hapd->iface);
if (uuid) {
os_memcpy(wps->uuid, uuid, UUID_LEN);
wpa_hexdump(MSG_DEBUG, "WPS: Clone UUID from another "
"interface", wps->uuid, UUID_LEN);
} else {
uuid_gen_mac_addr(hapd->own_addr, wps->uuid);
wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC "
"address", wps->uuid, UUID_LEN);
}
} else {
os_memcpy(wps->uuid, hapd->conf->uuid, UUID_LEN);
wpa_hexdump(MSG_DEBUG, "WPS: Use configured UUID",
wps->uuid, UUID_LEN);
}
wps->ssid_len = hapd->conf->ssid.ssid_len;
os_memcpy(wps->ssid, hapd->conf->ssid.ssid, wps->ssid_len);
wps->ap = 1;
@ -543,13 +813,30 @@ int hostapd_init_wps(struct hostapd_data *hapd,
os_strdup(hapd->conf->serial_number) : NULL;
wps->config_methods =
wps_config_methods_str2bin(hapd->conf->config_methods);
if (hapd->conf->device_type &&
wps_dev_type_str2bin(hapd->conf->device_type,
wps->dev.pri_dev_type) < 0) {
wpa_printf(MSG_ERROR, "WPS: Invalid device_type");
#ifdef CONFIG_WPS2
if ((wps->config_methods &
(WPS_CONFIG_DISPLAY | WPS_CONFIG_VIRT_DISPLAY |
WPS_CONFIG_PHY_DISPLAY)) == WPS_CONFIG_DISPLAY) {
wpa_printf(MSG_INFO, "WPS: Converting display to "
"virtual_display for WPS 2.0 compliance");
wps->config_methods |= WPS_CONFIG_VIRT_DISPLAY;
}
if ((wps->config_methods &
(WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_VIRT_PUSHBUTTON |
WPS_CONFIG_PHY_PUSHBUTTON)) == WPS_CONFIG_PUSHBUTTON) {
wpa_printf(MSG_INFO, "WPS: Converting push_button to "
"virtual_push_button for WPS 2.0 compliance");
wps->config_methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
}
#endif /* CONFIG_WPS2 */
os_memcpy(wps->dev.pri_dev_type, hapd->conf->device_type,
WPS_DEV_TYPE_LEN);
if (hostapd_wps_set_vendor_ext(hapd, wps) < 0) {
os_free(wps);
return -1;
}
wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version);
wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
@ -647,10 +934,13 @@ int hostapd_init_wps(struct hostapd_data *hapd,
conf->skip_cred_build;
if (conf->ssid.security_policy == SECURITY_STATIC_WEP)
cfg.static_wep_only = 1;
cfg.dualband = interface_count(hapd->iface) > 1;
if (cfg.dualband)
wpa_printf(MSG_DEBUG, "WPS: Dualband AP");
wps->registrar = wps_registrar_init(wps, &cfg);
if (wps->registrar == NULL) {
printf("Failed to initialize WPS Registrar\n");
wpa_printf(MSG_ERROR, "Failed to initialize WPS Registrar");
os_free(wps->network_key);
os_free(wps);
return -1;
@ -662,14 +952,6 @@ int hostapd_init_wps(struct hostapd_data *hapd,
wps->model_description = hapd->conf->model_description;
wps->model_url = hapd->conf->model_url;
wps->upc = hapd->conf->upc;
if (hostapd_wps_upnp_init(hapd, wps) < 0) {
wpa_printf(MSG_ERROR, "Failed to initialize WPS UPnP");
wps_registrar_deinit(wps->registrar);
os_free(wps->network_key);
os_free(wps);
return -1;
}
#endif /* CONFIG_WPS_UPNP */
hostapd_register_probereq_cb(hapd, hostapd_wps_probe_req_rx, hapd);
@ -680,6 +962,28 @@ int hostapd_init_wps(struct hostapd_data *hapd,
}
int hostapd_init_wps_complete(struct hostapd_data *hapd)
{
struct wps_context *wps = hapd->wps;
if (wps == NULL)
return 0;
#ifdef CONFIG_WPS_UPNP
if (hostapd_wps_upnp_init(hapd, wps) < 0) {
wpa_printf(MSG_ERROR, "Failed to initialize WPS UPnP");
wps_registrar_deinit(wps->registrar);
os_free(wps->network_key);
os_free(wps);
hapd->wps = NULL;
return -1;
}
#endif /* CONFIG_WPS_UPNP */
return 0;
}
void hostapd_deinit_wps(struct hostapd_data *hapd)
{
eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
@ -707,6 +1011,17 @@ void hostapd_update_wps(struct hostapd_data *hapd)
{
if (hapd->wps == NULL)
return;
#ifdef CONFIG_WPS_UPNP
hapd->wps->friendly_name = hapd->conf->friendly_name;
hapd->wps->manufacturer_url = hapd->conf->manufacturer_url;
hapd->wps->model_description = hapd->conf->model_description;
hapd->wps->model_url = hapd->conf->model_url;
hapd->wps->upc = hapd->conf->upc;
#endif /* CONFIG_WPS_UPNP */
hostapd_wps_set_vendor_ext(hapd, hapd->wps);
if (hapd->conf->wps_state)
wps_registrar_update_ie(hapd->wps->registrar);
else
@ -714,29 +1029,72 @@ void hostapd_update_wps(struct hostapd_data *hapd)
}
int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
const char *pin, int timeout)
struct wps_add_pin_data {
const u8 *addr;
const u8 *uuid;
const u8 *pin;
size_t pin_len;
int timeout;
int added;
};
static int wps_add_pin(struct hostapd_data *hapd, void *ctx)
{
u8 u[UUID_LEN];
int any = 0;
struct wps_add_pin_data *data = ctx;
int ret;
if (hapd->wps == NULL)
return -1;
if (os_strcmp(uuid, "any") == 0)
any = 1;
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),
timeout);
return 0;
ret = wps_registrar_add_pin(hapd->wps->registrar, data->addr,
data->uuid, data->pin, data->pin_len,
data->timeout);
if (ret == 0)
data->added++;
return ret;
}
int hostapd_wps_button_pushed(struct hostapd_data *hapd)
int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
const char *uuid, const char *pin, int timeout)
{
if (hapd->wps == NULL)
u8 u[UUID_LEN];
struct wps_add_pin_data data;
data.addr = addr;
data.uuid = u;
data.pin = (const u8 *) pin;
data.pin_len = os_strlen(pin);
data.timeout = timeout;
data.added = 0;
if (os_strcmp(uuid, "any") == 0)
data.uuid = NULL;
else {
if (uuid_str2bin(uuid, u))
return -1;
data.uuid = u;
}
if (hostapd_wps_for_each(hapd, wps_add_pin, &data) < 0)
return -1;
return wps_registrar_button_pushed(hapd->wps->registrar);
return data.added ? 0 : -1;
}
static int wps_button_pushed(struct hostapd_data *hapd, void *ctx)
{
const u8 *p2p_dev_addr = ctx;
if (hapd->wps == NULL)
return 0;
return wps_registrar_button_pushed(hapd->wps->registrar, p2p_dev_addr);
}
int hostapd_wps_button_pushed(struct hostapd_data *hapd,
const u8 *p2p_dev_addr)
{
return hostapd_wps_for_each(hapd, wps_button_pushed,
(void *) p2p_dev_addr);
}
@ -777,7 +1135,7 @@ int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
if ((wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ||
wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) &&
hostapd_wps_add_pin(hapd, "any",
hostapd_wps_add_pin(hapd, NULL, "any",
wpabuf_head(wps->oob_conf.dev_password), 0) <
0)
goto error;
@ -794,7 +1152,8 @@ error:
#endif /* CONFIG_WPS_OOB */
static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr,
static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
const u8 *bssid,
const u8 *ie, size_t ie_len)
{
struct hostapd_data *hapd = ctx;
@ -819,15 +1178,28 @@ static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr,
wps_ie = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
if (wps_ie == NULL)
return 0;
if (wps_validate_probe_req(wps_ie, addr) < 0) {
wpabuf_free(wps_ie);
return 0;
}
if (wpabuf_len(wps_ie) > 0) {
wps_registrar_probe_req_rx(hapd->wps->registrar, addr, wps_ie);
int p2p_wildcard = 0;
#ifdef CONFIG_P2P
if (elems.ssid && elems.ssid_len == P2P_WILDCARD_SSID_LEN &&
os_memcmp(elems.ssid, P2P_WILDCARD_SSID,
P2P_WILDCARD_SSID_LEN) == 0)
p2p_wildcard = 1;
#endif /* CONFIG_P2P */
wps_registrar_probe_req_rx(hapd->wps->registrar, addr, wps_ie,
p2p_wildcard);
#ifdef CONFIG_WPS_UPNP
/* FIX: what exactly should be included in the WLANEvent?
* WPS attributes? Full ProbeReq frame? */
upnp_wps_device_send_wlan_event(hapd->wps_upnp, addr,
UPNP_WPS_WLANEVENT_TYPE_PROBE,
wps_ie);
if (!p2p_wildcard)
upnp_wps_device_send_wlan_event(
hapd->wps_upnp, addr,
UPNP_WPS_WLANEVENT_TYPE_PROBE, wps_ie);
#endif /* CONFIG_WPS_UPNP */
}
@ -864,6 +1236,7 @@ static int hostapd_rx_req_put_wlan_response(
*/
sta = ap_get_sta(hapd, mac_addr);
#ifndef CONFIG_WPS_STRICT
if (!sta) {
/*
* Workaround - Intel wsccmd uses bogus NewWLANEventMAC:
@ -877,8 +1250,9 @@ static int hostapd_rx_req_put_wlan_response(
break;
}
}
#endif /* CONFIG_WPS_STRICT */
if (!sta) {
if (!sta || !(sta->flags & WLAN_STA_WPS)) {
wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found");
return 0;
}
@ -911,26 +1285,19 @@ static int hostapd_wps_upnp_init(struct hostapd_data *hapd,
if (hapd->conf->ap_pin)
ctx->ap_pin = os_strdup(hapd->conf->ap_pin);
hapd->wps_upnp = upnp_wps_device_init(ctx, wps, hapd);
if (hapd->wps_upnp == NULL) {
os_free(ctx);
hapd->wps_upnp = upnp_wps_device_init(ctx, wps, hapd,
hapd->conf->upnp_iface);
if (hapd->wps_upnp == NULL)
return -1;
}
wps->wps_upnp = hapd->wps_upnp;
if (upnp_wps_device_start(hapd->wps_upnp, hapd->conf->upnp_iface)) {
upnp_wps_device_deinit(hapd->wps_upnp);
hapd->wps_upnp = NULL;
return -1;
}
return 0;
}
static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd)
{
upnp_wps_device_deinit(hapd->wps_upnp);
upnp_wps_device_deinit(hapd->wps_upnp, hapd);
}
#endif /* CONFIG_WPS_UPNP */
@ -950,6 +1317,7 @@ static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx)
struct hostapd_data *hapd = eloop_data;
wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out");
hostapd_wps_ap_pin_disable(hapd);
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_PIN_DISABLED);
}
@ -957,6 +1325,7 @@ static void hostapd_wps_ap_pin_enable(struct hostapd_data *hapd, int timeout)
{
wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout);
hapd->ap_pin_failures = 0;
hapd->ap_pin_failures_consecutive = 0;
hapd->conf->ap_setup_locked = 0;
if (hapd->wps->ap_setup_locked) {
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED);
@ -970,31 +1339,53 @@ static void hostapd_wps_ap_pin_enable(struct hostapd_data *hapd, int timeout)
}
void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd)
static int wps_ap_pin_disable(struct hostapd_data *hapd, void *ctx)
{
wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN");
os_free(hapd->conf->ap_pin);
hapd->conf->ap_pin = NULL;
#ifdef CONFIG_WPS_UPNP
upnp_wps_set_ap_pin(hapd->wps_upnp, NULL);
#endif /* CONFIG_WPS_UPNP */
eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL);
return 0;
}
void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd)
{
wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN");
hostapd_wps_for_each(hapd, wps_ap_pin_disable, NULL);
}
struct wps_ap_pin_data {
char pin_txt[9];
int timeout;
};
static int wps_ap_pin_set(struct hostapd_data *hapd, void *ctx)
{
struct wps_ap_pin_data *data = ctx;
os_free(hapd->conf->ap_pin);
hapd->conf->ap_pin = os_strdup(data->pin_txt);
#ifdef CONFIG_WPS_UPNP
upnp_wps_set_ap_pin(hapd->wps_upnp, data->pin_txt);
#endif /* CONFIG_WPS_UPNP */
hostapd_wps_ap_pin_enable(hapd, data->timeout);
return 0;
}
const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout)
{
unsigned int pin;
char pin_txt[9];
struct wps_ap_pin_data data;
pin = wps_generate_pin();
os_snprintf(pin_txt, sizeof(pin_txt), "%u", pin);
os_free(hapd->conf->ap_pin);
hapd->conf->ap_pin = os_strdup(pin_txt);
#ifdef CONFIG_WPS_UPNP
upnp_wps_set_ap_pin(hapd->wps_upnp, pin_txt);
#endif /* CONFIG_WPS_UPNP */
hostapd_wps_ap_pin_enable(hapd, timeout);
os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%08u", pin);
data.timeout = timeout;
hostapd_wps_for_each(hapd, wps_ap_pin_set, &data);
return hapd->conf->ap_pin;
}
@ -1008,13 +1399,75 @@ const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd)
int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
int timeout)
{
os_free(hapd->conf->ap_pin);
hapd->conf->ap_pin = os_strdup(pin);
if (hapd->conf->ap_pin == NULL)
struct wps_ap_pin_data data;
int ret;
ret = os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%s", pin);
if (ret < 0 || ret >= (int) sizeof(data.pin_txt))
return -1;
#ifdef CONFIG_WPS_UPNP
upnp_wps_set_ap_pin(hapd->wps_upnp, hapd->conf->ap_pin);
#endif /* CONFIG_WPS_UPNP */
hostapd_wps_ap_pin_enable(hapd, timeout);
data.timeout = timeout;
return hostapd_wps_for_each(hapd, wps_ap_pin_set, &data);
}
static int wps_update_ie(struct hostapd_data *hapd, void *ctx)
{
if (hapd->wps)
wps_registrar_update_ie(hapd->wps->registrar);
return 0;
}
void hostapd_wps_update_ie(struct hostapd_data *hapd)
{
hostapd_wps_for_each(hapd, wps_update_ie, NULL);
}
int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
const char *auth, const char *encr, const char *key)
{
struct wps_credential cred;
size_t len;
os_memset(&cred, 0, sizeof(cred));
len = os_strlen(ssid);
if ((len & 1) || len > 2 * sizeof(cred.ssid) ||
hexstr2bin(ssid, cred.ssid, len / 2))
return -1;
cred.ssid_len = len / 2;
if (os_strncmp(auth, "OPEN", 4) == 0)
cred.auth_type = WPS_AUTH_OPEN;
else if (os_strncmp(auth, "WPAPSK", 6) == 0)
cred.auth_type = WPS_AUTH_WPAPSK;
else if (os_strncmp(auth, "WPA2PSK", 7) == 0)
cred.auth_type = WPS_AUTH_WPA2PSK;
else
return -1;
if (encr) {
if (os_strncmp(encr, "NONE", 4) == 0)
cred.encr_type = WPS_ENCR_NONE;
else if (os_strncmp(encr, "WEP", 3) == 0)
cred.encr_type = WPS_ENCR_WEP;
else if (os_strncmp(encr, "TKIP", 4) == 0)
cred.encr_type = WPS_ENCR_TKIP;
else if (os_strncmp(encr, "CCMP", 4) == 0)
cred.encr_type = WPS_ENCR_AES;
else
return -1;
} else
cred.encr_type = WPS_ENCR_NONE;
if (key) {
len = os_strlen(key);
if ((len & 1) || len > 2 * sizeof(cred.key) ||
hexstr2bin(key, cred.key, len / 2))
return -1;
cred.key_len = len / 2;
}
return wps_registrar_config_ap(hapd->wps->registrar, &cred);
}

View File

@ -19,11 +19,13 @@
int hostapd_init_wps(struct hostapd_data *hapd,
struct hostapd_bss_config *conf);
int hostapd_init_wps_complete(struct hostapd_data *hapd);
void hostapd_deinit_wps(struct hostapd_data *hapd);
void hostapd_update_wps(struct hostapd_data *hapd);
int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
const char *pin, int timeout);
int hostapd_wps_button_pushed(struct hostapd_data *hapd);
int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
const char *uuid, const char *pin, int timeout);
int hostapd_wps_button_pushed(struct hostapd_data *hapd,
const u8 *p2p_dev_addr);
int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
char *path, char *method, char *name);
int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr,
@ -33,6 +35,9 @@ const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout);
const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd);
int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
int timeout);
void hostapd_wps_update_ie(struct hostapd_data *hapd);
int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
const char *auth, const char *encr, const char *key);
#else /* CONFIG_WPS */
@ -46,6 +51,11 @@ static inline void hostapd_deinit_wps(struct hostapd_data *hapd)
{
}
static inline int hostapd_init_wps_complete(struct hostapd_data *hapd)
{
return 0;
}
static inline void hostapd_update_wps(struct hostapd_data *hapd)
{
}
@ -57,7 +67,8 @@ static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd,
return 0;
}
static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd)
static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd,
const u8 *p2p_dev_addr)
{
return 0;
}

View File

@ -46,28 +46,34 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
{
return akm == WPA_KEY_MGMT_IEEE8021X ||
akm == WPA_KEY_MGMT_FT_IEEE8021X ||
akm == WPA_KEY_MGMT_IEEE8021X_SHA256;
return !!(akm & (WPA_KEY_MGMT_IEEE8021X |
WPA_KEY_MGMT_FT_IEEE8021X |
WPA_KEY_MGMT_IEEE8021X_SHA256));
}
static inline int wpa_key_mgmt_wpa_psk(int akm)
{
return akm == WPA_KEY_MGMT_PSK ||
akm == WPA_KEY_MGMT_FT_PSK ||
akm == WPA_KEY_MGMT_PSK_SHA256;
return !!(akm & (WPA_KEY_MGMT_PSK |
WPA_KEY_MGMT_FT_PSK |
WPA_KEY_MGMT_PSK_SHA256));
}
static inline int wpa_key_mgmt_ft(int akm)
{
return akm == WPA_KEY_MGMT_FT_PSK ||
akm == WPA_KEY_MGMT_FT_IEEE8021X;
return !!(akm & (WPA_KEY_MGMT_FT_PSK |
WPA_KEY_MGMT_FT_IEEE8021X));
}
static inline int wpa_key_mgmt_sha256(int akm)
{
return akm == WPA_KEY_MGMT_PSK_SHA256 ||
akm == WPA_KEY_MGMT_IEEE8021X_SHA256;
return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 |
WPA_KEY_MGMT_IEEE8021X_SHA256));
}
static inline int wpa_key_mgmt_wpa(int akm)
{
return wpa_key_mgmt_wpa_ieee8021x(akm) ||
wpa_key_mgmt_wpa_psk(akm);
}
@ -136,6 +142,15 @@ enum wpa_states {
*/
WPA_DISCONNECTED,
/**
* WPA_INTERFACE_DISABLED - Interface disabled
*
* This stat eis entered if the network interface is disabled, e.g.,
* due to rfkill. wpa_supplicant refuses any new operations that would
* use the radio until the interface has been enabled.
*/
WPA_INTERFACE_DISABLED,
/**
* WPA_INACTIVE - Inactive state (wpa_supplicant disabled)
*
@ -252,4 +267,18 @@ enum hostapd_hw_mode {
NUM_HOSTAPD_MODES
};
/**
* enum wpa_ctrl_req_type - Control interface request types
*/
enum wpa_ctrl_req_type {
WPA_CTRL_REQ_UNKNOWN,
WPA_CTRL_REQ_EAP_IDENTITY,
WPA_CTRL_REQ_EAP_PASSWORD,
WPA_CTRL_REQ_EAP_NEW_PASSWORD,
WPA_CTRL_REQ_EAP_PIN,
WPA_CTRL_REQ_EAP_OTP,
WPA_CTRL_REQ_EAP_PASSPHRASE,
NUM_WPA_CTRL_REQS
};
#endif /* DEFS_H */

279
external/bsd/wpa/dist/src/common/gas.c vendored Normal file
View File

@ -0,0 +1,279 @@
/*
* Generic advertisement service (GAS) (IEEE 802.11u)
* Copyright (c) 2009, Atheros Communications
* Copyright (c) 2011, Qualcomm Atheros
*
* 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 "common.h"
#include "ieee802_11_defs.h"
#include "gas.h"
static struct wpabuf *
gas_build_req(u8 action, u8 dialog_token, size_t size)
{
struct wpabuf *buf;
buf = wpabuf_alloc(100 + size);
if (buf == NULL)
return NULL;
wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
wpabuf_put_u8(buf, action);
wpabuf_put_u8(buf, dialog_token);
return buf;
}
static struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size)
{
return gas_build_req(WLAN_PA_GAS_INITIAL_REQ, dialog_token,
size);
}
struct wpabuf * gas_build_comeback_req(u8 dialog_token)
{
return gas_build_req(WLAN_PA_GAS_COMEBACK_REQ, dialog_token, 0);
}
static struct wpabuf *
gas_build_resp(u8 action, u8 dialog_token, u16 status_code, u8 frag_id,
u8 more, u16 comeback_delay, size_t size)
{
struct wpabuf *buf;
buf = wpabuf_alloc(100 + size);
if (buf == NULL)
return NULL;
wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
wpabuf_put_u8(buf, action);
wpabuf_put_u8(buf, dialog_token);
wpabuf_put_le16(buf, status_code);
if (action == WLAN_PA_GAS_COMEBACK_RESP)
wpabuf_put_u8(buf, frag_id | (more ? 0x80 : 0));
wpabuf_put_le16(buf, comeback_delay);
return buf;
}
struct wpabuf *
gas_build_initial_resp(u8 dialog_token, u16 status_code, u16 comeback_delay,
size_t size)
{
return gas_build_resp(WLAN_PA_GAS_INITIAL_RESP, dialog_token,
status_code, 0, 0, comeback_delay, size);
}
static struct wpabuf *
gas_build_comeback_resp(u8 dialog_token, u16 status_code, u8 frag_id, u8 more,
u16 comeback_delay, size_t size)
{
return gas_build_resp(WLAN_PA_GAS_COMEBACK_RESP, dialog_token,
status_code, frag_id, more, comeback_delay,
size);
}
/**
* gas_add_adv_proto_anqp - Add an Advertisement Protocol element
* @buf: Buffer to which the element is added
* @query_resp_len_limit: Query Response Length Limit in units of 256 octets
* @pame_bi: Pre-Association Message Exchange BSSID Independent (0/1)
*
*
* @query_resp_len_limit is 0 for request and 1-0x7f for response. 0x7f means
* that the maximum limit is determined by the maximum allowable number of
* fragments in the GAS Query Response Fragment ID.
*/
static void gas_add_adv_proto_anqp(struct wpabuf *buf, u8 query_resp_len_limit,
u8 pame_bi)
{
/* Advertisement Protocol IE */
wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
wpabuf_put_u8(buf, 2); /* Length */
wpabuf_put_u8(buf, (query_resp_len_limit & 0x7f) |
(pame_bi ? 0x80 : 0));
/* Advertisement Protocol */
wpabuf_put_u8(buf, ACCESS_NETWORK_QUERY_PROTOCOL);
}
struct wpabuf * gas_anqp_build_initial_req(u8 dialog_token, size_t size)
{
struct wpabuf *buf;
buf = gas_build_initial_req(dialog_token, 4 + size);
if (buf == NULL)
return NULL;
gas_add_adv_proto_anqp(buf, 0, 0);
wpabuf_put(buf, 2); /* Query Request Length to be filled */
return buf;
}
struct wpabuf * gas_anqp_build_initial_resp(u8 dialog_token, u16 status_code,
u16 comeback_delay, size_t size)
{
struct wpabuf *buf;
buf = gas_build_initial_resp(dialog_token, status_code, comeback_delay,
4 + size);
if (buf == NULL)
return NULL;
gas_add_adv_proto_anqp(buf, 0x7f, 0);
wpabuf_put(buf, 2); /* Query Response Length to be filled */
return buf;
}
struct wpabuf * gas_anqp_build_initial_resp_buf(u8 dialog_token,
u16 status_code,
u16 comeback_delay,
struct wpabuf *payload)
{
struct wpabuf *buf;
buf = gas_anqp_build_initial_resp(dialog_token, status_code,
comeback_delay,
payload ? wpabuf_len(payload) : 0);
if (buf == NULL)
return NULL;
if (payload)
wpabuf_put_buf(buf, payload);
gas_anqp_set_len(buf);
return buf;
}
struct wpabuf * gas_anqp_build_comeback_resp(u8 dialog_token, u16 status_code,
u8 frag_id, u8 more,
u16 comeback_delay, size_t size)
{
struct wpabuf *buf;
buf = gas_build_comeback_resp(dialog_token, status_code,
frag_id, more, comeback_delay, 4 + size);
if (buf == NULL)
return NULL;
gas_add_adv_proto_anqp(buf, 0x7f, 0);
wpabuf_put(buf, 2); /* Query Response Length to be filled */
return buf;
}
struct wpabuf * gas_anqp_build_comeback_resp_buf(u8 dialog_token,
u16 status_code,
u8 frag_id, u8 more,
u16 comeback_delay,
struct wpabuf *payload)
{
struct wpabuf *buf;
buf = gas_anqp_build_comeback_resp(dialog_token, status_code, frag_id,
more, comeback_delay,
payload ? wpabuf_len(payload) : 0);
if (buf == NULL)
return NULL;
if (payload)
wpabuf_put_buf(buf, payload);
gas_anqp_set_len(buf);
return buf;
}
/**
* gas_anqp_set_len - Set Query Request/Response Length
* @buf: GAS message
*
* This function is used to update the Query Request/Response Length field once
* the payload has been filled.
*/
void gas_anqp_set_len(struct wpabuf *buf)
{
u8 action;
size_t offset;
u8 *len;
if (buf == NULL || wpabuf_len(buf) < 2)
return;
action = *(wpabuf_head_u8(buf) + 1);
switch (action) {
case WLAN_PA_GAS_INITIAL_REQ:
offset = 3 + 4;
break;
case WLAN_PA_GAS_INITIAL_RESP:
offset = 7 + 4;
break;
case WLAN_PA_GAS_COMEBACK_RESP:
offset = 8 + 4;
break;
default:
return;
}
if (wpabuf_len(buf) < offset + 2)
return;
len = wpabuf_mhead_u8(buf) + offset;
WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
}
/**
* gas_anqp_add_element - Add ANQP element header
* @buf: GAS message
* @info_id: ANQP Info ID
* Returns: Pointer to the Length field for gas_anqp_set_element_len()
*/
u8 * gas_anqp_add_element(struct wpabuf *buf, u16 info_id)
{
wpabuf_put_le16(buf, info_id);
return wpabuf_put(buf, 2); /* Length to be filled */
}
/**
* gas_anqp_set_element_len - Update ANQP element Length field
* @buf: GAS message
* @len_pos: Length field position from gas_anqp_add_element()
*
* This function is called after the ANQP element payload has been added to the
* buffer.
*/
void gas_anqp_set_element_len(struct wpabuf *buf, u8 *len_pos)
{
WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(buf, 0) - len_pos - 2);
}

42
external/bsd/wpa/dist/src/common/gas.h vendored Normal file
View File

@ -0,0 +1,42 @@
/*
* Generic advertisement service (GAS) (IEEE 802.11u)
* Copyright (c) 2009, Atheros Communications
* Copyright (c) 2011, Qualcomm Atheros
*
* 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.
*/
#ifndef GAS_H
#define GAS_H
struct wpabuf * gas_build_comeback_req(u8 dialog_token);
struct wpabuf * gas_build_initial_resp(u8 dialog_token, u16 status_code,
u16 comeback_delay, size_t size);
struct wpabuf * gas_anqp_build_initial_req(u8 dialog_token, size_t size);
struct wpabuf * gas_anqp_build_initial_resp(u8 dialog_token, u16 status_code,
u16 comeback_delay, size_t size);
struct wpabuf * gas_anqp_build_initial_resp_buf(u8 dialog_token,
u16 status_code,
u16 comeback_delay,
struct wpabuf *payload);
struct wpabuf * gas_anqp_build_comeback_resp(u8 dialog_token, u16 status_code,
u8 frag_id, u8 more,
u16 comeback_delay, size_t size);
struct wpabuf * gas_anqp_build_comeback_resp_buf(u8 dialog_token,
u16 status_code,
u8 frag_id, u8 more,
u16 comeback_delay,
struct wpabuf *payload);
void gas_anqp_set_len(struct wpabuf *buf);
u8 * gas_anqp_add_element(struct wpabuf *buf, u16 info_id);
void gas_anqp_set_element_len(struct wpabuf *buf, u8 *len_pos);
#endif /* GAS_H */

View File

@ -75,7 +75,7 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
elems->wmm_tspec_len = elen;
break;
default:
wpa_printf(MSG_MSGDUMP, "unknown WMM "
wpa_printf(MSG_EXCESSIVE, "unknown WMM "
"information element ignored "
"(subtype=%d len=%lu)",
pos[4], (unsigned long) elen);
@ -88,7 +88,23 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
elems->wps_ie_len = elen;
break;
default:
wpa_printf(MSG_MSGDUMP, "Unknown Microsoft "
wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
"information element ignored "
"(type=%d len=%lu)",
pos[3], (unsigned long) elen);
return -1;
}
break;
case OUI_WFA:
switch (pos[3]) {
case P2P_OUI_TYPE:
/* Wi-Fi Alliance - P2P IE */
elems->p2p = pos;
elems->p2p_len = elen;
break;
default:
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
"information element ignored "
"(type=%d len=%lu)\n",
pos[3], (unsigned long) elen);
@ -103,18 +119,18 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
elems->vendor_ht_cap_len = elen;
break;
default:
wpa_printf(MSG_MSGDUMP, "Unknown Broadcom "
wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
"information element ignored "
"(type=%d len=%lu)\n",
"(type=%d len=%lu)",
pos[3], (unsigned long) elen);
return -1;
}
break;
default:
wpa_printf(MSG_MSGDUMP, "unknown vendor specific information "
"element ignored (vendor OUI %02x:%02x:%02x "
"len=%lu)",
wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
"information element ignored (vendor OUI "
"%02x:%02x:%02x len=%lu)",
pos[0], pos[1], pos[2], (unsigned long) elen);
return -1;
}
@ -238,6 +254,15 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->ht_operation = pos;
elems->ht_operation_len = elen;
break;
case WLAN_EID_LINK_ID:
if (elen < 18)
break;
elems->link_id = pos;
break;
case WLAN_EID_INTERWORKING:
elems->interworking = pos;
elems->interworking_len = elen;
break;
default:
unknown++;
if (!show_errors)
@ -324,3 +349,43 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
return buf;
}
const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
{
u16 fc, type, stype;
/*
* PS-Poll frames are 16 bytes. All other frames are
* 24 bytes or longer.
*/
if (len < 16)
return NULL;
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_DATA:
if (len < 24)
return NULL;
switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
case WLAN_FC_FROMDS | WLAN_FC_TODS:
case WLAN_FC_TODS:
return hdr->addr1;
case WLAN_FC_FROMDS:
return hdr->addr2;
default:
return NULL;
}
case WLAN_FC_TYPE_CTRL:
if (stype != WLAN_FC_STYPE_PSPOLL)
return NULL;
return hdr->addr1;
case WLAN_FC_TYPE_MGMT:
return hdr->addr3;
default:
return NULL;
}
}

View File

@ -40,6 +40,9 @@ struct ieee802_11_elems {
const u8 *ht_capabilities;
const u8 *ht_operation;
const u8 *vendor_ht_cap;
const u8 *p2p;
const u8 *link_id;
const u8 *interworking;
u8 ssid_len;
u8 supp_rates_len;
@ -64,6 +67,8 @@ struct ieee802_11_elems {
u8 ht_capabilities_len;
u8 ht_operation_len;
u8 vendor_ht_cap_len;
u8 p2p_len;
u8 interworking_len;
};
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
@ -74,5 +79,7 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
int ieee802_11_ie_count(const u8 *ies, size_t ies_len);
struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
u32 oui_type);
struct ieee80211_hdr;
const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len);
#endif /* IEEE802_11_COMMON_H */

View File

@ -71,6 +71,12 @@
#define WLAN_FC_STYPE_CFPOLL 6
#define WLAN_FC_STYPE_CFACKPOLL 7
#define WLAN_FC_STYPE_QOS_DATA 8
#define WLAN_FC_STYPE_QOS_DATA_CFACK 9
#define WLAN_FC_STYPE_QOS_DATA_CFPOLL 10
#define WLAN_FC_STYPE_QOS_DATA_CFACKPOLL 11
#define WLAN_FC_STYPE_QOS_NULL 12
#define WLAN_FC_STYPE_QOS_CFPOLL 14
#define WLAN_FC_STYPE_QOS_CFACKPOLL 15
/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
@ -95,6 +101,11 @@
/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */
#define WLAN_STATUS_SUCCESS 0
#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
#define WLAN_STATUS_TDLS_WAKEUP_ALTERNATE 2
#define WLAN_STATUS_TDLS_WAKEUP_REJECT 3
#define WLAN_STATUS_SECURITY_DISABLED 5
#define WLAN_STATUS_UNACCEPTABLE_LIFETIME 6
#define WLAN_STATUS_NOT_IN_SAME_BSS 7
#define WLAN_STATUS_CAPS_UNSUPPORTED 10
#define WLAN_STATUS_REASSOC_NO_ASSOC 11
#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12
@ -114,9 +125,10 @@
#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24
/* IEEE 802.11g */
#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
#define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26
#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27
#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 26
#define WLAN_STATUS_ASSOC_DENIED_NO_HT 27
#define WLAN_STATUS_R0KH_UNREACHABLE 28
#define WLAN_STATUS_ASSOC_DENIED_NO_PCO 29
/* IEEE 802.11w */
#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30
#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
@ -141,6 +153,17 @@
#define WLAN_STATUS_INVALID_PMKID 53
#define WLAN_STATUS_INVALID_MDIE 54
#define WLAN_STATUS_INVALID_FTIE 55
#define WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED 59
#define WLAN_STATUS_NO_OUTSTANDING_GAS_REQ 60
#define WLAN_STATUS_GAS_RESP_NOT_RECEIVED 61
#define WLAN_STATUS_STA_TIMED_OUT_WAITING_FOR_GAS_RESP 62
#define WLAN_STATUS_GAS_RESP_LARGER_THAN_LIMIT 63
#define WLAN_STATUS_REQ_REFUSED_HOME 64
#define WLAN_STATUS_ADV_SRV_UNREACHABLE 65
#define WLAN_STATUS_REQ_REFUSED_SSPN 67
#define WLAN_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68
#define WLAN_STATUS_INVALID_RSNIE 72
#define WLAN_STATUS_TRANSMISSION_FAILURE 79
/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
#define WLAN_REASON_UNSPECIFIED 1
@ -168,6 +191,10 @@
#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22
#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23
#define WLAN_REASON_CIPHER_SUITE_REJECTED 24
#define WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE 25
#define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26
/* IEEE 802.11e */
#define WLAN_REASON_DISASSOC_LOW_ACK 34
/* Information Element IDs */
@ -202,10 +229,17 @@
#define WLAN_EID_RIC_DATA 57
#define WLAN_EID_HT_OPERATION 61
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
#define WLAN_EID_TIME_ADVERTISEMENT 69
#define WLAN_EID_20_40_BSS_COEXISTENCE 72
#define WLAN_EID_20_40_BSS_INTOLERANT 73
#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
#define WLAN_EID_MMIE 76
#define WLAN_EID_TIME_ZONE 98
#define WLAN_EID_LINK_ID 101
#define WLAN_EID_INTERWORKING 107
#define WLAN_EID_ADV_PROTO 108
#define WLAN_EID_ROAMING_CONSORTIUM 111
#define WLAN_EID_EXT_CAPAB 127
#define WLAN_EID_VENDOR_SPECIFIC 221
@ -219,7 +253,19 @@
#define WLAN_ACTION_FT 6
#define WLAN_ACTION_HT 7
#define WLAN_ACTION_SA_QUERY 8
#define WLAN_ACTION_WNM 10
#define WLAN_ACTION_UNPROTECTED_WNM 11
#define WLAN_ACTION_TDLS 12
#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
#define WLAN_ACTION_VENDOR_SPECIFIC 127
/* Public action codes */
#define WLAN_PA_VENDOR_SPECIFIC 9
#define WLAN_PA_GAS_INITIAL_REQ 10
#define WLAN_PA_GAS_INITIAL_RESP 11
#define WLAN_PA_GAS_COMEBACK_REQ 12
#define WLAN_PA_GAS_COMEBACK_RESP 13
#define WLAN_TDLS_DISCOVERY_RESPONSE 14
/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
#define WLAN_SA_QUERY_REQUEST 0
@ -227,11 +273,99 @@
#define WLAN_SA_QUERY_TR_ID_LEN 2
/* TDLS action codes */
#define WLAN_TDLS_SETUP_REQUEST 0
#define WLAN_TDLS_SETUP_RESPONSE 1
#define WLAN_TDLS_SETUP_CONFIRM 2
#define WLAN_TDLS_TEARDOWN 3
#define WLAN_TDLS_PEER_TRAFFIC_INDICATION 4
#define WLAN_TDLS_CHANNEL_SWITCH_REQUEST 5
#define WLAN_TDLS_CHANNEL_SWITCH_RESPONSE 6
#define WLAN_TDLS_PEER_PSM_REQUEST 7
#define WLAN_TDLS_PEER_PSM_RESPONSE 8
#define WLAN_TDLS_PEER_TRAFFIC_RESPONSE 9
#define WLAN_TDLS_DISCOVERY_REQUEST 10
/* Timeout Interval Type */
#define WLAN_TIMEOUT_REASSOC_DEADLINE 1
#define WLAN_TIMEOUT_KEY_LIFETIME 2
#define WLAN_TIMEOUT_ASSOC_COMEBACK 3
/* Interworking element (IEEE 802.11u) - Access Network Options */
#define INTERWORKING_ANO_ACCESS_NETWORK_MASK 0x0f
#define INTERWORKING_ANO_INTERNET 0x10
#define INTERWORKING_ANO_ASRA 0x20
#define INTERWORKING_ANO_ESR 0x40
#define INTERWORKING_ANO_UESA 0x80
#define INTERWORKING_ANT_PRIVATE 0
#define INTERWORKING_ANT_PRIVATE_WITH_GUEST 1
#define INTERWORKING_ANT_CHARGEABLE_PUBLIC 2
#define INTERWORKING_ANT_FREE_PUBLIC 3
#define INTERWORKING_ANT_PERSONAL_DEVICE 4
#define INTERWORKING_ANT_EMERGENCY_SERVICES 5
#define INTERWORKING_ANT_TEST 6
#define INTERWORKING_ANT_WILDCARD 15
/* Advertisement Protocol ID definitions (IEEE Std 802.11u-2011) */
enum adv_proto_id {
ACCESS_NETWORK_QUERY_PROTOCOL = 0,
MIH_INFO_SERVICE = 1,
MIH_CMD_AND_EVENT_DISCOVERY = 2,
EMERGENCY_ALERT_SYSTEM = 3,
ADV_PROTO_VENDOR_SPECIFIC = 221
};
/* Access Network Query Protocol info ID definitions (IEEE Std 802.11u-2011) */
enum anqp_info_id {
ANQP_QUERY_LIST = 256,
ANQP_CAPABILITY_LIST = 257,
ANQP_VENUE_NAME = 258,
ANQP_EMERGENCY_CALL_NUMBER = 259,
ANQP_NETWORK_AUTH_TYPE = 260,
ANQP_ROAMING_CONSORTIUM = 261,
ANQP_IP_ADDR_TYPE_AVAILABILITY = 262,
ANQP_NAI_REALM = 263,
ANQP_3GPP_CELLULAR_NETWORK = 264,
ANQP_AP_GEOSPATIAL_LOCATION = 265,
ANQP_AP_CIVIC_LOCATION = 266,
ANQP_AP_LOCATION_PUBLIC_URI = 267,
ANQP_DOMAIN_NAME = 268,
ANQP_EMERGENCY_ALERT_URI = 269,
ANQP_EMERGENCY_NAI = 271,
ANQP_VENDOR_SPECIFIC = 56797
};
/* NAI Realm list - EAP Method subfield - Authentication Parameter ID */
enum nai_realm_eap_auth_param {
NAI_REALM_EAP_AUTH_EXPANDED_EAP_METHOD = 1,
NAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH = 2,
NAI_REALM_EAP_AUTH_INNER_AUTH_EAP_METHOD = 3,
NAI_REALM_EAP_AUTH_EXPANDED_INNER_EAP_METHOD = 4,
NAI_REALM_EAP_AUTH_CRED_TYPE = 5,
NAI_REALM_EAP_AUTH_TUNNELED_CRED_TYPE = 6,
NAI_REALM_EAP_AUTH_VENDOR_SPECIFIC = 221
};
enum nai_realm_eap_auth_inner_non_eap {
NAI_REALM_INNER_NON_EAP_PAP = 1,
NAI_REALM_INNER_NON_EAP_CHAP = 2,
NAI_REALM_INNER_NON_EAP_MSCHAP = 3,
NAI_REALM_INNER_NON_EAP_MSCHAPV2 = 4
};
enum nai_realm_eap_cred_type {
NAI_REALM_CRED_TYPE_SIM = 1,
NAI_REALM_CRED_TYPE_USIM = 2,
NAI_REALM_CRED_TYPE_NFC_SECURE_ELEMENT = 3,
NAI_REALM_CRED_TYPE_HARDWARE_TOKEN = 4,
NAI_REALM_CRED_TYPE_SOFTOKEN = 5,
NAI_REALM_CRED_TYPE_CERTIFICATE = 6,
NAI_REALM_CRED_TYPE_USERNAME_PASSWORD = 7,
NAI_REALM_CRED_TYPE_NONE = 8,
NAI_REALM_CRED_TYPE_ANONYMOUS = 9,
NAI_REALM_CRED_TYPE_VENDOR_SPECIFIC = 10
};
#ifdef _MSC_VER
#pragma pack(push, 1)
@ -273,6 +407,7 @@ struct ieee80211_mgmt {
} STRUCT_PACKED auth;
struct {
le16 reason_code;
u8 variable[0];
} STRUCT_PACKED deauth;
struct {
le16 capab_info;
@ -296,6 +431,7 @@ struct ieee80211_mgmt {
} STRUCT_PACKED reassoc_req;
struct {
le16 reason_code;
u8 variable[0];
} STRUCT_PACKED disassoc;
struct {
u8 timestamp[8];
@ -355,6 +491,28 @@ struct ieee80211_mgmt {
u8 action; /* */
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
} STRUCT_PACKED sa_query_resp;
struct {
u8 action;
u8 variable[0];
} STRUCT_PACKED public_action;
struct {
u8 action; /* 9 */
u8 oui[3];
/* Vendor-specific content */
u8 variable[0];
} STRUCT_PACKED vs_public_action;
struct {
u8 action; /* 7 */
u8 dialog_token;
u8 req_mode;
le16 disassoc_timer;
u8 validity_interval;
/* BSS Termination Duration (optional),
* Session Information URL (optional),
* BSS Transition Candidate List
* Entries */
u8 variable[0];
} STRUCT_PACKED bss_tm_req;
} u;
} STRUCT_PACKED action;
} u;
@ -473,11 +631,14 @@ struct ieee80211_ht_operation {
#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10))
#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11))
#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
* 00:50:F2 */
#define WPA_IE_VENDOR_TYPE 0x0050f201
#define WPS_IE_VENDOR_TYPE 0x0050f204
#define OUI_WFA 0x506f9a
#define P2P_IE_VENDOR_TYPE 0x506f9a09
#define WMM_OUI_TYPE 2
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
@ -544,7 +705,7 @@ struct wmm_parameter_element {
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 qos_info; /* AP/STA specific QoS info */
u8 reserved; /* 0 */
struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */
@ -587,6 +748,115 @@ enum {
};
/* Wi-Fi Direct (P2P) */
#define P2P_OUI_TYPE 9
enum p2p_attr_id {
P2P_ATTR_STATUS = 0,
P2P_ATTR_MINOR_REASON_CODE = 1,
P2P_ATTR_CAPABILITY = 2,
P2P_ATTR_DEVICE_ID = 3,
P2P_ATTR_GROUP_OWNER_INTENT = 4,
P2P_ATTR_CONFIGURATION_TIMEOUT = 5,
P2P_ATTR_LISTEN_CHANNEL = 6,
P2P_ATTR_GROUP_BSSID = 7,
P2P_ATTR_EXT_LISTEN_TIMING = 8,
P2P_ATTR_INTENDED_INTERFACE_ADDR = 9,
P2P_ATTR_MANAGEABILITY = 10,
P2P_ATTR_CHANNEL_LIST = 11,
P2P_ATTR_NOTICE_OF_ABSENCE = 12,
P2P_ATTR_DEVICE_INFO = 13,
P2P_ATTR_GROUP_INFO = 14,
P2P_ATTR_GROUP_ID = 15,
P2P_ATTR_INTERFACE = 16,
P2P_ATTR_OPERATING_CHANNEL = 17,
P2P_ATTR_INVITATION_FLAGS = 18,
P2P_ATTR_VENDOR_SPECIFIC = 221
};
#define P2P_MAX_GO_INTENT 15
/* P2P Capability - Device Capability bitmap */
#define P2P_DEV_CAPAB_SERVICE_DISCOVERY BIT(0)
#define P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY BIT(1)
#define P2P_DEV_CAPAB_CONCURRENT_OPER BIT(2)
#define P2P_DEV_CAPAB_INFRA_MANAGED BIT(3)
#define P2P_DEV_CAPAB_DEVICE_LIMIT BIT(4)
#define P2P_DEV_CAPAB_INVITATION_PROCEDURE BIT(5)
/* P2P Capability - Group Capability bitmap */
#define P2P_GROUP_CAPAB_GROUP_OWNER BIT(0)
#define P2P_GROUP_CAPAB_PERSISTENT_GROUP BIT(1)
#define P2P_GROUP_CAPAB_GROUP_LIMIT BIT(2)
#define P2P_GROUP_CAPAB_INTRA_BSS_DIST BIT(3)
#define P2P_GROUP_CAPAB_CROSS_CONN BIT(4)
#define P2P_GROUP_CAPAB_PERSISTENT_RECONN BIT(5)
#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6)
/* Invitation Flags */
#define P2P_INVITATION_FLAGS_TYPE BIT(0)
/* P2P Manageability */
#define P2P_MAN_DEVICE_MANAGEMENT BIT(0)
#define P2P_MAN_CROSS_CONNECTION_PERMITTED BIT(1)
#define P2P_MAN_COEXISTENCE_OPTIONAL BIT(2)
enum p2p_status_code {
P2P_SC_SUCCESS = 0,
P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE = 1,
P2P_SC_FAIL_INCOMPATIBLE_PARAMS = 2,
P2P_SC_FAIL_LIMIT_REACHED = 3,
P2P_SC_FAIL_INVALID_PARAMS = 4,
P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE = 5,
P2P_SC_FAIL_PREV_PROTOCOL_ERROR = 6,
P2P_SC_FAIL_NO_COMMON_CHANNELS = 7,
P2P_SC_FAIL_UNKNOWN_GROUP = 8,
P2P_SC_FAIL_BOTH_GO_INTENT_15 = 9,
P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10,
P2P_SC_FAIL_REJECTED_BY_USER = 11,
};
#define P2P_WILDCARD_SSID "DIRECT-"
#define P2P_WILDCARD_SSID_LEN 7
/* P2P action frames */
enum p2p_act_frame_type {
P2P_NOA = 0,
P2P_PRESENCE_REQ = 1,
P2P_PRESENCE_RESP = 2,
P2P_GO_DISC_REQ = 3
};
/* P2P public action frames */
enum p2p_action_frame_type {
P2P_GO_NEG_REQ = 0,
P2P_GO_NEG_RESP = 1,
P2P_GO_NEG_CONF = 2,
P2P_INVITATION_REQ = 3,
P2P_INVITATION_RESP = 4,
P2P_DEV_DISC_REQ = 5,
P2P_DEV_DISC_RESP = 6,
P2P_PROV_DISC_REQ = 7,
P2P_PROV_DISC_RESP = 8
};
enum p2p_service_protocol_type {
P2P_SERV_ALL_SERVICES = 0,
P2P_SERV_BONJOUR = 1,
P2P_SERV_UPNP = 2,
P2P_SERV_WS_DISCOVERY = 3,
P2P_SERV_VENDOR_SPECIFIC = 255
};
enum p2p_sd_status {
P2P_SD_SUCCESS = 0,
P2P_SD_PROTO_NOT_AVAILABLE = 1,
P2P_SD_REQUESTED_INFO_NOT_AVAILABLE = 2,
P2P_SD_BAD_REQUEST = 3
};
#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
@ -604,4 +874,44 @@ enum {
#define WLAN_AKM_SUITE_8021X 0x000FAC01
#define WLAN_AKM_SUITE_PSK 0x000FAC02
/* IEEE 802.11v - WNM Action field values */
enum wnm_action {
WNM_EVENT_REQ = 0,
WNM_EVENT_REPORT = 1,
WNM_DIAGNOSTIC_REQ = 2,
WNM_DIAGNOSTIC_REPORT = 3,
WNM_LOCATION_CFG_REQ = 4,
WNM_LOCATION_CFG_RESP = 5,
WNM_BSS_TRANS_MGMT_QUERY = 6,
WNM_BSS_TRANS_MGMT_REQ = 7,
WNM_BSS_TRANS_MGMT_RESP = 8,
WNM_FMS_REQ = 9,
WNM_FMS_RESP = 10,
WNM_COLLOCATED_INTERFERENCE_REQ = 11,
WNM_COLLOCATED_INTERFERENCE_REPORT = 12,
WNM_TFS_REQ = 13,
WNM_TFS_RESP = 14,
WNM_TFS_NOTIFY = 15,
WNM_SLEEP_MODE_REQ = 16,
WNM_SLEEP_MODE_RESP = 17,
WNM_TIM_BROADCAST_REQ = 18,
WNM_TIM_BROADCAST_RESP = 19,
WNM_QOS_TRAFFIC_CAPAB_UPDATE = 20,
WNM_CHANNEL_USAGE_REQ = 21,
WNM_CHANNEL_USAGE_RESP = 22,
WNM_DMS_REQ = 23,
WNM_DMS_RESP = 24,
WNM_TIMING_MEASUREMENT_REQ = 25,
WNM_NOTIFICATION_REQ = 26,
WNM_NOTIFICATION_RESP = 27
};
/* IEEE 802.11v - BSS Transition Management Request - Request Mode */
#define WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED BIT(0)
#define WNM_BSS_TM_REQ_ABRIDGED BIT(1)
#define WNM_BSS_TM_REQ_DISASSOC_IMMINENT BIT(2)
#define WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED BIT(3)
#define WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT BIT(4)
#endif /* IEEE802_11_DEFS_H */

View File

@ -1,6 +1,10 @@
#ifndef VERSION_H
#define VERSION_H
#define VERSION_STR "0.7.3"
#ifndef VERSION_STR_POSTFIX
#define VERSION_STR_POSTFIX ""
#endif /* VERSION_STR_POSTFIX */
#define VERSION_STR "1.0" VERSION_STR_POSTFIX
#endif /* VERSION_H */

View File

@ -126,6 +126,8 @@ void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
MAC2STR(addr1), MAC2STR(addr2));
wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN);
wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len);
}
@ -186,6 +188,154 @@ int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr,
return 0;
}
static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
struct wpa_ft_ies *parse)
{
const u8 *end, *pos;
parse->ftie = ie;
parse->ftie_len = ie_len;
pos = ie + sizeof(struct rsn_ftie);
end = ie + ie_len;
while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
switch (pos[0]) {
case FTIE_SUBELEM_R1KH_ID:
if (pos[1] != FT_R1KH_ID_LEN) {
wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "
"length in FTIE: %d", pos[1]);
return -1;
}
parse->r1kh_id = pos + 2;
break;
case FTIE_SUBELEM_GTK:
parse->gtk = pos + 2;
parse->gtk_len = pos[1];
break;
case FTIE_SUBELEM_R0KH_ID:
if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {
wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "
"length in FTIE: %d", pos[1]);
return -1;
}
parse->r0kh_id = pos + 2;
parse->r0kh_id_len = pos[1];
break;
#ifdef CONFIG_IEEE80211W
case FTIE_SUBELEM_IGTK:
parse->igtk = pos + 2;
parse->igtk_len = pos[1];
break;
#endif /* CONFIG_IEEE80211W */
}
pos += 2 + pos[1];
}
return 0;
}
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
struct wpa_ft_ies *parse)
{
const u8 *end, *pos;
struct wpa_ie_data data;
int ret;
const struct rsn_ftie *ftie;
int prot_ie_count = 0;
os_memset(parse, 0, sizeof(*parse));
if (ies == NULL)
return 0;
pos = ies;
end = ies + ies_len;
while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
switch (pos[0]) {
case WLAN_EID_RSN:
parse->rsn = pos + 2;
parse->rsn_len = pos[1];
ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
parse->rsn_len + 2,
&data);
if (ret < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse "
"RSN IE: %d", ret);
return -1;
}
if (data.num_pmkid == 1 && data.pmkid)
parse->rsn_pmkid = data.pmkid;
break;
case WLAN_EID_MOBILITY_DOMAIN:
parse->mdie = pos + 2;
parse->mdie_len = pos[1];
break;
case WLAN_EID_FAST_BSS_TRANSITION:
if (pos[1] < sizeof(*ftie))
return -1;
ftie = (const struct rsn_ftie *) (pos + 2);
prot_ie_count = ftie->mic_control[1];
if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
return -1;
break;
case WLAN_EID_TIMEOUT_INTERVAL:
parse->tie = pos + 2;
parse->tie_len = pos[1];
break;
case WLAN_EID_RIC_DATA:
if (parse->ric == NULL)
parse->ric = pos;
break;
}
pos += 2 + pos[1];
}
if (prot_ie_count == 0)
return 0; /* no MIC */
/*
* Check that the protected IE count matches with IEs included in the
* frame.
*/
if (parse->rsn)
prot_ie_count--;
if (parse->mdie)
prot_ie_count--;
if (parse->ftie)
prot_ie_count--;
if (prot_ie_count < 0) {
wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
"the protected IE count");
return -1;
}
if (prot_ie_count == 0 && parse->ric) {
wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
"included in protected IE count");
return -1;
}
/* Determine the end of the RIC IE(s) */
pos = parse->ric;
while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
prot_ie_count) {
prot_ie_count--;
pos += 2 + pos[1];
}
parse->ric_len = pos - parse->ric;
if (prot_ie_count) {
wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
"frame", (int) prot_ie_count);
return -1;
}
return 0;
}
#endif /* CONFIG_IEEE80211R */
@ -403,6 +553,144 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
}
static int wpa_selector_to_bitfield(const u8 *s)
{
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
return WPA_CIPHER_NONE;
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40)
return WPA_CIPHER_WEP40;
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
return WPA_CIPHER_TKIP;
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
return WPA_CIPHER_CCMP;
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104)
return WPA_CIPHER_WEP104;
return 0;
}
static int wpa_key_mgmt_to_bitfield(const u8 *s)
{
if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
return WPA_KEY_MGMT_IEEE8021X;
if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
return WPA_KEY_MGMT_PSK;
if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
return WPA_KEY_MGMT_WPA_NONE;
return 0;
}
int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
struct wpa_ie_data *data)
{
const struct wpa_ie_hdr *hdr;
const u8 *pos;
int left;
int i, count;
os_memset(data, 0, sizeof(*data));
data->proto = WPA_PROTO_WPA;
data->pairwise_cipher = WPA_CIPHER_TKIP;
data->group_cipher = WPA_CIPHER_TKIP;
data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
data->capabilities = 0;
data->pmkid = NULL;
data->num_pmkid = 0;
data->mgmt_group_cipher = 0;
if (wpa_ie_len == 0) {
/* No WPA IE - fail silently */
return -1;
}
if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) {
wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
__func__, (unsigned long) wpa_ie_len);
return -1;
}
hdr = (const struct wpa_ie_hdr *) wpa_ie;
if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
hdr->len != wpa_ie_len - 2 ||
RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
WPA_GET_LE16(hdr->version) != WPA_VERSION) {
wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
__func__);
return -2;
}
pos = (const u8 *) (hdr + 1);
left = wpa_ie_len - sizeof(*hdr);
if (left >= WPA_SELECTOR_LEN) {
data->group_cipher = wpa_selector_to_bitfield(pos);
pos += WPA_SELECTOR_LEN;
left -= WPA_SELECTOR_LEN;
} else if (left > 0) {
wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
__func__, left);
return -3;
}
if (left >= 2) {
data->pairwise_cipher = 0;
count = WPA_GET_LE16(pos);
pos += 2;
left -= 2;
if (count == 0 || left < count * WPA_SELECTOR_LEN) {
wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
"count %u left %u", __func__, count, left);
return -4;
}
for (i = 0; i < count; i++) {
data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
pos += WPA_SELECTOR_LEN;
left -= WPA_SELECTOR_LEN;
}
} else if (left == 1) {
wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
__func__);
return -5;
}
if (left >= 2) {
data->key_mgmt = 0;
count = WPA_GET_LE16(pos);
pos += 2;
left -= 2;
if (count == 0 || left < count * WPA_SELECTOR_LEN) {
wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
"count %u left %u", __func__, count, left);
return -6;
}
for (i = 0; i < count; i++) {
data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
pos += WPA_SELECTOR_LEN;
left -= WPA_SELECTOR_LEN;
}
} else if (left == 1) {
wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
__func__);
return -7;
}
if (left >= 2) {
data->capabilities = WPA_GET_LE16(pos);
pos += 2;
left -= 2;
}
if (left > 0) {
wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
__func__, left);
}
return 0;
}
#ifdef CONFIG_IEEE80211R
/**

View File

@ -56,6 +56,7 @@
#endif /* CONFIG_IEEE80211R */
#define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
#define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
#define RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
#define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0)
#define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
@ -68,6 +69,7 @@
#ifdef CONFIG_IEEE80211W
#define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
#endif /* CONFIG_IEEE80211W */
#define RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
/* EAPOL-Key Key Data Encapsulation
* GroupKey and PeerKey require encryption, otherwise, encryption is optional.
@ -115,7 +117,13 @@
/* B4-B5: GTKSA Replay Counter */
#define WPA_CAPABILITY_MFPR BIT(6)
#define WPA_CAPABILITY_MFPC BIT(7)
/* B8: Reserved */
#define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9)
#define WPA_CAPABILITY_SPP_A_MSDU_CAPABLE BIT(10)
#define WPA_CAPABILITY_SPP_A_MSDU_REQUIRED BIT(11)
#define WPA_CAPABILITY_PBAC BIT(12)
#define WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST BIT(13)
/* B14-B15: Reserved */
/* IEEE 802.11r */
@ -337,6 +345,8 @@ struct wpa_ie_data {
int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
struct wpa_ie_data *data);
int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
struct wpa_ie_data *data);
void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
u8 *pmkid, int use_sha256);
@ -348,4 +358,27 @@ int wpa_compare_rsn_ie(int ft_initial_assoc,
const u8 *ie2, size_t ie2len);
int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid);
struct wpa_ft_ies {
const u8 *mdie;
size_t mdie_len;
const u8 *ftie;
size_t ftie_len;
const u8 *r1kh_id;
const u8 *gtk;
size_t gtk_len;
const u8 *r0kh_id;
size_t r0kh_id_len;
const u8 *rsn;
size_t rsn_len;
const u8 *rsn_pmkid;
const u8 *tie;
size_t tie_len;
const u8 *igtk;
size_t igtk_len;
const u8 *ric;
size_t ric_len;
};
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse);
#endif /* WPA_COMMON_H */

View File

@ -20,6 +20,12 @@
#include <sys/un.h>
#endif /* CONFIG_CTRL_IFACE_UNIX */
#ifdef ANDROID
#include <dirent.h>
#include <cutils/sockets.h>
#include "private/android_filesystem_config.h"
#endif /* ANDROID */
#include "wpa_ctrl.h"
#include "common.h"
@ -58,6 +64,14 @@ struct wpa_ctrl {
#ifdef CONFIG_CTRL_IFACE_UNIX
#ifndef CONFIG_CTRL_IFACE_CLIENT_DIR
#define CONFIG_CTRL_IFACE_CLIENT_DIR "/tmp"
#endif /* CONFIG_CTRL_IFACE_CLIENT_DIR */
#ifndef CONFIG_CTRL_IFACE_CLIENT_PREFIX
#define CONFIG_CTRL_IFACE_CLIENT_PREFIX "wpa_ctrl_"
#endif /* CONFIG_CTRL_IFACE_CLIENT_PREFIX */
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
{
struct wpa_ctrl *ctrl;
@ -81,7 +95,9 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
counter++;
try_again:
ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
"/tmp/wpa_ctrl_%d-%d", getpid(), counter);
CONFIG_CTRL_IFACE_CLIENT_DIR "/"
CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d",
(int) getpid(), counter);
if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
close(ctrl->s);
os_free(ctrl);
@ -105,6 +121,31 @@ try_again:
return NULL;
}
#ifdef ANDROID
chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
/*
* If the ctrl_path isn't an absolute pathname, assume that
* it's the name of a socket in the Android reserved namespace.
* Otherwise, it's a normal UNIX domain socket appearing in the
* filesystem.
*/
if (ctrl_path != NULL && *ctrl_path != '/') {
char buf[21];
os_snprintf(buf, sizeof(buf), "wpa_%s", ctrl_path);
if (socket_local_client_connect(
ctrl->s, buf,
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_DGRAM) < 0) {
close(ctrl->s);
unlink(ctrl->local.sun_path);
os_free(ctrl);
return NULL;
}
return ctrl;
}
#endif /* ANDROID */
ctrl->dest.sun_family = AF_UNIX;
res = os_strlcpy(ctrl->dest.sun_path, ctrl_path,
sizeof(ctrl->dest.sun_path));
@ -127,11 +168,64 @@ try_again:
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
{
if (ctrl == NULL)
return;
unlink(ctrl->local.sun_path);
close(ctrl->s);
if (ctrl->s >= 0)
close(ctrl->s);
os_free(ctrl);
}
#ifdef ANDROID
/**
* wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
* may be left over from clients that were previously connected to
* wpa_supplicant. This keeps these files from being orphaned in the
* event of crashes that prevented them from being removed as part
* of the normal orderly shutdown.
*/
void wpa_ctrl_cleanup(void)
{
DIR *dir;
struct dirent entry;
struct dirent *result;
size_t dirnamelen;
int prefixlen = os_strlen(CONFIG_CTRL_IFACE_CLIENT_PREFIX);
size_t maxcopy;
char pathname[PATH_MAX];
char *namep;
if ((dir = opendir(CONFIG_CTRL_IFACE_CLIENT_DIR)) == NULL)
return;
dirnamelen = (size_t) os_snprintf(pathname, sizeof(pathname), "%s/",
CONFIG_CTRL_IFACE_CLIENT_DIR);
if (dirnamelen >= sizeof(pathname)) {
closedir(dir);
return;
}
namep = pathname + dirnamelen;
maxcopy = PATH_MAX - dirnamelen;
while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
if (os_strncmp(entry.d_name, CONFIG_CTRL_IFACE_CLIENT_PREFIX,
prefixlen) == 0) {
if (os_strlcpy(namep, entry.d_name, maxcopy) < maxcopy)
unlink(pathname);
}
}
closedir(dir);
}
#endif /* ANDROID */
#else /* CONFIG_CTRL_IFACE_UNIX */
#ifdef ANDROID
void wpa_ctrl_cleanup(void)
{
}
#endif /* ANDROID */
#endif /* CONFIG_CTRL_IFACE_UNIX */
@ -234,11 +328,13 @@ int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
os_free(cmd_buf);
for (;;) {
tv.tv_sec = 2;
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(ctrl->s, &rfds);
res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
if (res < 0)
return res;
if (FD_ISSET(ctrl->s, &rfds)) {
res = recv(ctrl->s, reply, *reply_len, 0);
if (res < 0)

View File

@ -32,6 +32,8 @@ extern "C" {
#define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED "
/** Disconnected, data connection is not available */
#define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED "
/** Association rejected during connection attempt */
#define WPA_EVENT_ASSOC_REJECT "CTRL-EVENT-ASSOC-REJECT "
/** wpa_supplicant is exiting */
#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING "
/** Password change was completed successfully */
@ -54,6 +56,8 @@ extern "C" {
#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE "
/** New scan results available */
#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS "
/** wpa_supplicant state change */
#define WPA_EVENT_STATE_CHANGE "CTRL-EVENT-STATE-CHANGE "
/** A new BSS entry was added (followed by BSS entry id and BSSID) */
#define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED "
/** A BSS entry was removed (followed by BSS entry id and BSSID) */
@ -63,6 +67,8 @@ extern "C" {
#define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED "
/** Available WPS AP with active PBC found in scan results */
#define WPS_EVENT_AP_AVAILABLE_PBC "WPS-AP-AVAILABLE-PBC "
/** Available WPS AP with our address as authorized in scan results */
#define WPS_EVENT_AP_AVAILABLE_AUTH "WPS-AP-AVAILABLE-AUTH "
/** Available WPS AP with recently selected PIN registrar found in scan results
*/
#define WPS_EVENT_AP_AVAILABLE_PIN "WPS-AP-AVAILABLE-PIN "
@ -81,11 +87,51 @@ extern "C" {
#define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN "
#define WPS_EVENT_OPEN_NETWORK "WPS-OPEN-NETWORK "
/* WPS ER events */
#define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD "
#define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE "
#define WPS_EVENT_ER_ENROLLEE_ADD "WPS-ER-ENROLLEE-ADD "
#define WPS_EVENT_ER_ENROLLEE_REMOVE "WPS-ER-ENROLLEE-REMOVE "
#define WPS_EVENT_ER_AP_SETTINGS "WPS-ER-AP-SETTINGS "
#define WPS_EVENT_ER_SET_SEL_REG "WPS-ER-AP-SET-SEL-REG "
/** P2P device found */
#define P2P_EVENT_DEVICE_FOUND "P2P-DEVICE-FOUND "
/** P2P device lost */
#define P2P_EVENT_DEVICE_LOST "P2P-DEVICE-LOST "
/** A P2P device requested GO negotiation, but we were not ready to start the
* negotiation */
#define P2P_EVENT_GO_NEG_REQUEST "P2P-GO-NEG-REQUEST "
#define P2P_EVENT_GO_NEG_SUCCESS "P2P-GO-NEG-SUCCESS "
#define P2P_EVENT_GO_NEG_FAILURE "P2P-GO-NEG-FAILURE "
#define P2P_EVENT_GROUP_FORMATION_SUCCESS "P2P-GROUP-FORMATION-SUCCESS "
#define P2P_EVENT_GROUP_FORMATION_FAILURE "P2P-GROUP-FORMATION-FAILURE "
#define P2P_EVENT_GROUP_STARTED "P2P-GROUP-STARTED "
#define P2P_EVENT_GROUP_REMOVED "P2P-GROUP-REMOVED "
#define P2P_EVENT_CROSS_CONNECT_ENABLE "P2P-CROSS-CONNECT-ENABLE "
#define P2P_EVENT_CROSS_CONNECT_DISABLE "P2P-CROSS-CONNECT-DISABLE "
/* parameters: <peer address> <PIN> */
#define P2P_EVENT_PROV_DISC_SHOW_PIN "P2P-PROV-DISC-SHOW-PIN "
/* parameters: <peer address> */
#define P2P_EVENT_PROV_DISC_ENTER_PIN "P2P-PROV-DISC-ENTER-PIN "
/* parameters: <peer address> */
#define P2P_EVENT_PROV_DISC_PBC_REQ "P2P-PROV-DISC-PBC-REQ "
/* parameters: <peer address> */
#define P2P_EVENT_PROV_DISC_PBC_RESP "P2P-PROV-DISC-PBC-RESP "
/* parameters: <freq> <src addr> <dialog token> <update indicator> <TLVs> */
#define P2P_EVENT_SERV_DISC_REQ "P2P-SERV-DISC-REQ "
/* parameters: <src addr> <update indicator> <TLVs> */
#define P2P_EVENT_SERV_DISC_RESP "P2P-SERV-DISC-RESP "
#define P2P_EVENT_INVITATION_RECEIVED "P2P-INVITATION-RECEIVED "
#define P2P_EVENT_INVITATION_RESULT "P2P-INVITATION-RESULT "
#define P2P_EVENT_FIND_STOPPED "P2P-FIND-STOPPED "
#define INTERWORKING_AP "INTERWORKING-AP "
#define INTERWORKING_NO_MATCH "INTERWORKING-NO-MATCH "
/* hostapd control interface - fixed message prefixes */
#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED "
@ -223,6 +269,17 @@ int wpa_ctrl_pending(struct wpa_ctrl *ctrl);
*/
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
#ifdef ANDROID
/**
* wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
* may be left over from clients that were previously connected to
* wpa_supplicant. This keeps these files from being orphaned in the
* event of crashes that prevented them from being removed as part
* of the normal orderly shutdown.
*/
void wpa_ctrl_cleanup(void);
#endif /* ANDROID */
#ifdef CONFIG_CTRL_IFACE_UDP
#define WPA_CTRL_IFACE_PORT 9877
#define WPA_GLOBAL_CTRL_IFACE_PORT 9878

View File

@ -48,6 +48,7 @@ LIB_OBJS += crypto_internal-modexp.o
LIB_OBJS += crypto_internal-rsa.o
LIB_OBJS += tls_internal.o
LIB_OBJS += fips_prf_internal.o
LIB_OBJS += random.o
libcrypto.a: $(LIB_OBJS)

View File

@ -63,7 +63,8 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
ctx->key_len = key_len;
os_memcpy(k_pad, key, key_len);
os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
if (key_len < sizeof(k_pad))
os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x36;
MD5Init(&ctx->u.md5);
@ -81,7 +82,8 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
ctx->key_len = key_len;
os_memcpy(k_pad, key, key_len);
os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
if (key_len < sizeof(k_pad))
os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x36;
SHA1Init(&ctx->u.sha1);

View File

@ -16,6 +16,7 @@
#include "common.h"
#include "crypto.h"
#include "random.h"
#include "dh_groups.h"
@ -564,7 +565,8 @@ struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv)
if (*priv == NULL)
return NULL;
if (os_get_random(wpabuf_put(*priv, dh->prime_len), dh->prime_len)) {
if (random_get_bytes(wpabuf_put(*priv, dh->prime_len), dh->prime_len))
{
wpabuf_free(*priv);
*priv = NULL;
return NULL;

View File

@ -28,13 +28,14 @@ int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
u8 *xpos = x;
u32 carry;
if (seed_len > sizeof(xkey))
if (seed_len < sizeof(xkey))
os_memset(xkey + seed_len, 0, sizeof(xkey) - seed_len);
else
seed_len = sizeof(xkey);
/* FIPS 186-2 + change notice 1 */
os_memcpy(xkey, seed, seed_len);
os_memset(xkey + seed_len, 0, 64 - seed_len);
t[0] = 0x67452301;
t[1] = 0xEFCDAB89;
t[2] = 0x98BADCFE;

View File

@ -188,7 +188,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
MD5Transform(ctx->buf, (u32 *) ctx->in);
byteReverse((unsigned char *) ctx->buf, 4);
os_memcpy(digest, ctx->buf, 16);
os_memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
os_memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
/* The four core functions - F1 is optimized somewhat */

View File

@ -19,6 +19,60 @@
#include "ms_funcs.h"
#include "crypto.h"
/**
* utf8_to_ucs2 - Convert UTF-8 string to UCS-2 encoding
* @utf8_string: UTF-8 string (IN)
* @utf8_string_len: Length of utf8_string (IN)
* @ucs2_buffer: UCS-2 buffer (OUT)
* @ucs2_buffer_size: Length of UCS-2 buffer (IN)
* @ucs2_string_size: Number of 2-byte words in the resulting UCS-2 string
* Returns: 0 on success, -1 on failure
*/
static int utf8_to_ucs2(const u8 *utf8_string, size_t utf8_string_len,
u8 *ucs2_buffer, size_t ucs2_buffer_size,
size_t *ucs2_string_size)
{
size_t i, j;
for (i = 0, j = 0; i < utf8_string_len; i++) {
u8 c = utf8_string[i];
if (j >= ucs2_buffer_size) {
/* input too long */
return -1;
}
if (c <= 0x7F) {
WPA_PUT_LE16(ucs2_buffer + j, c);
j += 2;
} else if (i == utf8_string_len - 1 ||
j >= ucs2_buffer_size - 1) {
/* incomplete surrogate */
return -1;
} else {
u8 c2 = utf8_string[++i];
if ((c & 0xE0) == 0xC0) {
/* two-byte encoding */
WPA_PUT_LE16(ucs2_buffer + j,
((c & 0x1F) << 6) | (c2 & 0x3F));
j += 2;
} else if (i == utf8_string_len ||
j >= ucs2_buffer_size - 1) {
/* incomplete surrogate */
return -1;
} else {
/* three-byte encoding */
u8 c3 = utf8_string[++i];
WPA_PUT_LE16(ucs2_buffer + j,
((c & 0xF) << 12) |
((c2 & 0x3F) << 6) | (c3 & 0x3F));
}
}
}
if (ucs2_string_size)
*ucs2_string_size = j / 2;
return 0;
}
/**
* challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2
@ -53,7 +107,7 @@ static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
/**
* nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3
* @password: 0-to-256-unicode-char Password (IN; ASCII)
* @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @password_hash: 16-octet PasswordHash (OUT)
* Returns: 0 on success, -1 on failure
@ -62,18 +116,13 @@ int nt_password_hash(const u8 *password, size_t password_len,
u8 *password_hash)
{
u8 buf[512], *pos;
size_t i, len;
size_t len, max_len;
if (password_len > 256)
password_len = 256;
max_len = sizeof(buf);
if (utf8_to_ucs2(password, password_len, buf, max_len, &len) < 0)
return -1;
/* Convert password into unicode */
for (i = 0; i < password_len; i++) {
buf[2 * i] = password[i];
buf[2 * i + 1] = 0;
}
len = password_len * 2;
len *= 2;
pos = buf;
return md4_vector(1, (const u8 **) &pos, &len, password_hash);
}
@ -117,7 +166,7 @@ void challenge_response(const u8 *challenge, const u8 *password_hash,
* @peer_challenge: 16-octet PeerChallenge (IN)
* @username: 0-to-256-char UserName (IN)
* @username_len: Length of username
* @password: 0-to-256-unicode-char Password (IN; ASCII)
* @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @response: 24-octet Response (OUT)
* Returns: 0 on success, -1 on failure
@ -225,7 +274,7 @@ int generate_authenticator_response_pwhash(
/**
* generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
* @password: 0-to-256-unicode-char Password (IN; ASCII)
* @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @nt_response: 24-octet NT-Response (IN)
* @peer_challenge: 16-octet PeerChallenge (IN)
@ -254,7 +303,7 @@ int generate_authenticator_response(const u8 *password, size_t password_len,
/**
* nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
* @challenge: 8-octet Challenge (IN)
* @password: 0-to-256-unicode-char Password (IN; ASCII)
* @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @response: 24-octet Response (OUT)
* Returns: 0 on success, -1 on failure
@ -375,7 +424,7 @@ int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
/**
* encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
* @password: 0-to-256-unicode-char Password (IN; ASCII)
* @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @password_hash: 16-octet PasswordHash (IN)
* @pw_block: 516-byte PwBlock (OUT)
@ -385,18 +434,23 @@ int encrypt_pw_block_with_password_hash(
const u8 *password, size_t password_len,
const u8 *password_hash, u8 *pw_block)
{
size_t i, offset;
size_t ucs2_len, offset;
u8 *pos;
if (password_len > 256)
os_memset(pw_block, 0, PWBLOCK_LEN);
if (utf8_to_ucs2(password, password_len, pw_block, 512, &ucs2_len) < 0)
return -1;
os_memset(pw_block, 0, PWBLOCK_LEN);
offset = (256 - password_len) * 2;
if (os_get_random(pw_block, offset) < 0)
if (ucs2_len > 256)
return -1;
for (i = 0; i < password_len; i++)
pw_block[offset + i * 2] = password[i];
offset = (256 - ucs2_len) * 2;
if (offset != 0) {
os_memmove(pw_block + offset, pw_block, ucs2_len * 2);
if (os_get_random(pw_block, offset) < 0)
return -1;
}
/*
* PasswordLength is 4 octets, but since the maximum password length is
* 256, only first two (in little endian byte order) can be non-zero.
@ -410,9 +464,9 @@ int encrypt_pw_block_with_password_hash(
/**
* new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9
* @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
* @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
* @new_password_len: Length of new_password
* @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
* @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
* @old_password_len: Length of old_password
* @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
* Returns: 0 on success, -1 on failure
@ -450,9 +504,9 @@ void nt_password_hash_encrypted_with_block(const u8 *password_hash,
/**
* old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12
* @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
* @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
* @new_password_len: Length of new_password
* @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
* @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
* @old_password_len: Length of old_password
* @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT)
* Returns: 0 on success, -1 on failure

View File

@ -0,0 +1,430 @@
/*
* Random number generator
* Copyright (c) 2010-2011, 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.
*
* This random number generator is used to provide additional entropy to the
* one provided by the operating system (os_get_random()) for session key
* generation. The os_get_random() output is expected to be secure and the
* implementation here is expected to provide only limited protection against
* cases where os_get_random() cannot provide strong randomness. This
* implementation shall not be assumed to be secure as the sole source of
* randomness. The random_get_bytes() function mixes in randomness from
* os_get_random() and as such, calls to os_get_random() can be replaced with
* calls to random_get_bytes() without reducing security.
*
* The design here follows partially the design used in the Linux
* drivers/char/random.c, but the implementation here is simpler and not as
* strong. This is a compromise to reduce duplicated CPU effort and to avoid
* extra code/memory size. As pointed out above, os_get_random() needs to be
* guaranteed to be secure for any of the security assumptions to hold.
*/
#include "utils/includes.h"
#ifdef __linux__
#include <fcntl.h>
#endif /* __linux__ */
#include "utils/common.h"
#include "utils/eloop.h"
#include "sha1.h"
#include "random.h"
#define POOL_WORDS 32
#define POOL_WORDS_MASK (POOL_WORDS - 1)
#define POOL_TAP1 26
#define POOL_TAP2 20
#define POOL_TAP3 14
#define POOL_TAP4 7
#define POOL_TAP5 1
#define EXTRACT_LEN 16
#define MIN_READY_MARK 2
static u32 pool[POOL_WORDS];
static unsigned int input_rotate = 0;
static unsigned int pool_pos = 0;
static u8 dummy_key[20];
#ifdef __linux__
static size_t dummy_key_avail = 0;
static int random_fd = -1;
#endif /* __linux__ */
static unsigned int own_pool_ready = 0;
#define RANDOM_ENTROPY_SIZE 20
static char *random_entropy_file = NULL;
static int random_entropy_file_read = 0;
#define MIN_COLLECT_ENTROPY 1000
static unsigned int entropy = 0;
static unsigned int total_collected = 0;
static void random_write_entropy(void);
static u32 __ROL32(u32 x, u32 y)
{
return (x << (y & 31)) | (x >> (32 - (y & 31)));
}
static void random_mix_pool(const void *buf, size_t len)
{
static const u32 twist[8] = {
0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278
};
const u8 *pos = buf;
u32 w;
wpa_hexdump_key(MSG_EXCESSIVE, "random_mix_pool", buf, len);
while (len--) {
w = __ROL32(*pos++, input_rotate & 31);
input_rotate += pool_pos ? 7 : 14;
pool_pos = (pool_pos - 1) & POOL_WORDS_MASK;
w ^= pool[pool_pos];
w ^= pool[(pool_pos + POOL_TAP1) & POOL_WORDS_MASK];
w ^= pool[(pool_pos + POOL_TAP2) & POOL_WORDS_MASK];
w ^= pool[(pool_pos + POOL_TAP3) & POOL_WORDS_MASK];
w ^= pool[(pool_pos + POOL_TAP4) & POOL_WORDS_MASK];
w ^= pool[(pool_pos + POOL_TAP5) & POOL_WORDS_MASK];
pool[pool_pos] = (w >> 3) ^ twist[w & 7];
}
}
static void random_extract(u8 *out)
{
unsigned int i;
u8 hash[SHA1_MAC_LEN];
u32 *hash_ptr;
u32 buf[POOL_WORDS / 2];
/* First, add hash back to pool to make backtracking more difficult. */
hmac_sha1(dummy_key, sizeof(dummy_key), (const u8 *) pool,
sizeof(pool), hash);
random_mix_pool(hash, sizeof(hash));
/* Hash half the pool to extra data */
for (i = 0; i < POOL_WORDS / 2; i++)
buf[i] = pool[(pool_pos - i) & POOL_WORDS_MASK];
hmac_sha1(dummy_key, sizeof(dummy_key), (const u8 *) buf,
sizeof(buf), hash);
/*
* Fold the hash to further reduce any potential output pattern.
* Though, compromise this to reduce CPU use for the most common output
* length (32) and return 16 bytes from instead of only half.
*/
hash_ptr = (u32 *) hash;
hash_ptr[0] ^= hash_ptr[4];
os_memcpy(out, hash, EXTRACT_LEN);
}
void random_add_randomness(const void *buf, size_t len)
{
struct os_time t;
static unsigned int count = 0;
count++;
wpa_printf(MSG_MSGDUMP, "Add randomness: count=%u entropy=%u",
count, entropy);
if (entropy > MIN_COLLECT_ENTROPY && (count & 0x3ff) != 0) {
/*
* No need to add more entropy at this point, so save CPU and
* skip the update.
*/
return;
}
os_get_time(&t);
wpa_hexdump_key(MSG_EXCESSIVE, "random pool",
(const u8 *) pool, sizeof(pool));
random_mix_pool(&t, sizeof(t));
random_mix_pool(buf, len);
wpa_hexdump_key(MSG_EXCESSIVE, "random pool",
(const u8 *) pool, sizeof(pool));
entropy++;
total_collected++;
}
int random_get_bytes(void *buf, size_t len)
{
int ret;
u8 *bytes = buf;
size_t left;
wpa_printf(MSG_MSGDUMP, "Get randomness: len=%u entropy=%u",
(unsigned int) len, entropy);
/* Start with assumed strong randomness from OS */
ret = os_get_random(buf, len);
wpa_hexdump_key(MSG_EXCESSIVE, "random from os_get_random",
buf, len);
/* Mix in additional entropy extracted from the internal pool */
left = len;
while (left) {
size_t siz, i;
u8 tmp[EXTRACT_LEN];
random_extract(tmp);
wpa_hexdump_key(MSG_EXCESSIVE, "random from internal pool",
tmp, sizeof(tmp));
siz = left > EXTRACT_LEN ? EXTRACT_LEN : left;
for (i = 0; i < siz; i++)
*bytes++ ^= tmp[i];
left -= siz;
}
wpa_hexdump_key(MSG_EXCESSIVE, "mixed random", buf, len);
if (entropy < len)
entropy = 0;
else
entropy -= len;
return ret;
}
int random_pool_ready(void)
{
#ifdef __linux__
int fd;
ssize_t res;
/*
* Make sure that there is reasonable entropy available before allowing
* some key derivation operations to proceed.
*/
if (dummy_key_avail == sizeof(dummy_key))
return 1; /* Already initialized - good to continue */
/*
* Try to fetch some more data from the kernel high quality
* /dev/random. There may not be enough data available at this point,
* so use non-blocking read to avoid blocking the application
* completely.
*/
fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
if (fd < 0) {
#ifndef CONFIG_NO_STDOUT_DEBUG
int error = errno;
perror("open(/dev/random)");
wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
strerror(error));
#endif /* CONFIG_NO_STDOUT_DEBUG */
return -1;
}
res = read(fd, dummy_key + dummy_key_avail,
sizeof(dummy_key) - dummy_key_avail);
if (res < 0) {
wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: "
"%s", strerror(errno));
res = 0;
}
wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from "
"/dev/random", (unsigned) res,
(unsigned) (sizeof(dummy_key) - dummy_key_avail));
dummy_key_avail += res;
close(fd);
if (dummy_key_avail == sizeof(dummy_key)) {
if (own_pool_ready < MIN_READY_MARK)
own_pool_ready = MIN_READY_MARK;
random_write_entropy();
return 1;
}
wpa_printf(MSG_INFO, "random: Only %u/%u bytes of strong "
"random data available from /dev/random",
(unsigned) dummy_key_avail, (unsigned) sizeof(dummy_key));
if (own_pool_ready >= MIN_READY_MARK ||
total_collected + 10 * own_pool_ready > MIN_COLLECT_ENTROPY) {
wpa_printf(MSG_INFO, "random: Allow operation to proceed "
"based on internal entropy");
return 1;
}
wpa_printf(MSG_INFO, "random: Not enough entropy pool available for "
"secure operations");
return 0;
#else /* __linux__ */
/* TODO: could do similar checks on non-Linux platforms */
return 1;
#endif /* __linux__ */
}
void random_mark_pool_ready(void)
{
own_pool_ready++;
wpa_printf(MSG_DEBUG, "random: Mark internal entropy pool to be "
"ready (count=%u/%u)", own_pool_ready, MIN_READY_MARK);
random_write_entropy();
}
#ifdef __linux__
static void random_close_fd(void)
{
if (random_fd >= 0) {
eloop_unregister_read_sock(random_fd);
close(random_fd);
random_fd = -1;
}
}
static void random_read_fd(int sock, void *eloop_ctx, void *sock_ctx)
{
ssize_t res;
if (dummy_key_avail == sizeof(dummy_key)) {
random_close_fd();
return;
}
res = read(sock, dummy_key + dummy_key_avail,
sizeof(dummy_key) - dummy_key_avail);
if (res < 0) {
wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: "
"%s", strerror(errno));
return;
}
wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from /dev/random",
(unsigned) res,
(unsigned) (sizeof(dummy_key) - dummy_key_avail));
dummy_key_avail += res;
if (dummy_key_avail == sizeof(dummy_key)) {
random_close_fd();
if (own_pool_ready < MIN_READY_MARK)
own_pool_ready = MIN_READY_MARK;
random_write_entropy();
}
}
#endif /* __linux__ */
static void random_read_entropy(void)
{
char *buf;
size_t len;
if (!random_entropy_file)
return;
buf = os_readfile(random_entropy_file, &len);
if (buf == NULL)
return; /* entropy file not yet available */
if (len != 1 + RANDOM_ENTROPY_SIZE) {
wpa_printf(MSG_DEBUG, "random: Invalid entropy file %s",
random_entropy_file);
os_free(buf);
return;
}
own_pool_ready = (u8) buf[0];
random_add_randomness(buf + 1, RANDOM_ENTROPY_SIZE);
random_entropy_file_read = 1;
os_free(buf);
wpa_printf(MSG_DEBUG, "random: Added entropy from %s "
"(own_pool_ready=%u)",
random_entropy_file, own_pool_ready);
}
static void random_write_entropy(void)
{
char buf[RANDOM_ENTROPY_SIZE];
FILE *f;
u8 opr;
int fail = 0;
if (!random_entropy_file)
return;
if (random_get_bytes(buf, RANDOM_ENTROPY_SIZE) < 0)
return;
f = fopen(random_entropy_file, "wb");
if (f == NULL) {
wpa_printf(MSG_ERROR, "random: Could not open entropy file %s "
"for writing", random_entropy_file);
return;
}
opr = own_pool_ready > 0xff ? 0xff : own_pool_ready;
if (fwrite(&opr, 1, 1, f) != 1 ||
fwrite(buf, RANDOM_ENTROPY_SIZE, 1, f) != 1)
fail = 1;
fclose(f);
if (fail) {
wpa_printf(MSG_ERROR, "random: Could not write entropy data "
"to %s", random_entropy_file);
return;
}
wpa_printf(MSG_DEBUG, "random: Updated entropy file %s "
"(own_pool_ready=%u)",
random_entropy_file, own_pool_ready);
}
void random_init(const char *entropy_file)
{
os_free(random_entropy_file);
if (entropy_file)
random_entropy_file = os_strdup(entropy_file);
else
random_entropy_file = NULL;
random_read_entropy();
#ifdef __linux__
if (random_fd >= 0)
return;
random_fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
if (random_fd < 0) {
#ifndef CONFIG_NO_STDOUT_DEBUG
int error = errno;
perror("open(/dev/random)");
wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
strerror(error));
#endif /* CONFIG_NO_STDOUT_DEBUG */
return;
}
wpa_printf(MSG_DEBUG, "random: Trying to read entropy from "
"/dev/random");
eloop_register_read_sock(random_fd, random_read_fd, NULL, NULL);
#endif /* __linux__ */
random_write_entropy();
}
void random_deinit(void)
{
#ifdef __linux__
random_close_fd();
#endif /* __linux__ */
random_write_entropy();
os_free(random_entropy_file);
random_entropy_file = NULL;
}

View File

@ -0,0 +1,34 @@
/*
* Random number generator
* Copyright (c) 2010-2011, 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.
*/
#ifndef RANDOM_H
#define RANDOM_H
#ifdef CONFIG_NO_RANDOM_POOL
#define random_init(e) do { } while (0)
#define random_deinit() do { } while (0)
#define random_add_randomness(b, l) do { } while (0)
#define random_get_bytes(b, l) os_get_random((b), (l))
#define random_pool_ready() 1
#define random_mark_pool_ready() do { } while (0)
#else /* CONFIG_NO_RANDOM_POOL */
void random_init(const char *entropy_file);
void random_deinit(void);
void random_add_randomness(const void *buf, size_t len);
int random_get_bytes(void *buf, size_t len);
int random_pool_ready(void);
void random_mark_pool_ready(void);
#endif /* CONFIG_NO_RANDOM_POOL */
#endif /* RANDOM_H */

View File

@ -1,6 +1,6 @@
/*
* SHA-256 hash implementation and interface functions
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2011, 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
@ -18,10 +18,12 @@
#include "sha256.h"
#include "crypto.h"
#define SHA256_BLOCK_SIZE 64
struct sha256_state {
u64 length;
u32 state[8], curlen;
u8 buf[64];
u8 buf[SHA256_BLOCK_SIZE];
};
static void sha256_init(struct sha256_state *md);
@ -162,28 +164,27 @@ static int sha256_process(struct sha256_state *md, const unsigned char *in,
unsigned long inlen)
{
unsigned long n;
#define block_size 64
if (md->curlen > sizeof(md->buf))
if (md->curlen >= sizeof(md->buf))
return -1;
while (inlen > 0) {
if (md->curlen == 0 && inlen >= block_size) {
if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE) {
if (sha256_compress(md, (unsigned char *) in) < 0)
return -1;
md->length += block_size * 8;
in += block_size;
inlen -= block_size;
md->length += SHA256_BLOCK_SIZE * 8;
in += SHA256_BLOCK_SIZE;
inlen -= SHA256_BLOCK_SIZE;
} else {
n = MIN(inlen, (block_size - md->curlen));
n = MIN(inlen, (SHA256_BLOCK_SIZE - md->curlen));
os_memcpy(md->buf + md->curlen, in, n);
md->curlen += n;
in += n;
inlen -= n;
if (md->curlen == block_size) {
if (md->curlen == SHA256_BLOCK_SIZE) {
if (sha256_compress(md, md->buf) < 0)
return -1;
md->length += 8 * block_size;
md->length += 8 * SHA256_BLOCK_SIZE;
md->curlen = 0;
}
}
@ -217,14 +218,14 @@ static int sha256_done(struct sha256_state *md, unsigned char *out)
* encoding like normal.
*/
if (md->curlen > 56) {
while (md->curlen < 64) {
while (md->curlen < SHA256_BLOCK_SIZE) {
md->buf[md->curlen++] = (unsigned char) 0;
}
sha256_compress(md, md->buf);
md->curlen = 0;
}
/* pad upto 56 bytes of zeroes */
/* pad up to 56 bytes of zeroes */
while (md->curlen < 56) {
md->buf[md->curlen++] = (unsigned char) 0;
}

View File

@ -24,8 +24,6 @@ struct tls_keys {
size_t client_random_len;
const u8 *server_random;
size_t server_random_len;
const u8 *inner_secret; /* TLS/IA inner secret */
size_t inner_secret_len;
};
enum tls_event {
@ -72,6 +70,7 @@ struct tls_config {
const char *pkcs11_engine_path;
const char *pkcs11_module_path;
int fips_mode;
int cert_in_cb;
void (*event_cb)(void *ctx, enum tls_event ev,
union tls_event_data *data);
@ -114,7 +113,6 @@ struct tls_config {
* specific for now)
* @cert_id: the certificate's id when using engine
* @ca_cert_id: the CA certificate's id when using engine
* @tls_ia: Whether to enable TLS/IA (for EAP-TTLSv1)
* @flags: Parameter options (TLS_CONN_*)
*
* TLS connection parameters to be configured with tls_connection_set_params()
@ -142,7 +140,6 @@ struct tls_connection_params {
const char *dh_file;
const u8 *dh_blob;
size_t dh_blob_len;
int tls_ia;
/* OpenSSL specific variables */
int engine;
@ -281,20 +278,6 @@ int __must_check tls_connection_set_verify(void *tls_ctx,
struct tls_connection *conn,
int verify_peer);
/**
* tls_connection_set_ia - Set TLS/IA parameters
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* @tls_ia: 1 = enable TLS/IA
* Returns: 0 on success, -1 on failure
*
* This function is used to configure TLS/IA in server mode where
* tls_connection_set_params() is not used.
*/
int __must_check tls_connection_set_ia(void *tls_ctx,
struct tls_connection *conn,
int tls_ia);
/**
* tls_connection_get_keys - Get master key and random data from TLS connection
* @tls_ctx: TLS context data from tls_init()
@ -514,7 +497,6 @@ int tls_connection_get_write_alerts(void *tls_ctx,
int tls_connection_get_keyblock_size(void *tls_ctx,
struct tls_connection *conn);
#define TLS_CAPABILITY_IA 0x0001 /* TLS Inner Application (TLS/IA) */
/**
* tls_capabilities - Get supported TLS capabilities
* @tls_ctx: TLS context data from tls_init()
@ -522,42 +504,6 @@ int tls_connection_get_keyblock_size(void *tls_ctx,
*/
unsigned int tls_capabilities(void *tls_ctx);
/**
* tls_connection_ia_send_phase_finished - Send a TLS/IA PhaseFinished message
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* @final: 1 = FinalPhaseFinished, 0 = IntermediatePhaseFinished
* Returns: Encrypted TLS/IA data, %NULL on failure
*
* This function is used to send the TLS/IA end phase message, e.g., when the
* EAP server completes EAP-TTLSv1.
*/
struct wpabuf * tls_connection_ia_send_phase_finished(
void *tls_ctx, struct tls_connection *conn, int final);
/**
* tls_connection_ia_final_phase_finished - Has final phase been completed
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* Returns: 1 if valid FinalPhaseFinished has been received, 0 if not, or -1
* on failure
*/
int __must_check tls_connection_ia_final_phase_finished(
void *tls_ctx, struct tls_connection *conn);
/**
* tls_connection_ia_permute_inner_secret - Permute TLS/IA inner secret
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* @key: Session key material (session_key vectors with 2-octet length), or
* %NULL if no session key was generating in the current phase
* @key_len: Length of session key material
* Returns: 0 on success, -1 on failure
*/
int __must_check tls_connection_ia_permute_inner_secret(
void *tls_ctx, struct tls_connection *conn,
const u8 *key, size_t key_len);
typedef int (*tls_session_ticket_cb)
(void *ctx, const u8 *ticket, size_t len, const u8 *client_random,
const u8 *server_random, u8 *master_secret);

View File

@ -1,6 +1,6 @@
/*
* SSL/TLS interface functions for GnuTLS
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2011, 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
@ -19,28 +19,12 @@
#include <gnutls/pkcs12.h>
#endif /* PKCS12_FUNCS */
#ifdef CONFIG_GNUTLS_EXTRA
#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
#define GNUTLS_IA
#include <gnutls/extra.h>
#if LIBGNUTLS_VERSION_NUMBER == 0x010302
/* This function is not included in the current gnutls/extra.h even though it
* should be, so define it here as a workaround for the time being. */
int gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum);
#endif /* LIBGNUTLS_VERSION_NUMBER == 0x010302 */
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
#endif /* CONFIG_GNUTLS_EXTRA */
#include "common.h"
#include "tls.h"
#ifndef TLS_RANDOM_SIZE
#define TLS_RANDOM_SIZE 32
#endif
#ifndef TLS_MASTER_SIZE
#define TLS_MASTER_SIZE 48
#endif
#define WPA_TLS_RANDOM_SIZE 32
#define WPA_TLS_MASTER_SIZE 48
#if LIBGNUTLS_VERSION_NUMBER < 0x010302
@ -77,9 +61,9 @@ typedef struct {
gnutls_mac_algorithm_t write_mac_algorithm;
gnutls_compression_method_t write_compression_algorithm;
cipher_suite_st current_cipher_suite;
opaque master_secret[TLS_MASTER_SIZE];
opaque client_random[TLS_RANDOM_SIZE];
opaque server_random[TLS_RANDOM_SIZE];
opaque master_secret[WPA_TLS_MASTER_SIZE];
opaque client_random[WPA_TLS_RANDOM_SIZE];
opaque server_random[WPA_TLS_RANDOM_SIZE];
/* followed by stuff we are not interested in */
} security_parameters_st;
@ -118,21 +102,6 @@ struct tls_connection {
int params_set;
gnutls_certificate_credentials_t xcred;
int tls_ia;
int final_phase_finished;
#ifdef GNUTLS_IA
gnutls_ia_server_credentials_t iacred_srv;
gnutls_ia_client_credentials_t iacred_cli;
/* Session keys generated in the current phase for inner secret
* permutation before generating/verifying PhaseFinished. */
u8 *session_keys;
size_t session_keys_len;
u8 inner_secret[TLS_MASTER_SIZE];
#endif /* GNUTLS_IA */
};
@ -285,8 +254,12 @@ static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf,
static int tls_gnutls_init_session(struct tls_global *global,
struct tls_connection *conn)
{
#if LIBGNUTLS_VERSION_NUMBER >= 0x020200
const char *err;
#else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */
const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
const int protos[2] = { GNUTLS_TLS1, 0 };
#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */
int ret;
ret = gnutls_init(&conn->session,
@ -301,6 +274,15 @@ static int tls_gnutls_init_session(struct tls_global *global,
if (ret < 0)
goto fail;
#if LIBGNUTLS_VERSION_NUMBER >= 0x020200
ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0",
&err);
if (ret < 0) {
wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at "
"'%s'", err);
goto fail;
}
#else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */
ret = gnutls_certificate_type_set_priority(conn->session, cert_types);
if (ret < 0)
goto fail;
@ -308,6 +290,7 @@ static int tls_gnutls_init_session(struct tls_global *global,
ret = gnutls_protocol_set_priority(conn->session, protos);
if (ret < 0)
goto fail;
#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */
gnutls_transport_set_pull_function(conn->session, tls_pull_func);
gnutls_transport_set_push_function(conn->session, tls_push_func);
@ -364,17 +347,6 @@ void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
if (conn == NULL)
return;
#ifdef GNUTLS_IA
if (conn->iacred_srv)
gnutls_ia_free_server_credentials(conn->iacred_srv);
if (conn->iacred_cli)
gnutls_ia_free_client_credentials(conn->iacred_cli);
if (conn->session_keys) {
os_memset(conn->session_keys, 0, conn->session_keys_len);
os_free(conn->session_keys);
}
#endif /* GNUTLS_IA */
gnutls_certificate_free_credentials(conn->xcred);
gnutls_deinit(conn->session);
os_free(conn->pre_shared_secret);
@ -407,14 +379,6 @@ int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
wpabuf_free(conn->push_buf);
conn->push_buf = NULL;
conn->established = 0;
conn->final_phase_finished = 0;
#ifdef GNUTLS_IA
if (conn->session_keys) {
os_memset(conn->session_keys, 0, conn->session_keys_len);
os_free(conn->session_keys);
}
conn->session_keys_len = 0;
#endif /* GNUTLS_IA */
gnutls_deinit(conn->session);
if (tls_gnutls_init_session(global, conn)) {
@ -597,11 +561,13 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
}
#if LIBGNUTLS_VERSION_NUMBER >= 0x020800
if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
gnutls_certificate_set_verify_flags(
conn->xcred,
GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
}
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
}
if (params->client_cert && params->private_key) {
@ -646,7 +612,6 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
}
}
conn->tls_ia = params->tls_ia;
conn->params_set = 1;
ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
@ -656,28 +621,6 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
gnutls_strerror(ret));
}
#ifdef GNUTLS_IA
if (conn->iacred_cli)
gnutls_ia_free_client_credentials(conn->iacred_cli);
ret = gnutls_ia_allocate_client_credentials(&conn->iacred_cli);
if (ret) {
wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
gnutls_strerror(ret));
return -1;
}
ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
conn->iacred_cli);
if (ret) {
wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
gnutls_strerror(ret));
gnutls_ia_free_client_credentials(conn->iacred_cli);
conn->iacred_cli = NULL;
return -1;
}
#endif /* GNUTLS_IE */
return ret;
}
@ -729,11 +672,13 @@ int tls_global_set_params(void *tls_ctx,
GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
}
#if LIBGNUTLS_VERSION_NUMBER >= 0x020800
if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
gnutls_certificate_set_verify_flags(
global->xcred,
GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
}
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
}
if (params->client_cert && params->private_key) {
@ -822,10 +767,11 @@ int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
os_memset(keys, 0, sizeof(*keys));
#if LIBGNUTLS_VERSION_NUMBER < 0x020c00
#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
sec = &conn->session->security_parameters;
keys->master_key = sec->master_secret;
keys->master_key_len = TLS_MASTER_SIZE;
keys->master_key_len = WPA_TLS_MASTER_SIZE;
keys->client_random = sec->client_random;
keys->server_random = sec->server_random;
#else /* GNUTLS_INTERNAL_STRUCTURE_HACK */
@ -835,16 +781,12 @@ int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
(u8 *) gnutls_session_get_server_random(conn->session);
/* No access to master_secret */
#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020c00 */
#ifdef GNUTLS_IA
gnutls_ia_extract_inner_secret(conn->session,
(char *) conn->inner_secret);
keys->inner_secret = conn->inner_secret;
keys->inner_secret_len = TLS_MASTER_SIZE;
#endif /* GNUTLS_IA */
keys->client_random_len = TLS_RANDOM_SIZE;
keys->server_random_len = TLS_RANDOM_SIZE;
#if LIBGNUTLS_VERSION_NUMBER < 0x020c00
keys->client_random_len = WPA_TLS_RANDOM_SIZE;
keys->server_random_len = WPA_TLS_RANDOM_SIZE;
#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020c00 */
return 0;
}
@ -883,11 +825,13 @@ static int tls_connection_verify_peer(struct tls_connection *conn,
if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
*err = GNUTLS_A_INTERNAL_ERROR;
if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
"algorithm");
*err = GNUTLS_A_INSUFFICIENT_SECURITY;
}
#if LIBGNUTLS_VERSION_NUMBER >= 0x020800
if (status & GNUTLS_CERT_NOT_ACTIVATED) {
wpa_printf(MSG_INFO, "TLS: Certificate not yet "
"activated");
@ -897,6 +841,7 @@ static int tls_connection_verify_peer(struct tls_connection *conn,
wpa_printf(MSG_INFO, "TLS: Certificate expired");
*err = GNUTLS_A_CERTIFICATE_EXPIRED;
}
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
return -1;
}
@ -988,7 +933,7 @@ static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
wpabuf_size(ad));
wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
if (res < 0) {
wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
"(%s)", __func__, (int) res,
gnutls_strerror(res));
wpabuf_free(ad);
@ -1062,20 +1007,7 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
goto out;
}
#ifdef CONFIG_GNUTLS_EXTRA
if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) {
wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation");
conn->failed++;
return NULL;
}
#endif /* CONFIG_GNUTLS_EXTRA */
if (conn->tls_ia)
wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake");
else {
wpa_printf(MSG_DEBUG, "TLS: Handshake completed "
"successfully");
}
wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
conn->established = 1;
if (conn->push_buf == NULL) {
/* Need to return something to get final TLS ACK. */
@ -1122,12 +1054,6 @@ struct wpabuf * tls_connection_encrypt(void *tls_ctx,
ssize_t res;
struct wpabuf *buf;
#ifdef GNUTLS_IA
if (conn->tls_ia)
res = gnutls_ia_send(conn->session, wpabuf_head(in_data),
wpabuf_len(in_data));
else
#endif /* GNUTLS_IA */
res = gnutls_record_send(conn->session, wpabuf_head(in_data),
wpabuf_len(in_data));
if (res < 0) {
@ -1170,65 +1096,6 @@ struct wpabuf * tls_connection_decrypt(void *tls_ctx,
if (out == NULL)
return NULL;
#ifdef GNUTLS_IA
if (conn->tls_ia) {
res = gnutls_ia_recv(conn->session, wpabuf_mhead(out),
wpabuf_size(out));
if (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) {
int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
__func__, final ? "Final" : "Intermediate");
res = gnutls_ia_permute_inner_secret(
conn->session, conn->session_keys_len,
(char *) conn->session_keys);
if (conn->session_keys) {
os_memset(conn->session_keys, 0,
conn->session_keys_len);
os_free(conn->session_keys);
}
conn->session_keys = NULL;
conn->session_keys_len = 0;
if (res) {
wpa_printf(MSG_DEBUG, "%s: Failed to permute "
"inner secret: %s",
__func__, gnutls_strerror(res));
wpabuf_free(out);
return NULL;
}
res = gnutls_ia_verify_endphase(conn->session,
wpabuf_head(out));
if (res == 0) {
wpa_printf(MSG_DEBUG, "%s: Correct endphase "
"checksum", __func__);
} else {
wpa_printf(MSG_INFO, "%s: Endphase "
"verification failed: %s",
__func__, gnutls_strerror(res));
wpabuf_free(out);
return NULL;
}
if (final)
conn->final_phase_finished = 1;
return out;
}
if (res < 0) {
wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
"(%s)", __func__, (int) res,
gnutls_strerror(res));
wpabuf_free(out);
return NULL;
}
wpabuf_put(out, res);
return out;
}
#endif /* GNUTLS_IA */
res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
wpabuf_size(out));
if (res < 0) {
@ -1319,133 +1186,7 @@ int tls_connection_get_keyblock_size(void *tls_ctx,
unsigned int tls_capabilities(void *tls_ctx)
{
unsigned int capa = 0;
#ifdef GNUTLS_IA
capa |= TLS_CAPABILITY_IA;
#endif /* GNUTLS_IA */
return capa;
}
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
int tls_ia)
{
#ifdef GNUTLS_IA
int ret;
if (conn == NULL)
return -1;
conn->tls_ia = tls_ia;
if (!tls_ia)
return 0;
ret = gnutls_ia_allocate_server_credentials(&conn->iacred_srv);
if (ret) {
wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
gnutls_strerror(ret));
return -1;
}
ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
conn->iacred_srv);
if (ret) {
wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
gnutls_strerror(ret));
gnutls_ia_free_server_credentials(conn->iacred_srv);
conn->iacred_srv = NULL;
return -1;
}
return 0;
#else /* GNUTLS_IA */
return -1;
#endif /* GNUTLS_IA */
}
struct wpabuf * tls_connection_ia_send_phase_finished(
void *tls_ctx, struct tls_connection *conn, int final)
{
#ifdef GNUTLS_IA
int ret;
struct wpabuf *buf;
if (conn == NULL || conn->session == NULL || !conn->tls_ia)
return NULL;
ret = gnutls_ia_permute_inner_secret(conn->session,
conn->session_keys_len,
(char *) conn->session_keys);
if (conn->session_keys) {
os_memset(conn->session_keys, 0, conn->session_keys_len);
os_free(conn->session_keys);
}
conn->session_keys = NULL;
conn->session_keys_len = 0;
if (ret) {
wpa_printf(MSG_DEBUG, "%s: Failed to permute inner secret: %s",
__func__, gnutls_strerror(ret));
return NULL;
}
ret = gnutls_ia_endphase_send(conn->session, final);
if (ret) {
wpa_printf(MSG_DEBUG, "%s: Failed to send endphase: %s",
__func__, gnutls_strerror(ret));
return NULL;
}
buf = conn->push_buf;
conn->push_buf = NULL;
return buf;
#else /* GNUTLS_IA */
return NULL;
#endif /* GNUTLS_IA */
}
int tls_connection_ia_final_phase_finished(void *tls_ctx,
struct tls_connection *conn)
{
if (conn == NULL)
return -1;
return conn->final_phase_finished;
}
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
struct tls_connection *conn,
const u8 *key, size_t key_len)
{
#ifdef GNUTLS_IA
if (conn == NULL || !conn->tls_ia)
return -1;
if (conn->session_keys) {
os_memset(conn->session_keys, 0, conn->session_keys_len);
os_free(conn->session_keys);
}
conn->session_keys_len = 0;
if (key) {
conn->session_keys = os_malloc(key_len);
if (conn->session_keys == NULL)
return -1;
os_memcpy(conn->session_keys, key, key_len);
conn->session_keys_len = key_len;
} else {
conn->session_keys = NULL;
conn->session_keys_len = 0;
}
return 0;
#else /* GNUTLS_IA */
return -1;
#endif /* GNUTLS_IA */
}

View File

@ -1,6 +1,6 @@
/*
* TLS interface functions and an internal TLS implementation
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2011, 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
@ -211,6 +211,9 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
return -1;
}
tlsv1_client_set_time_checks(
conn->client, !(params->flags & TLS_CONN_DISABLE_TIME_CHECKS));
return 0;
#else /* CONFIG_TLS_INTERNAL_CLIENT */
return -1;
@ -287,13 +290,6 @@ int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
}
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
int tls_ia)
{
return -1;
}
int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
struct tls_keys *keys)
{
@ -608,28 +604,6 @@ unsigned int tls_capabilities(void *tls_ctx)
}
struct wpabuf * tls_connection_ia_send_phase_finished(
void *tls_ctx, struct tls_connection *conn, int final)
{
return NULL;
}
int tls_connection_ia_final_phase_finished(void *tls_ctx,
struct tls_connection *conn)
{
return -1;
}
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
struct tls_connection *conn,
const u8 *key, size_t key_len)
{
return -1;
}
int tls_connection_set_session_ticket_cb(void *tls_ctx,
struct tls_connection *conn,
tls_session_ticket_cb cb,

View File

@ -84,13 +84,6 @@ int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
}
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
int tls_ia)
{
return -1;
}
int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
struct tls_keys *keys)
{
@ -205,25 +198,3 @@ unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
}
struct wpabuf * tls_connection_ia_send_phase_finished(
void *tls_ctx, struct tls_connection *conn, int final)
{
return NULL;
}
int tls_connection_ia_final_phase_finished(void *tls_ctx,
struct tls_connection *conn)
{
return -1;
}
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
struct tls_connection *conn,
const u8 *key, size_t key_len)
{
return -1;
}

View File

@ -419,13 +419,6 @@ int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
}
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
int tls_ia)
{
return -1;
}
int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
struct tls_keys *keys)
{
@ -649,28 +642,6 @@ unsigned int tls_capabilities(void *tls_ctx)
}
struct wpabuf * tls_connection_ia_send_phase_finished(
void *tls_ctx, struct tls_connection *conn, int final)
{
return NULL;
}
int tls_connection_ia_final_phase_finished(void *tls_ctx,
struct tls_connection *conn)
{
return -1;
}
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
struct tls_connection *conn,
const u8 *key, size_t key_len)
{
return -1;
}
int tls_connection_set_session_ticket_cb(void *tls_ctx,
struct tls_connection *conn,
tls_session_ticket_cb cb,

View File

@ -1,6 +1,6 @@
/*
* SSL/TLS interface functions for OpenSSL
* Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2011, 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
@ -28,6 +28,11 @@
#include <openssl/engine.h>
#endif /* OPENSSL_NO_ENGINE */
#ifdef ANDROID
#include <openssl/pem.h>
#include "keystore_get.h"
#endif /* ANDROID */
#include "common.h"
#include "crypto.h"
#include "tls.h"
@ -54,6 +59,7 @@ struct tls_global {
void (*event_cb)(void *ctx, enum tls_event ev,
union tls_event_data *data);
void *cb_ctx;
int cert_in_cb;
};
static struct tls_global *tls_global = NULL;
@ -81,6 +87,8 @@ struct tls_connection {
unsigned int server_cert_only:1;
u8 srv_cert_hash[32];
unsigned int flags;
};
@ -687,6 +695,7 @@ void * tls_init(const struct tls_config *conf)
if (conf) {
tls_global->event_cb = conf->event_cb;
tls_global->cb_ctx = conf->cb_ctx;
tls_global->cert_in_cb = conf->cert_in_cb;
}
#ifdef CONFIG_FIPS
@ -711,7 +720,7 @@ void * tls_init(const struct tls_config *conf)
#endif /* CONFIG_FIPS */
SSL_load_error_strings();
SSL_library_init();
#ifndef OPENSSL_NO_SHA256
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
EVP_add_digest(EVP_sha256());
#endif /* OPENSSL_NO_SHA256 */
/* TODO: if /dev/urandom is available, PRNG is seeded
@ -1137,7 +1146,7 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
return;
os_memset(&ev, 0, sizeof(ev));
if (conn->cert_probe) {
if (conn->cert_probe || tls_global->cert_in_cb) {
cert = get_x509_cert(err_cert);
ev.peer_cert.cert = cert;
}
@ -1178,13 +1187,22 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
conn = SSL_get_app_data(ssl);
match = conn ? conn->subject_match : NULL;
altmatch = conn ? conn->altsubject_match : NULL;
if (conn == NULL)
return 0;
match = conn->subject_match;
altmatch = conn->altsubject_match;
if (!preverify_ok && !conn->ca_cert_verify)
preverify_ok = 1;
if (!preverify_ok && depth > 0 && conn->server_cert_only)
preverify_ok = 1;
if (!preverify_ok && (conn->flags & TLS_CONN_DISABLE_TIME_CHECKS) &&
(err == X509_V_ERR_CERT_HAS_EXPIRED ||
err == X509_V_ERR_CERT_NOT_YET_VALID)) {
wpa_printf(MSG_DEBUG, "OpenSSL: Ignore certificate validity "
"time mismatch");
preverify_ok = 1;
}
err_str = X509_verify_cert_error_string(err);
@ -1290,6 +1308,19 @@ static int tls_load_ca_der(void *_ssl_ctx, const char *ca_cert)
#endif /* OPENSSL_NO_STDIO */
#ifdef ANDROID
static BIO * BIO_from_keystore(const char *key)
{
BIO *bio = NULL;
char value[KEYSTORE_MESSAGE_SIZE];
int length = keystore_get(key, strlen(key), value);
if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL)
BIO_write(bio, value, length);
return bio;
}
#endif /* ANDROID */
static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
const char *ca_cert, const u8 *ca_cert_blob,
size_t ca_cert_blob_len, const char *ca_path)
@ -1380,6 +1411,36 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
return 0;
}
#ifdef ANDROID
if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
BIO *bio = BIO_from_keystore(&ca_cert[11]);
STACK_OF(X509_INFO) *stack = NULL;
int i;
if (bio) {
stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
BIO_free(bio);
}
if (!stack)
return -1;
for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
X509_INFO *info = sk_X509_INFO_value(stack, i);
if (info->x509) {
X509_STORE_add_cert(ssl_ctx->cert_store,
info->x509);
}
if (info->crl) {
X509_STORE_add_crl(ssl_ctx->cert_store,
info->crl);
}
}
sk_X509_INFO_pop_free(stack, X509_INFO_free);
SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
return 0;
}
#endif /* ANDROID */
#ifdef CONFIG_NATIVE_WINDOWS
if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) ==
0) {
@ -1550,26 +1611,42 @@ static int tls_connection_client_cert(struct tls_connection *conn,
if (client_cert == NULL)
return -1;
#ifdef ANDROID
if (os_strncmp("keystore://", client_cert, 11) == 0) {
BIO *bio = BIO_from_keystore(&client_cert[11]);
X509 *x509 = NULL;
int ret = -1;
if (bio) {
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
BIO_free(bio);
}
if (x509) {
if (SSL_use_certificate(conn->ssl, x509) == 1)
ret = 0;
X509_free(x509);
}
return ret;
}
#endif /* ANDROID */
#ifndef OPENSSL_NO_STDIO
if (SSL_use_certificate_file(conn->ssl, client_cert,
SSL_FILETYPE_ASN1) == 1) {
wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (DER)"
" --> OK");
return 0;
} else {
tls_show_errors(MSG_DEBUG, __func__,
"SSL_use_certificate_file (DER) failed");
}
if (SSL_use_certificate_file(conn->ssl, client_cert,
SSL_FILETYPE_PEM) == 1) {
ERR_clear_error();
wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)"
" --> OK");
return 0;
} else {
tls_show_errors(MSG_DEBUG, __func__,
"SSL_use_certificate_file (PEM) failed");
}
tls_show_errors(MSG_DEBUG, __func__,
"SSL_use_certificate_file failed");
#else /* OPENSSL_NO_STDIO */
wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
#endif /* OPENSSL_NO_STDIO */
@ -1900,10 +1977,6 @@ static int tls_connection_private_key(void *_ssl_ctx,
"ASN1(EVP_PKEY_RSA) --> OK");
ok = 1;
break;
} else {
tls_show_errors(MSG_DEBUG, __func__,
"SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA)"
" failed");
}
if (SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA, conn->ssl,
@ -1913,10 +1986,6 @@ static int tls_connection_private_key(void *_ssl_ctx,
"ASN1(EVP_PKEY_DSA) --> OK");
ok = 1;
break;
} else {
tls_show_errors(MSG_DEBUG, __func__,
"SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA)"
" failed");
}
if (SSL_use_RSAPrivateKey_ASN1(conn->ssl,
@ -1926,9 +1995,6 @@ static int tls_connection_private_key(void *_ssl_ctx,
"SSL_use_RSAPrivateKey_ASN1 --> OK");
ok = 1;
break;
} else {
tls_show_errors(MSG_DEBUG, __func__,
"SSL_use_RSAPrivateKey_ASN1 failed");
}
if (tls_read_pkcs12_blob(ssl_ctx, conn->ssl, private_key_blob,
@ -1942,6 +2008,26 @@ static int tls_connection_private_key(void *_ssl_ctx,
break;
}
#ifdef ANDROID
if (!ok && private_key &&
os_strncmp("keystore://", private_key, 11) == 0) {
BIO *bio = BIO_from_keystore(&private_key[11]);
EVP_PKEY *pkey = NULL;
if (bio) {
pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
BIO_free(bio);
}
if (pkey) {
if (SSL_use_PrivateKey(conn->ssl, pkey) == 1) {
wpa_printf(MSG_DEBUG, "OpenSSL: Private key "
"from keystore");
ok = 1;
}
EVP_PKEY_free(pkey);
}
}
#endif /* ANDROID */
while (!ok && private_key) {
#ifndef OPENSSL_NO_STDIO
if (SSL_use_PrivateKey_file(conn->ssl, private_key,
@ -1950,10 +2036,6 @@ static int tls_connection_private_key(void *_ssl_ctx,
"SSL_use_PrivateKey_File (DER) --> OK");
ok = 1;
break;
} else {
tls_show_errors(MSG_DEBUG, __func__,
"SSL_use_PrivateKey_File (DER) "
"failed");
}
if (SSL_use_PrivateKey_file(conn->ssl, private_key,
@ -1962,10 +2044,6 @@ static int tls_connection_private_key(void *_ssl_ctx,
"SSL_use_PrivateKey_File (PEM) --> OK");
ok = 1;
break;
} else {
tls_show_errors(MSG_DEBUG, __func__,
"SSL_use_PrivateKey_File (PEM) "
"failed");
}
#else /* OPENSSL_NO_STDIO */
wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO",
@ -1991,9 +2069,9 @@ static int tls_connection_private_key(void *_ssl_ctx,
}
if (!ok) {
wpa_printf(MSG_INFO, "OpenSSL: Failed to load private key");
tls_show_errors(MSG_INFO, __func__,
"Failed to load private key");
os_free(passwd);
ERR_clear_error();
return -1;
}
ERR_clear_error();
@ -2663,6 +2741,8 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
return -1;
}
conn->flags = params->flags;
tls_get_errors(tls_ctx);
return 0;
@ -2731,35 +2811,6 @@ unsigned int tls_capabilities(void *tls_ctx)
}
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
int tls_ia)
{
return -1;
}
struct wpabuf * tls_connection_ia_send_phase_finished(
void *tls_ctx, struct tls_connection *conn, int final)
{
return NULL;
}
int tls_connection_ia_final_phase_finished(void *tls_ctx,
struct tls_connection *conn)
{
return -1;
}
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
struct tls_connection *conn,
const u8 *key, size_t key_len)
{
return -1;
}
#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
/* Pre-shared secred requires a patch to openssl, so this function is
* commented out unless explicitly needed for EAP-FAST in order to be able to

View File

@ -736,32 +736,3 @@ unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
}
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
int tls_ia)
{
return -1;
}
struct wpabuf * tls_connection_ia_send_phase_finished(
void *tls_ctx, struct tls_connection *conn, int final);
{
return NULL;
}
int tls_connection_ia_final_phase_finished(void *tls_ctx,
struct tls_connection *conn)
{
return -1;
}
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
struct tls_connection *conn,
const u8 *key, size_t key_len)
{
return -1;
}

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@
*/
#define ATH_WPS_IE
#include "os/linux/include/ieee80211_external.h"
#include "ieee80211_external.h"
#ifdef CONFIG_WPS
@ -56,7 +56,7 @@
#include "linux_ioctl.h"
struct madwifi_driver_data {
struct atheros_driver_data {
struct hostapd_data *hapd; /* back pointer */
char iface[IFNAMSIZ + 1];
@ -70,11 +70,14 @@ struct madwifi_driver_data {
struct hostap_sta_driver_data acct_data;
struct l2_packet_data *sock_raw; /* raw 802.11 management frames */
struct wpabuf *wpa_ie;
struct wpabuf *wps_beacon_ie;
struct wpabuf *wps_probe_resp_ie;
};
static int madwifi_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
static int atheros_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
int reason_code);
static int madwifi_set_privacy(void *priv, int enabled);
static int atheros_set_privacy(void *priv, int enabled);
static const char * athr_get_ioctl_name(int op)
{
@ -125,16 +128,8 @@ static const char * athr_get_ioctl_name(int op)
return "FILTERFRAME";
case IEEE80211_IOCTL_SET_RTPARAMS:
return "SET_RTPARAMS";
case IEEE80211_IOCTL_SENDADDBA:
return "SENDADDBA";
case IEEE80211_IOCTL_GETADDBASTATUS:
return "GETADDBASTATUS";
case IEEE80211_IOCTL_SENDDELBA:
return "SENDDELBA";
case IEEE80211_IOCTL_SET_MEDENYENTRY:
return "SET_MEDENYENTRY";
case IEEE80211_IOCTL_SET_ADDBARESP:
return "SET_ADDBARESP";
case IEEE80211_IOCTL_GET_MACADDR:
return "GET_MACADDR";
case IEEE80211_IOCTL_SET_HBRPARAMS:
@ -179,7 +174,7 @@ static const char * athr_get_param_name(int op)
static int
set80211priv(struct madwifi_driver_data *drv, int op, void *data, int len)
set80211priv(struct atheros_driver_data *drv, int op, void *data, int len)
{
struct iwreq iwr;
int do_inline = len < IFNAMSIZ;
@ -218,7 +213,7 @@ set80211priv(struct madwifi_driver_data *drv, int op, void *data, int len)
}
static int
set80211param(struct madwifi_driver_data *drv, int op, int arg)
set80211param(struct atheros_driver_data *drv, int op, int arg)
{
struct iwreq iwr;
@ -255,7 +250,7 @@ ether_sprintf(const u8 *addr)
* Configure WPA parameters.
*/
static int
madwifi_configure_wpa(struct madwifi_driver_data *drv,
atheros_configure_wpa(struct atheros_driver_data *drv,
struct wpa_bss_params *params)
{
int v;
@ -320,6 +315,14 @@ madwifi_configure_wpa(struct madwifi_driver_data *drv,
v = 0;
if (params->rsn_preauth)
v |= BIT(0);
#ifdef CONFIG_IEEE80211W
if (params->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
v |= BIT(7);
if (params->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
v |= BIT(6);
}
#endif /* CONFIG_IEEE80211W */
wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x",
__func__, params->rsn_preauth);
if (set80211param(drv, IEEE80211_PARAM_RSNCAPS, v)) {
@ -336,9 +339,9 @@ madwifi_configure_wpa(struct madwifi_driver_data *drv,
}
static int
madwifi_set_ieee8021x(void *priv, struct wpa_bss_params *params)
atheros_set_ieee8021x(void *priv, struct wpa_bss_params *params)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled);
@ -348,14 +351,14 @@ madwifi_set_ieee8021x(void *priv, struct wpa_bss_params *params)
IEEE80211_AUTH_AUTO) < 0)
return -1;
/* IEEE80211_AUTH_AUTO ends up enabling Privacy; clear that */
return madwifi_set_privacy(drv, 0);
return atheros_set_privacy(drv, 0);
}
if (!params->wpa && !params->ieee802_1x) {
hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!");
return -1;
}
if (params->wpa && madwifi_configure_wpa(drv, params) != 0) {
if (params->wpa && atheros_configure_wpa(drv, params) != 0) {
hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!");
return -1;
@ -371,9 +374,9 @@ madwifi_set_ieee8021x(void *priv, struct wpa_bss_params *params)
}
static int
madwifi_set_privacy(void *priv, int enabled)
atheros_set_privacy(void *priv, int enabled)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
@ -381,9 +384,9 @@ madwifi_set_privacy(void *priv, int enabled)
}
static int
madwifi_set_sta_authorized(void *priv, const u8 *addr, int authorized)
atheros_set_sta_authorized(void *priv, const u8 *addr, int authorized)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
struct ieee80211req_mlme mlme;
int ret;
@ -406,21 +409,21 @@ madwifi_set_sta_authorized(void *priv, const u8 *addr, int authorized)
}
static int
madwifi_sta_set_flags(void *priv, const u8 *addr,
atheros_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 & WPA_STA_AUTHORIZED)
return madwifi_set_sta_authorized(priv, addr, 1);
return atheros_set_sta_authorized(priv, addr, 1);
if (!(flags_and & WPA_STA_AUTHORIZED))
return madwifi_set_sta_authorized(priv, addr, 0);
return atheros_set_sta_authorized(priv, addr, 0);
return 0;
}
static int
madwifi_del_key(void *priv, const u8 *addr, int key_idx)
atheros_del_key(void *priv, const u8 *addr, int key_idx)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
struct ieee80211req_del_key wk;
int ret;
@ -446,17 +449,17 @@ madwifi_del_key(void *priv, const u8 *addr, int key_idx)
}
static int
madwifi_set_key(const char *ifname, void *priv, enum wpa_alg alg,
atheros_set_key(const char *ifname, void *priv, enum wpa_alg alg,
const u8 *addr, int key_idx, int set_tx, const u8 *seq,
size_t seq_len, const u8 *key, size_t key_len)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
struct ieee80211req_key wk;
u_int8_t cipher;
int ret;
if (alg == WPA_ALG_NONE)
return madwifi_del_key(drv, addr, key_idx);
return atheros_del_key(drv, addr, key_idx);
wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%s key_idx=%d",
__func__, alg, ether_sprintf(addr), key_idx);
@ -471,6 +474,11 @@ madwifi_set_key(const char *ifname, void *priv, enum wpa_alg alg,
case WPA_ALG_CCMP:
cipher = IEEE80211_CIPHER_AES_CCM;
break;
#ifdef CONFIG_IEEE80211W
case WPA_ALG_IGTK:
cipher = IEEE80211_CIPHER_AES_CMAC;
break;
#endif /* CONFIG_IEEE80211W */
default:
printf("%s: unknown/unsupported algorithm %d\n",
__func__, alg);
@ -486,10 +494,11 @@ madwifi_set_key(const char *ifname, void *priv, enum wpa_alg alg,
memset(&wk, 0, sizeof(wk));
wk.ik_type = cipher;
wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;
if (addr == NULL) {
if (addr == NULL || is_broadcast_ether_addr(addr)) {
memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
wk.ik_keyix = key_idx;
wk.ik_flags |= IEEE80211_KEY_DEFAULT;
if (set_tx)
wk.ik_flags |= IEEE80211_KEY_DEFAULT;
} else {
memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
wk.ik_keyix = IEEE80211_KEYIX_NONE;
@ -510,10 +519,10 @@ madwifi_set_key(const char *ifname, void *priv, enum wpa_alg alg,
static int
madwifi_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
atheros_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
u8 *seq)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
struct ieee80211req_key wk;
wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d",
@ -557,20 +566,20 @@ madwifi_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
static int
madwifi_flush(void *priv)
atheros_flush(void *priv)
{
u8 allsta[IEEE80211_ADDR_LEN];
memset(allsta, 0xff, IEEE80211_ADDR_LEN);
return madwifi_sta_deauth(priv, NULL, allsta,
return atheros_sta_deauth(priv, NULL, allsta,
IEEE80211_REASON_AUTH_LEAVE);
}
static int
madwifi_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data,
atheros_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data,
const u8 *addr)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
struct ieee80211req_sta_stats stats;
memset(data, 0, sizeof(*data));
@ -602,9 +611,9 @@ madwifi_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data,
static int
madwifi_sta_clear_stats(void *priv, const u8 *addr)
atheros_sta_clear_stats(void *priv, const u8 *addr)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
struct ieee80211req_mlme mlme;
int ret;
@ -624,20 +633,61 @@ madwifi_sta_clear_stats(void *priv, const u8 *addr)
static int
madwifi_set_opt_ie(void *priv, const u8 *ie, size_t ie_len)
atheros_set_opt_ie(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.
*/
struct atheros_driver_data *drv = priv;
u8 buf[512];
struct ieee80211req_getset_appiebuf *app_ie;
wpa_printf(MSG_DEBUG, "%s buflen = %lu", __func__,
(unsigned long) ie_len);
wpa_hexdump(MSG_DEBUG, "atheros: set_generic_elem", ie, ie_len);
wpabuf_free(drv->wpa_ie);
drv->wpa_ie = wpabuf_alloc_copy(ie, ie_len);
app_ie = (struct ieee80211req_getset_appiebuf *) buf;
os_memcpy(&(app_ie->app_buf[0]), ie, ie_len);
app_ie->app_buflen = ie_len;
app_ie->app_frmtype = IEEE80211_APPIE_FRAME_BEACON;
/* append WPS IE for Beacon */
if (drv->wps_beacon_ie != NULL) {
os_memcpy(&(app_ie->app_buf[ie_len]),
wpabuf_head(drv->wps_beacon_ie),
wpabuf_len(drv->wps_beacon_ie));
app_ie->app_buflen = ie_len + wpabuf_len(drv->wps_beacon_ie);
}
wpa_hexdump(MSG_DEBUG, "atheros: SET_APPIEBUF(Beacon)",
app_ie->app_buf, app_ie->app_buflen);
set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, app_ie,
sizeof(struct ieee80211req_getset_appiebuf) +
app_ie->app_buflen);
/* append WPS IE for Probe Response */
app_ie->app_frmtype = IEEE80211_APPIE_FRAME_PROBE_RESP;
if (drv->wps_probe_resp_ie != NULL) {
os_memcpy(&(app_ie->app_buf[ie_len]),
wpabuf_head(drv->wps_probe_resp_ie),
wpabuf_len(drv->wps_probe_resp_ie));
app_ie->app_buflen = ie_len +
wpabuf_len(drv->wps_probe_resp_ie);
} else
app_ie->app_buflen = ie_len;
wpa_hexdump(MSG_DEBUG, "atheros: SET_APPIEBUF(ProbeResp)",
app_ie->app_buf, app_ie->app_buflen);
set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, app_ie,
sizeof(struct ieee80211req_getset_appiebuf) +
app_ie->app_buflen);
return 0;
}
static int
madwifi_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
atheros_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
int reason_code)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
struct ieee80211req_mlme mlme;
int ret;
@ -658,10 +708,10 @@ madwifi_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
}
static int
madwifi_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
atheros_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
int reason_code)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
struct ieee80211req_mlme mlme;
int ret;
@ -682,10 +732,10 @@ madwifi_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
}
#ifdef CONFIG_WPS
static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf,
static void atheros_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf,
size_t len)
{
struct madwifi_driver_data *drv = ctx;
struct atheros_driver_data *drv = ctx;
const struct ieee80211_mgmt *mgmt;
u16 fc;
union wpa_event_data event;
@ -703,6 +753,8 @@ static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf,
os_memset(&event, 0, sizeof(event));
event.rx_probe_req.sa = mgmt->sa;
event.rx_probe_req.da = mgmt->da;
event.rx_probe_req.bssid = mgmt->bssid;
event.rx_probe_req.ie = mgmt->u.probe_req.variable;
event.rx_probe_req.ie_len =
len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
@ -710,7 +762,7 @@ static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf,
}
#endif /* CONFIG_WPS */
static int madwifi_receive_probe_req(struct madwifi_driver_data *drv)
static int atheros_receive_probe_req(struct atheros_driver_data *drv)
{
int ret = 0;
#ifdef CONFIG_WPS
@ -725,7 +777,7 @@ static int madwifi_receive_probe_req(struct madwifi_driver_data *drv)
return ret;
drv->sock_raw = l2_packet_init(drv->iface, NULL, ETH_P_80211_RAW,
madwifi_raw_receive, drv, 1);
atheros_raw_receive, drv, 1);
if (drv->sock_raw == NULL)
return -1;
#endif /* CONFIG_WPS */
@ -734,43 +786,74 @@ static int madwifi_receive_probe_req(struct madwifi_driver_data *drv)
#ifdef CONFIG_WPS
static int
madwifi_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype)
atheros_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype)
{
struct madwifi_driver_data *drv = priv;
u8 buf[256];
struct atheros_driver_data *drv = priv;
u8 buf[512];
struct ieee80211req_getset_appiebuf *beac_ie;
wpa_printf(MSG_DEBUG, "%s buflen = %lu", __func__,
(unsigned long) len);
wpa_printf(MSG_DEBUG, "%s buflen = %lu frametype=%u", __func__,
(unsigned long) len, frametype);
wpa_hexdump(MSG_DEBUG, "atheros: IE", ie, len);
beac_ie = (struct ieee80211req_getset_appiebuf *) buf;
beac_ie->app_frmtype = frametype;
beac_ie->app_buflen = len;
memcpy(&(beac_ie->app_buf[0]), ie, len);
os_memcpy(&(beac_ie->app_buf[0]), ie, len);
/* append the WPA/RSN IE if it is set already */
if (((frametype == IEEE80211_APPIE_FRAME_BEACON) ||
(frametype == IEEE80211_APPIE_FRAME_PROBE_RESP)) &&
(drv->wpa_ie != NULL)) {
wpa_hexdump_buf(MSG_DEBUG, "atheros: Append WPA/RSN IE",
drv->wpa_ie);
os_memcpy(&(beac_ie->app_buf[len]), wpabuf_head(drv->wpa_ie),
wpabuf_len(drv->wpa_ie));
beac_ie->app_buflen += wpabuf_len(drv->wpa_ie);
}
wpa_hexdump(MSG_DEBUG, "atheros: SET_APPIEBUF",
beac_ie->app_buf, beac_ie->app_buflen);
return set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, beac_ie,
sizeof(struct ieee80211req_getset_appiebuf) + len);
sizeof(struct ieee80211req_getset_appiebuf) +
beac_ie->app_buflen);
}
static int
madwifi_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
const struct wpabuf *proberesp)
atheros_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
const struct wpabuf *proberesp,
const struct wpabuf *assocresp)
{
if (madwifi_set_wps_ie(priv, beacon ? wpabuf_head(beacon) : NULL,
struct atheros_driver_data *drv = priv;
wpa_hexdump_buf(MSG_DEBUG, "atheros: set_ap_wps_ie - beacon", beacon);
wpa_hexdump_buf(MSG_DEBUG, "atheros: set_ap_wps_ie - proberesp",
proberesp);
wpa_hexdump_buf(MSG_DEBUG, "atheros: set_ap_wps_ie - assocresp",
assocresp);
wpabuf_free(drv->wps_beacon_ie);
drv->wps_beacon_ie = beacon ? wpabuf_dup(beacon) : NULL;
wpabuf_free(drv->wps_probe_resp_ie);
drv->wps_probe_resp_ie = proberesp ? wpabuf_dup(proberesp) : NULL;
atheros_set_wps_ie(priv, assocresp ? wpabuf_head(assocresp) : NULL,
assocresp ? wpabuf_len(assocresp) : 0,
IEEE80211_APPIE_FRAME_ASSOC_RESP);
if (atheros_set_wps_ie(priv, beacon ? wpabuf_head(beacon) : NULL,
beacon ? wpabuf_len(beacon) : 0,
IEEE80211_APPIE_FRAME_BEACON))
return -1;
return madwifi_set_wps_ie(priv,
return atheros_set_wps_ie(priv,
proberesp ? wpabuf_head(proberesp) : NULL,
proberesp ? wpabuf_len(proberesp): 0,
IEEE80211_APPIE_FRAME_PROBE_RESP);
}
#else /* CONFIG_WPS */
#define madwifi_set_ap_wps_ie NULL
#define atheros_set_ap_wps_ie NULL
#endif /* CONFIG_WPS */
static void
madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
atheros_new_sta(struct atheros_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
{
struct hostapd_data *hapd = drv->hapd;
struct ieee80211req_wpaie ie;
@ -791,17 +874,21 @@ madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
__func__, strerror(errno));
goto no_ie;
}
wpa_hexdump(MSG_MSGDUMP, "madwifi req WPA IE",
wpa_hexdump(MSG_MSGDUMP, "atheros req WPA IE",
ie.wpa_ie, IEEE80211_MAX_OPT_IE);
wpa_hexdump(MSG_MSGDUMP, "madwifi req RSN IE",
wpa_hexdump(MSG_MSGDUMP, "atheros req RSN IE",
ie.rsn_ie, IEEE80211_MAX_OPT_IE);
#ifdef ATH_WPS_IE
wpa_hexdump(MSG_MSGDUMP, "atheros req WPS IE",
ie.wps_ie, IEEE80211_MAX_OPT_IE);
#endif /* ATH_WPS_IE */
iebuf = ie.wpa_ie;
/* madwifi seems to return some random data if WPA/RSN IE is not set.
/* atheros seems to return some random data if WPA/RSN IE is not set.
* Assume the IE was not included if the IE type is unknown. */
if (iebuf[0] != WLAN_EID_VENDOR_SPECIFIC)
iebuf[1] = 0;
if (iebuf[1] == 0 && ie.rsn_ie[1] > 0) {
/* madwifi-ng svn #1453 added rsn_ie. Use it, if wpa_ie was not
/* atheros-ng svn #1453 added rsn_ie. Use it, if wpa_ie was not
* set. This is needed for WPA2. */
iebuf = ie.rsn_ie;
if (iebuf[0] != WLAN_EID_RSN)
@ -809,13 +896,23 @@ madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
}
ielen = iebuf[1];
#ifdef ATH_WPS_IE
/* if WPS IE is present, preference is given to WPS */
if (ie.wps_ie &&
(ie.wps_ie[1] > 0 && (ie.wps_ie[0] == WLAN_EID_VENDOR_SPECIFIC))) {
iebuf = ie.wps_ie;
ielen = ie.wps_ie[1];
}
#endif /* ATH_WPS_IE */
if (ielen == 0)
iebuf = NULL;
else
ielen += 2;
no_ie:
drv_event_assoc(hapd, addr, iebuf, ielen);
drv_event_assoc(hapd, addr, iebuf, ielen, 0);
if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
/* Cached accounting data is not valid anymore. */
@ -825,7 +922,7 @@ no_ie:
}
static void
madwifi_wireless_event_wireless_custom(struct madwifi_driver_data *drv,
atheros_wireless_event_wireless_custom(struct atheros_driver_data *drv,
char *custom, char *end)
{
wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
@ -897,14 +994,14 @@ madwifi_wireless_event_wireless_custom(struct madwifi_driver_data *drv,
"length %d", len);
return;
}
madwifi_raw_receive(drv, NULL,
atheros_raw_receive(drv, NULL,
(u8 *) custom + WPS_FRAM_TAG_SIZE, len);
#endif /* CONFIG_WPS */
}
}
static void
madwifi_wireless_event_wireless(struct madwifi_driver_data *drv,
atheros_wireless_event_wireless(struct atheros_driver_data *drv,
char *data, int len)
{
struct iw_event iwe_buf, *iwe = &iwe_buf;
@ -943,7 +1040,7 @@ madwifi_wireless_event_wireless(struct madwifi_driver_data *drv,
(u8 *) iwe->u.addr.sa_data);
break;
case IWEVREGISTERED:
madwifi_new_sta(drv, (u8 *) iwe->u.addr.sa_data);
atheros_new_sta(drv, (u8 *) iwe->u.addr.sa_data);
break;
case IWEVASSOCREQIE:
/* Driver hack.. Use IWEVASSOCREQIE to bypass
@ -958,7 +1055,7 @@ madwifi_wireless_event_wireless(struct madwifi_driver_data *drv,
return; /* XXX */
memcpy(buf, custom, iwe->u.data.length);
buf[iwe->u.data.length] = '\0';
madwifi_wireless_event_wireless_custom(
atheros_wireless_event_wireless_custom(
drv, buf, buf + iwe->u.data.length);
free(buf);
break;
@ -970,10 +1067,10 @@ madwifi_wireless_event_wireless(struct madwifi_driver_data *drv,
static void
madwifi_wireless_event_rtm_newlink(void *ctx,
atheros_wireless_event_rtm_newlink(void *ctx,
struct ifinfomsg *ifi, u8 *buf, size_t len)
{
struct madwifi_driver_data *drv = ctx;
struct atheros_driver_data *drv = ctx;
int attrlen, rta_len;
struct rtattr *attr;
@ -986,7 +1083,7 @@ madwifi_wireless_event_rtm_newlink(void *ctx,
rta_len = RTA_ALIGN(sizeof(struct rtattr));
while (RTA_OK(attr, attrlen)) {
if (attr->rta_type == IFLA_WIRELESS) {
madwifi_wireless_event_wireless(
atheros_wireless_event_wireless(
drv, ((char *) attr) + rta_len,
attr->rta_len - rta_len);
}
@ -996,7 +1093,7 @@ madwifi_wireless_event_rtm_newlink(void *ctx,
static int
madwifi_get_we_version(struct madwifi_driver_data *drv)
atheros_get_we_version(struct atheros_driver_data *drv)
{
struct iw_range *range;
struct iwreq iwr;
@ -1036,23 +1133,23 @@ madwifi_get_we_version(struct madwifi_driver_data *drv)
drv->we_version = range->we_version_compiled;
}
free(range);
os_free(range);
return 0;
}
static int
madwifi_wireless_event_init(struct madwifi_driver_data *drv)
atheros_wireless_event_init(struct atheros_driver_data *drv)
{
struct netlink_config *cfg;
madwifi_get_we_version(drv);
atheros_get_we_version(drv);
cfg = os_zalloc(sizeof(*cfg));
if (cfg == NULL)
return -1;
cfg->ctx = drv;
cfg->newlink_cb = madwifi_wireless_event_rtm_newlink;
cfg->newlink_cb = atheros_wireless_event_rtm_newlink;
drv->netlink = netlink_init(cfg);
if (drv->netlink == NULL) {
os_free(cfg);
@ -1064,10 +1161,10 @@ madwifi_wireless_event_init(struct madwifi_driver_data *drv)
static int
madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
int encrypt, const u8 *own_addr)
atheros_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
int encrypt, const u8 *own_addr, u32 flags)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
unsigned char buf[3000];
unsigned char *bp = buf;
struct l2_ethhdr *eth;
@ -1107,22 +1204,22 @@ madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
static void
handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
{
struct madwifi_driver_data *drv = ctx;
struct atheros_driver_data *drv = ctx;
drv_event_eapol_rx(drv->hapd, src_addr, buf + sizeof(struct l2_ethhdr),
len - sizeof(struct l2_ethhdr));
}
static void *
madwifi_init(struct hostapd_data *hapd, struct wpa_init_params *params)
atheros_init(struct hostapd_data *hapd, struct wpa_init_params *params)
{
struct madwifi_driver_data *drv;
struct atheros_driver_data *drv;
struct ifreq ifr;
struct iwreq iwr;
char brname[IFNAMSIZ];
drv = os_zalloc(sizeof(struct madwifi_driver_data));
drv = os_zalloc(sizeof(struct atheros_driver_data));
if (drv == NULL) {
printf("Could not allocate memory for madwifi driver data\n");
printf("Could not allocate memory for atheros driver data\n");
return NULL;
}
@ -1179,11 +1276,11 @@ madwifi_init(struct hostapd_data *hapd, struct wpa_init_params *params)
/* mark down during setup */
linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0);
madwifi_set_privacy(drv, 0); /* default to no privacy */
atheros_set_privacy(drv, 0); /* default to no privacy */
madwifi_receive_probe_req(drv);
atheros_receive_probe_req(drv);
if (madwifi_wireless_event_init(drv))
if (atheros_wireless_event_init(drv))
goto bad;
return drv;
@ -1201,9 +1298,9 @@ bad:
static void
madwifi_deinit(void *priv)
atheros_deinit(void *priv)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
netlink_deinit(drv->netlink);
(void) linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0);
@ -1215,13 +1312,16 @@ madwifi_deinit(void *priv)
l2_packet_deinit(drv->sock_xmit);
if (drv->sock_raw)
l2_packet_deinit(drv->sock_raw);
wpabuf_free(drv->wpa_ie);
wpabuf_free(drv->wps_beacon_ie);
wpabuf_free(drv->wps_probe_resp_ie);
free(drv);
}
static int
madwifi_set_ssid(void *priv, const u8 *buf, int len)
atheros_set_ssid(void *priv, const u8 *buf, int len)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
struct iwreq iwr;
memset(&iwr, 0, sizeof(iwr));
@ -1239,9 +1339,9 @@ madwifi_set_ssid(void *priv, const u8 *buf, int len)
}
static int
madwifi_get_ssid(void *priv, u8 *buf, int len)
atheros_get_ssid(void *priv, u8 *buf, int len)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
struct iwreq iwr;
int ret = 0;
@ -1249,6 +1349,8 @@ madwifi_get_ssid(void *priv, u8 *buf, int len)
os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
iwr.u.essid.pointer = (caddr_t) buf;
iwr.u.essid.length = len;
iwr.u.essid.length = (len > IW_ESSID_MAX_SIZE) ?
IW_ESSID_MAX_SIZE : len;
if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
perror("ioctl[SIOCGIWESSID]");
@ -1260,39 +1362,86 @@ madwifi_get_ssid(void *priv, u8 *buf, int len)
}
static int
madwifi_set_countermeasures(void *priv, int enabled)
atheros_set_countermeasures(void *priv, int enabled)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled);
}
static int
madwifi_commit(void *priv)
atheros_commit(void *priv)
{
struct madwifi_driver_data *drv = priv;
struct atheros_driver_data *drv = priv;
return linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1);
}
static int atheros_set_authmode(void *priv, int auth_algs)
{
int authmode;
if ((auth_algs & WPA_AUTH_ALG_OPEN) &&
(auth_algs & WPA_AUTH_ALG_SHARED))
authmode = IEEE80211_AUTH_AUTO;
else if (auth_algs & WPA_AUTH_ALG_OPEN)
authmode = IEEE80211_AUTH_OPEN;
else if (auth_algs & WPA_AUTH_ALG_SHARED)
authmode = IEEE80211_AUTH_SHARED;
else
return -1;
return set80211param(priv, IEEE80211_PARAM_AUTHMODE, authmode);
}
static int atheros_set_ap(void *priv, struct wpa_driver_ap_params *params)
{
/*
* TODO: Use this to replace set_authmode, set_privacy, set_ieee8021x,
* set_generic_elem, and hapd_set_ssid.
*/
wpa_printf(MSG_DEBUG, "atheros: set_ap - pairwise_ciphers=0x%x "
"group_cipher=0x%x key_mgmt_suites=0x%x auth_algs=0x%x "
"wpa_version=0x%x privacy=%d interworking=%d",
params->pairwise_ciphers, params->group_cipher,
params->key_mgmt_suites, params->auth_algs,
params->wpa_version, params->privacy, params->interworking);
wpa_hexdump_ascii(MSG_DEBUG, "atheros: SSID",
params->ssid, params->ssid_len);
if (params->hessid)
wpa_printf(MSG_DEBUG, "atheros: HESSID " MACSTR,
MAC2STR(params->hessid));
wpa_hexdump_buf(MSG_DEBUG, "atheros: beacon_ies",
params->beacon_ies);
wpa_hexdump_buf(MSG_DEBUG, "atheros: proberesp_ies",
params->proberesp_ies);
wpa_hexdump_buf(MSG_DEBUG, "atheros: assocresp_ies",
params->assocresp_ies);
return 0;
}
const struct wpa_driver_ops wpa_driver_atheros_ops = {
.name = "atheros",
.hapd_init = madwifi_init,
.hapd_deinit = madwifi_deinit,
.set_ieee8021x = madwifi_set_ieee8021x,
.set_privacy = madwifi_set_privacy,
.set_key = madwifi_set_key,
.get_seqnum = madwifi_get_seqnum,
.flush = madwifi_flush,
.set_generic_elem = madwifi_set_opt_ie,
.sta_set_flags = madwifi_sta_set_flags,
.read_sta_data = madwifi_read_sta_driver_data,
.hapd_send_eapol = madwifi_send_eapol,
.sta_disassoc = madwifi_sta_disassoc,
.sta_deauth = madwifi_sta_deauth,
.hapd_set_ssid = madwifi_set_ssid,
.hapd_get_ssid = madwifi_get_ssid,
.set_countermeasures = madwifi_set_countermeasures,
.sta_clear_stats = madwifi_sta_clear_stats,
.commit = madwifi_commit,
.set_ap_wps_ie = madwifi_set_ap_wps_ie,
.hapd_init = atheros_init,
.hapd_deinit = atheros_deinit,
.set_ieee8021x = atheros_set_ieee8021x,
.set_privacy = atheros_set_privacy,
.set_key = atheros_set_key,
.get_seqnum = atheros_get_seqnum,
.flush = atheros_flush,
.set_generic_elem = atheros_set_opt_ie,
.sta_set_flags = atheros_sta_set_flags,
.read_sta_data = atheros_read_sta_driver_data,
.hapd_send_eapol = atheros_send_eapol,
.sta_disassoc = atheros_sta_disassoc,
.sta_deauth = atheros_sta_deauth,
.hapd_set_ssid = atheros_set_ssid,
.hapd_get_ssid = atheros_get_ssid,
.set_countermeasures = atheros_set_countermeasures,
.sta_clear_stats = atheros_sta_clear_stats,
.commit = atheros_commit,
.set_ap_wps_ie = atheros_set_ap_wps_ie,
.set_authmode = atheros_set_authmode,
.set_ap = atheros_set_ap,
};

View File

@ -0,0 +1,89 @@
/*
* Common driver-related functions
* Copyright (c) 2003-2011, 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 "utils/common.h"
#include "driver.h"
void wpa_scan_results_free(struct wpa_scan_results *res)
{
size_t i;
if (res == NULL)
return;
for (i = 0; i < res->num; i++)
os_free(res->res[i]);
os_free(res->res);
os_free(res);
}
const char * event_to_string(enum wpa_event_type event)
{
#define E2S(n) case EVENT_ ## n: return #n
switch (event) {
E2S(ASSOC);
E2S(DISASSOC);
E2S(MICHAEL_MIC_FAILURE);
E2S(SCAN_RESULTS);
E2S(ASSOCINFO);
E2S(INTERFACE_STATUS);
E2S(PMKID_CANDIDATE);
E2S(STKSTART);
E2S(TDLS);
E2S(FT_RESPONSE);
E2S(IBSS_RSN_START);
E2S(AUTH);
E2S(DEAUTH);
E2S(ASSOC_REJECT);
E2S(AUTH_TIMED_OUT);
E2S(ASSOC_TIMED_OUT);
E2S(FT_RRB_RX);
E2S(WPS_BUTTON_PUSHED);
E2S(TX_STATUS);
E2S(RX_FROM_UNKNOWN);
E2S(RX_MGMT);
E2S(RX_ACTION);
E2S(REMAIN_ON_CHANNEL);
E2S(CANCEL_REMAIN_ON_CHANNEL);
E2S(MLME_RX);
E2S(RX_PROBE_REQ);
E2S(NEW_STA);
E2S(EAPOL_RX);
E2S(SIGNAL_CHANGE);
E2S(INTERFACE_ENABLED);
E2S(INTERFACE_DISABLED);
E2S(CHANNEL_LIST_CHANGED);
E2S(INTERFACE_UNAVAILABLE);
E2S(BEST_CHANNEL);
E2S(UNPROT_DEAUTH);
E2S(UNPROT_DISASSOC);
E2S(STATION_LOW_ACK);
E2S(P2P_DEV_FOUND);
E2S(P2P_GO_NEG_REQ_RX);
E2S(P2P_GO_NEG_COMPLETED);
E2S(P2P_PROV_DISC_REQUEST);
E2S(P2P_PROV_DISC_RESPONSE);
E2S(P2P_SD_REQUEST);
E2S(P2P_SD_RESPONSE);
E2S(IBSS_PEER_LOST);
E2S(DRIVER_GTK_REKEY);
E2S(SCHED_SCAN_STOPPED);
E2S(DRIVER_CLIENT_POLL_OK);
}
return "UNKNOWN";
#undef E2S
}

View File

@ -32,6 +32,7 @@
#include "netlink.h"
#include "linux_ioctl.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
/* MTU to be set for the wlan#ap device; this is mainly needed for IEEE 802.1X
@ -84,8 +85,8 @@ static void handle_data(struct hostap_driver_data *drv, u8 *buf, size_t len,
sa = hdr->addr2;
os_memset(&event, 0, sizeof(event));
event.rx_from_unknown.frame = buf;
event.rx_from_unknown.len = len;
event.rx_from_unknown.bssid = get_hdr_bssid(hdr, len);
event.rx_from_unknown.addr = sa;
wpa_supplicant_event(drv->hapd, EVENT_RX_FROM_UNKNOWN, &event);
pos = (u8 *) (hdr + 1);
@ -148,7 +149,6 @@ static void handle_frame(struct hostap_driver_data *drv, 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;
union wpa_event_data event;
@ -185,7 +185,6 @@ static void handle_frame(struct hostap_driver_data *drv, u8 *buf, size_t len)
return;
}
len -= extra_len + 2;
extra = buf + len;
} else if (ver == 1 || ver == 2) {
handle_tx_callback(drv, buf, data_len, ver == 2 ? 1 : 0);
return;
@ -289,7 +288,8 @@ static int hostap_send_mlme(void *priv, const u8 *msg, size_t len)
static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data,
size_t data_len, int encrypt, const u8 *own_addr)
size_t data_len, int encrypt, const u8 *own_addr,
u32 flags)
{
struct hostap_driver_data *drv = priv;
struct ieee80211_hdr *hdr;
@ -763,7 +763,8 @@ static int hostap_set_generic_elem(void *priv,
static int hostap_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
const struct wpabuf *proberesp)
const struct wpabuf *proberesp,
const struct wpabuf *assocresp)
{
struct hostap_driver_data *drv = priv;
@ -1034,6 +1035,16 @@ static int hostap_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
struct hostap_driver_data *drv = priv;
struct ieee80211_mgmt mgmt;
if (is_broadcast_ether_addr(addr)) {
/*
* New Prism2.5/3 STA firmware versions seem to have issues
* with this broadcast deauth frame. This gets the firmware in
* odd state where nothing works correctly, so let's skip
* sending this for the hostap driver.
*/
return 0;
}
memset(&mgmt, 0, sizeof(mgmt));
mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_DEAUTH);
@ -1046,6 +1057,25 @@ static int hostap_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
}
static int hostap_set_freq(void *priv, struct hostapd_freq_params *freq)
{
struct hostap_driver_data *drv = priv;
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
iwr.u.freq.m = freq->channel;
iwr.u.freq.e = 0;
if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
perror("ioctl[SIOCSIWFREQ]");
return -1;
}
return 0;
}
static int hostap_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
int reason)
{
@ -1114,6 +1144,33 @@ static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv,
return mode;
}
static void wpa_driver_hostap_poll_client(void *priv, const u8 *own_addr,
const u8 *addr, int qos)
{
struct ieee80211_hdr hdr;
os_memset(&hdr, 0, sizeof(hdr));
/*
* WLAN_FC_STYPE_NULLFUNC would be more appropriate,
* but it is apparently not retried so TX Exc events
* are not received for it.
* This is the reason the driver overrides the default
* handling.
*/
hdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA,
WLAN_FC_STYPE_DATA);
hdr.frame_control |=
host_to_le16(WLAN_FC_FROMDS);
os_memcpy(hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);
os_memcpy(hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
os_memcpy(hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr));
}
#else /* HOSTAPD */
struct wpa_driver_hostap_data {
@ -1306,7 +1363,8 @@ static int wpa_driver_hostap_set_key(const char *ifname, void *priv,
HOSTAP_CRYPT_ALG_NAME_LEN);
param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
param->u.crypt.idx = key_idx;
os_memcpy(param->u.crypt.seq, seq, seq_len);
if (seq)
os_memcpy(param->u.crypt.seq, seq, seq_len);
param->u.crypt.key_len = key_len;
os_memcpy((u8 *) (param + 1), key, key_len);
@ -1619,6 +1677,8 @@ const struct wpa_driver_ops wpa_driver_hostap_ops = {
.sta_clear_stats = hostap_sta_clear_stats,
.get_hw_feature_data = hostap_get_hw_feature_data,
.set_ap_wps_ie = hostap_set_ap_wps_ie,
.set_freq = hostap_set_freq,
.poll_client = wpa_driver_hostap_poll_client,
#else /* HOSTAPD */
.get_bssid = wpa_driver_hostap_get_bssid,
.get_ssid = wpa_driver_hostap_get_ssid,

View File

@ -69,6 +69,7 @@
#define MADWIFI_NG
#endif /* IEEE80211_IOCTL_SETWMMPARAMS */
#define WPA_KEY_RSC_LEN 8
#ifdef HOSTAPD
@ -461,7 +462,7 @@ wpa_driver_madwifi_set_key(const char *ifname, void *priv, enum wpa_alg alg,
memset(&wk, 0, sizeof(wk));
wk.ik_type = cipher;
wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;
if (addr == NULL) {
if (addr == NULL || is_broadcast_ether_addr(addr)) {
memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
wk.ik_keyix = key_idx;
wk.ik_flags |= IEEE80211_KEY_DEFAULT;
@ -733,6 +734,8 @@ static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf,
os_memset(&event, 0, sizeof(event));
event.rx_probe_req.sa = mgmt->sa;
event.rx_probe_req.da = mgmt->da;
event.rx_probe_req.bssid = mgmt->bssid;
event.rx_probe_req.ie = mgmt->u.probe_req.variable;
event.rx_probe_req.ie_len =
len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
@ -787,7 +790,8 @@ madwifi_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype)
static int
madwifi_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
const struct wpabuf *proberesp)
const struct wpabuf *proberesp,
const struct wpabuf *assocresp)
{
if (madwifi_set_wps_ie(priv, beacon ? wpabuf_head(beacon) : NULL,
beacon ? wpabuf_len(beacon) : 0,
@ -802,6 +806,24 @@ madwifi_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
#define madwifi_set_ap_wps_ie NULL
#endif /* CONFIG_WPS */
static int madwifi_set_freq(void *priv, struct hostapd_freq_params *freq)
{
struct madwifi_driver_data *drv = priv;
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
iwr.u.freq.m = freq->channel;
iwr.u.freq.e = 0;
if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
perror("ioctl[SIOCSIWFREQ]");
return -1;
}
return 0;
}
static void
madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
{
@ -846,7 +868,7 @@ madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
ielen += 2;
no_ie:
drv_event_assoc(hapd, addr, iebuf, ielen);
drv_event_assoc(hapd, addr, iebuf, ielen, 0);
if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
/* Cached accounting data is not valid anymore. */
@ -1065,7 +1087,7 @@ madwifi_wireless_event_init(struct madwifi_driver_data *drv)
static int
madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
int encrypt, const u8 *own_addr)
int encrypt, const u8 *own_addr, u32 flags)
{
struct madwifi_driver_data *drv = priv;
unsigned char buf[3000];
@ -1509,8 +1531,7 @@ wpa_driver_madwifi_set_key(const char *ifname, void *priv, enum wpa_alg alg,
wk.ik_keyix = key_idx;
wk.ik_keylen = key_len;
#ifdef WORDS_BIGENDIAN
#define WPA_KEY_RSC_LEN 8
{
if (seq) {
size_t i;
u8 tmp[WPA_KEY_RSC_LEN];
os_memset(tmp, 0, sizeof(tmp));
@ -1519,7 +1540,8 @@ wpa_driver_madwifi_set_key(const char *ifname, void *priv, enum wpa_alg alg,
os_memcpy(&wk.ik_keyrsc, tmp, WPA_KEY_RSC_LEN);
}
#else /* WORDS_BIGENDIAN */
os_memcpy(&wk.ik_keyrsc, seq, seq_len);
if (seq)
os_memcpy(&wk.ik_keyrsc, seq, seq_len);
#endif /* WORDS_BIGENDIAN */
os_memcpy(wk.ik_keydata, key, key_len);
@ -1838,6 +1860,7 @@ const struct wpa_driver_ops wpa_driver_madwifi_ops = {
.sta_clear_stats = madwifi_sta_clear_stats,
.commit = madwifi_commit,
.set_ap_wps_ie = madwifi_set_ap_wps_ie,
.set_freq = madwifi_set_freq,
#else /* HOSTAPD */
.get_bssid = wpa_driver_madwifi_get_bssid,
.get_ssid = wpa_driver_madwifi_get_ssid,

View File

@ -1001,8 +1001,7 @@ static int wpa_driver_ndis_set_key(const char *ifname, void *priv,
int res, pairwise;
u8 bssid[ETH_ALEN];
if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
ETH_ALEN) == 0) {
if (addr == NULL || is_broadcast_ether_addr(addr)) {
/* Group Key */
pairwise = 0;
if (wpa_driver_ndis_get_bssid(drv, bssid) < 0)
@ -1066,6 +1065,7 @@ wpa_driver_ndis_associate(void *priv,
{
struct wpa_driver_ndis_data *drv = priv;
u32 auth_mode, encr, priv_mode, mode;
u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
drv->mode = params->mode;
@ -1091,7 +1091,6 @@ wpa_driver_ndis_associate(void *priv,
if (params->key_mgmt_suite == KEY_MGMT_NONE ||
params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) {
/* Re-set WEP keys if static WEP configuration is used. */
u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
int i;
for (i = 0; i < 4; i++) {
if (!params->wep_key[i])
@ -1125,6 +1124,22 @@ wpa_driver_ndis_associate(void *priv,
} else if (params->key_mgmt_suite == KEY_MGMT_WPS) {
auth_mode = Ndis802_11AuthModeOpen;
priv_mode = Ndis802_11PrivFilterAcceptAll;
if (params->wps == WPS_MODE_PRIVACY) {
u8 dummy_key[5] = { 0x11, 0x22, 0x33, 0x44, 0x55 };
/*
* Some NDIS drivers refuse to associate in open mode
* configuration due to Privacy field mismatch, so use
* a workaround to make the configuration look like
* matching one for WPS provisioning.
*/
wpa_printf(MSG_DEBUG, "NDIS: Set dummy WEP key as a "
"workaround to allow driver to associate "
"for WPS");
wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP,
bcast, 0, 1,
NULL, 0, dummy_key,
sizeof(dummy_key));
}
#endif /* CONFIG_WPS */
} else {
priv_mode = Ndis802_11PrivFilter8021xWEP;
@ -1148,6 +1163,12 @@ wpa_driver_ndis_associate(void *priv,
encr = Ndis802_11Encryption1Enabled;
break;
case CIPHER_NONE:
#ifdef CONFIG_WPS
if (params->wps == WPS_MODE_PRIVACY) {
encr = Ndis802_11Encryption1Enabled;
break;
}
#endif /* CONFIG_WPS */
if (params->group_suite == CIPHER_CCMP)
encr = Ndis802_11Encryption3Enabled;
else if (params->group_suite == CIPHER_TKIP)
@ -1156,7 +1177,14 @@ wpa_driver_ndis_associate(void *priv,
encr = Ndis802_11EncryptionDisabled;
break;
default:
#ifdef CONFIG_WPS
if (params->wps == WPS_MODE_PRIVACY) {
encr = Ndis802_11Encryption1Enabled;
break;
}
#endif /* CONFIG_WPS */
encr = Ndis802_11EncryptionDisabled;
break;
};
if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER,
@ -3185,94 +3213,33 @@ wpa_driver_ndis_get_interfaces(void *global_priv)
}
const struct wpa_driver_ops wpa_driver_ndis_ops = {
"ndis",
"Windows NDIS driver",
wpa_driver_ndis_get_bssid,
wpa_driver_ndis_get_ssid,
wpa_driver_ndis_set_key,
wpa_driver_ndis_init,
wpa_driver_ndis_deinit,
NULL /* set_param */,
NULL /* set_countermeasures */,
wpa_driver_ndis_deauthenticate,
wpa_driver_ndis_disassociate,
wpa_driver_ndis_associate,
wpa_driver_ndis_add_pmkid,
wpa_driver_ndis_remove_pmkid,
wpa_driver_ndis_flush_pmkid,
wpa_driver_ndis_get_capa,
wpa_driver_ndis_poll,
wpa_driver_ndis_get_ifname,
wpa_driver_ndis_get_mac_addr,
NULL /* send_eapol */,
NULL /* set_operstate */,
NULL /* mlme_setprotection */,
NULL /* get_hw_feature_data */,
NULL /* set_channel */,
NULL /* set_ssid */,
NULL /* set_bssid */,
NULL /* send_mlme */,
NULL /* mlme_add_sta */,
NULL /* mlme_remove_sta */,
NULL /* update_ft_ies */,
NULL /* send_ft_action */,
wpa_driver_ndis_get_scan_results,
NULL /* set_country */,
NULL /* global_init */,
NULL /* global_deinit */,
NULL /* init2 */,
wpa_driver_ndis_get_interfaces,
wpa_driver_ndis_scan,
NULL /* authenticate */,
NULL /* set_beacon */,
NULL /* hapd_init */,
NULL /* hapd_deinit */,
NULL /* set_ieee8021x */,
NULL /* set_privacy */,
NULL /* get_seqnum */,
NULL /* flush */,
NULL /* set_generic_elem */,
NULL /* read_sta_data */,
NULL /* hapd_send_eapol */,
NULL /* sta_deauth */,
NULL /* sta_disassoc */,
NULL /* sta_remove */,
NULL /* hapd_get_ssid */,
NULL /* hapd_set_ssid */,
NULL /* hapd_set_countermeasures */,
NULL /* sta_add */,
NULL /* get_inact_sec */,
NULL /* sta_clear_stats */,
NULL /* set_freq */,
NULL /* set_rts */,
NULL /* set_frag */,
NULL /* sta_set_flags */,
NULL /* set_rate_sets */,
NULL /* set_cts_protect */,
NULL /* set_preamble */,
NULL /* set_short_slot_time */,
NULL /* set_tx_queue_params */,
NULL /* valid_bss_mask */,
NULL /* if_add */,
NULL /* if_remove */,
NULL /* set_sta_vlan */,
NULL /* commit */,
NULL /* send_ether */,
NULL /* set_radius_acl_auth */,
NULL /* set_radius_acl_expire */,
NULL /* set_ht_params */,
NULL /* set_ap_wps_ie */,
NULL /* set_supp_port */,
NULL /* set_wds_sta */,
NULL /* send_action */,
NULL /* remain_on_channel */,
NULL /* cancel_remain_on_channel */,
NULL /* probe_req_report */,
NULL /* disable_11b_rates */,
NULL /* deinit_ap */,
NULL /* suspend */,
NULL /* resume */,
NULL /* signal_monitor */,
NULL /* send_frame */
};
static const char *ndis_drv_name = "ndis";
static const char *ndis_drv_desc = "Windows NDIS driver";
struct wpa_driver_ops wpa_driver_ndis_ops;
void driver_ndis_init_ops(void)
{
os_memset(&wpa_driver_ndis_ops, 0, sizeof(wpa_driver_ndis_ops));
wpa_driver_ndis_ops.name = ndis_drv_name;
wpa_driver_ndis_ops.desc = ndis_drv_desc;
wpa_driver_ndis_ops.get_bssid = wpa_driver_ndis_get_bssid;
wpa_driver_ndis_ops.get_ssid = wpa_driver_ndis_get_ssid;
wpa_driver_ndis_ops.set_key = wpa_driver_ndis_set_key;
wpa_driver_ndis_ops.init = wpa_driver_ndis_init;
wpa_driver_ndis_ops.deinit = wpa_driver_ndis_deinit;
wpa_driver_ndis_ops.deauthenticate = wpa_driver_ndis_deauthenticate;
wpa_driver_ndis_ops.disassociate = wpa_driver_ndis_disassociate;
wpa_driver_ndis_ops.associate = wpa_driver_ndis_associate;
wpa_driver_ndis_ops.add_pmkid = wpa_driver_ndis_add_pmkid;
wpa_driver_ndis_ops.remove_pmkid = wpa_driver_ndis_remove_pmkid;
wpa_driver_ndis_ops.flush_pmkid = wpa_driver_ndis_flush_pmkid;
wpa_driver_ndis_ops.get_capa = wpa_driver_ndis_get_capa;
wpa_driver_ndis_ops.poll = wpa_driver_ndis_poll;
wpa_driver_ndis_ops.get_ifname = wpa_driver_ndis_get_ifname;
wpa_driver_ndis_ops.get_mac_addr = wpa_driver_ndis_get_mac_addr;
wpa_driver_ndis_ops.get_scan_results2 =
wpa_driver_ndis_get_scan_results;
wpa_driver_ndis_ops.get_interfaces = wpa_driver_ndis_get_interfaces;
wpa_driver_ndis_ops.scan2 = wpa_driver_ndis_scan;
}

File diff suppressed because it is too large Load Diff

View File

@ -1178,8 +1178,7 @@ static int wpa_driver_ralink_set_key(const char *ifname, void *priv,
drv->bAddWepKey = FALSE;
if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
ETH_ALEN) == 0) {
if (addr == NULL || is_broadcast_ether_addr(addr)) {
/* Group Key */
pairwise = 0;
wpa_driver_ralink_get_bssid(drv, bssid);

View File

@ -14,10 +14,10 @@
#include "includes.h"
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/sockios.h>
#include <linux/if_ether.h>
#include <linux/mii.h>
#include <net/if.h>
#include "common.h"
#include "driver.h"
@ -364,7 +364,7 @@ static void * wpa_driver_roboswitch_init(void *ctx, const char *ifname)
/* copy ifname and take a pointer to the second to last character */
sep = drv->ifname +
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)) - 2;
/* find the '.' seperating <interface> and <vlan> */
/* find the '.' separating <interface> and <vlan> */
while (sep > drv->ifname && *sep != '.') sep--;
if (sep <= drv->ifname) {
wpa_printf(MSG_INFO, "%s: No <interface>.<vlan> pair in "

View File

@ -20,7 +20,9 @@
#include "includes.h"
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <net/if_arp.h>
#include "wireless_copy.h"
@ -31,6 +33,7 @@
#include "priv_netlink.h"
#include "netlink.h"
#include "linux_ioctl.h"
#include "rfkill.h"
#include "driver.h"
#include "driver_wext.h"
@ -561,10 +564,28 @@ static void wpa_driver_wext_event_link(struct wpa_driver_wext_data *drv,
del ? "removed" : "added");
if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) {
if (del)
if (del) {
if (drv->if_removed) {
wpa_printf(MSG_DEBUG, "WEXT: if_removed "
"already set - ignore event");
return;
}
drv->if_removed = 1;
else
} else {
if (if_nametoindex(drv->ifname) == 0) {
wpa_printf(MSG_DEBUG, "WEXT: Interface %s "
"does not exist - ignore "
"RTM_NEWLINK",
drv->ifname);
return;
}
if (!drv->if_removed) {
wpa_printf(MSG_DEBUG, "WEXT: if_removed "
"already cleared - ignore event");
return;
}
drv->if_removed = 0;
}
}
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
@ -620,6 +641,7 @@ static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi,
struct wpa_driver_wext_data *drv = ctx;
int attrlen, rta_len;
struct rtattr *attr;
char namebuf[IFNAMSIZ];
if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, buf, len)) {
wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d",
@ -634,6 +656,35 @@ static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi,
(ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
(ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
wpa_printf(MSG_DEBUG, "WEXT: Interface down");
drv->if_disabled = 1;
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
}
if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
if (if_indextoname(ifi->ifi_index, namebuf) &&
linux_iface_up(drv->ioctl_sock, drv->ifname) == 0) {
wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up "
"event since interface %s is down",
namebuf);
} else if (if_nametoindex(drv->ifname) == 0) {
wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up "
"event since interface %s does not exist",
drv->ifname);
} else if (drv->if_removed) {
wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up "
"event since interface %s is marked "
"removed", drv->ifname);
} else {
wpa_printf(MSG_DEBUG, "WEXT: Interface up");
drv->if_disabled = 0;
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
NULL);
}
}
/*
* Some drivers send the association event before the operup event--in
* this case, lifting operstate in wpa_driver_wext_set_operstate()
@ -687,6 +738,62 @@ static void wpa_driver_wext_event_rtm_dellink(void *ctx, struct ifinfomsg *ifi,
}
static void wpa_driver_wext_rfkill_blocked(void *ctx)
{
wpa_printf(MSG_DEBUG, "WEXT: RFKILL blocked");
/*
* This may be for any interface; use ifdown event to disable
* interface.
*/
}
static void wpa_driver_wext_rfkill_unblocked(void *ctx)
{
struct wpa_driver_wext_data *drv = ctx;
wpa_printf(MSG_DEBUG, "WEXT: RFKILL unblocked");
if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) {
wpa_printf(MSG_DEBUG, "WEXT: Could not set interface UP "
"after rfkill unblock");
return;
}
/* rtnetlink ifup handler will report interface as enabled */
}
static void wext_get_phy_name(struct wpa_driver_wext_data *drv)
{
/* Find phy (radio) to which this interface belongs */
char buf[90], *pos;
int f, rv;
drv->phyname[0] = '\0';
snprintf(buf, sizeof(buf) - 1, "/sys/class/net/%s/phy80211/name",
drv->ifname);
f = open(buf, O_RDONLY);
if (f < 0) {
wpa_printf(MSG_DEBUG, "Could not open file %s: %s",
buf, strerror(errno));
return;
}
rv = read(f, drv->phyname, sizeof(drv->phyname) - 1);
close(f);
if (rv < 0) {
wpa_printf(MSG_DEBUG, "Could not read file %s: %s",
buf, strerror(errno));
return;
}
drv->phyname[rv] = '\0';
pos = os_strchr(drv->phyname, '\n');
if (pos)
*pos = '\0';
wpa_printf(MSG_DEBUG, "wext: interface %s phy: %s",
drv->ifname, drv->phyname);
}
/**
* wpa_driver_wext_init - Initialize WE driver interface
* @ctx: context to be used when calling wpa_supplicant functions,
@ -698,6 +805,7 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
{
struct wpa_driver_wext_data *drv;
struct netlink_config *cfg;
struct rfkill_config *rcfg;
char path[128];
struct stat buf;
@ -711,6 +819,7 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
if (stat(path, &buf) == 0) {
wpa_printf(MSG_DEBUG, "WEXT: cfg80211-based driver detected");
drv->cfg80211 = 1;
wext_get_phy_name(drv);
}
drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
@ -731,6 +840,19 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
goto err2;
}
rcfg = os_zalloc(sizeof(*rcfg));
if (rcfg == NULL)
goto err3;
rcfg->ctx = drv;
os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
rcfg->blocked_cb = wpa_driver_wext_rfkill_blocked;
rcfg->unblocked_cb = wpa_driver_wext_rfkill_unblocked;
drv->rfkill = rfkill_init(rcfg);
if (drv->rfkill == NULL) {
wpa_printf(MSG_DEBUG, "WEXT: RFKILL status not available");
os_free(rcfg);
}
drv->mlme_sock = -1;
if (wpa_driver_wext_finish_drv_init(drv) < 0)
@ -741,6 +863,7 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
return drv;
err3:
rfkill_deinit(drv->rfkill);
netlink_deinit(drv->netlink);
err2:
close(drv->ioctl_sock);
@ -750,10 +873,29 @@ err1:
}
static void wpa_driver_wext_send_rfkill(void *eloop_ctx, void *timeout_ctx)
{
wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
}
static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
{
if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0)
return -1;
int send_rfkill_event = 0;
if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) {
if (rfkill_is_blocked(drv->rfkill)) {
wpa_printf(MSG_DEBUG, "WEXT: Could not yet enable "
"interface '%s' due to rfkill",
drv->ifname);
drv->if_disabled = 1;
send_rfkill_event = 1;
} else {
wpa_printf(MSG_ERROR, "WEXT: Could not set "
"interface '%s' UP", drv->ifname);
return -1;
}
}
/*
* Make sure that the driver does not have any obsolete PMKID entries.
@ -795,6 +937,11 @@ static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
netlink_send_oper_ifla(drv->netlink, drv->ifindex,
1, IF_OPER_DORMANT);
if (send_rfkill_event) {
eloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill,
drv, drv->ctx);
}
return 0;
}
@ -822,6 +969,7 @@ void wpa_driver_wext_deinit(void *priv)
netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP);
netlink_deinit(drv->netlink);
rfkill_deinit(drv->rfkill);
if (drv->mlme_sock >= 0)
eloop_unregister_read_sock(drv->mlme_sock);
@ -894,7 +1042,7 @@ int wpa_driver_wext_scan(void *priv, struct wpa_driver_scan_params *params)
/* Not all drivers generate "scan completed" wireless event, so try to
* read results after a timeout. */
timeout = 5;
timeout = 10;
if (drv->scan_complete_events) {
/*
* The driver seems to deliver SIOCGIWSCAN events to notify
@ -1040,7 +1188,8 @@ static void wext_get_scan_freq(struct iw_event *iwe,
}
static void wext_get_scan_qual(struct iw_event *iwe,
static void wext_get_scan_qual(struct wpa_driver_wext_data *drv,
struct iw_event *iwe,
struct wext_scan_data *res)
{
res->res.qual = iwe->u.qual.qual;
@ -1054,6 +1203,14 @@ static void wext_get_scan_qual(struct iw_event *iwe,
res->res.flags |= WPA_SCAN_NOISE_INVALID;
if (iwe->u.qual.updated & IW_QUAL_DBM)
res->res.flags |= WPA_SCAN_LEVEL_DBM;
if ((iwe->u.qual.updated & IW_QUAL_DBM) ||
((iwe->u.qual.level != 0) &&
(iwe->u.qual.level > drv->max_level))) {
if (iwe->u.qual.level >= 64)
res->res.level -= 0x100;
if (iwe->u.qual.noise >= 64)
res->res.noise -= 0x100;
}
}
@ -1255,7 +1412,7 @@ static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res,
tmp[res->num++] = r;
res->res = tmp;
}
/**
* wpa_driver_wext_get_scan_results - Fetch the latest scan results
@ -1265,7 +1422,7 @@ static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res,
struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv)
{
struct wpa_driver_wext_data *drv = priv;
size_t ap_num = 0, len;
size_t len;
int first;
u8 *res_buf;
struct iw_event iwe_buf, *iwe = &iwe_buf;
@ -1277,7 +1434,6 @@ struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv)
if (res_buf == NULL)
return NULL;
ap_num = 0;
first = 1;
res = os_zalloc(sizeof(*res));
@ -1329,7 +1485,7 @@ struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv)
wext_get_scan_freq(iwe, &data);
break;
case IWEVQUAL:
wext_get_scan_qual(iwe, &data);
wext_get_scan_qual(drv, iwe, &data);
break;
case SIOCGIWENCODE:
wext_get_scan_encode(iwe, &data);
@ -1427,6 +1583,8 @@ static int wpa_driver_wext_get_range(void *priv)
"assuming WPA is not supported");
}
drv->max_level = range->max_qual.level;
os_free(range);
return 0;
}
@ -1498,8 +1656,7 @@ static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg,
iwr.u.encoding.pointer = (caddr_t) ext;
iwr.u.encoding.length = sizeof(*ext) + key_len;
if (addr == NULL ||
os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
if (addr == NULL || is_broadcast_ether_addr(addr))
ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY;
if (set_tx)
ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY;
@ -1702,8 +1859,10 @@ static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv)
{
struct iwreq iwr;
const u8 null_bssid[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
#ifndef ANDROID
u8 ssid[32];
int i;
#endif /* ANDROID */
/*
* Only force-disconnect when the card is in infrastructure mode,
@ -1718,32 +1877,39 @@ static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv)
}
if (iwr.u.mode == IW_MODE_INFRA) {
/* Clear the BSSID selection */
if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0) {
wpa_printf(MSG_DEBUG, "WEXT: Failed to clear BSSID "
"selection on disconnect");
}
#ifndef ANDROID
if (drv->cfg80211) {
/*
* cfg80211 supports SIOCSIWMLME commands, so there is
* no need for the random SSID hack, but clear the
* BSSID and SSID.
* SSID.
*/
if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0 ||
wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) {
if (wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) {
wpa_printf(MSG_DEBUG, "WEXT: Failed to clear "
"to disconnect");
"SSID on disconnect");
}
return;
}
/*
* Clear the BSSID selection and set a random SSID to make sure
* the driver will not be trying to associate with something
* even if it does not understand SIOCSIWMLME commands (or
* tries to associate automatically after deauth/disassoc).
* Set a random SSID to make sure the driver will not be trying
* to associate with something even if it does not understand
* SIOCSIWMLME commands (or tries to associate automatically
* after deauth/disassoc).
*/
for (i = 0; i < 32; i++)
ssid[i] = rand() & 0xFF;
if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0 ||
wpa_driver_wext_set_ssid(drv, ssid, 32) < 0) {
if (wpa_driver_wext_set_ssid(drv, ssid, 32) < 0) {
wpa_printf(MSG_DEBUG, "WEXT: Failed to set bogus "
"BSSID/SSID to disconnect");
"SSID to disconnect");
}
#endif /* ANDROID */
}
}
@ -2167,6 +2333,13 @@ int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv)
}
static const char * wext_get_radio_name(void *priv)
{
struct wpa_driver_wext_data *drv = priv;
return drv->phyname;
}
const struct wpa_driver_ops wpa_driver_wext_ops = {
.name = "wext",
.desc = "Linux wireless extensions (generic)",
@ -2186,4 +2359,5 @@ const struct wpa_driver_ops wpa_driver_wext_ops = {
.flush_pmkid = wpa_driver_wext_flush_pmkid,
.get_capa = wpa_driver_wext_get_capa,
.set_operstate = wpa_driver_wext_set_operstate,
.get_radio_name = wext_get_radio_name,
};

View File

@ -23,9 +23,12 @@ struct wpa_driver_wext_data {
int ioctl_sock;
int mlme_sock;
char ifname[IFNAMSIZ + 1];
char phyname[32];
int ifindex;
int ifindex2;
int if_removed;
int if_disabled;
struct rfkill_data *rfkill;
u8 *assoc_req_ies;
size_t assoc_req_ies_len;
u8 *assoc_resp_ies;
@ -45,6 +48,8 @@ struct wpa_driver_wext_data {
int scan_complete_events;
int cfg80211; /* whether driver is using cfg80211 */
u8 max_level;
};
int wpa_driver_wext_get_bssid(void *priv, u8 *bssid);

View File

@ -24,6 +24,9 @@
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
#include <net/if_dl.h>
#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */
#ifdef __sun__
#include <sys/sockio.h>
#endif /* __sun__ */
#include "common.h"
#include "eloop.h"
@ -311,7 +314,7 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr)
static int wired_send_eapol(void *priv, const u8 *addr,
const u8 *data, size_t data_len, int encrypt,
const u8 *own_addr)
const u8 *own_addr, u32 flags)
{
struct wpa_driver_wired_data *drv = priv;
struct ieee8023_hdr *hdr;
@ -462,6 +465,10 @@ static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add)
struct ifreq ifr;
int s;
#ifdef __sun__
return -1;
#endif /* __sun__ */
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket");

View File

@ -24,25 +24,12 @@ extern struct wpa_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */
#ifdef CONFIG_DRIVER_HOSTAP
extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */
#endif /* CONFIG_DRIVER_HOSTAP */
#ifdef CONFIG_DRIVER_HERMES
extern struct wpa_driver_ops wpa_driver_hermes_ops; /* driver_hermes.c */
#endif /* CONFIG_DRIVER_HERMES */
#ifdef CONFIG_DRIVER_MADWIFI
extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */
#endif /* CONFIG_DRIVER_MADWIFI */
#ifdef CONFIG_DRIVER_ATMEL
extern struct wpa_driver_ops wpa_driver_atmel_ops; /* driver_atmel.c */
#endif /* CONFIG_DRIVER_ATMEL */
#ifdef CONFIG_DRIVER_NDISWRAPPER
/* driver_ndiswrapper.c */
extern struct wpa_driver_ops wpa_driver_ndiswrapper_ops;
#endif /* CONFIG_DRIVER_NDISWRAPPER */
#ifdef CONFIG_DRIVER_BROADCOM
extern struct wpa_driver_ops wpa_driver_broadcom_ops; /* driver_broadcom.c */
#endif /* CONFIG_DRIVER_BROADCOM */
#ifdef CONFIG_DRIVER_IPW
extern struct wpa_driver_ops wpa_driver_ipw_ops; /* driver_ipw.c */
#endif /* CONFIG_DRIVER_IPW */
#ifdef CONFIG_DRIVER_BSD
extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */
#endif /* CONFIG_DRIVER_BSD */
@ -87,24 +74,12 @@ struct wpa_driver_ops *wpa_drivers[] =
#ifdef CONFIG_DRIVER_HOSTAP
&wpa_driver_hostap_ops,
#endif /* CONFIG_DRIVER_HOSTAP */
#ifdef CONFIG_DRIVER_HERMES
&wpa_driver_hermes_ops,
#endif /* CONFIG_DRIVER_HERMES */
#ifdef CONFIG_DRIVER_MADWIFI
&wpa_driver_madwifi_ops,
#endif /* CONFIG_DRIVER_MADWIFI */
#ifdef CONFIG_DRIVER_ATMEL
&wpa_driver_atmel_ops,
#endif /* CONFIG_DRIVER_ATMEL */
#ifdef CONFIG_DRIVER_NDISWRAPPER
&wpa_driver_ndiswrapper_ops,
#endif /* CONFIG_DRIVER_NDISWRAPPER */
#ifdef CONFIG_DRIVER_BROADCOM
&wpa_driver_broadcom_ops,
#endif /* CONFIG_DRIVER_BROADCOM */
#ifdef CONFIG_DRIVER_IPW
&wpa_driver_ipw_ops,
#endif /* CONFIG_DRIVER_IPW */
#ifdef CONFIG_DRIVER_BSD
&wpa_driver_bsd_ops,
#endif /* CONFIG_DRIVER_BSD */

View File

@ -1,3 +1,15 @@
##### CLEAR VARS
DRV_CFLAGS =
DRV_WPA_CFLAGS =
DRV_AP_CFLAGS =
DRV_OBJS =
DRV_WPA_OBJS =
DRV_AP_OBJS =
DRV_LIBS =
DRV_WPA_LIBS =
DRV_AP_LIBS =
##### COMMON DRIVERS
ifdef CONFIG_DRIVER_HOSTAP
@ -31,11 +43,23 @@ NEED_SME=y
NEED_AP_MLME=y
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
DRV_LIBS += -lnl
NEED_RFKILL=y
ifdef CONFIG_LIBNL20
DRV_LIBS += -lnl-genl
DRV_CFLAGS += -DCONFIG_LIBNL20
ifdef CONFIG_LIBNL32
DRV_LIBS += -lnl-3
DRV_LIBS += -lnl-genl-3
DRV_CFLAGS += -DCONFIG_LIBNL20
else
ifdef CONFIG_LIBNL_TINY
DRV_LIBS += -lnl-tiny
else
DRV_LIBS += -lnl
endif
ifdef CONFIG_LIBNL20
DRV_LIBS += -lnl-genl
DRV_CFLAGS += -DCONFIG_LIBNL20
endif
endif
endif
@ -77,24 +101,7 @@ DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT
CONFIG_WIRELESS_EXTENSION=y
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
endif
ifdef CONFIG_DRIVER_HERMES
DRV_WPA_CFLAGS += -DCONFIG_DRIVER_HERMES
DRV_WPA_OBJS += ../src/drivers/driver_hermes.o
CONFIG_WIRELESS_EXTENSION=y
endif
ifdef CONFIG_DRIVER_ATMEL
DRV_WPA_CFLAGS += -DCONFIG_DRIVER_ATMEL
DRV_WPA_OBJS += ../src/drivers/driver_atmel.o
CONFIG_WIRELESS_EXTENSION=y
endif
ifdef CONFIG_DRIVER_NDISWRAPPER
DRV_WPA_CFLAGS += -DCONFIG_DRIVER_NDISWRAPPER
DRV_WPA_OBJS += ../src/drivers/driver_ndiswrapper.o
CONFIG_WIRELESS_EXTENSION=y
NEED_RFKILL=y
endif
ifdef CONFIG_DRIVER_RALINK
@ -109,12 +116,6 @@ DRV_WPA_CFLAGS += -DCONFIG_DRIVER_BROADCOM
DRV_WPA_OBJS += ../src/drivers/driver_broadcom.o
endif
ifdef CONFIG_DRIVER_IPW
DRV_WPA_CFLAGS += -DCONFIG_DRIVER_IPW
DRV_WPA_OBJS += ../src/drivers/driver_ipw.o
CONFIG_WIRELESS_EXTENSION=y
endif
ifdef CONFIG_DRIVER_NDIS
DRV_WPA_CFLAGS += -DCONFIG_DRIVER_NDIS
DRV_WPA_OBJS += ../src/drivers/driver_ndis.o
@ -152,6 +153,7 @@ endif
ifdef CONFIG_WIRELESS_EXTENSION
DRV_WPA_CFLAGS += -DCONFIG_WIRELESS_EXTENSION
DRV_WPA_OBJS += ../src/drivers/driver_wext.o
NEED_RFKILL=y
endif
ifdef NEED_NETLINK
@ -162,6 +164,10 @@ ifdef NEED_LINUX_IOCTL
DRV_OBJS += ../src/drivers/linux_ioctl.o
endif
ifdef NEED_RFKILL
DRV_OBJS += ../src/drivers/rfkill.o
endif
##### COMMON VARS
DRV_BOTH_CFLAGS := $(DRV_CFLAGS) $(DRV_WPA_CFLAGS) $(DRV_AP_CFLAGS)

View File

@ -0,0 +1,190 @@
##### CLEAR VARS
DRV_CFLAGS =
DRV_WPA_CFLAGS =
DRV_AP_CFLAGS =
DRV_OBJS =
DRV_WPA_OBJS =
DRV_AP_OBJS =
DRV_LIBS =
DRV_WPA_LIBS =
DRV_AP_LIBS =
##### COMMON DRIVERS
ifdef CONFIG_DRIVER_HOSTAP
DRV_CFLAGS += -DCONFIG_DRIVER_HOSTAP
DRV_OBJS += src/drivers/driver_hostap.c
CONFIG_WIRELESS_EXTENSION=y
NEED_AP_MLME=y
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
endif
ifdef CONFIG_DRIVER_WIRED
DRV_CFLAGS += -DCONFIG_DRIVER_WIRED
DRV_OBJS += src/drivers/driver_wired.c
endif
ifdef CONFIG_DRIVER_MADWIFI
DRV_CFLAGS += -DCONFIG_DRIVER_MADWIFI
DRV_OBJS += src/drivers/driver_madwifi.c
CONFIG_WIRELESS_EXTENSION=y
CONFIG_L2_PACKET=linux
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
endif
ifdef CONFIG_DRIVER_NL80211
DRV_CFLAGS += -DCONFIG_DRIVER_NL80211
DRV_OBJS += src/drivers/driver_nl80211.c
DRV_OBJS += src/utils/radiotap.c
NEED_SME=y
NEED_AP_MLME=y
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
NEED_RFKILL=y
ifdef CONFIG_LIBNL32
DRV_LIBS += -lnl-3
DRV_LIBS += -lnl-genl-3
DRV_CFLAGS += -DCONFIG_LIBNL20
else
ifdef CONFIG_LIBNL_TINY
DRV_LIBS += -lnl-tiny
else
DRV_LIBS += -lnl
endif
ifdef CONFIG_LIBNL20
DRV_LIBS += -lnl-genl
DRV_CFLAGS += -DCONFIG_LIBNL20
endif
endif
endif
ifdef CONFIG_DRIVER_BSD
ifndef CONFIG_L2_PACKET
CONFIG_L2_PACKET=freebsd
endif
DRV_CFLAGS += -DCONFIG_DRIVER_BSD
DRV_OBJS += src/drivers/driver_bsd.c
CONFIG_L2_FREEBSD=y
CONFIG_DNET_PCAP=y
endif
ifdef CONFIG_DRIVER_TEST
DRV_CFLAGS += -DCONFIG_DRIVER_TEST
DRV_OBJS += src/drivers/driver_test.c
NEED_AP_MLME=y
endif
ifdef CONFIG_DRIVER_NONE
DRV_CFLAGS += -DCONFIG_DRIVER_NONE
DRV_OBJS += src/drivers/driver_none.c
endif
##### PURE AP DRIVERS
ifdef CONFIG_DRIVER_ATHEROS
DRV_AP_CFLAGS += -DCONFIG_DRIVER_ATHEROS
DRV_AP_OBJS += src/drivers/driver_atheros.c
CONFIG_L2_PACKET=linux
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
endif
##### PURE CLIENT DRIVERS
ifdef CONFIG_DRIVER_WEXT
DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT
CONFIG_WIRELESS_EXTENSION=y
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
NEED_RFKILL=y
endif
ifdef CONFIG_DRIVER_RALINK
DRV_WPA_CFLAGS += -DCONFIG_DRIVER_RALINK
DRV_WPA_OBJS += src/drivers/driver_ralink.c
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
endif
ifdef CONFIG_DRIVER_BROADCOM
DRV_WPA_CFLAGS += -DCONFIG_DRIVER_BROADCOM
DRV_WPA_OBJS += src/drivers/driver_broadcom.c
endif
ifdef CONFIG_DRIVER_NDIS
DRV_WPA_CFLAGS += -DCONFIG_DRIVER_NDIS
DRV_WPA_OBJS += src/drivers/driver_ndis.c
ifdef CONFIG_NDIS_EVENTS_INTEGRATED
DRV_WPA_OBJS += src/drivers/driver_ndis_.c
endif
ifndef CONFIG_L2_PACKET
CONFIG_L2_PACKET=pcap
endif
CONFIG_WINPCAP=y
ifdef CONFIG_USE_NDISUIO
DRV_WPA_CFLAGS += -DCONFIG_USE_NDISUIO
endif
endif
ifdef CONFIG_DRIVER_OSX
DRV_WPA_CFLAGS += -DCONFIG_DRIVER_OSX
DRV_WPA_OBJS += src/drivers/driver_osx.c
DRV_WPA_LDFLAGS += -framework CoreFoundation
DRV_WPA_LDFLAGS += -F/System/Library/PrivateFrameworks -framework Apple80211
endif
ifdef CONFIG_DRIVER_IPHONE
DRV_WPA_CFLAGS += -DCONFIG_DRIVER_IPHONE
DRV_WPA_OBJS += src/drivers/driver_iphone.c
DRV_WPA_OBJS += src/drivers/MobileApple80211.c
DRV_WPA_LDFLAGS += -framework CoreFoundation
endif
ifdef CONFIG_DRIVER_ROBOSWITCH
DRV_WPA_CFLAGS += -DCONFIG_DRIVER_ROBOSWITCH
DRV_WPA_OBJS += src/drivers/driver_roboswitch.c
endif
ifdef CONFIG_WIRELESS_EXTENSION
DRV_WPA_CFLAGS += -DCONFIG_WIRELESS_EXTENSION
DRV_WPA_OBJS += src/drivers/driver_wext.c
NEED_RFKILL=y
endif
ifdef NEED_NETLINK
DRV_OBJS += src/drivers/netlink.c
endif
ifdef NEED_LINUX_IOCTL
DRV_OBJS += src/drivers/linux_ioctl.c
endif
ifdef NEED_RFKILL
DRV_OBJS += src/drivers/rfkill.c
endif
ifdef CONFIG_DRIVER_CUSTOM
DRV_CFLAGS += -DCONFIG_DRIVER_CUSTOM
endif
##### COMMON VARS
DRV_BOTH_CFLAGS := $(DRV_CFLAGS) $(DRV_WPA_CFLAGS) $(DRV_AP_CFLAGS)
DRV_WPA_CFLAGS += $(DRV_CFLAGS)
DRV_AP_CFLAGS += $(DRV_CFLAGS)
DRV_BOTH_LIBS := $(DRV_LIBS) $(DRV_WPA_LIBS) $(DRV_AP_LIBS)
DRV_WPA_LIBS += $(DRV_LIBS)
DRV_AP_LIBS += $(DRV_LIBS)
DRV_BOTH_OBJS := $(DRV_OBJS) $(DRV_WPA_OBJS) $(DRV_AP_OBJS)
DRV_WPA_OBJS += $(DRV_OBJS)
DRV_AP_OBJS += $(DRV_OBJS)
DRV_BOTH_LDFLAGS := $(DRV_LDFLAGS) $(DRV_WPA_LDFLAGS) $(DRV_AP_LDFLAGS)
DRV_WPA_LDFLAGS += $(DRV_LDFLAGS)
DRV_AP_LDFLAGS += $(DRV_LDFLAGS)

View File

@ -24,6 +24,7 @@
int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
{
struct ifreq ifr;
int ret;
if (sock < 0)
return -1;
@ -32,9 +33,10 @@ int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
ret = errno ? -errno : -999;
wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
ifname, strerror(errno));
return -1;
return ret;
}
if (dev_up) {
@ -48,15 +50,38 @@ int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
}
if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) {
ret = errno ? -errno : -999;
wpa_printf(MSG_ERROR, "Could not set interface %s flags: %s",
ifname, strerror(errno));
return -1;
return ret;
}
return 0;
}
int linux_iface_up(int sock, const char *ifname)
{
struct ifreq ifr;
int ret;
if (sock < 0)
return -1;
os_memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
ret = errno ? -errno : -999;
wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
ifname, strerror(errno));
return ret;
}
return !!(ifr.ifr_flags & IFF_UP);
}
int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr)
{
struct ifreq ifr;

View File

@ -16,6 +16,7 @@
#define LINUX_IOCTL_H
int linux_set_iface_flags(int sock, const char *ifname, int dev_up);
int linux_iface_up(int sock, const char *ifname);
int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr);
int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr);
int linux_br_add(int sock, const char *brname);

View File

@ -34,7 +34,7 @@ static void netlink_receive_link(struct netlink_data *netlink,
if (cb == NULL || NLMSG_PAYLOAD(h, 0) < sizeof(struct ifinfomsg))
return;
cb(netlink->cfg->ctx, NLMSG_DATA(h),
NLMSG_DATA(h) + NLMSG_ALIGN(sizeof(struct ifinfomsg)),
(u8 *) NLMSG_DATA(h) + NLMSG_ALIGN(sizeof(struct ifinfomsg)),
NLMSG_PAYLOAD(h, sizeof(struct ifinfomsg)));
}

View File

@ -16,6 +16,7 @@
#define NETLINK_H
struct netlink_data;
struct ifinfomsg;
struct netlink_config {
void *ctx;

Some files were not shown because too many files have changed in this diff Show More