from hostap.epitest.fi
This commit is contained in:
parent
320d4922ba
commit
111b9fd8ca
|
@ -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.
|
||||
|
|
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(¶ms, 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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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(¶ms, 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, ¶ms);
|
||||
}
|
||||
|
||||
|
||||
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, ¶ms);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(¶ms, 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, ¶ms))
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue