summaryrefslogtreecommitdiff
path: root/contrib/wpa/wpa_supplicant
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wpa/wpa_supplicant')
-rw-r--r--contrib/wpa/wpa_supplicant/Android.mk206
-rw-r--r--contrib/wpa/wpa_supplicant/ChangeLog139
-rw-r--r--contrib/wpa/wpa_supplicant/README17
-rw-r--r--contrib/wpa/wpa_supplicant/README-DPP195
-rw-r--r--contrib/wpa/wpa_supplicant/README-HS2019
-rw-r--r--contrib/wpa/wpa_supplicant/README-P2P6
-rw-r--r--contrib/wpa/wpa_supplicant/android.config87
-rw-r--r--contrib/wpa/wpa_supplicant/ap.c266
-rw-r--r--contrib/wpa/wpa_supplicant/ap.h21
-rw-r--r--contrib/wpa/wpa_supplicant/autoscan.c9
-rw-r--r--contrib/wpa/wpa_supplicant/bgscan.c2
-rw-r--r--contrib/wpa/wpa_supplicant/bgscan_learn.c3
-rw-r--r--contrib/wpa/wpa_supplicant/bgscan_simple.c10
-rw-r--r--contrib/wpa/wpa_supplicant/bss.c73
-rw-r--r--contrib/wpa/wpa_supplicant/bss.h11
-rw-r--r--contrib/wpa/wpa_supplicant/config.c505
-rw-r--r--contrib/wpa/wpa_supplicant/config.h201
-rw-r--r--contrib/wpa/wpa_supplicant/config_file.c218
-rw-r--r--contrib/wpa/wpa_supplicant/config_ssid.h265
-rw-r--r--contrib/wpa/wpa_supplicant/ctrl_iface.c1597
-rw-r--r--contrib/wpa/wpa_supplicant/ctrl_iface_named_pipe.c6
-rw-r--r--contrib/wpa/wpa_supplicant/ctrl_iface_udp.c4
-rw-r--r--contrib/wpa/wpa_supplicant/ctrl_iface_unix.c14
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/Makefile4
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus-wpa_supplicant.conf8
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_common.c8
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_new.c600
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_new.h69
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c865
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h46
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c179
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.h1
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_wps.c364
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_old.c745
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_old.h142
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_old_handlers.c1393
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_old_handlers.h101
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_old_handlers_wps.c152
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/fi.epitest.hostap.WPASupplicant.service.in5
-rw-r--r--contrib/wpa/wpa_supplicant/defconfig134
-rw-r--r--contrib/wpa/wpa_supplicant/dpp_supplicant.c2246
-rw-r--r--contrib/wpa/wpa_supplicant/dpp_supplicant.h29
-rw-r--r--contrib/wpa/wpa_supplicant/driver_i.h226
-rw-r--r--contrib/wpa/wpa_supplicant/eapol_test.c3
-rwxr-xr-xcontrib/wpa/wpa_supplicant/eapol_test.py2
-rw-r--r--contrib/wpa/wpa_supplicant/events.c1246
-rwxr-xr-xcontrib/wpa/wpa_supplicant/examples/dbus-listen-preq.py20
-rw-r--r--contrib/wpa/wpa_supplicant/examples/dpp-qrcode.py130
-rwxr-xr-xcontrib/wpa/wpa_supplicant/examples/p2p-nfc.py168
-rw-r--r--contrib/wpa/wpa_supplicant/examples/p2p/p2p_connect.py70
-rw-r--r--contrib/wpa/wpa_supplicant/examples/p2p/p2p_disconnect.py30
-rw-r--r--contrib/wpa/wpa_supplicant/examples/p2p/p2p_find.py34
-rw-r--r--contrib/wpa/wpa_supplicant/examples/p2p/p2p_flush.py30
-rw-r--r--contrib/wpa/wpa_supplicant/examples/p2p/p2p_group_add.py50
-rw-r--r--contrib/wpa/wpa_supplicant/examples/p2p/p2p_invite.py44
-rw-r--r--contrib/wpa/wpa_supplicant/examples/p2p/p2p_listen.py32
-rw-r--r--contrib/wpa/wpa_supplicant/examples/p2p/p2p_stop_find.py32
-rwxr-xr-xcontrib/wpa/wpa_supplicant/examples/wpas-dbus-new-getall.py29
-rwxr-xr-xcontrib/wpa/wpa_supplicant/examples/wpas-dbus-new-signals.py34
-rwxr-xr-xcontrib/wpa/wpa_supplicant/examples/wpas-dbus-new-wps.py16
-rwxr-xr-xcontrib/wpa/wpa_supplicant/examples/wpas-dbus-new.py20
-rwxr-xr-xcontrib/wpa/wpa_supplicant/examples/wpas-test.py91
-rwxr-xr-xcontrib/wpa/wpa_supplicant/examples/wps-ap-cli6
-rwxr-xr-xcontrib/wpa/wpa_supplicant/examples/wps-nfc.py124
-rw-r--r--contrib/wpa/wpa_supplicant/gas_query.c128
-rw-r--r--contrib/wpa/wpa_supplicant/gas_query.h5
-rw-r--r--contrib/wpa/wpa_supplicant/hs20_supplicant.c145
-rw-r--r--contrib/wpa/wpa_supplicant/hs20_supplicant.h7
-rw-r--r--contrib/wpa/wpa_supplicant/ibss_rsn.c51
-rw-r--r--contrib/wpa/wpa_supplicant/interworking.c168
-rw-r--r--contrib/wpa/wpa_supplicant/interworking.h2
-rw-r--r--contrib/wpa/wpa_supplicant/main.c12
-rw-r--r--contrib/wpa/wpa_supplicant/mbo.c429
-rw-r--r--contrib/wpa/wpa_supplicant/mesh.c267
-rw-r--r--contrib/wpa/wpa_supplicant/mesh_mpm.c107
-rw-r--r--contrib/wpa/wpa_supplicant/mesh_rsn.c82
-rw-r--r--contrib/wpa/wpa_supplicant/notify.c137
-rw-r--r--contrib/wpa/wpa_supplicant/notify.h17
-rw-r--r--contrib/wpa/wpa_supplicant/offchannel.c5
-rw-r--r--contrib/wpa/wpa_supplicant/op_classes.c387
-rw-r--r--contrib/wpa/wpa_supplicant/p2p_supplicant.c501
-rw-r--r--contrib/wpa/wpa_supplicant/p2p_supplicant.h9
-rw-r--r--contrib/wpa/wpa_supplicant/preauth_test.c15
-rw-r--r--contrib/wpa/wpa_supplicant/rrm.c1575
-rw-r--r--contrib/wpa/wpa_supplicant/scan.c391
-rw-r--r--contrib/wpa/wpa_supplicant/sme.c1037
-rw-r--r--contrib/wpa/wpa_supplicant/sme.h19
-rw-r--r--contrib/wpa/wpa_supplicant/systemd/wpa_supplicant.service.in4
-rwxr-xr-xcontrib/wpa/wpa_supplicant/utils/log2pcap.py2
-rw-r--r--contrib/wpa/wpa_supplicant/wifi_display.c13
-rw-r--r--contrib/wpa/wpa_supplicant/wmm_ac.c16
-rw-r--r--contrib/wpa/wpa_supplicant/wnm_sta.c618
-rw-r--r--contrib/wpa/wpa_supplicant/wnm_sta.h18
-rw-r--r--contrib/wpa/wpa_supplicant/wpa_cli.c588
-rw-r--r--contrib/wpa/wpa_supplicant/wpa_passphrase.c8
-rw-r--r--contrib/wpa/wpa_supplicant/wpa_priv.c265
-rw-r--r--contrib/wpa/wpa_supplicant/wpa_supplicant.c2082
-rw-r--r--contrib/wpa/wpa_supplicant/wpa_supplicant.conf286
-rw-r--r--contrib/wpa/wpa_supplicant/wpa_supplicant_i.h248
-rw-r--r--contrib/wpa/wpa_supplicant/wpa_supplicant_template.conf1
-rw-r--r--contrib/wpa/wpa_supplicant/wpas_glue.c181
-rw-r--r--contrib/wpa/wpa_supplicant/wpas_kay.c175
-rw-r--r--contrib/wpa/wpa_supplicant/wpas_kay.h10
-rw-r--r--contrib/wpa/wpa_supplicant/wps_supplicant.c38
-rw-r--r--contrib/wpa/wpa_supplicant/wps_supplicant.h2
105 files changed, 17689 insertions, 5764 deletions
diff --git a/contrib/wpa/wpa_supplicant/Android.mk b/contrib/wpa/wpa_supplicant/Android.mk
index a8d6a7f944e9..529693131308 100644
--- a/contrib/wpa/wpa_supplicant/Android.mk
+++ b/contrib/wpa/wpa_supplicant/Android.mk
@@ -92,7 +92,10 @@ OBJS += eap_register.c
OBJS += src/utils/common.c
OBJS += src/utils/wpa_debug.c
OBJS += src/utils/wpabuf.c
+OBJS += src/utils/bitfield.c
OBJS += wmm_ac.c
+OBJS += op_classes.c
+OBJS += rrm.c
OBJS_p = wpa_passphrase.c
OBJS_p += src/utils/common.c
OBJS_p += src/utils/wpa_debug.c
@@ -204,6 +207,12 @@ L_CFLAGS += -DCONFIG_SUITEB192
NEED_SHA384=y
endif
+ifdef CONFIG_OCV
+L_CFLAGS += -DCONFIG_OCV
+OBJS += src/common/ocv.c
+CONFIG_IEEE80211W=y
+endif
+
ifdef CONFIG_IEEE80211W
L_CFLAGS += -DCONFIG_IEEE80211W
NEED_SHA256=y
@@ -221,8 +230,6 @@ ifdef CONFIG_MESH
NEED_80211_COMMON=y
NEED_SHA256=y
NEED_AES_SIV=y
-NEED_AES_OMAC1=y
-NEED_AES_CTR=y
CONFIG_SAE=y
CONFIG_AP=y
L_CFLAGS += -DCONFIG_MESH
@@ -238,6 +245,50 @@ NEED_ECC=y
NEED_DH_GROUPS=y
endif
+ifdef CONFIG_DPP
+L_CFLAGS += -DCONFIG_DPP
+OBJS += src/common/dpp.c
+OBJS += dpp_supplicant.c
+NEED_AES_SIV=y
+NEED_HMAC_SHA256_KDF=y
+NEED_HMAC_SHA384_KDF=y
+NEED_HMAC_SHA512_KDF=y
+NEED_SHA256=y
+NEED_SHA384=y
+NEED_SHA512=y
+NEED_JSON=y
+NEED_GAS_SERVER=y
+NEED_BASE64=y
+ifdef CONFIG_DPP2
+L_CFLAGS += -DCONFIG_DPP2
+endif
+endif
+
+ifdef CONFIG_OWE
+L_CFLAGS += -DCONFIG_OWE
+NEED_ECC=y
+NEED_HMAC_SHA256_KDF=y
+NEED_HMAC_SHA384_KDF=y
+NEED_HMAC_SHA512_KDF=y
+NEED_SHA256=y
+NEED_SHA384=y
+NEED_SHA512=y
+endif
+
+ifdef CONFIG_FILS
+L_CFLAGS += -DCONFIG_FILS
+NEED_SHA384=y
+NEED_AES_SIV=y
+ifdef CONFIG_FILS_SK_PFS
+L_CFLAGS += -DCONFIG_FILS_SK_PFS
+NEED_ECC=y
+endif
+endif
+
+ifdef CONFIG_MBO
+CONFIG_WNM=y
+endif
+
ifdef CONFIG_WNM
L_CFLAGS += -DCONFIG_WNM
OBJS += wnm_sta.c
@@ -254,15 +305,14 @@ ifdef CONFIG_TDLS_TESTING
L_CFLAGS += -DCONFIG_TDLS_TESTING
endif
-ifdef CONFIG_PEERKEY
-L_CFLAGS += -DCONFIG_PEERKEY
+ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+L_CFLAGS += -DCONFIG_PMKSA_CACHE_EXTERNAL
endif
ifndef CONFIG_NO_WPA
OBJS += src/rsn_supp/wpa.c
OBJS += src/rsn_supp/preauth.c
OBJS += src/rsn_supp/pmksa_cache.c
-OBJS += src/rsn_supp/peerkey.c
OBJS += src/rsn_supp/wpa_ie.c
OBJS += src/common/wpa_common.c
NEED_AES=y
@@ -294,7 +344,6 @@ OBJS += src/p2p/p2p_invitation.c
OBJS += src/p2p/p2p_dev_disc.c
OBJS += src/p2p/p2p_group.c
OBJS += src/ap/p2p_hostapd.c
-OBJS += src/utils/bitfield.c
L_CFLAGS += -DCONFIG_P2P
NEED_GAS=y
NEED_OFFCHANNEL=y
@@ -640,6 +689,7 @@ L_CFLAGS += -DEAP_PWD
OBJS += src/eap_peer/eap_pwd.c src/eap_common/eap_pwd_common.c
CONFIG_IEEE8021X_EAPOL=y
NEED_SHA256=y
+NEED_ECC=y
endif
ifdef CONFIG_EAP_EKE
@@ -811,13 +861,20 @@ OBJS += src/ap/ieee802_11_ht.c
ifdef CONFIG_IEEE80211AC
OBJS += src/ap/ieee802_11_vht.c
endif
+ifdef CONFIG_IEEE80211AX
+OBJS += src/ap/ieee802_11_he.c
endif
-ifdef CONFIG_WNM
+endif
+ifdef CONFIG_WNM_AP
+L_CFLAGS += -DCONFIG_WNM_AP
OBJS += src/ap/wnm_ap.c
endif
ifdef CONFIG_MBO
OBJS += src/ap/mbo_ap.c
endif
+ifdef CONFIG_FILS
+OBJS += src/ap/fils_hlp.c
+endif
ifdef CONFIG_CTRL_IFACE
OBJS += src/ap/ctrl_iface_ap.c
endif
@@ -832,11 +889,9 @@ L_CFLAGS += -DCONFIG_IEEE80211N
ifdef CONFIG_IEEE80211AC
L_CFLAGS += -DCONFIG_IEEE80211AC
endif
+ifdef CONFIG_IEEE80211AX
+L_CFLAGS += -DCONFIG_IEEE80211AX
endif
-
-ifdef CONFIG_MBO
-OBJS += mbo.c
-L_CFLAGS += -DCONFIG_MBO
endif
ifdef NEED_AP_MLME
@@ -852,6 +907,10 @@ L_CFLAGS += -DEAP_SERVER_WSC
OBJS += src/ap/wps_hostapd.c
OBJS += src/eap_server/eap_server_wsc.c
endif
+ifdef CONFIG_DPP
+OBJS += src/ap/dpp_hostapd.c
+OBJS += src/ap/gas_query_ap.c
+endif
ifdef CONFIG_INTERWORKING
OBJS += src/ap/gas_serv.c
endif
@@ -860,18 +919,21 @@ OBJS += src/ap/hs20.c
endif
endif
+ifdef CONFIG_MBO
+OBJS += mbo.c
+L_CFLAGS += -DCONFIG_MBO
+endif
+
+ifdef CONFIG_TESTING_OPTIONS
+L_CFLAGS += -DCONFIG_TESTING_OPTIONS
+endif
+
ifdef NEED_RSN_AUTHENTICATOR
L_CFLAGS += -DCONFIG_NO_RADIUS
NEED_AES_WRAP=y
OBJS += src/ap/wpa_auth.c
OBJS += src/ap/wpa_auth_ie.c
OBJS += src/ap/pmksa_cache_auth.c
-ifdef CONFIG_IEEE80211R
-OBJS += src/ap/wpa_auth_ft.c
-endif
-ifdef CONFIG_PEERKEY
-OBJS += src/ap/peerkey_auth.c
-endif
endif
ifdef CONFIG_ACS
@@ -971,25 +1033,40 @@ ifdef CONFIG_TLS_ADD_DL
LIBS += -ldl
LIBS_p += -ldl
endif
+ifndef CONFIG_TLS_DEFAULT_CIPHERS
+CONFIG_TLS_DEFAULT_CIPHERS = "DEFAULT:!EXP:!LOW"
+endif
+L_CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\"
endif
ifeq ($(CONFIG_TLS), gnutls)
+ifndef CONFIG_CRYPTO
+# default to libgcrypt
+CONFIG_CRYPTO=gnutls
+endif
ifdef TLS_FUNCS
OBJS += src/crypto/tls_gnutls.c
LIBS += -lgnutls -lgpg-error
endif
-OBJS += src/crypto/crypto_gnutls.c
-OBJS_p += src/crypto/crypto_gnutls.c
+OBJS += src/crypto/crypto_$(CONFIG_CRYPTO).c
+OBJS_p += src/crypto/crypto_$(CONFIG_CRYPTO).c
ifdef NEED_FIPS186_2_PRF
OBJS += src/crypto/fips_prf_internal.c
OBJS += src/crypto/sha1-internal.c
endif
+ifeq ($(CONFIG_CRYPTO), gnutls)
LIBS += -lgcrypt
LIBS_p += -lgcrypt
-CONFIG_INTERNAL_SHA256=y
CONFIG_INTERNAL_RC4=y
CONFIG_INTERNAL_DH_GROUP5=y
endif
+ifeq ($(CONFIG_CRYPTO), nettle)
+LIBS += -lnettle -lgmp
+LIBS_p += -lnettle -lgmp
+CONFIG_INTERNAL_RC4=y
+CONFIG_INTERNAL_DH_GROUP5=y
+endif
+endif
ifeq ($(CONFIG_TLS), internal)
ifndef CONFIG_CRYPTO
@@ -1131,6 +1208,12 @@ endif
ifdef NEED_AES_EAX
AESOBJS += src/crypto/aes-eax.c
NEED_AES_CTR=y
+NEED_AES_OMAC1=y
+endif
+ifdef NEED_AES_SIV
+AESOBJS += src/crypto/aes-siv.c
+NEED_AES_CTR=y
+NEED_AES_OMAC1=y
endif
ifdef NEED_AES_CTR
AESOBJS += src/crypto/aes-ctr.c
@@ -1163,9 +1246,6 @@ ifdef CONFIG_INTERNAL_AES
AESOBJS += src/crypto/aes-internal-enc.c
endif
endif
-ifdef NEED_AES_SIV
-AESOBJS += src/crypto/aes-siv.c
-endif
ifdef NEED_AES
OBJS += $(AESOBJS)
endif
@@ -1173,8 +1253,10 @@ endif
SHA1OBJS =
ifdef NEED_SHA1
ifneq ($(CONFIG_TLS), openssl)
+ifneq ($(CONFIG_TLS), gnutls)
SHA1OBJS += src/crypto/sha1.c
endif
+endif
SHA1OBJS += src/crypto/sha1-prf.c
ifdef CONFIG_INTERNAL_SHA1
SHA1OBJS += src/crypto/sha1-internal.c
@@ -1200,9 +1282,11 @@ endif
MD5OBJS =
ifndef CONFIG_FIPS
ifneq ($(CONFIG_TLS), openssl)
+ifneq ($(CONFIG_TLS), gnutls)
MD5OBJS += src/crypto/md5.c
endif
endif
+endif
ifdef NEED_MD5
ifdef CONFIG_INTERNAL_MD5
MD5OBJS += src/crypto/md5-internal.c
@@ -1240,8 +1324,10 @@ SHA256OBJS = # none by default
ifdef NEED_SHA256
L_CFLAGS += -DCONFIG_SHA256
ifneq ($(CONFIG_TLS), openssl)
+ifneq ($(CONFIG_TLS), gnutls)
SHA256OBJS += src/crypto/sha256.c
endif
+endif
SHA256OBJS += src/crypto/sha256-prf.c
ifdef CONFIG_INTERNAL_SHA256
SHA256OBJS += src/crypto/sha256-internal.c
@@ -1261,12 +1347,34 @@ ifdef NEED_HMAC_SHA256_KDF
L_CFLAGS += -DCONFIG_HMAC_SHA256_KDF
SHA256OBJS += src/crypto/sha256-kdf.c
endif
+ifdef NEED_HMAC_SHA384_KDF
+L_CFLAGS += -DCONFIG_HMAC_SHA384_KDF
+SHA256OBJS += src/crypto/sha384-kdf.c
+endif
+ifdef NEED_HMAC_SHA512_KDF
+L_CFLAGS += -DCONFIG_HMAC_SHA512_KDF
+SHA256OBJS += src/crypto/sha512-kdf.c
+endif
OBJS += $(SHA256OBJS)
endif
ifdef NEED_SHA384
L_CFLAGS += -DCONFIG_SHA384
+ifneq ($(CONFIG_TLS), openssl)
+ifneq ($(CONFIG_TLS), gnutls)
+OBJS += src/crypto/sha384.c
+endif
+endif
OBJS += src/crypto/sha384-prf.c
endif
+ifdef NEED_SHA512
+L_CFLAGS += -DCONFIG_SHA512
+ifneq ($(CONFIG_TLS), openssl)
+ifneq ($(CONFIG_TLS), gnutls)
+OBJS += src/crypto/sha512.c
+endif
+endif
+OBJS += src/crypto/sha512-prf.c
+endif
ifdef NEED_DH_GROUPS
OBJS += src/crypto/dh_groups.c
@@ -1317,44 +1425,25 @@ endif
OBJS += ctrl_iface.c ctrl_iface_$(CONFIG_CTRL_IFACE).c
endif
-ifdef CONFIG_CTRL_IFACE_DBUS
-DBUS=y
-DBUS_CFLAGS += -DCONFIG_CTRL_IFACE_DBUS -DDBUS_API_SUBJECT_TO_CHANGE
-DBUS_OBJS += dbus/dbus_old.c dbus/dbus_old_handlers.c
-ifdef CONFIG_WPS
-DBUS_OBJS += dbus/dbus_old_handlers_wps.c
-endif
-DBUS_OBJS += dbus/dbus_dict_helpers.c
-DBUS_CFLAGS += $(DBUS_INCLUDE)
-endif
-
ifdef CONFIG_CTRL_IFACE_DBUS_NEW
-DBUS=y
-DBUS_CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_NEW
-DBUS_OBJS ?= dbus/dbus_dict_helpers.c
-DBUS_OBJS += dbus/dbus_new_helpers.c
-DBUS_OBJS += dbus/dbus_new.c dbus/dbus_new_handlers.c
+L_CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_NEW
+OBJS += dbus/dbus_dict_helpers.c
+OBJS += dbus/dbus_new_helpers.c
+OBJS += dbus/dbus_new.c dbus/dbus_new_handlers.c
+OBJS += dbus/dbus_common.c
ifdef CONFIG_WPS
-DBUS_OBJS += dbus/dbus_new_handlers_wps.c
+OBJS += dbus/dbus_new_handlers_wps.c
endif
ifdef CONFIG_P2P
-DBUS_OBJS += dbus/dbus_new_handlers_p2p.c
+OBJS += dbus/dbus_new_handlers_p2p.c
endif
ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
-DBUS_OBJS += dbus/dbus_new_introspect.c
-DBUS_CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_INTRO
-endif
-DBUS_CFLAGS += $(DBUS_INCLUDE)
+OBJS += dbus/dbus_new_introspect.c
+L_CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_INTRO
endif
-
-ifdef DBUS
-DBUS_CFLAGS += -DCONFIG_DBUS
-DBUS_OBJS += dbus/dbus_common.c
+L_CFLAGS += $(DBUS_INCLUDE)
endif
-OBJS += $(DBUS_OBJS)
-L_CFLAGS += $(DBUS_CFLAGS)
-
ifdef CONFIG_CTRL_IFACE_BINDER
WPA_SUPPLICANT_USE_BINDER=y
L_CFLAGS += -DCONFIG_BINDER -DCONFIG_CTRL_IFACE_BINDER
@@ -1490,6 +1579,12 @@ OBJS += src/utils/ext_password.c
L_CFLAGS += -DCONFIG_EXT_PASSWORD
endif
+ifdef NEED_GAS_SERVER
+OBJS += src/common/gas_server.c
+L_CFLAGS += -DCONFIG_GAS_SERVER
+NEED_GAS=y
+endif
+
ifdef NEED_GAS
OBJS += src/common/gas.c
OBJS += gas_query.c
@@ -1502,6 +1597,11 @@ OBJS += offchannel.c
L_CFLAGS += -DCONFIG_OFFCHANNEL
endif
+ifdef NEED_JSON
+OBJS += src/utils/json.c
+L_CFLAGS += -DCONFIG_JSON
+endif
+
OBJS += src/drivers/driver_common.c
OBJS += wpa_supplicant.c events.c blacklist.c wpas_glue.c scan.c
@@ -1580,9 +1680,7 @@ endif
# With BoringSSL we need libkeystore-engine in order to provide access to
# keystore keys.
-ifneq (,$(wildcard external/boringssl/flavor.mk))
LOCAL_SHARED_LIBRARIES += libkeystore-engine
-endif
ifdef CONFIG_DRIVER_NL80211
ifneq ($(wildcard external/libnl),)
diff --git a/contrib/wpa/wpa_supplicant/ChangeLog b/contrib/wpa/wpa_supplicant/ChangeLog
index f28055f4093e..89119e7bd18f 100644
--- a/contrib/wpa/wpa_supplicant/ChangeLog
+++ b/contrib/wpa/wpa_supplicant/ChangeLog
@@ -1,5 +1,144 @@
ChangeLog for wpa_supplicant
+2019-04-21 - v2.8
+ * SAE changes
+ - added support for SAE Password Identifier
+ - changed default configuration to enable only groups 19, 20, 21
+ (i.e., disable groups 25 and 26) and disable all unsuitable groups
+ completely based on REVmd changes
+ - do not regenerate PWE unnecessarily when the AP uses the
+ anti-clogging token mechanisms
+ - fixed some association cases where both SAE and FT-SAE were enabled
+ on both the station and the selected AP
+ - started to prefer FT-SAE over SAE AKM if both are enabled
+ - started to prefer FT-SAE over FT-PSK if both are enabled
+ - fixed FT-SAE when SAE PMKSA caching is used
+ - reject use of unsuitable groups based on new implementation guidance
+ in REVmd (allow only FFC groups with prime >= 3072 bits and ECC
+ groups with prime >= 256)
+ - minimize timing and memory use differences in PWE derivation
+ [https://w1.fi/security/2019-1/] (CVE-2019-9494)
+ * EAP-pwd changes
+ - minimize timing and memory use differences in PWE derivation
+ [https://w1.fi/security/2019-2/] (CVE-2019-9495)
+ - verify server scalar/element
+ [https://w1.fi/security/2019-4/] (CVE-2019-9499)
+ - fix message reassembly issue with unexpected fragment
+ [https://w1.fi/security/2019-5/]
+ - enforce rand,mask generation rules more strictly
+ - fix a memory leak in PWE derivation
+ - disallow ECC groups with a prime under 256 bits (groups 25, 26, and
+ 27)
+ * fixed CONFIG_IEEE80211R=y (FT) build without CONFIG_FILS=y
+ * Hotspot 2.0 changes
+ - do not indicate release number that is higher than the one
+ AP supports
+ - added support for release number 3
+ - enable PMF automatically for network profiles created from
+ credentials
+ * fixed OWE network profile saving
+ * fixed DPP network profile saving
+ * added support for RSN operating channel validation
+ (CONFIG_OCV=y and network profile parameter ocv=1)
+ * added Multi-AP backhaul STA support
+ * fixed build with LibreSSL
+ * number of MKA/MACsec fixes and extensions
+ * extended domain_match and domain_suffix_match to allow list of values
+ * fixed dNSName matching in domain_match and domain_suffix_match when
+ using wolfSSL
+ * started to prefer FT-EAP-SHA384 over WPA-EAP-SUITE-B-192 AKM if both
+ are enabled
+ * extended nl80211 Connect and external authentication to support
+ SAE, FT-SAE, FT-EAP-SHA384
+ * fixed KEK2 derivation for FILS+FT
+ * extended client_cert file to allow loading of a chain of PEM
+ encoded certificates
+ * extended beacon reporting functionality
+ * extended D-Bus interface with number of new properties
+ * fixed a regression in FT-over-DS with mac80211-based drivers
+ * OpenSSL: allow systemwide policies to be overridden
+ * extended driver flags indication for separate 802.1X and PSK
+ 4-way handshake offload capability
+ * added support for random P2P Device/Interface Address use
+ * extended PEAP to derive EMSK to enable use with ERP/FILS
+ * extended WPS to allow SAE configuration to be added automatically
+ for PSK (wps_cred_add_sae=1)
+ * removed support for the old D-Bus interface (CONFIG_CTRL_IFACE_DBUS)
+ * extended domain_match and domain_suffix_match to allow list of values
+ * added a RSN workaround for misbehaving PMF APs that advertise
+ IGTK/BIP KeyID using incorrect byte order
+ * fixed PTK rekeying with FILS and FT
+
+2018-12-02 - v2.7
+ * fixed WPA packet number reuse with replayed messages and key
+ reinstallation
+ [https://w1.fi/security/2017-1/] (CVE-2017-13077, CVE-2017-13078,
+ CVE-2017-13079, CVE-2017-13080, CVE-2017-13081, CVE-2017-13082,
+ CVE-2017-13086, CVE-2017-13087, CVE-2017-13088)
+ * fixed unauthenticated EAPOL-Key decryption in wpa_supplicant
+ [https://w1.fi/security/2018-1/] (CVE-2018-14526)
+ * added support for FILS (IEEE 802.11ai) shared key authentication
+ * added support for OWE (Opportunistic Wireless Encryption, RFC 8110;
+ and transition mode defined by WFA)
+ * added support for DPP (Wi-Fi Device Provisioning Protocol)
+ * added support for RSA 3k key case with Suite B 192-bit level
+ * fixed Suite B PMKSA caching not to update PMKID during each 4-way
+ handshake
+ * fixed EAP-pwd pre-processing with PasswordHashHash
+ * added EAP-pwd client support for salted passwords
+ * fixed a regression in TDLS prohibited bit validation
+ * started to use estimated throughput to avoid undesired signal
+ strength based roaming decision
+ * MACsec/MKA:
+ - new macsec_linux driver interface support for the Linux
+ kernel macsec module
+ - number of fixes and extensions
+ * added support for external persistent storage of PMKSA cache
+ (PMKSA_GET/PMKSA_ADD control interface commands; and
+ MESH_PMKSA_GET/MESH_PMKSA_SET for the mesh case)
+ * fixed mesh channel configuration pri/sec switch case
+ * added support for beacon report
+ * large number of other fixes, cleanup, and extensions
+ * added support for randomizing local address for GAS queries
+ (gas_rand_mac_addr parameter)
+ * fixed EAP-SIM/AKA/AKA' ext auth cases within TLS tunnel
+ * added option for using random WPS UUID (auto_uuid=1)
+ * added SHA256-hash support for OCSP certificate matching
+ * fixed EAP-AKA' to add AT_KDF into Synchronization-Failure
+ * fixed a regression in RSN pre-authentication candidate selection
+ * added option to configure allowed group management cipher suites
+ (group_mgmt network profile parameter)
+ * removed all PeerKey functionality
+ * fixed nl80211 AP and mesh mode configuration regression with
+ Linux 4.15 and newer
+ * added ap_isolate configuration option for AP mode
+ * added support for nl80211 to offload 4-way handshake into the driver
+ * added support for using wolfSSL cryptographic library
+ * SAE
+ - added support for configuring SAE password separately of the
+ WPA2 PSK/passphrase
+ - fixed PTK and EAPOL-Key integrity and key-wrap algorithm selection
+ for SAE;
+ note: this is not backwards compatible, i.e., both the AP and
+ station side implementations will need to be update at the same
+ time to maintain interoperability
+ - added support for Password Identifier
+ - fixed FT-SAE PMKID matching
+ * Hotspot 2.0
+ - added support for fetching of Operator Icon Metadata ANQP-element
+ - added support for Roaming Consortium Selection element
+ - added support for Terms and Conditions
+ - added support for OSEN connection in a shared RSN BSS
+ - added support for fetching Venue URL information
+ * added support for using OpenSSL 1.1.1
+ * FT
+ - disabled PMKSA caching with FT since it is not fully functional
+ - added support for SHA384 based AKM
+ - added support for BIP ciphers BIP-CMAC-256, BIP-GMAC-128,
+ BIP-GMAC-256 in addition to previously supported BIP-CMAC-128
+ - fixed additional IE inclusion in Reassociation Request frame when
+ using FT protocol
+
2016-10-02 - v2.6
* fixed WNM Sleep Mode processing when PMF is not enabled
[http://w1.fi/security/2015-6/] (CVE-2015-5310)
diff --git a/contrib/wpa/wpa_supplicant/README b/contrib/wpa/wpa_supplicant/README
index 11ab01a9c171..bbc86b137424 100644
--- a/contrib/wpa/wpa_supplicant/README
+++ b/contrib/wpa/wpa_supplicant/README
@@ -1,7 +1,7 @@
-WPA Supplicant
+wpa_supplicant
==============
-Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
This program is licensed under the BSD license (the one with
@@ -83,7 +83,7 @@ Supported WPA/IEEE 802.11i features:
authentication)
(following methods are supported, but since they do not generate keying
material, they cannot be used with WPA or IEEE 802.1X WEP keying)
- * EAP-MD5-Challenge
+ * EAP-MD5-Challenge
* EAP-MSCHAPv2
* EAP-GTC
* EAP-OTP
@@ -965,6 +965,17 @@ wpa_priv can control multiple interface with one process, but it is
also possible to run multiple wpa_priv processes at the same time, if
desired.
+It should be noted that the interface used between wpa_supplicant and
+wpa_priv does not include all the capabilities of the wpa_supplicant
+driver interface and at times, this interface lacks update especially
+for recent addition. Consequently, use of wpa_priv does come with the
+price of somewhat reduced available functionality. The next section
+describing how wpa_supplicant can be used with reduced privileges
+without having to handle the complexity of separate wpa_priv. While that
+approve does not provide separation for network admin capabilities, it
+does allow other root privileges to be dropped without the drawbacks of
+the wpa_priv process.
+
Linux capabilities instead of privileged process
------------------------------------------------
diff --git a/contrib/wpa/wpa_supplicant/README-DPP b/contrib/wpa/wpa_supplicant/README-DPP
new file mode 100644
index 000000000000..6496733735d4
--- /dev/null
+++ b/contrib/wpa/wpa_supplicant/README-DPP
@@ -0,0 +1,195 @@
+Device Provisioning Protocol (DPP)
+==================================
+
+This document describes how the Device Provisioning Protocol (DPP)
+implementation in wpa_supplicant and hostapd can be configured and how
+the STA device and AP can be configured to connect each other using DPP
+Connector mechanism.
+
+Introduction to DPP
+-------------------
+
+Device provisioning Protocol allows enrolling of interface-less devices
+in a secure Wi-Fi network using many methods like QR code based
+authentication( detailed below ), PKEX based authentication etc. In DPP
+a Configurator is used to provide network credentials to the devices.
+The three phases of DPP connection are authentication, configuration and
+network introduction.
+
+Build config setup
+------------------
+
+The following changes must go in the config file used to compile hostapd
+and wpa_supplicant.
+
+wpa_supplicant build config
+---------------------------
+
+Enable DPP and protected management frame in wpa_supplicant build config
+file
+
+CONFIG_IEEE80211W=y
+CONFIG_DPP=y
+
+hostapd build config
+--------------------
+
+Enable DPP and protected management frame in hostapd build config file
+
+CONFIG_IEEE80211W=y
+CONFIG_DPP=y
+
+Configurator build config
+-------------------------
+
+Any STA or AP device can act as a Configurator. Enable DPP and protected
+managment frames in build config. For an AP to act as Configurator,
+Interworking needs to be enabled. For wpa_supplicant it is not required.
+
+CONFIG_INTERWORKING=y
+
+
+Sample supplicant config file before provisioning
+-------------------------------------------------
+
+ctrl_interface=DIR=/var/run/wpa_supplicant
+ctrl_interface_group=0
+update_config=1
+pmf=2
+dpp_config_processing=2
+
+Sample hostapd config file before provisioning
+----------------------------------------------
+
+interface=wlan0
+driver=nl80211
+ctrl_interface=/var/run/hostapd
+ssid=test
+channel=1
+wpa=2
+wpa_key_mgmt=DPP
+ieee80211w=1
+wpa_pairwise=CCMP
+rsn_pairwise=CCMP
+
+
+Pre-requisites
+--------------
+
+It is assumed that an AP and client station are up by running hostapd
+and wpa_supplicant using respective config files.
+
+
+Creating Configurator
+---------------------
+
+Add a Configurator over the control interface (wpa_cli/hostapd_cli)
+
+> dpp_configurator_add
+(returns id)
+
+To get key of Configurator
+> dpp_configurator_get_key <id>
+
+
+How to configure an enrollee using Configurator
+-----------------------------------------------
+
+On enrollee side:
+
+Generate QR code for the device. Store the qr code id returned by the
+command.
+
+> dpp_bootstrap_gen type=qrcode mac=<mac-address-of-device> chan=<operating-channel> key=<key of the device>
+(returns bootstrapping info id)
+
+Get QR Code of device using the bootstrap info id.
+> dpp_bootstrap_get_uri <bootstrap-id>
+
+Make device listen to DPP request (The central frequency of channel 1 is
+2412) in case if enrollee is a client device.
+
+> dpp_listen <frequency>
+
+On Configurator side:
+
+Enter the QR Code in the Configurator.
+> dpp_qr_code "<QR-Code-read-from-enrollee>"
+
+On successfully adding QR Code, a bootstrapping info id is returned.
+
+Send provisioning request to enrollee. (conf is ap-dpp if enrollee is an
+AP. conf is sta-dpp if enrollee is a client)
+> dpp_auth_init peer=<qr-code-id> conf=<ap-dpp|sta-dpp> configurator=<configurator-id>
+
+The DPP values will be printed in the console. Save this values into the
+config file. If the enrollee is an AP, we need to manually write these
+values to the hostapd config file. If the enrollee is a client device,
+these details can be automatically saved to config file using the
+following command.
+
+> save_config
+
+To set values in runtime for AP enrollees
+
+> set dpp_connector <Connector-value-printed-on-console>
+> set dpp_csign <csign-value-on-console>
+> set dpp_netaccesskey <netaccess-value-on-console>
+
+To set values in runtime for client enrollees, set dpp_config_processing
+to 2 in wpa_supplicant conf file.
+
+Once the values are set in run-time (if not set in run-time, but saved
+in config files, they are taken up in next restart), the client device
+will automatically connect to the already provisioned AP and connection
+will be established.
+
+
+Self-configuring a device
+-------------------------
+
+It is possible for a device to configure itself if it is the
+Configurator for the network.
+
+Create a Configurator in the device and use the dpp_configurator_sign
+command to get DPP credentials.
+
+> dpp_configurator_add
+(returns configurator id)
+> dpp_configurator_sign conf=<ap-dpp|sta-dpp> configurator=<configurator-id>
+
+
+Sample AP configuration files after provisioning
+------------------------------------------------
+
+interface=wlan0
+driver=nl80211
+ctrl_interface=/var/run/hostapd
+ssid=test
+channel=1
+wpa=2
+wpa_key_mgmt=DPP
+ieee80211w=1
+wpa_pairwise=CCMP
+rsn_pairwise=CCMP
+dpp_connector=<Connector value provided by Configurator>
+dpp_csign=<C-Sign-Key value provided by Configurator>
+dpp_netaccesskey=<Net access key provided by Configurator>
+
+
+Sample station configuration file after provisioning
+----------------------------------------------------
+
+ctrl_interface=DIR=/var/run/wpa_supplicant
+ctrl_interface_group=0
+update_config=1
+pmf=2
+dpp_config_processing=2
+network={
+ ssid="test"
+ key_mgmt=DPP
+ ieee80211w=2
+ dpp_connector="<Connector value provided by Configurator>"
+ dpp_netaccesskey=<Net access key provided by Configurator>
+ dpp_csign=<C-sign-key value provided by Configurator>
+}
diff --git a/contrib/wpa/wpa_supplicant/README-HS20 b/contrib/wpa/wpa_supplicant/README-HS20
index e4eed2074f91..334287101c92 100644
--- a/contrib/wpa/wpa_supplicant/README-HS20
+++ b/contrib/wpa/wpa_supplicant/README-HS20
@@ -197,6 +197,20 @@ Credentials can be pre-configured for automatic network selection:
# pre-configured with the credential since the NAI Realm information
# may not be available or fetched.
#
+# required_roaming_consortium: Required Roaming Consortium OI
+# If required_roaming_consortium_len is non-zero, this field contains the
+# Roaming Consortium OI that is required to be advertised by the AP for
+# the credential to be considered matching.
+#
+# roaming_consortiums: Roaming Consortium OI(s) memberships
+# This string field contains one or more comma delimited OIs (hexdump)
+# identifying the roaming consortiums of which the provider is a member.
+# The list is sorted from the most preferred one to the least preferred
+# one. A match between the Roaming Consortium OIs advertised by an AP and
+# the OIs in this list indicates that successful authentication is
+# possible.
+# (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/RoamingConsortiumOI)
+#
# eap: Pre-configured EAP method
# This optional field can be used to specify which EAP method will be
# used with this credential. If not set, the EAP method is selected
@@ -295,6 +309,7 @@ Credentials can be pre-configured for automatic network selection:
# ca_cert="/etc/wpa_supplicant/ca.pem"
# domain="example.com"
# roaming_consortium=223344
+# roaming_consortiums="112233,4455667788,aabbcc"
# eap=TTLS
# phase2="auth=MSCHAPV2"
#}
@@ -591,7 +606,7 @@ network={
Hotspot 2.0 connection with external network selection
------------------------------------------------------
-When an component controlling wpa_supplicant takes care of Interworking
+When a component controlling wpa_supplicant takes care of Interworking
network selection, following configuration and network profile
parameters can be used to configure a temporary network profile for a
Hotspot 2.0 connection (e.g., with SET, ADD_NETWORK, SET_NETWORK, and
@@ -613,6 +628,7 @@ network={
eap=TTLS
phase2="auth=MSCHAPV2"
update_identifier=54321
+ roaming_consortium_selection=112233
#ocsp=2
}
@@ -628,4 +644,5 @@ update_identifier: PPS/UpdateIdentifier
ca_cert: from the downloaded trust root based on PPS information
eap: Credential/UsernamePassword/EAPMethod or NAI Realm list
phase2: Credential/UsernamePassword/EAPMethod or NAI Realm list
+roaming_consortium_selection: Matching OI from HomeSP/RoamingConsortiumOI
ocsp: Credential/CheckAAAServerCertStatus
diff --git a/contrib/wpa/wpa_supplicant/README-P2P b/contrib/wpa/wpa_supplicant/README-P2P
index 23ac7fa056a4..55a60a296ad7 100644
--- a/contrib/wpa/wpa_supplicant/README-P2P
+++ b/contrib/wpa/wpa_supplicant/README-P2P
@@ -150,7 +150,7 @@ join-a-group style PD instead of GO Negotiation style PD.
p2p_connect <peer device address> <pbc|pin|PIN#|p2ps> [display|keypad|p2ps]
[persistent|persistent=<network id>] [join|auth]
- [go_intent=<0..15>] [freq=<in MHz>] [ht40] [vht] [provdisc] [auto]
+ [go_intent=<0..15>] [freq=<in MHz>] [ht40] [vht] [he] [provdisc] [auto]
[ssid=<hexdump>]
Start P2P group formation with a discovered P2P peer. This includes
@@ -262,7 +262,7 @@ Parameters definition:
session_mac - Mandatory MAC address that owns/initiated the session
p2p_group_add [persistent|persistent=<network id>] [freq=<freq in MHz>]
- [ht40] [vht]
+ [ht40] [vht] [he]
Set up a P2P group owner manually (i.e., without group owner
negotiation with a specific peer). This is also known as autonomous
@@ -558,7 +558,7 @@ Remove all local services from internal SD query processing.
Invitation
p2p_invite [persistent=<network id>|group=<group ifname>] [peer=address]
- [go_dev_addr=address] [freq=<freq in MHz>] [ht40] [vht]
+ [go_dev_addr=address] [freq=<freq in MHz>] [ht40] [vht] [he]
[pref=<MHz>]
Invite a peer to join a group (e.g., group=wlan1) or to reinvoke a
diff --git a/contrib/wpa/wpa_supplicant/android.config b/contrib/wpa/wpa_supplicant/android.config
index 02505bb991aa..6536c110a3ca 100644
--- a/contrib/wpa/wpa_supplicant/android.config
+++ b/contrib/wpa/wpa_supplicant/android.config
@@ -1,9 +1,9 @@
# Example wpa_supplicant build time configuration
#
# This file lists the configuration options that are used when building the
-# hostapd binary. All lines starting with # are ignored. Configuration option
-# lines must be commented out complete, if they are not to be included, i.e.,
-# just setting VARIABLE=n is not disabling that variable.
+# wpa_supplicant binary. All lines starting with # are ignored. Configuration
+# option lines must be commented out complete, if they are not to be included,
+# i.e., just setting VARIABLE=n is not disabling that variable.
#
# This file is included in Makefile, so variables like CFLAGS and LIBS can also
# be modified from here. In most cases, these lines should use += in order not
@@ -91,10 +91,6 @@ CONFIG_EAP_PEAP=y
CONFIG_EAP_TTLS=y
# EAP-FAST
-# Note: Default OpenSSL package does not include support for all the
-# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
-# the OpenSSL library must be patched (openssl-0.9.8d-tls-extensions.patch)
-# to add the needed functions.
#CONFIG_EAP_FAST=y
# EAP-GTC
@@ -152,6 +148,9 @@ CONFIG_WPS_NFC=y
# EAP-IKEv2
#CONFIG_EAP_IKEV2=y
+# EAP-EKE
+#CONFIG_EAP_EKE=y
+
# PKCS#12 (PFX) support (used to read private key and certificate file from
# a file that usually has extension .p12 or .pfx)
CONFIG_PKCS12=y
@@ -176,8 +175,10 @@ CONFIG_SMARTCARD=y
# Select control interface backend for external programs, e.g, wpa_cli:
# unix = UNIX domain sockets (default for Linux/*BSD)
# udp = UDP sockets using localhost (127.0.0.1)
+# udp6 = UDP IPv6 sockets using localhost (::1)
# named_pipe = Windows Named Pipe (default for Windows)
# udp-remote = UDP sockets with remote access (only for tests systems/purpose)
+# udp6-remote = UDP IPv6 sockets with remote access (only for tests purpose)
# y = use default (backwards compatibility)
# If this option is commented out, control interface is not included in the
# build.
@@ -254,6 +255,9 @@ CONFIG_ELOOP=eloop
# Should we use epoll instead of select? Select is used by default.
#CONFIG_ELOOP_EPOLL=y
+# Should we use kqueue instead of select? Select is used by default.
+#CONFIG_ELOOP_KQUEUE=y
+
# Select layer 2 packet implementation
# linux = Linux packet socket (default)
# pcap = libpcap/libdnet/WinPcap
@@ -263,13 +267,19 @@ CONFIG_ELOOP=eloop
# none = Empty template
CONFIG_L2_PACKET=linux
-# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
-CONFIG_PEERKEY=y
+# Disable Linux packet socket workaround applicable for station interface
+# in a bridge for EAPOL frames. This should be uncommented only if the kernel
+# is known to not have the regression issue in packet socket behavior with
+# bridge interfaces (commit 'bridge: respect RFC2863 operational state')').
+#CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
# IEEE 802.11w (management frame protection), also known as PMF
# Driver support is also needed for IEEE 802.11w.
CONFIG_IEEE80211W=y
+# Support Operating Channel Validation
+#CONFIG_OCV=y
+
# Select TLS implementation
# openssl = OpenSSL (default)
# gnutls = GnuTLS
@@ -291,6 +301,10 @@ CONFIG_IEEE80211W=y
# will be used)
#CONFIG_TLSV12=y
+# Select which ciphers to use by default with OpenSSL if the user does not
+# specify them.
+#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
+
# 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
@@ -313,10 +327,6 @@ CONFIG_IEEE80211W=y
#CONFIG_NDIS_EVENTS_INTEGRATED=y
#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
-# Add support for old DBus control interface
-# (fi.epitest.hostap.WPASupplicant)
-#CONFIG_CTRL_IFACE_DBUS=y
-
# Add support for new DBus control interface
# (fi.w1.hostap.wpa_supplicant1)
#CONFIG_CTRL_IFACE_DBUS_NEW=y
@@ -349,7 +359,7 @@ CONFIG_IEEE80211W=y
# amount of memory/flash.
#CONFIG_DYNAMIC_EAP_METHODS=y
-# IEEE Std 802.11r-2008 (Fast BSS Transition)
+# IEEE Std 802.11r-2008 (Fast BSS Transition) for station mode
CONFIG_IEEE80211R=y
# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)
@@ -424,11 +434,21 @@ CONFIG_ANDROID_LOG=y
# 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
+
+# Wpa_supplicant's random pool is not necessary on Android. Randomness is
+# already provided by the entropymixer service which ensures sufficient
+# entropy is maintained across reboots. Commit b410eb1913 'Initialize
+# /dev/urandom earlier in boot' seeds /dev/urandom with that entropy before
+# either wpa_supplicant or hostapd are run.
+CONFIG_NO_RANDOM_POOL=y
# IEEE 802.11n (High Throughput) support (mainly for AP mode)
CONFIG_IEEE80211N=y
+# IEEE 802.11ac (Very High Throughput) support (mainly for AP mode)
+# (depends on CONFIG_IEEE80211N)
+#CONFIG_IEEE80211AC=y
+
# Wireless Network Management (IEEE Std 802.11v-2011)
# Note: This is experimental and not complete implementation.
CONFIG_WNM=y
@@ -442,6 +462,9 @@ CONFIG_INTERWORKING=y
# Hotspot 2.0
CONFIG_HS20=y
+# Enable interface matching in wpa_supplicant
+#CONFIG_MATCH_IFACE=y
+
# Disable roaming in wpa_supplicant
CONFIG_NO_ROAMING=y
@@ -460,8 +483,8 @@ CONFIG_P2P=y
# Enable TDLS support
CONFIG_TDLS=y
-# Wi-Fi Direct
-# This can be used to enable Wi-Fi Direct extensions for P2P using an external
+# Wi-Fi Display
+# This can be used to enable Wi-Fi Display extensions for P2P using an external
# program to control the additional information exchanges in the messages.
CONFIG_WIFI_DISPLAY=y
@@ -489,4 +512,34 @@ CONFIG_WIFI_DISPLAY=y
# Support Multi Band Operation
#CONFIG_MBO=y
+# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
+#CONFIG_FILS=y
+
+# Support RSN on IBSS networks
+# This is needed to be able to use mode=1 network profile with proto=RSN and
+# key_mgmt=WPA-PSK (i.e., full key management instead of WPA-None).
+#CONFIG_IBSS_RSN=y
+
+# External PMKSA cache control
+# This can be used to enable control interface commands that allow the current
+# PMKSA cache entries to be fetched and new entries to be added.
+#CONFIG_PMKSA_CACHE_EXTERNAL=y
+
+# Mesh Networking (IEEE 802.11s)
+#CONFIG_MESH=y
+
+# Background scanning modules
+# These can be used to request wpa_supplicant to perform background scanning
+# operations for roaming within an ESS (same SSID). See the bgscan parameter in
+# the wpa_supplicant.conf file for more details.
+# Periodic background scans based on signal strength
+#CONFIG_BGSCAN_SIMPLE=y
+# Learn channels used by the network and try to avoid bgscans on other
+# channels (experimental)
+#CONFIG_BGSCAN_LEARN=y
+
+# Opportunistic Wireless Encryption (OWE)
+# Experimental implementation of draft-harkins-owe-07.txt
+#CONFIG_OWE=y
+
include $(wildcard $(LOCAL_PATH)/android_config_*.inc)
diff --git a/contrib/wpa/wpa_supplicant/ap.c b/contrib/wpa/wpa_supplicant/ap.c
index 5afb772ba192..4e191694296b 100644
--- a/contrib/wpa/wpa_supplicant/ap.c
+++ b/contrib/wpa/wpa_supplicant/ap.c
@@ -46,23 +46,50 @@ static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
#ifdef CONFIG_IEEE80211N
static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
struct hostapd_config *conf,
struct hostapd_hw_modes *mode)
{
#ifdef CONFIG_P2P
u8 center_chan = 0;
u8 channel = conf->channel;
+#endif /* CONFIG_P2P */
if (!conf->secondary_channel)
goto no_vht;
+ /* Use the maximum oper channel width if it's given. */
+ if (ssid->max_oper_chwidth)
+ conf->vht_oper_chwidth = ssid->max_oper_chwidth;
+
+ ieee80211_freq_to_chan(ssid->vht_center_freq2,
+ &conf->vht_oper_centr_freq_seg1_idx);
+
+ if (!ssid->p2p_group) {
+ if (!ssid->vht_center_freq1 ||
+ conf->vht_oper_chwidth == VHT_CHANWIDTH_USE_HT)
+ goto no_vht;
+ ieee80211_freq_to_chan(ssid->vht_center_freq1,
+ &conf->vht_oper_centr_freq_seg0_idx);
+ wpa_printf(MSG_DEBUG, "VHT seg0 index %d for AP",
+ conf->vht_oper_centr_freq_seg0_idx);
+ return;
+ }
+
+#ifdef CONFIG_P2P
switch (conf->vht_oper_chwidth) {
case VHT_CHANWIDTH_80MHZ:
case VHT_CHANWIDTH_80P80MHZ:
center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel);
+ wpa_printf(MSG_DEBUG,
+ "VHT center channel %u for 80 or 80+80 MHz bandwidth",
+ center_chan);
break;
case VHT_CHANWIDTH_160MHZ:
center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
+ wpa_printf(MSG_DEBUG,
+ "VHT center channel %u for 160 MHz bandwidth",
+ center_chan);
break;
default:
/*
@@ -72,10 +99,17 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
*/
conf->vht_oper_chwidth = VHT_CHANWIDTH_160MHZ;
center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
- if (!center_chan) {
+ if (center_chan) {
+ wpa_printf(MSG_DEBUG,
+ "VHT center channel %u for auto-selected 160 MHz bandwidth",
+ center_chan);
+ } else {
conf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ;
center_chan = wpas_p2p_get_vht80_center(wpa_s, mode,
channel);
+ wpa_printf(MSG_DEBUG,
+ "VHT center channel %u for auto-selected 80 MHz bandwidth",
+ center_chan);
}
break;
}
@@ -83,15 +117,17 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
goto no_vht;
conf->vht_oper_centr_freq_seg0_idx = center_chan;
+ wpa_printf(MSG_DEBUG, "VHT seg0 index %d for P2P GO",
+ conf->vht_oper_centr_freq_seg0_idx);
return;
+#endif /* CONFIG_P2P */
no_vht:
- conf->vht_oper_centr_freq_seg0_idx =
- channel + conf->secondary_channel * 2;
-#else /* CONFIG_P2P */
+ wpa_printf(MSG_DEBUG,
+ "No VHT higher bandwidth support for the selected channel %d",
+ conf->channel);
conf->vht_oper_centr_freq_seg0_idx =
conf->channel + conf->secondary_channel * 2;
-#endif /* CONFIG_P2P */
conf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT;
}
#endif /* CONFIG_IEEE80211N */
@@ -123,6 +159,11 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
if (wpa_s->hw.modes) {
struct hostapd_hw_modes *mode = NULL;
int i, no_ht = 0;
+
+ wpa_printf(MSG_DEBUG,
+ "Determining HT/VHT options based on driver capabilities (freq=%u chan=%u)",
+ ssid->frequency, conf->channel);
+
for (i = 0; i < wpa_s->hw.num_modes; i++) {
if (wpa_s->hw.modes[i].mode == conf->hw_mode) {
mode = &wpa_s->hw.modes[i];
@@ -131,27 +172,54 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
}
#ifdef CONFIG_HT_OVERRIDES
- if (ssid->disable_ht) {
+ if (ssid->disable_ht)
+ ssid->ht = 0;
+#endif /* CONFIG_HT_OVERRIDES */
+
+ if (!ssid->ht) {
+ wpa_printf(MSG_DEBUG,
+ "HT not enabled in network profile");
conf->ieee80211n = 0;
conf->ht_capab = 0;
no_ht = 1;
}
-#endif /* CONFIG_HT_OVERRIDES */
if (!no_ht && mode && mode->ht_capab) {
+ wpa_printf(MSG_DEBUG,
+ "Enable HT support (p2p_group=%d 11a=%d ht40_hw_capab=%d ssid->ht40=%d)",
+ ssid->p2p_group,
+ conf->hw_mode == HOSTAPD_MODE_IEEE80211A,
+ !!(mode->ht_capab &
+ HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET),
+ ssid->ht40);
conf->ieee80211n = 1;
#ifdef CONFIG_P2P
- if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A &&
+ if (ssid->p2p_group &&
+ conf->hw_mode == HOSTAPD_MODE_IEEE80211A &&
(mode->ht_capab &
HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
- ssid->ht40)
+ ssid->ht40) {
conf->secondary_channel =
wpas_p2p_get_ht40_mode(wpa_s, mode,
conf->channel);
+ wpa_printf(MSG_DEBUG,
+ "HT secondary channel offset %d for P2P group",
+ conf->secondary_channel);
+ }
+#endif /* CONFIG_P2P */
+
+ if (!ssid->p2p_group &&
+ (mode->ht_capab &
+ HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
+ conf->secondary_channel = ssid->ht40;
+ wpa_printf(MSG_DEBUG,
+ "HT secondary channel offset %d for AP",
+ conf->secondary_channel);
+ }
+
if (conf->secondary_channel)
conf->ht_capab |=
HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
-#endif /* CONFIG_P2P */
/*
* white-list capabilities that won't cause issues
@@ -168,7 +236,8 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
if (mode->vht_capab && ssid->vht) {
conf->ieee80211ac = 1;
- wpas_conf_ap_vht(wpa_s, conf, mode);
+ conf->vht_capab |= mode->vht_capab;
+ wpas_conf_ap_vht(wpa_s, ssid, conf, mode);
}
}
}
@@ -229,11 +298,13 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_ACS */
- if (ieee80211_is_dfs(ssid->frequency) && wpa_s->conf->country[0]) {
+ if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes,
+ wpa_s->hw.num_modes) && wpa_s->conf->country[0]) {
conf->ieee80211h = 1;
conf->ieee80211d = 1;
conf->country[0] = wpa_s->conf->country[0];
conf->country[1] = wpa_s->conf->country[1];
+ conf->country[2] = ' ';
}
#ifdef CONFIG_P2P
@@ -265,6 +336,12 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
conf->supported_rates = list;
}
+#ifdef CONFIG_IEEE80211AX
+ if (ssid->mode == WPAS_MODE_P2P_GO ||
+ ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
+ conf->ieee80211ax = ssid->he;
+#endif /* CONFIG_IEEE80211AX */
+
bss->isolate = !wpa_s->conf->p2p_intra_bss;
bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk;
@@ -316,17 +393,34 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
for (i = 0; i < NUM_WEP_KEYS; i++) {
if (ssid->wep_key_len[i] == 0)
continue;
- wep->key[i] = os_malloc(ssid->wep_key_len[i]);
+ wep->key[i] = os_memdup(ssid->wep_key[i],
+ ssid->wep_key_len[i]);
if (wep->key[i] == NULL)
return -1;
- os_memcpy(wep->key[i], ssid->wep_key[i],
- ssid->wep_key_len[i]);
wep->len[i] = ssid->wep_key_len[i];
}
wep->idx = ssid->wep_tx_keyidx;
wep->keys_set = 1;
}
+ if (wpa_s->conf->go_interworking) {
+ wpa_printf(MSG_DEBUG,
+ "P2P: Enable Interworking with access_network_type: %d",
+ wpa_s->conf->go_access_network_type);
+ bss->interworking = wpa_s->conf->go_interworking;
+ bss->access_network_type = wpa_s->conf->go_access_network_type;
+ bss->internet = wpa_s->conf->go_internet;
+ if (wpa_s->conf->go_venue_group) {
+ wpa_printf(MSG_DEBUG,
+ "P2P: Venue group: %d Venue type: %d",
+ wpa_s->conf->go_venue_group,
+ wpa_s->conf->go_venue_type);
+ bss->venue_group = wpa_s->conf->go_venue_group;
+ bss->venue_type = wpa_s->conf->go_venue_type;
+ bss->venue_info_set = 1;
+ }
+ }
+
if (ssid->ap_max_inactivity)
bss->ap_max_inactivity = ssid->ap_max_inactivity;
@@ -406,6 +500,10 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
bss->ieee80211w = ssid->ieee80211w;
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+ bss->ocv = ssid->ocv;
+#endif /* CONFIG_OCV */
+
#ifdef CONFIG_WPS
/*
* Enable WPS by default for open and WPA/WPA2-Personal network, but
@@ -461,6 +559,9 @@ no_wps:
else
bss->max_num_sta = wpa_s->conf->max_num_sta;
+ if (!bss->isolate)
+ bss->isolate = wpa_s->conf->ap_isolate;
+
bss->disassoc_low_ack = wpa_s->conf->disassoc_low_ack;
if (wpa_s->conf->ap_vendor_elements) {
@@ -585,9 +686,18 @@ static void wpas_ap_configured_cb(void *ctx)
{
struct wpa_supplicant *wpa_s = ctx;
+ wpa_printf(MSG_DEBUG, "AP interface setup completed - state %s",
+ hostapd_state_text(wpa_s->ap_iface->state));
+ if (wpa_s->ap_iface->state == HAPD_IFACE_DISABLED) {
+ wpa_supplicant_ap_deinit(wpa_s);
+ return;
+ }
+
#ifdef CONFIG_ACS
- if (wpa_s->current_ssid && wpa_s->current_ssid->acs)
+ if (wpa_s->current_ssid && wpa_s->current_ssid->acs) {
wpa_s->assoc_freq = wpa_s->ap_iface->freq;
+ wpa_s->current_ssid->frequency = wpa_s->ap_iface->freq;
+ }
#endif /* CONFIG_ACS */
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
@@ -662,7 +772,8 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
else
params.uapsd = -1;
- if (ieee80211_is_dfs(params.freq.freq))
+ if (ieee80211_is_dfs(params.freq.freq, wpa_s->hw.modes,
+ wpa_s->hw.num_modes))
params.freq.freq = 0; /* set channel after CAC */
if (params.p2p)
@@ -692,13 +803,6 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
return -1;
}
- /* Use the maximum oper channel width if it's given. */
- if (ssid->max_oper_chwidth)
- conf->vht_oper_chwidth = ssid->max_oper_chwidth;
-
- ieee80211_freq_to_chan(ssid->vht_center_freq2,
- &conf->vht_oper_centr_freq_seg1_idx);
-
os_memcpy(wpa_s->ap_iface->conf->wmm_ac_params,
wpa_s->conf->wmm_ac_params,
sizeof(wpa_s->conf->wmm_ac_params));
@@ -777,6 +881,14 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN);
wpa_s->assoc_freq = ssid->frequency;
+#if defined(CONFIG_P2P) && defined(CONFIG_ACS)
+ if (wpa_s->p2p_go_do_acs) {
+ wpa_s->ap_iface->conf->channel = 0;
+ wpa_s->ap_iface->conf->hw_mode = wpa_s->p2p_go_acs_band;
+ ssid->acs = 1;
+ }
+#endif /* CONFIG_P2P && CONFIG_ACS */
+
if (hostapd_setup_interface(wpa_s->ap_iface)) {
wpa_printf(MSG_ERROR, "Failed to initialize AP interface");
wpa_supplicant_ap_deinit(wpa_s);
@@ -1277,13 +1389,16 @@ int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos)
void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
int offset, int width, int cf1, int cf2)
{
- if (!wpa_s->ap_iface)
- return;
+ struct hostapd_iface *iface = wpa_s->ap_iface;
+ if (!iface)
+ iface = wpa_s->ifmsh;
+ if (!iface)
+ return;
wpa_s->assoc_freq = freq;
if (wpa_s->current_ssid)
wpa_s->current_ssid->frequency = freq;
- hostapd_event_ch_switch(wpa_s->ap_iface->bss[0], freq, ht,
+ hostapd_event_ch_switch(iface->bss[0], freq, ht,
offset, width, cf1, cf2);
}
@@ -1436,66 +1551,123 @@ void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
if (wpa_s->ifmsh)
hostapd_ctrl_iface_pmksa_flush(wpa_s->ifmsh->bss[0]);
}
+
+
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+#ifdef CONFIG_MESH
+
+int wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr,
+ char *buf, size_t len)
+{
+ return hostapd_ctrl_iface_pmksa_list_mesh(wpa_s->ifmsh->bss[0], addr,
+ &buf[0], len);
+}
+
+
+int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd)
+{
+ struct external_pmksa_cache *entry;
+ void *pmksa_cache;
+
+ pmksa_cache = hostapd_ctrl_iface_pmksa_create_entry(wpa_s->own_addr,
+ cmd);
+ if (!pmksa_cache)
+ return -1;
+
+ entry = os_zalloc(sizeof(struct external_pmksa_cache));
+ if (!entry)
+ return -1;
+
+ entry->pmksa_cache = pmksa_cache;
+
+ dl_list_add(&wpa_s->mesh_external_pmksa_cache, &entry->list);
+
+ return 0;
+}
+
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
#endif /* CONFIG_CTRL_IFACE */
#ifdef NEED_AP_MLME
-void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
- struct dfs_event *radar)
+void wpas_ap_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
{
- if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+ struct hostapd_iface *iface = wpa_s->ap_iface;
+
+ if (!iface)
+ iface = wpa_s->ifmsh;
+ if (!iface || !iface->bss[0])
return;
wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
- hostapd_dfs_radar_detected(wpa_s->ap_iface, radar->freq,
+ hostapd_dfs_radar_detected(iface, radar->freq,
radar->ht_enabled, radar->chan_offset,
radar->chan_width,
radar->cf1, radar->cf2);
}
-void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
- struct dfs_event *radar)
+void wpas_ap_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
{
- if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+ struct hostapd_iface *iface = wpa_s->ap_iface;
+
+ if (!iface)
+ iface = wpa_s->ifmsh;
+ if (!iface || !iface->bss[0])
return;
wpa_printf(MSG_DEBUG, "DFS CAC started on %d MHz", radar->freq);
- hostapd_dfs_start_cac(wpa_s->ap_iface, radar->freq,
+ hostapd_dfs_start_cac(iface, radar->freq,
radar->ht_enabled, radar->chan_offset,
radar->chan_width, radar->cf1, radar->cf2);
}
-void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
- struct dfs_event *radar)
+void wpas_ap_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
{
- if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+ struct hostapd_iface *iface = wpa_s->ap_iface;
+
+ if (!iface)
+ iface = wpa_s->ifmsh;
+ if (!iface || !iface->bss[0])
return;
wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
- hostapd_dfs_complete_cac(wpa_s->ap_iface, 1, radar->freq,
+ hostapd_dfs_complete_cac(iface, 1, radar->freq,
radar->ht_enabled, radar->chan_offset,
radar->chan_width, radar->cf1, radar->cf2);
}
-void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
- struct dfs_event *radar)
+void wpas_ap_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
{
- if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+ struct hostapd_iface *iface = wpa_s->ap_iface;
+
+ if (!iface)
+ iface = wpa_s->ifmsh;
+ if (!iface || !iface->bss[0])
return;
wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
- hostapd_dfs_complete_cac(wpa_s->ap_iface, 0, radar->freq,
+ hostapd_dfs_complete_cac(iface, 0, radar->freq,
radar->ht_enabled, radar->chan_offset,
radar->chan_width, radar->cf1, radar->cf2);
}
-void wpas_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
- struct dfs_event *radar)
+void wpas_ap_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
{
- if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+ struct hostapd_iface *iface = wpa_s->ap_iface;
+
+ if (!iface)
+ iface = wpa_s->ifmsh;
+ if (!iface || !iface->bss[0])
return;
wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
- hostapd_dfs_nop_finished(wpa_s->ap_iface, radar->freq,
+ hostapd_dfs_nop_finished(iface, radar->freq,
radar->ht_enabled, radar->chan_offset,
radar->chan_width, radar->cf1, radar->cf2);
}
diff --git a/contrib/wpa/wpa_supplicant/ap.h b/contrib/wpa/wpa_supplicant/ap.h
index 5a59ddcc1c93..447b551863a3 100644
--- a/contrib/wpa/wpa_supplicant/ap.h
+++ b/contrib/wpa/wpa_supplicant/ap.h
@@ -85,17 +85,20 @@ int wpas_ap_stop_ap(struct wpa_supplicant *wpa_s);
int wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf,
size_t len);
void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
+int wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr,
+ char *buf, size_t len);
+int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd);
-void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
+void wpas_ap_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar);
+void wpas_ap_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
struct dfs_event *radar);
-void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
- struct dfs_event *radar);
-void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
- struct dfs_event *radar);
-void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
- struct dfs_event *radar);
-void wpas_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
- struct dfs_event *radar);
+void wpas_ap_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar);
+void wpas_ap_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar);
+void wpas_ap_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar);
void ap_periodic(struct wpa_supplicant *wpa_s);
diff --git a/contrib/wpa/wpa_supplicant/autoscan.c b/contrib/wpa/wpa_supplicant/autoscan.c
index 072a1d5414ae..5056a9300a87 100644
--- a/contrib/wpa/wpa_supplicant/autoscan.c
+++ b/contrib/wpa/wpa_supplicant/autoscan.c
@@ -47,11 +47,16 @@ int autoscan_init(struct wpa_supplicant *wpa_s, int req_scan)
struct sched_scan_plan *scan_plans;
/* Give preference to scheduled scan plans if supported/configured */
- if (wpa_s->sched_scan_plans)
+ if (wpa_s->sched_scan_plans) {
+ wpa_printf(MSG_DEBUG,
+ "autoscan: sched_scan_plans set - use it instead");
return 0;
+ }
- if (wpa_s->autoscan && wpa_s->autoscan_priv)
+ if (wpa_s->autoscan && wpa_s->autoscan_priv) {
+ wpa_printf(MSG_DEBUG, "autoscan: Already initialized");
return 0;
+ }
if (name == NULL)
return 0;
diff --git a/contrib/wpa/wpa_supplicant/bgscan.c b/contrib/wpa/wpa_supplicant/bgscan.c
index 798b43c3fdf7..1ea640114c8e 100644
--- a/contrib/wpa/wpa_supplicant/bgscan.c
+++ b/contrib/wpa/wpa_supplicant/bgscan.c
@@ -34,8 +34,6 @@ int bgscan_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
const struct bgscan_ops *ops = NULL;
bgscan_deinit(wpa_s);
- if (name == NULL)
- return -1;
params = os_strchr(name, ':');
if (params == NULL) {
diff --git a/contrib/wpa/wpa_supplicant/bgscan_learn.c b/contrib/wpa/wpa_supplicant/bgscan_learn.c
index a320cc43068c..cb732f709b9e 100644
--- a/contrib/wpa/wpa_supplicant/bgscan_learn.c
+++ b/contrib/wpa/wpa_supplicant/bgscan_learn.c
@@ -320,9 +320,6 @@ static int bgscan_learn_get_params(struct bgscan_learn_data *data,
{
const char *pos;
- if (params == NULL)
- return 0;
-
data->short_interval = atoi(params);
pos = os_strchr(params, ':');
diff --git a/contrib/wpa/wpa_supplicant/bgscan_simple.c b/contrib/wpa/wpa_supplicant/bgscan_simple.c
index a467cc5b9271..41a26df0d635 100644
--- a/contrib/wpa/wpa_supplicant/bgscan_simple.c
+++ b/contrib/wpa/wpa_supplicant/bgscan_simple.c
@@ -56,12 +56,7 @@ static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
} else {
if (data->scan_interval == data->short_interval) {
data->short_scan_count++;
- /*
- * Spend at most the duration of a long scan interval
- * scanning at the short scan interval. After that,
- * revert to the long scan interval.
- */
- if (data->short_scan_count > data->max_short_scans) {
+ if (data->short_scan_count >= data->max_short_scans) {
data->scan_interval = data->long_interval;
wpa_printf(MSG_DEBUG, "bgscan simple: Backing "
"off to long scan interval");
@@ -85,9 +80,6 @@ static int bgscan_simple_get_params(struct bgscan_simple_data *data,
{
const char *pos;
- if (params == NULL)
- return 0;
-
data->short_interval = atoi(params);
pos = os_strchr(params, ':');
diff --git a/contrib/wpa/wpa_supplicant/bss.c b/contrib/wpa/wpa_supplicant/bss.c
index 3a8778db9058..9b19f37affa0 100644
--- a/contrib/wpa/wpa_supplicant/bss.c
+++ b/contrib/wpa/wpa_supplicant/bss.c
@@ -1,6 +1,6 @@
/*
* BSS table
- * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -93,6 +93,7 @@ static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp)
ANQP_DUP(nai_realm);
ANQP_DUP(anqp_3gpp);
ANQP_DUP(domain_name);
+ ANQP_DUP(fils_realm_info);
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
ANQP_DUP(hs20_capability_list);
@@ -101,6 +102,8 @@ static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp)
ANQP_DUP(hs20_connection_capability);
ANQP_DUP(hs20_operating_class);
ANQP_DUP(hs20_osu_providers_list);
+ ANQP_DUP(hs20_operator_icon_metadata);
+ ANQP_DUP(hs20_osu_providers_nai_list);
#endif /* CONFIG_HS20 */
#undef ANQP_DUP
@@ -168,6 +171,7 @@ static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
wpabuf_free(anqp->nai_realm);
wpabuf_free(anqp->anqp_3gpp);
wpabuf_free(anqp->domain_name);
+ wpabuf_free(anqp->fils_realm_info);
while ((elem = dl_list_first(&anqp->anqp_elems,
struct wpa_bss_anqp_elem, list))) {
@@ -183,6 +187,8 @@ static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
wpabuf_free(anqp->hs20_connection_capability);
wpabuf_free(anqp->hs20_operating_class);
wpabuf_free(anqp->hs20_osu_providers_list);
+ wpabuf_free(anqp->hs20_operator_icon_metadata);
+ wpabuf_free(anqp->hs20_osu_providers_nai_list);
#endif /* CONFIG_HS20 */
os_free(anqp);
@@ -267,9 +273,9 @@ struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
}
-static void calculate_update_time(const struct os_reltime *fetch_time,
- unsigned int age_ms,
- struct os_reltime *update_time)
+void calculate_update_time(const struct os_reltime *fetch_time,
+ unsigned int age_ms,
+ struct os_reltime *update_time)
{
os_time_t usec;
@@ -595,6 +601,42 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
{
u32 changes;
+ if (bss->last_update_idx == wpa_s->bss_update_idx) {
+ struct os_reltime update_time;
+
+ /*
+ * Some drivers (e.g., cfg80211) include multiple BSS entries
+ * for the same BSS if that BSS's channel changes. The BSS list
+ * implementation in wpa_supplicant does not do that and we need
+ * to filter out the obsolete results here to make sure only the
+ * most current BSS information remains in the table.
+ */
+ wpa_printf(MSG_DEBUG, "BSS: " MACSTR
+ " has multiple entries in the scan results - select the most current one",
+ MAC2STR(bss->bssid));
+ calculate_update_time(fetch_time, res->age, &update_time);
+ wpa_printf(MSG_DEBUG,
+ "Previous last_update: %u.%06u (freq %d%s)",
+ (unsigned int) bss->last_update.sec,
+ (unsigned int) bss->last_update.usec,
+ bss->freq,
+ (bss->flags & WPA_BSS_ASSOCIATED) ? " assoc" : "");
+ wpa_printf(MSG_DEBUG, "New last_update: %u.%06u (freq %d%s)",
+ (unsigned int) update_time.sec,
+ (unsigned int) update_time.usec,
+ res->freq,
+ (res->flags & WPA_SCAN_ASSOCIATED) ? " assoc" : "");
+ if ((bss->flags & WPA_BSS_ASSOCIATED) ||
+ (!(res->flags & WPA_SCAN_ASSOCIATED) &&
+ !os_reltime_before(&bss->last_update, &update_time))) {
+ wpa_printf(MSG_DEBUG,
+ "Ignore this BSS entry since the previous update looks more current");
+ return bss;
+ }
+ wpa_printf(MSG_DEBUG,
+ "Accept this BSS entry since it looks more current than the previous update");
+ }
+
changes = wpa_bss_compare_res(bss, res);
if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
wpa_printf(MSG_DEBUG, "BSS: " MACSTR " changed freq %d --> %d",
@@ -1279,3 +1321,26 @@ int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates)
*rates = r;
return len;
}
+
+
+#ifdef CONFIG_FILS
+const u8 * wpa_bss_get_fils_cache_id(struct wpa_bss *bss)
+{
+ const u8 *ie;
+
+ if (bss) {
+ ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
+ if (ie && ie[1] >= 4 && WPA_GET_LE16(ie + 2) & BIT(7))
+ return ie + 4;
+ }
+
+ return NULL;
+}
+#endif /* CONFIG_FILS */
+
+
+int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab)
+{
+ return ieee802_11_ext_capab(wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB),
+ capab);
+}
diff --git a/contrib/wpa/wpa_supplicant/bss.h b/contrib/wpa/wpa_supplicant/bss.h
index 84e8fb07461e..3ce8cd3f429a 100644
--- a/contrib/wpa/wpa_supplicant/bss.h
+++ b/contrib/wpa/wpa_supplicant/bss.h
@@ -1,6 +1,6 @@
/*
* BSS table
- * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -40,6 +40,7 @@ struct wpa_bss_anqp {
struct wpabuf *nai_realm;
struct wpabuf *anqp_3gpp;
struct wpabuf *domain_name;
+ struct wpabuf *fils_realm_info;
struct dl_list anqp_elems; /* list of struct wpa_bss_anqp_elem */
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
@@ -49,6 +50,8 @@ struct wpa_bss_anqp {
struct wpabuf *hs20_connection_capability;
struct wpabuf *hs20_operating_class;
struct wpabuf *hs20_osu_providers_list;
+ struct wpabuf *hs20_operator_icon_metadata;
+ struct wpabuf *hs20_osu_providers_nai_list;
#endif /* CONFIG_HS20 */
};
@@ -144,6 +147,8 @@ int wpa_bss_get_max_rate(const struct wpa_bss *bss);
int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates);
struct wpa_bss_anqp * wpa_bss_anqp_alloc(void);
int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss);
+const u8 * wpa_bss_get_fils_cache_id(struct wpa_bss *bss);
+int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab);
static inline int bss_is_dmg(const struct wpa_bss *bss)
{
@@ -167,4 +172,8 @@ static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level)
bss->level = new_level;
}
+void calculate_update_time(const struct os_reltime *fetch_time,
+ unsigned int age_ms,
+ struct os_reltime *update_time);
+
#endif /* BSS_H */
diff --git a/contrib/wpa/wpa_supplicant/config.c b/contrib/wpa/wpa_supplicant/config.c
index dd922caf80af..2058175f885e 100644
--- a/contrib/wpa/wpa_supplicant/config.c
+++ b/contrib/wpa/wpa_supplicant/config.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant / Configuration parser and common functions
- * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -11,6 +11,7 @@
#include "common.h"
#include "utils/uuid.h"
#include "utils/ip_addr.h"
+#include "common/ieee802_1x_defs.h"
#include "crypto/sha1.h"
#include "rsn_supp/wpa.h"
#include "eap_peer/eap.h"
@@ -396,6 +397,50 @@ static char * wpa_config_write_bssid(const struct parse_data *data,
#endif /* NO_CONFIG_WRITE */
+static int wpa_config_parse_bssid_hint(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
+ os_strcmp(value, "any") == 0) {
+ ssid->bssid_hint_set = 0;
+ wpa_printf(MSG_MSGDUMP, "BSSID hint any");
+ return 0;
+ }
+ if (hwaddr_aton(value, ssid->bssid_hint)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID hint '%s'.",
+ line, value);
+ return -1;
+ }
+ ssid->bssid_hint_set = 1;
+ wpa_hexdump(MSG_MSGDUMP, "BSSID hint", ssid->bssid_hint, ETH_ALEN);
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_bssid_hint(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ char *value;
+ int res;
+
+ if (!ssid->bssid_hint_set)
+ return NULL;
+
+ value = os_malloc(20);
+ if (!value)
+ return NULL;
+ res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid_hint));
+ if (os_snprintf_error(20, res)) {
+ os_free(value);
+ return NULL;
+ }
+ return value;
+}
+#endif /* NO_CONFIG_WRITE */
+
+
static int wpa_config_parse_bssid_blacklist(const struct parse_data *data,
struct wpa_ssid *ssid, int line,
const char *value)
@@ -690,6 +735,10 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data,
val |= WPA_KEY_MGMT_FT_PSK;
else if (os_strcmp(start, "FT-EAP") == 0)
val |= WPA_KEY_MGMT_FT_IEEE8021X;
+#ifdef CONFIG_SHA384
+ else if (os_strcmp(start, "FT-EAP-SHA384") == 0)
+ val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
+#endif /* CONFIG_SHA384 */
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
@@ -719,6 +768,26 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data,
else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0)
val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
#endif /* CONFIG_SUITEB192 */
+#ifdef CONFIG_FILS
+ else if (os_strcmp(start, "FILS-SHA256") == 0)
+ val |= WPA_KEY_MGMT_FILS_SHA256;
+ else if (os_strcmp(start, "FILS-SHA384") == 0)
+ val |= WPA_KEY_MGMT_FILS_SHA384;
+#ifdef CONFIG_IEEE80211R
+ else if (os_strcmp(start, "FT-FILS-SHA256") == 0)
+ val |= WPA_KEY_MGMT_FT_FILS_SHA256;
+ else if (os_strcmp(start, "FT-FILS-SHA384") == 0)
+ val |= WPA_KEY_MGMT_FT_FILS_SHA384;
+#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_OWE
+ else if (os_strcmp(start, "OWE") == 0)
+ val |= WPA_KEY_MGMT_OWE;
+#endif /* CONFIG_OWE */
+#ifdef CONFIG_DPP
+ else if (os_strcmp(start, "DPP") == 0)
+ val |= WPA_KEY_MGMT_DPP;
+#endif /* CONFIG_DPP */
else {
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
line, start);
@@ -827,6 +896,18 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
}
pos += ret;
}
+
+#ifdef CONFIG_SHA384
+ if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
+ ret = os_snprintf(pos, end - pos, "%sFT-EAP-SHA384",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+#endif /* CONFIG_SHA384 */
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
@@ -921,6 +1002,71 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
}
#endif /* CONFIG_SUITEB192 */
+#ifdef CONFIG_FILS
+ if (ssid->key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
+ ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+ if (ssid->key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
+ ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+#ifdef CONFIG_IEEE80211R
+ if (ssid->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
+ ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+ if (ssid->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
+ ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_DPP
+ if (ssid->key_mgmt & WPA_KEY_MGMT_DPP) {
+ ret = os_snprintf(pos, end - pos, "%sDPP",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+#endif /* CONFIG_DPP */
+
+#ifdef CONFIG_OWE
+ if (ssid->key_mgmt & WPA_KEY_MGMT_OWE) {
+ ret = os_snprintf(pos, end - pos, "%sOWE",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+#endif /* CONFIG_OWE */
+
if (pos == buf) {
os_free(buf);
buf = NULL;
@@ -1042,6 +1188,40 @@ static char * wpa_config_write_group(const struct parse_data *data,
#endif /* NO_CONFIG_WRITE */
+static int wpa_config_parse_group_mgmt(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ int val;
+
+ val = wpa_config_parse_cipher(line, value);
+ if (val == -1)
+ return -1;
+
+ if (val & ~WPA_ALLOWED_GROUP_MGMT_CIPHERS) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: not allowed group management cipher (0x%x).",
+ line, val);
+ return -1;
+ }
+
+ if (ssid->group_mgmt_cipher == val)
+ return 1;
+ wpa_printf(MSG_MSGDUMP, "group_mgmt: 0x%x", val);
+ ssid->group_mgmt_cipher = val;
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_group_mgmt(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ return wpa_config_write_cipher(ssid->group_mgmt_cipher);
+}
+#endif /* NO_CONFIG_WRITE */
+
+
static int wpa_config_parse_auth_alg(const struct parse_data *data,
struct wpa_ssid *ssid, int line,
const char *value)
@@ -1816,6 +1996,140 @@ static char * wpa_config_write_mesh_basic_rates(const struct parse_data *data,
#endif /* CONFIG_MESH */
+#ifdef CONFIG_MACSEC
+
+static int wpa_config_parse_mka_cak(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ size_t len;
+
+ len = os_strlen(value);
+ if (len > 2 * MACSEC_CAK_MAX_LEN ||
+ (len != 2 * 16 && len != 2 * 32) ||
+ hexstr2bin(value, ssid->mka_cak, len / 2)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CAK '%s'.",
+ line, value);
+ return -1;
+ }
+ ssid->mka_cak_len = len / 2;
+ ssid->mka_psk_set |= MKA_PSK_SET_CAK;
+
+ wpa_hexdump_key(MSG_MSGDUMP, "MKA-CAK", ssid->mka_cak,
+ ssid->mka_cak_len);
+ return 0;
+}
+
+
+static int wpa_config_parse_mka_ckn(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ size_t len;
+
+ len = os_strlen(value);
+ if (len > 2 * MACSEC_CKN_MAX_LEN || /* too long */
+ len < 2 || /* too short */
+ len % 2 != 0 /* not an integral number of bytes */) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
+ line, value);
+ return -1;
+ }
+ ssid->mka_ckn_len = len / 2;
+ if (hexstr2bin(value, ssid->mka_ckn, ssid->mka_ckn_len)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
+ line, value);
+ return -1;
+ }
+
+ ssid->mka_psk_set |= MKA_PSK_SET_CKN;
+
+ wpa_hexdump_key(MSG_MSGDUMP, "MKA-CKN", ssid->mka_ckn,
+ ssid->mka_ckn_len);
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+
+static char * wpa_config_write_mka_cak(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ if (!(ssid->mka_psk_set & MKA_PSK_SET_CAK))
+ return NULL;
+
+ return wpa_config_write_string_hex(ssid->mka_cak, ssid->mka_cak_len);
+}
+
+
+static char * wpa_config_write_mka_ckn(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ if (!(ssid->mka_psk_set & MKA_PSK_SET_CKN))
+ return NULL;
+ return wpa_config_write_string_hex(ssid->mka_ckn, ssid->mka_ckn_len);
+}
+
+#endif /* NO_CONFIG_WRITE */
+
+#endif /* CONFIG_MACSEC */
+
+
+#ifdef CONFIG_OCV
+
+static int wpa_config_parse_ocv(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ char *end;
+
+ ssid->ocv = strtol(value, &end, 0);
+ if (*end || ssid->ocv < 0 || ssid->ocv > 1) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid ocv value '%s'.",
+ line, value);
+ return -1;
+ }
+ if (ssid->ocv && ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION)
+ ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_ocv(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ char *value = os_malloc(20);
+
+ if (!value)
+ return NULL;
+ os_snprintf(value, 20, "%d", ssid->ocv);
+ value[20 - 1] = '\0';
+ return value;
+}
+#endif /* NO_CONFIG_WRITE */
+
+#endif /* CONFIG_OCV */
+
+
+static int wpa_config_parse_peerkey(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ wpa_printf(MSG_INFO, "NOTE: Obsolete peerkey parameter ignored");
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_peerkey(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ return NULL;
+}
+#endif /* NO_CONFIG_WRITE */
+
+
/* Helper macros for network block parser */
#ifdef OFFSET
@@ -1907,24 +2221,34 @@ static const struct parse_data ssid_fields[] = {
{ STR_RANGE(ssid, 0, SSID_MAX_LEN) },
{ INT_RANGE(scan_ssid, 0, 1) },
{ FUNC(bssid) },
+ { FUNC(bssid_hint) },
{ FUNC(bssid_blacklist) },
{ FUNC(bssid_whitelist) },
{ FUNC_KEY(psk) },
{ INT(mem_only_psk) },
+ { STR_KEY(sae_password) },
+ { STR(sae_password_id) },
{ FUNC(proto) },
{ FUNC(key_mgmt) },
{ INT(bg_scan_period) },
{ FUNC(pairwise) },
{ FUNC(group) },
+ { FUNC(group_mgmt) },
{ FUNC(auth_alg) },
{ FUNC(scan_freq) },
{ FUNC(freq_list) },
+ { INT_RANGE(ht, 0, 1) },
+ { INT_RANGE(vht, 0, 1) },
+ { INT_RANGE(ht40, -1, 1) },
{ INT_RANGE(max_oper_chwidth, VHT_CHANWIDTH_USE_HT,
VHT_CHANWIDTH_80P80MHZ) },
+ { INT(vht_center_freq1) },
+ { INT(vht_center_freq2) },
#ifdef IEEE8021X_EAPOL
{ FUNC(eap) },
{ STR_LENe(identity) },
{ STR_LENe(anonymous_identity) },
+ { STR_LENe(imsi_identity) },
{ FUNC_KEY(password) },
{ STRe(ca_cert) },
{ STRe(ca_path) },
@@ -1933,6 +2257,7 @@ static const struct parse_data ssid_fields[] = {
{ STR_KEYe(private_key_passwd) },
{ STRe(dh_file) },
{ STRe(subject_match) },
+ { STRe(check_cert_subject) },
{ STRe(altsubject_match) },
{ STRe(domain_suffix_match) },
{ STRe(domain_match) },
@@ -1943,6 +2268,7 @@ static const struct parse_data ssid_fields[] = {
{ STR_KEYe(private_key2_passwd) },
{ STRe(dh_file2) },
{ STRe(subject_match2) },
+ { STRe(check_cert_subject2) },
{ STRe(altsubject_match2) },
{ STRe(domain_suffix_match2) },
{ STRe(domain_match2) },
@@ -1981,6 +2307,7 @@ static const struct parse_data ssid_fields[] = {
#ifdef CONFIG_MESH
{ INT_RANGE(mode, 0, 5) },
{ INT_RANGE(no_auto_peer, 0, 1) },
+ { INT_RANGE(mesh_rssi_threshold, -255, 1) },
#else /* CONFIG_MESH */
{ INT_RANGE(mode, 0, 4) },
#endif /* CONFIG_MESH */
@@ -1990,7 +2317,10 @@ static const struct parse_data ssid_fields[] = {
#ifdef CONFIG_IEEE80211W
{ INT_RANGE(ieee80211w, 0, 2) },
#endif /* CONFIG_IEEE80211W */
- { INT_RANGE(peerkey, 0, 1) },
+#ifdef CONFIG_OCV
+ { FUNC(ocv) },
+#endif /* CONFIG_OCV */
+ { FUNC(peerkey) /* obsolete - removed */ },
{ INT_RANGE(mixed_cell, 0, 1) },
{ INT_RANGE(frequency, 0, 65000) },
{ INT_RANGE(fixed_freq, 0, 1) },
@@ -2019,6 +2349,8 @@ static const struct parse_data ssid_fields[] = {
{ INT_RANGE(disable_sgi, 0, 1) },
{ INT_RANGE(disable_ldpc, 0, 1) },
{ INT_RANGE(ht40_intolerant, 0, 1) },
+ { INT_RANGE(tx_stbc, -1, 1) },
+ { INT_RANGE(rx_stbc, -1, 3) },
{ INT_RANGE(disable_max_amsdu, -1, 1) },
{ INT_RANGE(ampdu_factor, -1, 3) },
{ INT_RANGE(ampdu_density, -1, 7) },
@@ -2050,13 +2382,31 @@ static const struct parse_data ssid_fields[] = {
{ INT(beacon_int) },
#ifdef CONFIG_MACSEC
{ INT_RANGE(macsec_policy, 0, 1) },
+ { INT_RANGE(macsec_integ_only, 0, 1) },
+ { INT_RANGE(macsec_replay_protect, 0, 1) },
+ { INT(macsec_replay_window) },
+ { INT_RANGE(macsec_port, 1, 65534) },
+ { INT_RANGE(mka_priority, 0, 255) },
+ { FUNC_KEY(mka_cak) },
+ { FUNC_KEY(mka_ckn) },
#endif /* CONFIG_MACSEC */
#ifdef CONFIG_HS20
{ INT(update_identifier) },
+ { STR_RANGE(roaming_consortium_selection, 0, MAX_ROAMING_CONS_OI_LEN) },
#endif /* CONFIG_HS20 */
{ INT_RANGE(mac_addr, 0, 2) },
{ INT_RANGE(pbss, 0, 2) },
{ INT_RANGE(wps_disabled, 0, 1) },
+ { INT_RANGE(fils_dh_group, 0, 65535) },
+#ifdef CONFIG_DPP
+ { STR(dpp_connector) },
+ { STR_LEN(dpp_netaccesskey) },
+ { INT(dpp_netaccesskey_expiry) },
+ { STR_LEN(dpp_csign) },
+#endif /* CONFIG_DPP */
+ { INT_RANGE(owe_group, 0, 65535) },
+ { INT_RANGE(owe_only, 0, 1) },
+ { INT_RANGE(multi_ap_backhaul_sta, 0, 1) },
};
#undef OFFSET
@@ -2168,6 +2518,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
os_free(eap->eap_methods);
bin_clear_free(eap->identity, eap->identity_len);
os_free(eap->anonymous_identity);
+ os_free(eap->imsi_identity);
bin_clear_free(eap->password, eap->password_len);
os_free(eap->ca_cert);
os_free(eap->ca_path);
@@ -2176,6 +2527,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
str_clear_free(eap->private_key_passwd);
os_free(eap->dh_file);
os_free(eap->subject_match);
+ os_free(eap->check_cert_subject);
os_free(eap->altsubject_match);
os_free(eap->domain_suffix_match);
os_free(eap->domain_match);
@@ -2186,6 +2538,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
str_clear_free(eap->private_key2_passwd);
os_free(eap->dh_file2);
os_free(eap->subject_match2);
+ os_free(eap->check_cert_subject2);
os_free(eap->altsubject_match2);
os_free(eap->domain_suffix_match2);
os_free(eap->domain_match2);
@@ -2226,6 +2579,8 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
os_free(ssid->ssid);
str_clear_free(ssid->passphrase);
os_free(ssid->ext_psk);
+ str_clear_free(ssid->sae_password);
+ os_free(ssid->sae_password_id);
#ifdef IEEE8021X_EAPOL
eap_peer_config_free(&ssid->eap);
#endif /* IEEE8021X_EAPOL */
@@ -2242,6 +2597,12 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
#ifdef CONFIG_MESH
os_free(ssid->mesh_basic_rates);
#endif /* CONFIG_MESH */
+#ifdef CONFIG_HS20
+ os_free(ssid->roaming_consortium_selection);
+#endif /* CONFIG_HS20 */
+ os_free(ssid->dpp_connector);
+ bin_clear_free(ssid->dpp_netaccesskey, ssid->dpp_netaccesskey_len);
+ os_free(ssid->dpp_csign);
while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry,
list))) {
dl_list_del(&psk->list);
@@ -2495,6 +2856,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
ssid->group_cipher = DEFAULT_GROUP;
ssid->key_mgmt = DEFAULT_KEY_MGMT;
ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
+ ssid->ht = 1;
#ifdef IEEE8021X_EAPOL
ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
@@ -2506,12 +2868,15 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT;
ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT;
ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT;
+ ssid->mesh_rssi_threshold = DEFAULT_MESH_RSSI_THRESHOLD;
#endif /* CONFIG_MESH */
#ifdef CONFIG_HT_OVERRIDES
ssid->disable_ht = DEFAULT_DISABLE_HT;
ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
ssid->disable_sgi = DEFAULT_DISABLE_SGI;
ssid->disable_ldpc = DEFAULT_DISABLE_LDPC;
+ ssid->tx_stbc = DEFAULT_TX_STBC;
+ ssid->rx_stbc = DEFAULT_RX_STBC;
ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU;
ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR;
ssid->ampdu_density = DEFAULT_AMPDU_DENSITY;
@@ -2538,7 +2903,11 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
#ifdef CONFIG_IEEE80211W
ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT;
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_MACSEC
+ ssid->mka_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
+#endif /* CONFIG_MACSEC */
ssid->mac_addr = -1;
+ ssid->max_oper_chwidth = DEFAULT_MAX_OPER_CHWIDTH;
}
@@ -2849,11 +3218,64 @@ static int wpa_config_set_cred_req_conn_capab(struct wpa_cred *cred,
}
+static int wpa_config_set_cred_roaming_consortiums(struct wpa_cred *cred,
+ const char *value)
+{
+ u8 roaming_consortiums[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN];
+ size_t roaming_consortiums_len[MAX_ROAMING_CONS];
+ unsigned int num_roaming_consortiums = 0;
+ const char *pos, *end;
+ size_t len;
+
+ os_memset(roaming_consortiums, 0, sizeof(roaming_consortiums));
+ os_memset(roaming_consortiums_len, 0, sizeof(roaming_consortiums_len));
+
+ for (pos = value;;) {
+ end = os_strchr(pos, ',');
+ len = end ? (size_t) (end - pos) : os_strlen(pos);
+ if (!end && len == 0)
+ break;
+ if (len == 0 || (len & 1) != 0 ||
+ len / 2 > MAX_ROAMING_CONS_OI_LEN ||
+ hexstr2bin(pos,
+ roaming_consortiums[num_roaming_consortiums],
+ len / 2) < 0) {
+ wpa_printf(MSG_INFO,
+ "Invalid roaming_consortiums entry: %s",
+ pos);
+ return -1;
+ }
+ roaming_consortiums_len[num_roaming_consortiums] = len / 2;
+ num_roaming_consortiums++;
+
+ if (!end)
+ break;
+
+ if (num_roaming_consortiums >= MAX_ROAMING_CONS) {
+ wpa_printf(MSG_INFO,
+ "Too many roaming_consortiums OIs");
+ return -1;
+ }
+
+ pos = end + 1;
+ }
+
+ os_memcpy(cred->roaming_consortiums, roaming_consortiums,
+ sizeof(roaming_consortiums));
+ os_memcpy(cred->roaming_consortiums_len, roaming_consortiums_len,
+ sizeof(roaming_consortiums_len));
+ cred->num_roaming_consortiums = num_roaming_consortiums;
+
+ return 0;
+}
+
+
int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
const char *value, int line)
{
char *val;
size_t len;
+ int res;
if (os_strcmp(var, "temporary") == 0) {
cred->temporary = atoi(value);
@@ -3076,6 +3498,16 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
return 0;
}
+ if (os_strcmp(var, "roaming_consortiums") == 0) {
+ res = wpa_config_set_cred_roaming_consortiums(cred, val);
+ if (res < 0)
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid roaming_consortiums",
+ line);
+ os_free(val);
+ return res;
+ }
+
if (os_strcmp(var, "excluded_ssid") == 0) {
struct excluded_ssid *e;
@@ -3387,6 +3819,31 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var)
return buf;
}
+ if (os_strcmp(var, "roaming_consortiums") == 0) {
+ size_t buflen;
+ char *buf, *pos;
+ size_t i;
+
+ if (!cred->num_roaming_consortiums)
+ return NULL;
+ buflen = cred->num_roaming_consortiums *
+ MAX_ROAMING_CONS_OI_LEN * 2 + 1;
+ buf = os_malloc(buflen);
+ if (!buf)
+ return NULL;
+ pos = buf;
+ for (i = 0; i < cred->num_roaming_consortiums; i++) {
+ if (i > 0)
+ *pos++ = ',';
+ pos += wpa_snprintf_hex(
+ pos, buf + buflen - pos,
+ cred->roaming_consortiums[i],
+ cred->roaming_consortiums_len[i]);
+ }
+ *pos = '\0';
+ return buf;
+ }
+
if (os_strcmp(var, "excluded_ssid") == 0) {
unsigned int i;
char *buf, *end, *pos;
@@ -3644,6 +4101,7 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
config->max_num_sta = DEFAULT_MAX_NUM_STA;
+ config->ap_isolate = DEFAULT_AP_ISOLATE;
config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE;
config->scan_cur_freq = DEFAULT_SCAN_CUR_FREQ;
config->wmm_ac_params[0] = ac_be;
@@ -3658,12 +4116,16 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
#ifdef CONFIG_MBO
config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA;
+ config->disassoc_imminent_rssi_threshold =
+ DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD;
+ config->oce = DEFAULT_OCE_SUPPORT;
#endif /* CONFIG_MBO */
if (ctrl_interface)
config->ctrl_interface = os_strdup(ctrl_interface);
if (driver_param)
config->driver_param = os_strdup(driver_param);
+ config->gas_rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
return config;
}
@@ -4070,6 +4532,21 @@ static int wpa_config_process_p2p_no_go_freq(
return 0;
}
+
+static int wpa_config_process_p2p_device_persistent_mac_addr(
+ const struct global_parse_data *data,
+ struct wpa_config *config, int line, const char *pos)
+{
+ if (hwaddr_aton2(pos, config->p2p_device_persistent_mac_addr) < 0) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid p2p_device_persistent_mac_addr '%s'",
+ line, pos);
+ return -1;
+ }
+
+ return 0;
+}
+
#endif /* CONFIG_P2P */
@@ -4269,6 +4746,7 @@ static const struct global_parse_data global_fields[] = {
{ FUNC_NO_VAR(load_dynamic_eap), 0 },
#ifdef CONFIG_WPS
{ FUNC(uuid), CFG_CHANGED_UUID },
+ { INT_RANGE(auto_uuid, 0, 1), 0 },
{ STR_RANGE(device_name, 0, WPS_DEV_NAME_MAX_LEN),
CFG_CHANGED_DEVICE_NAME },
{ STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING },
@@ -4279,6 +4757,7 @@ static const struct global_parse_data global_fields[] = {
{ FUNC(os_version), CFG_CHANGED_OS_VERSION },
{ STR(config_methods), CFG_CHANGED_CONFIG_METHODS },
{ INT_RANGE(wps_cred_processing, 0, 2), 0 },
+ { INT_RANGE(wps_cred_add_sae, 0, 1), 0 },
{ FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION },
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
@@ -4301,6 +4780,7 @@ static const struct global_parse_data global_fields[] = {
{ INT_RANGE(p2p_optimize_listen_chan, 0, 1), 0 },
{ INT(p2p_go_ht40), 0 },
{ INT(p2p_go_vht), 0 },
+ { INT(p2p_go_he), 0 },
{ INT(p2p_disabled), 0 },
{ INT_RANGE(p2p_go_ctwindow, 0, 127), 0 },
{ INT(p2p_no_group_iface), 0 },
@@ -4310,6 +4790,9 @@ static const struct global_parse_data global_fields[] = {
{ IPV4(ip_addr_start), 0 },
{ IPV4(ip_addr_end), 0 },
{ INT_RANGE(p2p_cli_probe, 0, 1), 0 },
+ { INT(p2p_device_random_mac_addr), 0 },
+ { FUNC(p2p_device_persistent_mac_addr), 0 },
+ { INT(p2p_interface_random_mac_addr), 0 },
#endif /* CONFIG_P2P */
{ FUNC(country), CFG_CHANGED_COUNTRY },
{ INT(bss_max_count), 0 },
@@ -4318,6 +4801,7 @@ static const struct global_parse_data global_fields[] = {
{ INT_RANGE(filter_ssids, 0, 1), 0 },
{ INT_RANGE(filter_rssi, -100, 0), 0 },
{ INT(max_num_sta), 0 },
+ { INT_RANGE(ap_isolate, 0, 1), 0 },
{ INT_RANGE(disassoc_low_ack, 0, 1), 0 },
#ifdef CONFIG_HS20
{ INT_RANGE(hs20, 0, 1), 0 },
@@ -4325,6 +4809,11 @@ static const struct global_parse_data global_fields[] = {
{ INT_RANGE(interworking, 0, 1), 0 },
{ FUNC(hessid), 0 },
{ INT_RANGE(access_network_type, 0, 15), 0 },
+ { INT_RANGE(go_interworking, 0, 1), 0 },
+ { INT_RANGE(go_access_network_type, 0, 15), 0 },
+ { INT_RANGE(go_internet, 0, 1), 0 },
+ { INT_RANGE(go_venue_group, 0, 255), 0 },
+ { INT_RANGE(go_venue_type, 0, 255), 0 },
{ INT_RANGE(pbc_in_m1, 0, 1), 0 },
{ STR(autoscan), 0 },
{ INT_RANGE(wps_nfc_dev_pw_id, 0x10, 0xffff),
@@ -4345,9 +4834,10 @@ static const struct global_parse_data global_fields[] = {
{ FUNC(freq_list), 0 },
{ INT(scan_cur_freq), 0 },
{ INT(sched_scan_interval), 0 },
+ { INT(sched_scan_start_delay), 0 },
{ INT(tdls_external_control), 0},
{ STR(osu_dir), 0 },
- { STR(wowlan_triggers), 0 },
+ { STR(wowlan_triggers), CFG_CHANGED_WOWLAN_TRIGGERS },
{ INT(p2p_search_delay), 0},
{ INT(mac_addr), 0 },
{ INT(rand_addr_lifetime), 0 },
@@ -4361,16 +4851,23 @@ static const struct global_parse_data global_fields[] = {
{ INT_RANGE(fst_priority, 1, FST_MAX_PRIO_VALUE), 0 },
{ INT_RANGE(fst_llt, 1, FST_MAX_LLT_MS), 0 },
#endif /* CONFIG_FST */
+ { INT_RANGE(cert_in_cb, 0, 1), 0 },
{ INT_RANGE(wpa_rsc_relaxation, 0, 1), 0 },
{ STR(sched_scan_plans), CFG_CHANGED_SCHED_SCAN_PLANS },
#ifdef CONFIG_MBO
{ STR(non_pref_chan), 0 },
{ INT_RANGE(mbo_cell_capa, MBO_CELL_CAPA_AVAILABLE,
MBO_CELL_CAPA_NOT_SUPPORTED), 0 },
-#endif /*CONFIG_MBO */
+ { INT_RANGE(disassoc_imminent_rssi_threshold, -120, 0), 0 },
+ { INT_RANGE(oce, 0, 3), 0 },
+#endif /* CONFIG_MBO */
{ INT(gas_address3), 0 },
{ INT_RANGE(ftm_responder, 0, 1), 0 },
{ INT_RANGE(ftm_initiator, 0, 1), 0 },
+ { INT(gas_rand_addr_lifetime), 0 },
+ { INT_RANGE(gas_rand_mac_addr, 0, 2), 0 },
+ { INT_RANGE(dpp_config_processing, 0, 2), 0 },
+ { INT_RANGE(coloc_intf_reporting, 0, 1), 0 },
};
#undef FUNC
diff --git a/contrib/wpa/wpa_supplicant/config.h b/contrib/wpa/wpa_supplicant/config.h
index 48e64be5da1a..abbd8c90e2b5 100644
--- a/contrib/wpa/wpa_supplicant/config.h
+++ b/contrib/wpa/wpa_supplicant/config.h
@@ -32,6 +32,7 @@
#define DEFAULT_BSS_EXPIRATION_AGE 180
#define DEFAULT_BSS_EXPIRATION_SCAN_COUNT 2
#define DEFAULT_MAX_NUM_STA 128
+#define DEFAULT_AP_ISOLATE 0
#define DEFAULT_ACCESS_NETWORK_TYPE 15
#define DEFAULT_SCAN_CUR_FREQ 0
#define DEFAULT_P2P_SEARCH_DELAY 500
@@ -41,6 +42,8 @@
#define DEFAULT_P2P_GO_CTWINDOW 0
#define DEFAULT_WPA_RSC_RELAXATION 1
#define DEFAULT_MBO_CELL_CAPA MBO_CELL_CAPA_NOT_SUPPORTED
+#define DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD -75
+#define DEFAULT_OCE_SUPPORT OCE_STA
#include "config_ssid.h"
#include "wps/wps.h"
@@ -48,6 +51,9 @@
#include "common/ieee802_11_common.h"
+#define MAX_ROAMING_CONS 36
+#define MAX_ROAMING_CONS_OI_LEN 15
+
struct wpa_cred {
/**
* next - Next credential in the list
@@ -222,10 +228,43 @@ struct wpa_cred {
*/
size_t roaming_consortium_len;
+ /**
+ * required_roaming_consortium - Required Roaming Consortium OI
+ *
+ * If required_roaming_consortium_len is non-zero, this field contains
+ * the Roaming Consortium OI that is required to be advertised by the AP
+ * for the credential to be considered matching.
+ */
u8 required_roaming_consortium[15];
+
+ /**
+ * required_roaming_consortium_len - Length of required_roaming_consortium
+ */
size_t required_roaming_consortium_len;
/**
+ * roaming_consortiums - Roaming Consortium OI(s) memberships
+ *
+ * This field contains one or more OIs identifying the roaming
+ * consortiums of which the provider is a member. The list is sorted
+ * from the most preferred one to the least preferred one. A match
+ * between the Roaming Consortium OIs advertised by an AP and the OIs
+ * in this list indicates that successful authentication is possible.
+ * (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/RoamingConsortiumOI)
+ */
+ u8 roaming_consortiums[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN];
+
+ /**
+ * roaming_consortiums_len - Length on roaming_consortiums[i]
+ */
+ size_t roaming_consortiums_len[MAX_ROAMING_CONS];
+
+ /**
+ * num_roaming_consortiums - Number of entries in roaming_consortiums
+ */
+ unsigned int num_roaming_consortiums;
+
+ /**
* eap_method - EAP method to use
*
* Pre-configured EAP method to use with this credential or %NULL to
@@ -334,6 +373,7 @@ struct wpa_cred {
#define CFG_CHANGED_NFC_PASSWORD_TOKEN BIT(15)
#define CFG_CHANGED_P2P_PASSPHRASE_LEN BIT(16)
#define CFG_CHANGED_SCHED_SCAN_PLANS BIT(17)
+#define CFG_CHANGED_WOWLAN_TRIGGERS BIT(18)
/**
* struct wpa_config - wpa_supplicant configuration data
@@ -625,6 +665,13 @@ struct wpa_config {
u8 uuid[16];
/**
+ * auto_uuid - Automatic UUID behavior
+ * 0 = generate static value based on the local MAC address (default)
+ * 1 = generate a random UUID every time wpa_supplicant starts
+ */
+ int auto_uuid;
+
+ /**
* device_name - Device Name (WPS)
* User-friendly description of device; up to 32 octets encoded in
* UTF-8
@@ -698,6 +745,16 @@ struct wpa_config {
*/
int wps_cred_processing;
+ /**
+ * wps_cred_add_sae - Whether to enable SAE automatically for WPS
+ *
+ * 0 = only add the explicitly listed WPA2-PSK configuration
+ * 1 = add both the WPA2-PSK and SAE configuration and enable PMF so
+ * that the station gets configured in WPA3-Personal transition mode
+ * (supports both WPA2-Personal (PSK) and WPA3-Personal (SAE) APs).
+ */
+ int wps_cred_add_sae;
+
#define MAX_SEC_DEVICE_TYPES 5
/**
* sec_device_types - Secondary Device Types (P2P)
@@ -833,6 +890,20 @@ struct wpa_config {
unsigned int max_num_sta;
/**
+ * ap_isolate - Whether to use client isolation feature
+ *
+ * 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=0); except in P2P GO case,
+ * where p2p_intra_bss parameter is used to determine whether to allow
+ * intra-BSS forwarding (ap_isolate = !p2p_intra_bss).
+ *
+ * 0 = do not enable AP isolation
+ * 1 = enable AP isolation
+ */
+ int ap_isolate;
+
+ /**
* freq_list - Array of allowed scan frequencies or %NULL for all
*
* This is an optional zero-terminated array of frequencies in
@@ -854,7 +925,7 @@ struct wpa_config {
unsigned int changed_parameters;
/**
- * disassoc_low_ack - Disassocicate stations with massive packet loss
+ * disassoc_low_ack - Disassociate stations with massive packet loss
*/
int disassoc_low_ack;
@@ -872,6 +943,34 @@ struct wpa_config {
*/
int access_network_type;
+ /**
+ * go_interworking - Whether Interworking for P2P GO is enabled
+ */
+ int go_interworking;
+
+ /**
+ * go_access_network_type - P2P GO Access Network Type
+ *
+ * This indicates which access network type to advertise if Interworking
+ * is enabled for P2P GO.
+ */
+ int go_access_network_type;
+
+ /**
+ * go_internet - Interworking: Internet connectivity (0 or 1)
+ */
+ int go_internet;
+
+ /**
+ * go_venue_group - Interworking: Venue group
+ */
+ int go_venue_group;
+
+ /**
+ * go_venue_type: Interworking: Venue type
+ */
+ int go_venue_type;
+
/**
* hessid - Homogenous ESS identifier
*
@@ -990,6 +1089,16 @@ struct wpa_config {
int p2p_go_vht;
/**
+ * p2p_go_he - Default mode for 11ax HE enable when operating as GO
+ *
+ * This will take effect for p2p_group_add, p2p_connect, and p2p_invite.
+ * Note that regulatory constraints and driver capabilities are
+ * consulted anyway, so setting it to 1 can't do real harm.
+ * By default: 0 (disabled)
+ */
+ int p2p_go_he;
+
+ /**
* p2p_go_ctwindow - CTWindow to use when operating as GO
*
* By default: 0 (no CTWindow). Values 0-127 can be used to indicate
@@ -1096,6 +1205,15 @@ struct wpa_config {
unsigned int sched_scan_interval;
/**
+ * sched_scan_start_delay - Schedule scan start delay before first scan
+ *
+ * Delay (in seconds) before scheduling first scan plan cycle. The
+ * driver may ignore this parameter and start immediately (or at any
+ * other time), if this feature is not supported.
+ */
+ unsigned int sched_scan_start_delay;
+
+ /**
* tdls_external_control - External control for TDLS setup requests
*
* Enable TDLS mode where external programs are given the control
@@ -1291,6 +1409,19 @@ struct wpa_config {
* mbo_cell_capa - Cellular capabilities for MBO
*/
enum mbo_cellular_capa mbo_cell_capa;
+
+ /**
+ * disassoc_imminent_rssi_threshold - RSSI threshold of candidate AP
+ * when disassociation imminent is set.
+ */
+ int disassoc_imminent_rssi_threshold;
+
+ /**
+ * oce - Enable OCE in STA and/or STA-CFON mode
+ * - Set BIT(0) to enable OCE in non-AP STA mode
+ * - Set BIT(1) to enable OCE in STA-CFON mode
+ */
+ unsigned int oce;
#endif /* CONFIG_MBO */
/**
@@ -1328,6 +1459,74 @@ struct wpa_config {
* wpa_supplicant.
*/
int ftm_initiator;
+
+ /**
+ * gas_rand_addr_lifetime - Lifetime of random MAC address for ANQP in
+ * seconds
+ */
+ unsigned int gas_rand_addr_lifetime;
+
+ /**
+ * gas_rand_mac_addr - GAS MAC address policy
+ *
+ * 0 = use permanent MAC address
+ * 1 = use random MAC address
+ * 2 = like 1, but maintain OUI (with local admin bit set)
+ */
+ int gas_rand_mac_addr;
+
+ /**
+ * dpp_config_processing - How to process DPP configuration
+ *
+ * 0 = report received configuration to an external program for
+ * processing; do not generate any network profile internally
+ * 1 = report received configuration to an external program and generate
+ * a network profile internally, but do not automatically connect
+ * to the created (disabled) profile; the network profile id is
+ * reported to external programs
+ * 2 = report received configuration to an external program, generate
+ * a network profile internally, try to connect to the created
+ * profile automatically
+ */
+ int dpp_config_processing;
+
+ /**
+ * coloc_intf_reporting - Colocated interference reporting
+ *
+ * dot11CoLocIntfReportingActivated
+ * 0 = disabled (false)
+ * 1 = enabled (true)
+ */
+ int coloc_intf_reporting;
+
+ /**
+ * p2p_device_random_mac_addr - P2P Device MAC address policy default
+ *
+ * 0 = use permanent MAC address
+ * 1 = use random MAC address on creating the interface if there is no
+ * persistent groups.
+ *
+ * By default, permanent MAC address is used.
+ */
+ int p2p_device_random_mac_addr;
+
+ /**
+ * p2p_device_persistent_mac_addr - Record last used MAC address
+ *
+ * If there are saved persistent groups, P2P cannot generate another
+ * random MAC address, and need to restore to last used MAC address.
+ */
+ u8 p2p_device_persistent_mac_addr[ETH_ALEN];
+
+ /**
+ * p2p_interface_random_mac_addr - P2P Interface MAC address policy default
+ *
+ * 0 = use permanent MAC address
+ * 1 = use random MAC address on creating the interface.
+ *
+ * By default, permanent MAC address is used.
+ */
+ int p2p_interface_random_mac_addr;
};
diff --git a/contrib/wpa/wpa_supplicant/config_file.c b/contrib/wpa/wpa_supplicant/config_file.c
index 7ae16545bebc..26f6ee147844 100644
--- a/contrib/wpa/wpa_supplicant/config_file.c
+++ b/contrib/wpa/wpa_supplicant/config_file.c
@@ -19,6 +19,7 @@
#include "config.h"
#include "base64.h"
#include "uuid.h"
+#include "common/ieee802_1x_defs.h"
#include "p2p/p2p.h"
#include "eap_peer/eap_methods.h"
#include "eap_peer/eap.h"
@@ -136,9 +137,13 @@ static int wpa_config_validate_network(struct wpa_ssid *ssid, int line)
wpa_config_update_psk(ssid);
}
+ if (ssid->disabled == 2)
+ ssid->p2p_persistent_group = 1;
+
if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
- !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
- !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) {
+ !(ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
+ WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256 |
+ WPA_CIPHER_NONE))) {
/* Group cipher cannot be stronger than the pairwise cipher. */
wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher"
" list since it was not allowed for pairwise "
@@ -155,6 +160,15 @@ static int wpa_config_validate_network(struct wpa_ssid *ssid, int line)
errors++;
}
+#ifdef CONFIG_OCV
+ if (ssid->ocv && ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: PMF needs to be enabled whenever using OCV",
+ line);
+ errors++;
+ }
+#endif /* CONFIG_OCV */
+
return errors;
}
@@ -308,7 +322,7 @@ static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line,
encoded_len += len;
}
- if (!end) {
+ if (!end || !encoded) {
wpa_printf(MSG_ERROR, "Line %d: blob was not terminated "
"properly", *line);
os_free(encoded);
@@ -393,7 +407,8 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
if (f == NULL) {
wpa_printf(MSG_ERROR, "Failed to open config file '%s', "
"error: %s", name, strerror(errno));
- os_free(config);
+ if (config != cfgp)
+ os_free(config);
return NULL;
}
@@ -459,7 +474,8 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
#ifndef WPA_IGNORE_CONFIG_ERRORS
if (errors) {
- wpa_config_free(config);
+ if (config != cfgp)
+ wpa_config_free(config);
config = NULL;
head = NULL;
}
@@ -477,7 +493,7 @@ static void write_str(FILE *f, const char *field, struct wpa_ssid *ssid)
if (value == NULL)
return;
fprintf(f, "\t%s=%s\n", field, value);
- os_free(value);
+ str_clear_free(value);
}
@@ -499,6 +515,17 @@ static void write_bssid(FILE *f, struct wpa_ssid *ssid)
}
+static void write_bssid_hint(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value = wpa_config_get(ssid, "bssid_hint");
+
+ if (!value)
+ return;
+ fprintf(f, "\tbssid_hint=%s\n", value);
+ os_free(value);
+}
+
+
static void write_psk(FILE *f, struct wpa_ssid *ssid)
{
char *value;
@@ -578,6 +605,22 @@ static void write_group(FILE *f, struct wpa_ssid *ssid)
}
+static void write_group_mgmt(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (!ssid->group_mgmt_cipher)
+ return;
+
+ value = wpa_config_get(ssid, "group_mgmt");
+ if (!value)
+ return;
+ if (value[0])
+ fprintf(f, "\tgroup_mgmt=%s\n", value);
+ os_free(value);
+}
+
+
static void write_auth_alg(FILE *f, struct wpa_ssid *ssid)
{
char *value;
@@ -662,6 +705,40 @@ static void write_psk_list(FILE *f, struct wpa_ssid *ssid)
#endif /* CONFIG_P2P */
+#ifdef CONFIG_MACSEC
+
+static void write_mka_cak(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (!(ssid->mka_psk_set & MKA_PSK_SET_CAK))
+ return;
+
+ value = wpa_config_get(ssid, "mka_cak");
+ if (!value)
+ return;
+ fprintf(f, "\tmka_cak=%s\n", value);
+ os_free(value);
+}
+
+
+static void write_mka_ckn(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (!(ssid->mka_psk_set & MKA_PSK_SET_CKN))
+ return;
+
+ value = wpa_config_get(ssid, "mka_ckn");
+ if (!value)
+ return;
+ fprintf(f, "\tmka_ckn=%s\n", value);
+ os_free(value);
+}
+
+#endif /* CONFIG_MACSEC */
+
+
static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
{
int i;
@@ -675,15 +752,19 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
STR(ssid);
INT(scan_ssid);
write_bssid(f, ssid);
+ write_bssid_hint(f, ssid);
write_str(f, "bssid_blacklist", ssid);
write_str(f, "bssid_whitelist", ssid);
write_psk(f, ssid);
INT(mem_only_psk);
+ STR(sae_password);
+ STR(sae_password_id);
write_proto(f, ssid);
write_key_mgmt(f, ssid);
INT_DEF(bg_scan_period, DEFAULT_BG_SCAN_PERIOD);
write_pairwise(f, ssid);
write_group(f, ssid);
+ write_group_mgmt(f, ssid);
write_auth_alg(f, ssid);
STR(bgscan);
STR(autoscan);
@@ -692,6 +773,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
write_eap(f, ssid);
STR(identity);
STR(anonymous_identity);
+ STR(imsi_identity);
STR(password);
STR(ca_cert);
STR(ca_path);
@@ -700,6 +782,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
STR(private_key_passwd);
STR(dh_file);
STR(subject_match);
+ STR(check_cert_subject);
STR(altsubject_match);
STR(domain_suffix_match);
STR(domain_match);
@@ -710,6 +793,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
STR(private_key2_passwd);
STR(dh_file2);
STR(subject_match2);
+ STR(check_cert_subject2);
STR(altsubject_match2);
STR(domain_suffix_match2);
STR(domain_match2);
@@ -752,11 +836,16 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
#endif /* CONFIG_ACS */
write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1);
INT(disabled);
- INT(peerkey);
INT(mixed_cell);
- INT(max_oper_chwidth);
+ INT(vht);
+ INT_DEF(ht, 1);
+ INT(ht40);
+ INT_DEF(max_oper_chwidth, DEFAULT_MAX_OPER_CHWIDTH);
+ INT(vht_center_freq1);
+ INT(vht_center_freq2);
INT(pbss);
INT(wps_disabled);
+ INT(fils_dh_group);
#ifdef CONFIG_IEEE80211W
write_int(f, "ieee80211w", ssid->ieee80211w,
MGMT_FRAME_PROTECTION_DEFAULT);
@@ -772,9 +861,17 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
INT(beacon_int);
#ifdef CONFIG_MACSEC
INT(macsec_policy);
+ write_mka_cak(f, ssid);
+ write_mka_ckn(f, ssid);
+ INT(macsec_integ_only);
+ INT(macsec_replay_protect);
+ INT(macsec_replay_window);
+ INT(macsec_port);
+ INT_DEF(mka_priority, DEFAULT_PRIO_NOT_KEY_SERVER);
#endif /* CONFIG_MACSEC */
#ifdef CONFIG_HS20
INT(update_identifier);
+ STR(roaming_consortium_selection);
#endif /* CONFIG_HS20 */
write_int(f, "mac_addr", ssid->mac_addr, -1);
#ifdef CONFIG_MESH
@@ -783,16 +880,28 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
INT_DEF(dot11MeshRetryTimeout, DEFAULT_MESH_RETRY_TIMEOUT);
INT_DEF(dot11MeshConfirmTimeout, DEFAULT_MESH_CONFIRM_TIMEOUT);
INT_DEF(dot11MeshHoldingTimeout, DEFAULT_MESH_HOLDING_TIMEOUT);
+ INT_DEF(mesh_rssi_threshold, DEFAULT_MESH_RSSI_THRESHOLD);
#endif /* CONFIG_MESH */
INT(wpa_ptk_rekey);
INT(group_rekey);
INT(ignore_broadcast_ssid);
+#ifdef CONFIG_DPP
+ STR(dpp_connector);
+ STR(dpp_netaccesskey);
+ INT(dpp_netaccesskey_expiry);
+ STR(dpp_csign);
+#endif /* CONFIG_DPP */
+ INT(owe_group);
+ INT(owe_only);
+ INT(multi_ap_backhaul_sta);
#ifdef CONFIG_HT_OVERRIDES
INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40);
INT_DEF(disable_sgi, DEFAULT_DISABLE_SGI);
INT_DEF(disable_ldpc, DEFAULT_DISABLE_LDPC);
INT(ht40_intolerant);
+ INT_DEF(tx_stbc, DEFAULT_TX_STBC);
+ INT_DEF(rx_stbc, DEFAULT_RX_STBC);
INT_DEF(disable_max_amsdu, DEFAULT_DISABLE_MAX_AMSDU);
INT_DEF(ampdu_factor, DEFAULT_AMPDU_FACTOR);
INT_DEF(ampdu_density, DEFAULT_AMPDU_DENSITY);
@@ -949,6 +1058,20 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
fprintf(f, "\n");
}
+ if (cred->num_roaming_consortiums) {
+ size_t j;
+
+ fprintf(f, "\troaming_consortiums=\"");
+ for (i = 0; i < cred->num_roaming_consortiums; i++) {
+ if (i > 0)
+ fprintf(f, ",");
+ for (j = 0; j < cred->roaming_consortiums_len[i]; j++)
+ fprintf(f, "%02x",
+ cred->roaming_consortiums[i][j]);
+ }
+ fprintf(f, "\"\n");
+ }
+
if (cred->sim_num != DEFAULT_USER_SELECTED_SIM)
fprintf(f, "\tsim_num=%d\n", cred->sim_num);
}
@@ -1039,6 +1162,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
uuid_bin2str(config->uuid, buf, sizeof(buf));
fprintf(f, "uuid=%s\n", buf);
}
+ if (config->auto_uuid)
+ fprintf(f, "auto_uuid=%d\n", config->auto_uuid);
if (config->device_name)
fprintf(f, "device_name=%s\n", config->device_name);
if (config->manufacturer)
@@ -1064,6 +1189,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->wps_cred_processing)
fprintf(f, "wps_cred_processing=%d\n",
config->wps_cred_processing);
+ if (config->wps_cred_add_sae)
+ fprintf(f, "wps_cred_add_sae=%d\n",
+ config->wps_cred_add_sae);
if (config->wps_vendor_ext_m1) {
int i, len = wpabuf_len(config->wps_vendor_ext_m1);
const u8 *p = wpabuf_head_u8(config->wps_vendor_ext_m1);
@@ -1076,6 +1204,17 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
}
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
+ {
+ int i;
+ char _buf[WPS_DEV_TYPE_BUFSIZE], *buf;
+
+ for (i = 0; i < config->num_sec_device_types; i++) {
+ buf = wps_dev_type_bin2str(config->sec_device_type[i],
+ _buf, sizeof(_buf));
+ if (buf)
+ fprintf(f, "sec_device_type=%s\n", buf);
+ }
+ }
if (config->p2p_listen_reg_class)
fprintf(f, "p2p_listen_reg_class=%d\n",
config->p2p_listen_reg_class);
@@ -1128,6 +1267,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
fprintf(f, "p2p_go_ht40=%d\n", config->p2p_go_ht40);
if (config->p2p_go_vht)
fprintf(f, "p2p_go_vht=%d\n", config->p2p_go_vht);
+ if (config->p2p_go_he)
+ fprintf(f, "p2p_go_he=%d\n", config->p2p_go_he);
if (config->p2p_go_ctwindow != DEFAULT_P2P_GO_CTWINDOW)
fprintf(f, "p2p_go_ctwindow=%d\n", config->p2p_go_ctwindow);
if (config->p2p_disabled)
@@ -1175,8 +1316,12 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
config->bss_expiration_scan_count);
if (config->filter_ssids)
fprintf(f, "filter_ssids=%d\n", config->filter_ssids);
+ if (config->filter_rssi)
+ fprintf(f, "filter_rssi=%d\n", config->filter_rssi);
if (config->max_num_sta != DEFAULT_MAX_NUM_STA)
fprintf(f, "max_num_sta=%u\n", config->max_num_sta);
+ if (config->ap_isolate != DEFAULT_AP_ISOLATE)
+ fprintf(f, "ap_isolate=%u\n", config->ap_isolate);
if (config->disassoc_low_ack)
fprintf(f, "disassoc_low_ack=%d\n", config->disassoc_low_ack);
#ifdef CONFIG_HS20
@@ -1191,6 +1336,17 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->access_network_type != DEFAULT_ACCESS_NETWORK_TYPE)
fprintf(f, "access_network_type=%d\n",
config->access_network_type);
+ if (config->go_interworking)
+ fprintf(f, "go_interworking=%d\n", config->go_interworking);
+ if (config->go_access_network_type)
+ fprintf(f, "go_access_network_type=%d\n",
+ config->go_access_network_type);
+ if (config->go_internet)
+ fprintf(f, "go_internet=%d\n", config->go_internet);
+ if (config->go_venue_group)
+ fprintf(f, "go_venue_group=%d\n", config->go_venue_group);
+ if (config->go_venue_type)
+ fprintf(f, "go_venue_type=%d\n", config->go_venue_type);
#endif /* CONFIG_INTERWORKING */
if (config->pbc_in_m1)
fprintf(f, "pbc_in_m1=%d\n", config->pbc_in_m1);
@@ -1226,7 +1382,7 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->sae_groups) {
int i;
fprintf(f, "sae_groups=");
- for (i = 0; config->sae_groups[i] >= 0; i++) {
+ for (i = 0; config->sae_groups[i] > 0; i++) {
fprintf(f, "%s%d", i > 0 ? " " : "",
config->sae_groups[i]);
}
@@ -1264,6 +1420,10 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
fprintf(f, "sched_scan_interval=%u\n",
config->sched_scan_interval);
+ if (config->sched_scan_start_delay)
+ fprintf(f, "sched_scan_start_delay=%u\n",
+ config->sched_scan_start_delay);
+
if (config->external_sim)
fprintf(f, "external_sim=%d\n", config->external_sim);
@@ -1278,6 +1438,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->bgscan)
fprintf(f, "bgscan=\"%s\"\n", config->bgscan);
+ if (config->autoscan)
+ fprintf(f, "autoscan=%s\n", config->autoscan);
+
if (config->p2p_search_delay != DEFAULT_P2P_SEARCH_DELAY)
fprintf(f, "p2p_search_delay=%u\n",
config->p2p_search_delay);
@@ -1335,6 +1498,12 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
fprintf(f, "non_pref_chan=%s\n", config->non_pref_chan);
if (config->mbo_cell_capa != DEFAULT_MBO_CELL_CAPA)
fprintf(f, "mbo_cell_capa=%u\n", config->mbo_cell_capa);
+ if (config->disassoc_imminent_rssi_threshold !=
+ DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD)
+ fprintf(f, "disassoc_imminent_rssi_threshold=%d\n",
+ config->disassoc_imminent_rssi_threshold);
+ if (config->oce != DEFAULT_OCE_SUPPORT)
+ fprintf(f, "oce=%u\n", config->oce);
#endif /* CONFIG_MBO */
if (config->gas_address3)
@@ -1344,6 +1513,37 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
fprintf(f, "ftm_responder=%d\n", config->ftm_responder);
if (config->ftm_initiator)
fprintf(f, "ftm_initiator=%d\n", config->ftm_initiator);
+
+ if (config->osu_dir)
+ fprintf(f, "osu_dir=%s\n", config->osu_dir);
+
+ if (config->fst_group_id)
+ fprintf(f, "fst_group_id=%s\n", config->fst_group_id);
+ if (config->fst_priority)
+ fprintf(f, "fst_priority=%d\n", config->fst_priority);
+ if (config->fst_llt)
+ fprintf(f, "fst_llt=%d\n", config->fst_llt);
+
+ if (config->gas_rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME)
+ fprintf(f, "gas_rand_addr_lifetime=%u\n",
+ config->gas_rand_addr_lifetime);
+ if (config->gas_rand_mac_addr)
+ fprintf(f, "gas_rand_mac_addr=%d\n", config->gas_rand_mac_addr);
+ if (config->dpp_config_processing)
+ fprintf(f, "dpp_config_processing=%d\n",
+ config->dpp_config_processing);
+ if (config->coloc_intf_reporting)
+ fprintf(f, "coloc_intf_reporting=%d\n",
+ config->coloc_intf_reporting);
+ if (config->p2p_device_random_mac_addr)
+ fprintf(f, "p2p_device_random_mac_addr=%d\n",
+ config->p2p_device_random_mac_addr);
+ if (!is_zero_ether_addr(config->p2p_device_persistent_mac_addr))
+ fprintf(f, "p2p_device_persistent_mac_addr=" MACSTR "\n",
+ MAC2STR(config->p2p_device_persistent_mac_addr));
+ if (config->p2p_interface_random_mac_addr)
+ fprintf(f, "p2p_interface_random_mac_addr=%d\n",
+ config->p2p_interface_random_mac_addr);
}
#endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/contrib/wpa/wpa_supplicant/config_ssid.h b/contrib/wpa/wpa_supplicant/config_ssid.h
index 010b594af85e..1b2b1f1a36f1 100644
--- a/contrib/wpa/wpa_supplicant/config_ssid.h
+++ b/contrib/wpa/wpa_supplicant/config_ssid.h
@@ -28,14 +28,18 @@
#define DEFAULT_MESH_RETRY_TIMEOUT 40
#define DEFAULT_MESH_CONFIRM_TIMEOUT 40
#define DEFAULT_MESH_HOLDING_TIMEOUT 40
+#define DEFAULT_MESH_RSSI_THRESHOLD 1 /* no change */
#define DEFAULT_DISABLE_HT 0
#define DEFAULT_DISABLE_HT40 0
#define DEFAULT_DISABLE_SGI 0
#define DEFAULT_DISABLE_LDPC 0
+#define DEFAULT_TX_STBC -1 /* no change */
+#define DEFAULT_RX_STBC -1 /* no change */
#define DEFAULT_DISABLE_MAX_AMSDU -1 /* no change */
#define DEFAULT_AMPDU_FACTOR -1 /* no change */
#define DEFAULT_AMPDU_DENSITY -1 /* no change */
#define DEFAULT_USER_SELECTED_SIM 1
+#define DEFAULT_MAX_OPER_CHWIDTH -1
struct psk_list_entry {
struct dl_list list;
@@ -146,6 +150,19 @@ struct wpa_ssid {
int bssid_set;
/**
+ * bssid_hint - BSSID hint
+ *
+ * If set, this is configured to the driver as a preferred initial BSSID
+ * while connecting to this network.
+ */
+ u8 bssid_hint[ETH_ALEN];
+
+ /**
+ * bssid_hint_set - Whether BSSID hint is configured for this network
+ */
+ int bssid_hint_set;
+
+ /**
* go_p2p_dev_addr - GO's P2P Device Address or all zeros if not set
*/
u8 go_p2p_dev_addr[ETH_ALEN];
@@ -170,6 +187,24 @@ struct wpa_ssid {
char *passphrase;
/**
+ * sae_password - SAE password
+ *
+ * This parameter can be used to set a password for SAE. By default, the
+ * passphrase value is used if this separate parameter is not used, but
+ * passphrase follows the WPA-PSK constraints (8..63 characters) even
+ * though SAE passwords do not have such constraints.
+ */
+ char *sae_password;
+
+ /**
+ * sae_password_id - SAE password identifier
+ *
+ * This parameter can be used to identify a specific SAE password. If
+ * not included, the default SAE password is used instead.
+ */
+ char *sae_password_id;
+
+ /**
* ext_psk - PSK/passphrase name in external storage
*
* If this is set, PSK/passphrase will be fetched from external storage
@@ -196,6 +231,15 @@ struct wpa_ssid {
int group_cipher;
/**
+ * group_mgmt_cipher - Bitfield of allowed group management ciphers
+ *
+ * This is a bitfield of WPA_CIPHER_AES_128_CMAC and WPA_CIPHER_BIP_*
+ * values. If 0, no constraint is used for the cipher, i.e., whatever
+ * the AP uses is accepted.
+ */
+ int group_mgmt_cipher;
+
+ /**
* key_mgmt - Bitfield of allowed key management protocols
*
* WPA_KEY_MGMT_*
@@ -392,17 +436,6 @@ struct wpa_ssid {
int disabled_for_connect;
/**
- * peerkey - Whether PeerKey handshake for direct links is allowed
- *
- * This is only used when both RSN/WPA2 and IEEE 802.11e (QoS) are
- * enabled.
- *
- * 0 = disabled (default)
- * 1 = enabled
- */
- int peerkey;
-
- /**
* id_str - Network identifier string for external scripts
*
* This value is passed to external ctrl_iface monitors in
@@ -427,6 +460,17 @@ struct wpa_ssid {
enum mfp_options ieee80211w;
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+ /**
+ * ocv - Enable/disable operating channel validation
+ *
+ * If this parameter is set to 1, stations will exchange OCI element
+ * to cryptographically verify the operating channel. Setting this
+ * parameter to 0 disables this option. Default value: 0.
+ */
+ int ocv;
+#endif /* CONFIG_OCV */
+
/**
* frequency - Channel frequency in megahertz (MHz) for IBSS
*
@@ -470,12 +514,16 @@ struct wpa_ssid {
int dot11MeshConfirmTimeout; /* msec */
int dot11MeshHoldingTimeout; /* msec */
+ int ht;
int ht40;
int vht;
- u8 max_oper_chwidth;
+ int he;
+ int max_oper_chwidth;
+
+ unsigned int vht_center_freq1;
unsigned int vht_center_freq2;
/**
@@ -650,6 +698,22 @@ struct wpa_ssid {
* By default (empty string): Use whatever the OS has configured.
*/
char *ht_mcs;
+
+ /**
+ * tx_stbc - Indicate STBC support for TX streams
+ *
+ * Value: -1..1, by default (-1): use whatever the OS or card has
+ * configured. See IEEE Std 802.11-2016, 9.4.2.56.2.
+ */
+ int tx_stbc;
+
+ /**
+ * rx_stbc - Indicate STBC support for RX streams
+ *
+ * Value: -1..3, by default (-1): use whatever the OS or card has
+ * configured. See IEEE Std 802.11-2016, 9.4.2.56.2.
+ */
+ int rx_stbc;
#endif /* CONFIG_HT_OVERRIDES */
#ifdef CONFIG_VHT_OVERRIDES
@@ -728,10 +792,100 @@ struct wpa_ssid {
* determine whether to use a secure session or not.
*/
int macsec_policy;
+
+ /**
+ * macsec_integ_only - Determines how MACsec are transmitted
+ *
+ * This setting applies only when MACsec is in use, i.e.,
+ * - macsec_policy is enabled
+ * - the key server has decided to enable MACsec
+ *
+ * 0: Encrypt traffic (default)
+ * 1: Integrity only
+ */
+ int macsec_integ_only;
+
+ /**
+ * macsec_replay_protect - Enable MACsec replay protection
+ *
+ * This setting applies only when MACsec is in use, i.e.,
+ * - macsec_policy is enabled
+ * - the key server has decided to enable MACsec
+ *
+ * 0: Replay protection disabled (default)
+ * 1: Replay protection enabled
+ */
+ int macsec_replay_protect;
+
+ /**
+ * macsec_replay_window - MACsec replay protection window
+ *
+ * A window in which replay is tolerated, to allow receipt of frames
+ * that have been misordered by the network.
+ *
+ * This setting applies only when MACsec replay protection active, i.e.,
+ * - macsec_replay_protect is enabled
+ * - the key server has decided to enable MACsec
+ *
+ * 0: No replay window, strict check (default)
+ * 1..2^32-1: number of packets that could be misordered
+ */
+ u32 macsec_replay_window;
+
+ /**
+ * macsec_port - MACsec port (in SCI)
+ *
+ * Port component of the SCI.
+ *
+ * Range: 1-65534 (default: 1)
+ */
+ int macsec_port;
+
+ /**
+ * mka_priority - Priority of MKA Actor
+ *
+ * Range: 0-255 (default: 255)
+ */
+ int mka_priority;
+
+ /**
+ * mka_ckn - MKA pre-shared CKN
+ */
+#define MACSEC_CKN_MAX_LEN 32
+ size_t mka_ckn_len;
+ u8 mka_ckn[MACSEC_CKN_MAX_LEN];
+
+ /**
+ * mka_cak - MKA pre-shared CAK
+ */
+#define MACSEC_CAK_MAX_LEN 32
+ size_t mka_cak_len;
+ u8 mka_cak[MACSEC_CAK_MAX_LEN];
+
+#define MKA_PSK_SET_CKN BIT(0)
+#define MKA_PSK_SET_CAK BIT(1)
+#define MKA_PSK_SET (MKA_PSK_SET_CKN | MKA_PSK_SET_CAK)
+ /**
+ * mka_psk_set - Whether mka_ckn and mka_cak are set
+ */
+ u8 mka_psk_set;
#endif /* CONFIG_MACSEC */
#ifdef CONFIG_HS20
int update_identifier;
+
+ /**
+ * roaming_consortium_selection - Roaming Consortium Selection
+ *
+ * The matching Roaming Consortium OI that was used to generate this
+ * network profile.
+ */
+ u8 *roaming_consortium_selection;
+
+ /**
+ * roaming_consortium_selection_len - roaming_consortium_selection len
+ */
+ size_t roaming_consortium_selection_len;
#endif /* CONFIG_HS20 */
unsigned int wps_run;
@@ -758,12 +912,99 @@ struct wpa_ssid {
int no_auto_peer;
/**
+ * mesh_rssi_threshold - Set mesh parameter mesh_rssi_threshold (dBm)
+ *
+ * -255..-1 = threshold value in dBm
+ * 0 = not using RSSI threshold
+ * 1 = do not change driver default
+ */
+ int mesh_rssi_threshold;
+
+ /**
* wps_disabled - WPS disabled in AP mode
*
* 0 = WPS enabled and configured (default)
* 1 = WPS disabled
*/
int wps_disabled;
+
+ /**
+ * fils_dh_group - FILS DH Group
+ *
+ * 0 = PFS disabled with FILS shared key authentication
+ * 1-65535 DH Group to use for FILS PFS
+ */
+ int fils_dh_group;
+
+ /**
+ * dpp_connector - DPP Connector (signedConnector as string)
+ */
+ char *dpp_connector;
+
+ /**
+ * dpp_netaccesskey - DPP netAccessKey (own private key)
+ */
+ u8 *dpp_netaccesskey;
+
+ /**
+ * dpp_netaccesskey_len - DPP netAccessKey length in octets
+ */
+ size_t dpp_netaccesskey_len;
+
+ /**
+ * net_access_key_expiry - DPP netAccessKey expiry in UNIX time stamp
+ *
+ * 0 indicates no expiration.
+ */
+ unsigned int dpp_netaccesskey_expiry;
+
+ /**
+ * dpp_csign - C-sign-key (Configurator public key)
+ */
+ u8 *dpp_csign;
+
+ /**
+ * dpp_csign_len - C-sign-key length in octets
+ */
+ size_t dpp_csign_len;
+
+ /**
+ * owe_group - OWE DH Group
+ *
+ * 0 = use default (19) first and then try all supported groups one by
+ * one if AP rejects the selected group
+ * 1-65535 DH Group to use for OWE
+ *
+ * Groups 19 (NIST P-256), 20 (NIST P-384), and 21 (NIST P-521) are
+ * currently supported.
+ */
+ int owe_group;
+
+ /**
+ * owe_only - OWE-only mode (disable transition mode)
+ *
+ * 0 = enable transition mode (allow connection to either OWE or open
+ * BSS)
+ * 1 = disable transition mode (allow connection only with OWE)
+ */
+ int owe_only;
+
+ /**
+ * owe_transition_bss_select_count - OWE transition BSS select count
+ *
+ * This is an internally used variable (i.e., not used in external
+ * configuration) to track the number of selection attempts done for
+ * OWE BSS in transition mode. This allows fallback to an open BSS if
+ * the selection attempts for OWE BSS exceed the configured threshold.
+ */
+ int owe_transition_bss_select_count;
+
+ /**
+ * multi_ap_backhaul_sta - Multi-AP backhaul STA
+ * 0 = normal (non-Multi-AP) station
+ * 1 = Multi-AP backhaul station
+ */
+ int multi_ap_backhaul_sta;
};
#endif /* CONFIG_SSID_H */
diff --git a/contrib/wpa/wpa_supplicant/ctrl_iface.c b/contrib/wpa/wpa_supplicant/ctrl_iface.c
index d814fdf7fd2d..198ac562d8b6 100644
--- a/contrib/wpa/wpa_supplicant/ctrl_iface.c
+++ b/contrib/wpa/wpa_supplicant/ctrl_iface.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant / Control interface (shared code for all backends)
- * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -20,6 +20,9 @@
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/wpa_ctrl.h"
+#ifdef CONFIG_DPP
+#include "common/dpp.h"
+#endif /* CONFIG_DPP */
#include "crypto/tls.h"
#include "ap/hostapd.h"
#include "eap_peer/eap.h"
@@ -52,6 +55,8 @@
#include "offchannel.h"
#include "drivers/driver.h"
#include "mesh.h"
+#include "dpp_supplicant.h"
+#include "sme.h"
static int wpa_supplicant_global_iface_list(struct wpa_global *global,
char *buf, int len);
@@ -61,6 +66,7 @@ static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
char *val);
+
static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
{
char *pos;
@@ -339,6 +345,75 @@ static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s,
}
+static int
+wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ int relative_rssi;
+
+ if (os_strcmp(cmd, "disable") == 0) {
+ wpa_s->srp.relative_rssi_set = 0;
+ return 0;
+ }
+
+ relative_rssi = atoi(cmd);
+ if (relative_rssi < 0 || relative_rssi > 100)
+ return -1;
+ wpa_s->srp.relative_rssi = relative_rssi;
+ wpa_s->srp.relative_rssi_set = 1;
+ return 0;
+}
+
+
+static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ char *pos;
+ int adjust_rssi;
+
+ /* <band>:adjust_value */
+ pos = os_strchr(cmd, ':');
+ if (!pos)
+ return -1;
+ pos++;
+ adjust_rssi = atoi(pos);
+ if (adjust_rssi < -100 || adjust_rssi > 100)
+ return -1;
+
+ if (os_strncmp(cmd, "2G", 2) == 0)
+ wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G;
+ else if (os_strncmp(cmd, "5G", 2) == 0)
+ wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G;
+ else
+ return -1;
+
+ wpa_s->srp.relative_adjust_rssi = adjust_rssi;
+
+ return 0;
+}
+
+
+static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ struct wpabuf *ric_ies;
+
+ if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
+ wpabuf_free(wpa_s->ric_ies);
+ wpa_s->ric_ies = NULL;
+ return 0;
+ }
+
+ ric_ies = wpabuf_parse_bin(cmd);
+ if (!ric_ies)
+ return -1;
+
+ wpabuf_free(wpa_s->ric_ies);
+ wpa_s->ric_ies = ric_ies;
+
+ return 0;
+}
+
+
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
char *cmd)
{
@@ -365,16 +440,29 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
-1, -1, -1, atoi(value));
} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
- atoi(value)))
+ atoi(value))) {
ret = -1;
+ } else {
+ value[-1] = '=';
+ wpa_config_process_global(wpa_s->conf, cmd, -1);
+ }
} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
0) {
if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
- atoi(value)))
+ atoi(value))) {
ret = -1;
+ } else {
+ value[-1] = '=';
+ wpa_config_process_global(wpa_s->conf, cmd, -1);
+ }
} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
- if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
+ if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
+ atoi(value))) {
ret = -1;
+ } else {
+ value[-1] = '=';
+ wpa_config_process_global(wpa_s->conf, cmd, -1);
+ }
} else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
wpa_s->wps_fragment_size = atoi(value);
#ifdef CONFIG_WPS_TESTING
@@ -494,6 +582,59 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
ret = set_disallow_aps(wpa_s, value);
} else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
wpa_s->no_keep_alive = !!atoi(value);
+#ifdef CONFIG_DPP
+ } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) {
+ os_free(wpa_s->dpp_configurator_params);
+ wpa_s->dpp_configurator_params = os_strdup(value);
+ } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) {
+ wpa_s->dpp_init_max_tries = atoi(value);
+ } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) {
+ wpa_s->dpp_init_retry_time = atoi(value);
+ } else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
+ wpa_s->dpp_resp_wait_time = atoi(value);
+ } else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) {
+ wpa_s->dpp_resp_max_tries = atoi(value);
+ } else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) {
+ wpa_s->dpp_resp_retry_time = atoi(value);
+#ifdef CONFIG_TESTING_OPTIONS
+ } else if (os_strcasecmp(cmd, "dpp_pkex_own_mac_override") == 0) {
+ if (hwaddr_aton(value, dpp_pkex_own_mac_override))
+ ret = -1;
+ } else if (os_strcasecmp(cmd, "dpp_pkex_peer_mac_override") == 0) {
+ if (hwaddr_aton(value, dpp_pkex_peer_mac_override))
+ ret = -1;
+ } else if (os_strcasecmp(cmd, "dpp_pkex_ephemeral_key_override") == 0) {
+ size_t hex_len = os_strlen(value);
+
+ if (hex_len >
+ 2 * sizeof(dpp_pkex_ephemeral_key_override))
+ ret = -1;
+ else if (hexstr2bin(value, dpp_pkex_ephemeral_key_override,
+ hex_len / 2))
+ ret = -1;
+ else
+ dpp_pkex_ephemeral_key_override_len = hex_len / 2;
+ } else if (os_strcasecmp(cmd, "dpp_protocol_key_override") == 0) {
+ size_t hex_len = os_strlen(value);
+
+ if (hex_len > 2 * sizeof(dpp_protocol_key_override))
+ ret = -1;
+ else if (hexstr2bin(value, dpp_protocol_key_override,
+ hex_len / 2))
+ ret = -1;
+ else
+ dpp_protocol_key_override_len = hex_len / 2;
+ } else if (os_strcasecmp(cmd, "dpp_nonce_override") == 0) {
+ size_t hex_len = os_strlen(value);
+
+ if (hex_len > 2 * sizeof(dpp_nonce_override))
+ ret = -1;
+ else if (hexstr2bin(value, dpp_nonce_override, hex_len / 2))
+ ret = -1;
+ else
+ dpp_nonce_override_len = hex_len / 2;
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_DPP */
#ifdef CONFIG_TESTING_OPTIONS
} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
wpa_s->ext_mgmt_frame_handling = !!atoi(value);
@@ -515,9 +656,54 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
wpa_s->ignore_auth_resp = !!atoi(value);
} else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) {
wpa_s->ignore_assoc_disallow = !!atoi(value);
+ wpa_drv_ignore_assoc_disallow(wpa_s,
+ wpa_s->ignore_assoc_disallow);
} else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
wpa_s->reject_btm_req_reason = atoi(value);
+ } else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) {
+ os_free(wpa_s->get_pref_freq_list_override);
+ if (!value[0])
+ wpa_s->get_pref_freq_list_override = NULL;
+ else
+ wpa_s->get_pref_freq_list_override = os_strdup(value);
+ } else if (os_strcasecmp(cmd, "sae_commit_override") == 0) {
+ wpabuf_free(wpa_s->sae_commit_override);
+ if (value[0] == '\0')
+ wpa_s->sae_commit_override = NULL;
+ else
+ wpa_s->sae_commit_override = wpabuf_parse_bin(value);
+#ifdef CONFIG_DPP
+ } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
+ os_free(wpa_s->dpp_config_obj_override);
+ if (value[0] == '\0')
+ wpa_s->dpp_config_obj_override = NULL;
+ else
+ wpa_s->dpp_config_obj_override = os_strdup(value);
+ } else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) {
+ os_free(wpa_s->dpp_discovery_override);
+ if (value[0] == '\0')
+ wpa_s->dpp_discovery_override = NULL;
+ else
+ wpa_s->dpp_discovery_override = os_strdup(value);
+ } else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) {
+ os_free(wpa_s->dpp_groups_override);
+ if (value[0] == '\0')
+ wpa_s->dpp_groups_override = NULL;
+ else
+ wpa_s->dpp_groups_override = os_strdup(value);
+ } else if (os_strcasecmp(cmd,
+ "dpp_ignore_netaccesskey_mismatch") == 0) {
+ wpa_s->dpp_ignore_netaccesskey_mismatch = atoi(value);
+ } else if (os_strcasecmp(cmd, "dpp_test") == 0) {
+ dpp_test = atoi(value);
+#endif /* CONFIG_DPP */
#endif /* CONFIG_TESTING_OPTIONS */
+#ifdef CONFIG_FILS
+ } else if (os_strcasecmp(cmd, "disable_fils") == 0) {
+ wpa_s->disable_fils = !!atoi(value);
+ wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils);
+ wpa_supplicant_set_default_scan_ies(wpa_s);
+#endif /* CONFIG_FILS */
#ifndef CONFIG_NO_CONFIG_BLOBS
} else if (os_strcmp(cmd, "blob") == 0) {
ret = wpas_ctrl_set_blob(wpa_s, value);
@@ -527,11 +713,53 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_MBO
} else if (os_strcasecmp(cmd, "non_pref_chan") == 0) {
ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
+ if (ret == 0) {
+ value[-1] = '=';
+ wpa_config_process_global(wpa_s->conf, cmd, -1);
+ }
} else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
wpas_mbo_update_cell_capa(wpa_s, atoi(value));
+ } else if (os_strcasecmp(cmd, "oce") == 0) {
+ wpa_s->conf->oce = atoi(value);
+ if (wpa_s->conf->oce) {
+ if ((wpa_s->conf->oce & OCE_STA) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
+ wpa_s->enable_oce = OCE_STA;
+
+ if ((wpa_s->conf->oce & OCE_STA_CFON) &&
+ (wpa_s->drv_flags &
+ WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
+ /* TODO: Need to add STA-CFON support */
+ wpa_printf(MSG_ERROR,
+ "OCE STA-CFON feature is not yet supported");
+ return -1;
+ }
+ } else {
+ wpa_s->enable_oce = 0;
+ }
+ wpa_supplicant_set_default_scan_ies(wpa_s);
#endif /* CONFIG_MBO */
} else if (os_strcasecmp(cmd, "lci") == 0) {
ret = wpas_ctrl_iface_set_lci(wpa_s, value);
+ } else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) {
+ ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value));
+ } else if (os_strcasecmp(cmd, "relative_rssi") == 0) {
+ ret = wpas_ctrl_set_relative_rssi(wpa_s, value);
+ } else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) {
+ ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value);
+ } else if (os_strcasecmp(cmd, "ric_ies") == 0) {
+ ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
+ } else if (os_strcasecmp(cmd, "roaming") == 0) {
+ ret = wpa_drv_roaming(wpa_s, atoi(value), NULL);
+#ifdef CONFIG_WNM
+ } else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) {
+ struct wpabuf *elems;
+
+ elems = wpabuf_parse_bin(value);
+ if (!elems)
+ return -1;
+ wnm_set_coloc_intf_elems(wpa_s, elems);
+#endif /* CONFIG_WNM */
} else {
value[-1] = '=';
ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
@@ -577,6 +805,12 @@ static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_TESTING_GET_GTK */
} else if (os_strcmp(cmd, "tls_library") == 0) {
res = tls_get_library_version(buf, buflen);
+#ifdef CONFIG_TESTING_OPTIONS
+ } else if (os_strcmp(cmd, "anonce") == 0) {
+ return wpa_snprintf_hex(buf, buflen,
+ wpa_sm_get_anonce(wpa_s->wpa),
+ WPA_NONCE_LEN);
+#endif /* CONFIG_TESTING_OPTIONS */
} else {
res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
}
@@ -610,27 +844,6 @@ static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
#endif /* IEEE8021X_EAPOL */
-#ifdef CONFIG_PEERKEY
-/* MLME-STKSTART.request(peer) */
-static int wpa_supplicant_ctrl_iface_stkstart(
- struct wpa_supplicant *wpa_s, char *addr)
-{
- u8 peer[ETH_ALEN];
-
- if (hwaddr_aton(addr, peer)) {
- wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
- "address '%s'", addr);
- return -1;
- }
-
- wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
- MAC2STR(peer));
-
- return wpa_sm_stkstart(wpa_s->wpa, peer);
-}
-#endif /* CONFIG_PEERKEY */
-
-
#ifdef CONFIG_TDLS
static int wpa_supplicant_ctrl_iface_tdls_discover(
@@ -955,8 +1168,11 @@ static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_AP
u8 *_p2p_dev_addr = NULL;
#endif /* CONFIG_AP */
+ char *pos;
+ int multi_ap = 0;
- if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
+ if (!cmd || os_strcmp(cmd, "any") == 0 ||
+ os_strncmp(cmd, "any ", 4) == 0) {
_bssid = NULL;
#ifdef CONFIG_P2P
} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
@@ -968,18 +1184,29 @@ static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
}
_p2p_dev_addr = p2p_dev_addr;
#endif /* CONFIG_P2P */
+ } else if (os_strncmp(cmd, "multi_ap=", 9) == 0) {
+ _bssid = NULL;
+ multi_ap = atoi(cmd + 9);
} else if (hwaddr_aton(cmd, bssid)) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
cmd);
return -1;
}
+ if (cmd) {
+ pos = os_strstr(cmd, " multi_ap=");
+ if (pos) {
+ pos += 10;
+ multi_ap = atoi(pos);
+ }
+ }
+
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
#endif /* CONFIG_AP */
- return wpas_wps_start_pbc(wpa_s, _bssid, 0);
+ return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap);
}
@@ -1905,6 +2132,18 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
pos += ret;
}
+ if (wpa_s->connection_set &&
+ (wpa_s->connection_ht || wpa_s->connection_vht ||
+ wpa_s->connection_he)) {
+ ret = os_snprintf(pos, end - pos,
+ "wifi_generation=%u\n",
+ wpa_s->connection_he ? 6 :
+ (wpa_s->connection_vht ? 5 : 4));
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+
#ifdef CONFIG_AP
if (wpa_s->ap_iface) {
pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
@@ -1914,6 +2153,7 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_AP */
pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
}
+#ifdef CONFIG_SME
#ifdef CONFIG_SAE
if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
#ifdef CONFIG_AP
@@ -1927,6 +2167,7 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
pos += ret;
}
#endif /* CONFIG_SAE */
+#endif /* CONFIG_SME */
ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
wpa_supplicant_state_txt(wpa_s->wpa_state));
if (os_snprintf_error(end - pos, ret))
@@ -2048,6 +2289,12 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
pos += res;
}
+#ifdef CONFIG_MACSEC
+ res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos);
+ if (res > 0)
+ pos += res;
+#endif /* CONFIG_MACSEC */
+
sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
if (sess_id) {
char *start = pos;
@@ -2081,6 +2328,13 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_WPS */
+ if (wpa_s->ieee80211ac) {
+ ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+
#ifdef ANDROID
/*
* Allow using the STATUS command with default behavior, say for debug,
@@ -2437,6 +2691,59 @@ static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
}
#endif /* CONFIG_SUITEB192 */
+#ifdef CONFIG_FILS
+ if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
+ ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+ if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
+ ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+#ifdef CONFIG_IEEE80211R
+ if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
+ ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+ if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
+ ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_OWE
+ if (data.key_mgmt & WPA_KEY_MGMT_OWE) {
+ ret = os_snprintf(pos, end - pos, "%sOWE",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+#endif /* CONFIG_OWE */
+
+#ifdef CONFIG_DPP
+ if (data.key_mgmt & WPA_KEY_MGMT_DPP) {
+ ret = os_snprintf(pos, end - pos, "%sDPP",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+#endif /* CONFIG_DPP */
+
if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
ret = os_snprintf(pos, end - pos, "%sOSEN",
pos == start ? "" : "+");
@@ -2512,7 +2819,7 @@ static int wpa_supplicant_ctrl_iface_scan_result(
{
char *pos, *end;
int ret;
- const u8 *ie, *ie2, *osen_ie, *p2p, *mesh;
+ const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe;
mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
@@ -2543,6 +2850,14 @@ static int wpa_supplicant_ctrl_iface_scan_result(
if (osen_ie)
pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
osen_ie, 2 + osen_ie[1]);
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+ if (owe) {
+ ret = os_snprintf(pos, end - pos,
+ ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
ret = os_snprintf(pos, end - pos, "[WEP]");
@@ -2608,6 +2923,14 @@ static int wpa_supplicant_ctrl_iface_scan_result(
pos += ret;
}
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_FILS
+ if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
+ ret = os_snprintf(pos, end - pos, "[FILS]");
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
+#endif /* CONFIG_FILS */
#ifdef CONFIG_FST
if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
ret = os_snprintf(pos, end - pos, "[FST]");
@@ -2616,6 +2939,12 @@ static int wpa_supplicant_ctrl_iface_scan_result(
pos += ret;
}
#endif /* CONFIG_FST */
+ if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
+ ret = os_snprintf(pos, end - pos, "[UTF-8]");
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
ret = os_snprintf(pos, end - pos, "\t%s",
wpa_ssid_txt(bss->ssid, bss->ssid_len));
@@ -2835,9 +3164,8 @@ static int wpa_supplicant_ctrl_iface_select_network(
if (pos) {
int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
if (freqs) {
- wpa_s->scan_req = MANUAL_SCAN_REQ;
- os_free(wpa_s->manual_scan_freqs);
- wpa_s->manual_scan_freqs = freqs;
+ os_free(wpa_s->select_network_scan_freqs);
+ wpa_s->select_network_scan_freqs = freqs;
}
}
@@ -3012,6 +3340,7 @@ static int wpa_supplicant_ctrl_iface_update_network(
return 0; /* No change to the previously configured value */
if (os_strcmp(name, "bssid") != 0 &&
+ os_strcmp(name, "bssid_hint") != 0 &&
os_strcmp(name, "priority") != 0) {
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
@@ -3647,6 +3976,66 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
pos += ret;
}
#endif /* CONFIG_SUITEB192 */
+#ifdef CONFIG_OWE
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
+ ret = os_snprintf(pos, end - pos, " OWE");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_OWE */
+#ifdef CONFIG_DPP
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
+ ret = os_snprintf(pos, end - pos, " DPP");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_DPP */
+#ifdef CONFIG_FILS
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) {
+ ret = os_snprintf(pos, end - pos, " FILS-SHA256");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) {
+ ret = os_snprintf(pos, end - pos, " FILS-SHA384");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#ifdef CONFIG_IEEE80211R
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) {
+ ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) {
+ ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211R
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) {
+ ret = os_snprintf(pos, end - pos, " FT-PSK");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_SAE
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) {
+ ret = os_snprintf(pos, end - pos, " SAE");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_SAE */
return pos - buf;
}
@@ -3749,6 +4138,26 @@ static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_SAE */
+#ifdef CONFIG_FILS
+ if (wpa_is_fils_supported(wpa_s)) {
+ ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+
+#ifdef CONFIG_FILS_SK_PFS
+ if (wpa_is_fils_sk_pfs_supported(wpa_s)) {
+ ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_FILS_SK_PFS */
+#endif /* CONFIG_FILS */
+
return pos - buf;
}
@@ -4006,6 +4415,47 @@ static int wpa_supplicant_ctrl_iface_get_capability(
}
#endif /* CONFIG_ACS */
+#ifdef CONFIG_FILS
+ if (os_strcmp(field, "fils") == 0) {
+#ifdef CONFIG_FILS_SK_PFS
+ if (wpa_is_fils_supported(wpa_s) &&
+ wpa_is_fils_sk_pfs_supported(wpa_s)) {
+ res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS");
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ }
+#endif /* CONFIG_FILS_SK_PFS */
+
+ if (wpa_is_fils_supported(wpa_s)) {
+ res = os_snprintf(buf, buflen, "FILS");
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ }
+ }
+#endif /* CONFIG_FILS */
+
+ if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) {
+ res = os_snprintf(buf, buflen, "MULTIBSS-STA");
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ }
+
+#ifdef CONFIG_DPP
+ if (os_strcmp(field, "dpp") == 0) {
+#ifdef CONFIG_DPP2
+ res = os_snprintf(buf, buflen, "DPP=2");
+#else /* CONFIG_DPP2 */
+ res = os_snprintf(buf, buflen, "DPP=1");
+#endif /* CONFIG_DPP2 */
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ }
+#endif /* CONFIG_DPP */
+
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
field);
@@ -4048,13 +4498,85 @@ static char * anqp_add_hex(char *pos, char *end, const char *title,
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_FILS
+static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end)
+{
+ char *start = pos;
+ const u8 *ie, *ie_end;
+ u16 info, realms;
+ int ret;
+
+ ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
+ if (!ie)
+ return 0;
+ ie_end = ie + 2 + ie[1];
+ ie += 2;
+ if (ie_end - ie < 2)
+ return -1;
+
+ info = WPA_GET_LE16(ie);
+ ie += 2;
+ ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info);
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+
+ if (info & BIT(7)) {
+ /* Cache Identifier Included */
+ if (ie_end - ie < 2)
+ return -1;
+ ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n",
+ ie[0], ie[1]);
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ ie += 2;
+ }
+
+ if (info & BIT(8)) {
+ /* HESSID Included */
+ if (ie_end - ie < ETH_ALEN)
+ return -1;
+ ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n",
+ MAC2STR(ie));
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ ie += ETH_ALEN;
+ }
+
+ realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3;
+ if (realms) {
+ if (ie_end - ie < realms * 2)
+ return -1;
+ ret = os_snprintf(pos, end - pos, "fils_realms=");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+
+ ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2);
+ if (ret <= 0)
+ return 0;
+ pos += ret;
+ ie += realms * 2;
+ ret = os_snprintf(pos, end - pos, "\n");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+
+ return pos - start;
+}
+#endif /* CONFIG_FILS */
+
+
static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
unsigned long mask, char *buf, size_t buflen)
{
size_t i;
int ret;
char *pos, *end;
- const u8 *ie, *ie2, *osen_ie;
+ const u8 *ie, *ie2, *osen_ie, *mesh, *owe;
pos = buf;
end = buf + buflen;
@@ -4163,18 +4685,30 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
return 0;
pos += ret;
+ mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
+
ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
if (ie)
pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
2 + ie[1]);
ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
if (ie2)
- pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
+ pos = wpa_supplicant_ie_txt(pos, end,
+ mesh ? "RSN" : "WPA2", ie2,
2 + ie2[1]);
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
if (osen_ie)
pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
osen_ie, 2 + osen_ie[1]);
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+ if (owe) {
+ ret = os_snprintf(
+ pos, end - pos,
+ ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
if (!ie && !ie2 && !osen_ie &&
(bss->caps & IEEE80211_CAP_PRIVACY)) {
@@ -4183,6 +4717,14 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
return 0;
pos += ret;
}
+
+ if (mesh) {
+ ret = os_snprintf(pos, end - pos, "[MESH]");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+
if (bss_is_dmg(bss)) {
const char *s;
ret = os_snprintf(pos, end - pos, "[DMG]");
@@ -4236,6 +4778,28 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
pos += ret;
}
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_FILS
+ if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
+ ret = os_snprintf(pos, end - pos, "[FILS]");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_FST
+ if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
+ ret = os_snprintf(pos, end - pos, "[FST]");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+#endif /* CONFIG_FST */
+ if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
+ ret = os_snprintf(pos, end - pos, "[UTF-8]");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
ret = os_snprintf(pos, end - pos, "\n");
if (os_snprintf_error(end - pos, ret))
@@ -4320,6 +4884,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
pos = anqp_add_hex(pos, end, "anqp_domain_name",
anqp->domain_name);
+ pos = anqp_add_hex(pos, end, "anqp_fils_realm_info",
+ anqp->fils_realm_info);
#ifdef CONFIG_HS20
pos = anqp_add_hex(pos, end, "hs20_capability_list",
anqp->hs20_capability_list);
@@ -4333,6 +4899,10 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
anqp->hs20_operating_class);
pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
anqp->hs20_osu_providers_list);
+ pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata",
+ anqp->hs20_operator_icon_metadata);
+ pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list",
+ anqp->hs20_osu_providers_nai_list);
#endif /* CONFIG_HS20 */
dl_list_for_each(elem, &anqp->anqp_elems,
@@ -4381,6 +4951,44 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
}
#endif /* CONFIG_FST */
+ if (mask & WPA_BSS_MASK_UPDATE_IDX) {
+ ret = os_snprintf(pos, end - pos, "update_idx=%u\n",
+ bss->last_update_idx);
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+
+ if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) {
+ ret = os_snprintf(pos, end - pos, "beacon_ie=");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+
+ ie = (const u8 *) (bss + 1);
+ ie += bss->ie_len;
+ for (i = 0; i < bss->beacon_ie_len; i++) {
+ ret = os_snprintf(pos, end - pos, "%02x", *ie++);
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+
+ ret = os_snprintf(pos, end - pos, "\n");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+
+#ifdef CONFIG_FILS
+ if (mask & WPA_BSS_MASK_FILS_INDICATION) {
+ ret = print_fils_indication(bss, pos, end);
+ if (ret < 0)
+ return 0;
+ pos += ret;
+ }
+#endif /* CONFIG_FILS */
+
if (mask & WPA_BSS_MASK_DELIM) {
ret = os_snprintf(pos, end - pos, "====\n");
if (os_snprintf_error(end - pos, ret))
@@ -4471,6 +5079,8 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
bss = dl_list_entry(next, struct wpa_bss,
list_id);
}
+ } else if (os_strncmp(cmd, "CURRENT", 7) == 0) {
+ bss = wpa_s->current_bss;
#ifdef CONFIG_P2P
} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
if (hwaddr_aton(cmd + 13, bssid) == 0)
@@ -4486,10 +5096,11 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
bss = NULL;
dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
{
- if (i-- == 0) {
+ if (i == 0) {
bss = tmp;
break;
}
+ i--;
}
}
@@ -4975,6 +5586,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
size_t group_ssid_len = 0;
+ int he;
if (!wpa_s->global->p2p_init_wpa_s)
return -1;
@@ -4987,7 +5599,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
* [persistent|persistent=<network id>]
* [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
- * [ht40] [vht] [auto] [ssid=<hexdump>] */
+ * [ht40] [vht] [he] [auto] [ssid=<hexdump>] */
if (hwaddr_aton(cmd, addr))
return -1;
@@ -5018,6 +5630,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
vht;
+ he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
pos2 = os_strstr(pos, " go_intent=");
if (pos2) {
@@ -5088,7 +5701,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
persistent_group, automatic, join,
auth, go_intent, freq, freq2, persistent_id,
- pd, ht40, vht, max_oper_chwidth,
+ pd, ht40, vht, max_oper_chwidth, he,
group_ssid, group_ssid_len);
if (new_pin == -2) {
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
@@ -5644,7 +6257,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
struct wpa_ssid *ssid;
u8 *_peer = NULL, peer[ETH_ALEN];
int freq = 0, pref_freq = 0;
- int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
+ int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
id = atoi(cmd);
pos = os_strstr(cmd, " peer=");
@@ -5681,6 +6294,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
vht;
+ he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
pos = os_strstr(cmd, "freq2=");
if (pos)
@@ -5695,7 +6309,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
return -1;
return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
- max_oper_chwidth, pref_freq);
+ max_oper_chwidth, pref_freq, he);
}
@@ -5743,7 +6357,8 @@ static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
int id, int freq, int vht_center_freq2,
- int ht40, int vht, int vht_chwidth)
+ int ht40, int vht, int vht_chwidth,
+ int he)
{
struct wpa_ssid *ssid;
@@ -5757,7 +6372,7 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
vht_center_freq2, 0, ht40, vht,
- vht_chwidth, NULL, 0, 0);
+ vht_chwidth, he, NULL, 0, 0);
}
@@ -5766,20 +6381,31 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
int freq = 0, persistent = 0, group_id = -1;
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+ int he = wpa_s->conf->p2p_go_he;
int max_oper_chwidth, chwidth = 0, freq2 = 0;
char *token, *context = NULL;
+#ifdef CONFIG_ACS
+ int acs = 0;
+#endif /* CONFIG_ACS */
while ((token = str_token(cmd, " ", &context))) {
- if (sscanf(token, "freq=%d", &freq) == 1 ||
- sscanf(token, "freq2=%d", &freq2) == 1 ||
+ if (sscanf(token, "freq2=%d", &freq2) == 1 ||
sscanf(token, "persistent=%d", &group_id) == 1 ||
sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
continue;
+#ifdef CONFIG_ACS
+ } else if (os_strcmp(token, "freq=acs") == 0) {
+ acs = 1;
+#endif /* CONFIG_ACS */
+ } else if (sscanf(token, "freq=%d", &freq) == 1) {
+ continue;
} else if (os_strcmp(token, "ht40") == 0) {
ht40 = 1;
} else if (os_strcmp(token, "vht") == 0) {
vht = 1;
ht40 = 1;
+ } else if (os_strcmp(token, "he") == 0) {
+ he = 1;
} else if (os_strcmp(token, "persistent") == 0) {
persistent = 1;
} else {
@@ -5790,6 +6416,26 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
}
}
+#ifdef CONFIG_ACS
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
+ (acs || freq == 2 || freq == 5)) {
+ if (freq == 2 && wpa_s->best_24_freq <= 0) {
+ wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G;
+ wpa_s->p2p_go_do_acs = 1;
+ freq = 0;
+ } else if (freq == 5 && wpa_s->best_5_freq <= 0) {
+ wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A;
+ wpa_s->p2p_go_do_acs = 1;
+ freq = 0;
+ } else {
+ wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY;
+ wpa_s->p2p_go_do_acs = 1;
+ }
+ } else {
+ wpa_s->p2p_go_do_acs = 0;
+ }
+#endif /* CONFIG_ACS */
+
max_oper_chwidth = parse_freq(chwidth, freq2);
if (max_oper_chwidth < 0)
return -1;
@@ -5797,10 +6443,10 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
if (group_id >= 0)
return p2p_ctrl_group_add_persistent(wpa_s, group_id,
freq, freq2, ht40, vht,
- max_oper_chwidth);
+ max_oper_chwidth, he);
return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
- max_oper_chwidth);
+ max_oper_chwidth, he);
}
@@ -5827,10 +6473,24 @@ static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd,
}
+static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global,
+ const u8 *p2p_dev_addr)
+{
+ struct wpa_supplicant *wpa_s;
+
+ for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+ if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr))
+ return 1;
+ }
+
+ return 0;
+}
+
+
static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
char *buf, size_t buflen)
{
- u8 addr[ETH_ALEN], *addr_ptr;
+ u8 addr[ETH_ALEN], *addr_ptr, group_capab;
int next, res;
const struct p2p_peer_info *info;
char *pos, *end;
@@ -5859,6 +6519,16 @@ static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
if (info == NULL)
return -1;
+ group_capab = info->group_capab;
+
+ if (group_capab &&
+ !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) {
+ wpa_printf(MSG_DEBUG,
+ "P2P: Could not find any BSS with p2p_dev_addr "
+ MACSTR ", hence override group_capab from 0x%x to 0",
+ MAC2STR(info->p2p_device_addr), group_capab);
+ group_capab = 0;
+ }
pos = buf;
end = buf + buflen;
@@ -5884,7 +6554,7 @@ static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
info->serial_number,
info->config_methods,
info->dev_capab,
- info->group_capab,
+ group_capab,
info->level);
if (os_snprintf_error(end - pos, res))
return pos - buf;
@@ -6165,6 +6835,20 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
return 0;
}
+ if (os_strcmp(cmd, "override_pref_op_chan") == 0) {
+ int op_class, chan;
+
+ op_class = atoi(param);
+ param = os_strchr(param, ':');
+ if (!param)
+ return -1;
+ param++;
+ chan = atoi(param);
+ p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class,
+ chan);
+ return 0;
+ }
+
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
cmd);
@@ -6176,6 +6860,12 @@ static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
{
os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
wpa_s->force_long_sd = 0;
+
+#ifdef CONFIG_TESTING_OPTIONS
+ os_free(wpa_s->get_pref_freq_list_override);
+ wpa_s->get_pref_freq_list_override = NULL;
+#endif /* CONFIG_TESTING_OPTIONS */
+
wpas_p2p_stop_find(wpa_s);
wpa_s->parent->p2ps_method_config_any = 0;
if (wpa_s->global->p2p)
@@ -6383,7 +7073,7 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
u16 id[MAX_ANQP_INFO_ID];
size_t num_id = 0;
u32 subtypes = 0;
- int get_cell_pref = 0;
+ u32 mbo_subtypes = 0;
used = hwaddr_aton2(dst, dst_addr);
if (used < 0)
@@ -6404,9 +7094,10 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
} else if (os_strncmp(pos, "mbo:", 4) == 0) {
#ifdef CONFIG_MBO
int num = atoi(pos + 4);
- if (num != MBO_ANQP_SUBTYPE_CELL_CONN_PREF)
+
+ if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE)
return -1;
- get_cell_pref = 1;
+ mbo_subtypes |= BIT(num);
#else /* CONFIG_MBO */
return -1;
#endif /* CONFIG_MBO */
@@ -6421,11 +7112,11 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
pos++;
}
- if (num_id == 0)
+ if (num_id == 0 && !subtypes && !mbo_subtypes)
return -1;
return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes,
- get_cell_pref);
+ mbo_subtypes);
}
@@ -6762,6 +7453,9 @@ static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
autoscan_init(wpa_s, 1);
else if (state == WPA_SCANNING)
wpa_supplicant_reinit_autoscan(wpa_s);
+ else
+ wpa_printf(MSG_DEBUG, "No autoscan update in state %s",
+ wpa_supplicant_state_txt(state));
return 0;
}
@@ -6824,26 +7518,41 @@ static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
{
int query_reason, list = 0;
+ char *btm_candidates = NULL;
query_reason = atoi(cmd);
cmd = os_strchr(cmd, ' ');
if (cmd) {
- cmd++;
- if (os_strncmp(cmd, "list", 4) == 0) {
+ if (os_strncmp(cmd, " list", 5) == 0)
list = 1;
- } else {
- wpa_printf(MSG_DEBUG, "WNM Query: Invalid option %s",
- cmd);
- return -1;
- }
+ else
+ btm_candidates = cmd;
}
wpa_printf(MSG_DEBUG,
"CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s",
query_reason, list ? " candidate list" : "");
- return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, list);
+ return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason,
+ btm_candidates,
+ list);
+}
+
+
+static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ struct wpabuf *elems;
+ int ret;
+
+ elems = wpabuf_parse_bin(cmd);
+ if (!elems)
+ return -1;
+
+ ret = wnm_send_coloc_intf_report(wpa_s, 0, elems);
+ wpabuf_free(elems);
+ return ret;
}
#endif /* CONFIG_WNM */
@@ -6879,10 +7588,17 @@ static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
pos += ret;
}
- if (si.center_frq1 > 0 && si.center_frq2 > 0) {
- ret = os_snprintf(pos, end - pos,
- "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n",
- si.center_frq1, si.center_frq2);
+ if (si.center_frq1 > 0) {
+ ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
+ si.center_frq1);
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
+
+ if (si.center_frq2 > 0) {
+ ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
+ si.center_frq2);
if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
@@ -6930,6 +7646,46 @@ static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s,
}
+#ifdef CONFIG_TESTING_OPTIONS
+int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
+ enum wpa_driver_if_type if_type,
+ unsigned int *num,
+ unsigned int *freq_list)
+{
+ char *pos = wpa_s->get_pref_freq_list_override;
+ char *end;
+ unsigned int count = 0;
+
+ /* Override string format:
+ * <if_type1>:<freq1>,<freq2>,... <if_type2>:... */
+
+ while (pos) {
+ if (atoi(pos) == (int) if_type)
+ break;
+ pos = os_strchr(pos, ' ');
+ if (pos)
+ pos++;
+ }
+ if (!pos)
+ return -1;
+ pos = os_strchr(pos, ':');
+ if (!pos)
+ return -1;
+ pos++;
+ end = os_strchr(pos, ' ');
+ while (pos && (!end || pos < end) && count < *num) {
+ freq_list[count++] = atoi(pos);
+ pos = os_strchr(pos, ',');
+ if (pos)
+ pos++;
+ }
+
+ *num = count;
+ return 0;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
static int wpas_ctrl_iface_get_pref_freq_list(
struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
{
@@ -6959,7 +7715,7 @@ static int wpas_ctrl_iface_get_pref_freq_list(
wpa_printf(MSG_DEBUG,
"CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)",
- iface_type, buf);
+ iface_type, cmd);
ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list);
if (ret)
@@ -7116,7 +7872,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
- wpas_abort_ongoing_scan(wpa_s);
+ if (wpas_abort_ongoing_scan(wpa_s) == 0)
+ wpa_s->ignore_post_flush_scan_res = 1;
if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
/*
@@ -7157,6 +7914,22 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_s->after_wps = 0;
wpa_s->known_wps_freq = 0;
+#ifdef CONFIG_DPP
+ wpas_dpp_deinit(wpa_s);
+ wpa_s->dpp_init_max_tries = 0;
+ wpa_s->dpp_init_retry_time = 0;
+ wpa_s->dpp_resp_wait_time = 0;
+ wpa_s->dpp_resp_max_tries = 0;
+ wpa_s->dpp_resp_retry_time = 0;
+#ifdef CONFIG_TESTING_OPTIONS
+ os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN);
+ os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN);
+ dpp_pkex_ephemeral_key_override_len = 0;
+ dpp_protocol_key_override_len = 0;
+ dpp_nonce_override_len = 0;
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_DPP */
+
#ifdef CONFIG_TDLS
#ifdef CONFIG_TDLS_TESTING
tdls_testing = 0;
@@ -7218,13 +7991,29 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_s->p2p_go_csa_on_inv = 0;
wpa_s->ignore_auth_resp = 0;
wpa_s->ignore_assoc_disallow = 0;
+ wpa_s->testing_resend_assoc = 0;
wpa_s->reject_btm_req_reason = 0;
wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
+ os_free(wpa_s->get_pref_freq_list_override);
+ wpa_s->get_pref_freq_list_override = NULL;
+ wpabuf_free(wpa_s->sae_commit_override);
+ wpa_s->sae_commit_override = NULL;
+#ifdef CONFIG_DPP
+ os_free(wpa_s->dpp_config_obj_override);
+ wpa_s->dpp_config_obj_override = NULL;
+ os_free(wpa_s->dpp_discovery_override);
+ wpa_s->dpp_discovery_override = NULL;
+ os_free(wpa_s->dpp_groups_override);
+ wpa_s->dpp_groups_override = NULL;
+ dpp_test = DPP_TEST_DISABLED;
+#endif /* CONFIG_DPP */
#endif /* CONFIG_TESTING_OPTIONS */
wpa_s->disconnected = 0;
os_free(wpa_s->next_scan_freqs);
wpa_s->next_scan_freqs = NULL;
+ os_free(wpa_s->select_network_scan_freqs);
+ wpa_s->select_network_scan_freqs = NULL;
wpa_bss_flush(wpa_s);
if (!dl_list_empty(&wpa_s->bss)) {
@@ -7242,6 +8031,13 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
#ifdef CONFIG_SME
wpa_s->sme.last_unprot_disconnect.sec = 0;
#endif /* CONFIG_SME */
+
+ wpabuf_free(wpa_s->ric_ies);
+ wpa_s->ric_ies = NULL;
+
+ wpa_supplicant_update_channel_list(wpa_s, NULL);
+
+ free_bss_tmp_disallowed(wpa_s);
}
@@ -7539,6 +8335,19 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
goto done;
}
+ pos = os_strstr(params, "bssid=");
+ if (pos) {
+ u8 bssid[ETH_ALEN];
+
+ pos += 6;
+ if (hwaddr_aton(pos, bssid)) {
+ wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos);
+ *reply_len = -1;
+ goto done;
+ }
+ os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN);
+ }
+
pos = params;
while (pos && *pos != '\0') {
if (os_strncmp(pos, "ssid ", 5) == 0) {
@@ -7824,6 +8633,124 @@ static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s,
}
+static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s,
+ char *param)
+{
+ struct wpa_scan_res *res;
+ struct os_reltime now;
+ char *pos, *end;
+ int ret = -1;
+
+ if (!param)
+ return -1;
+
+ if (os_strcmp(param, "START") == 0) {
+ wpa_bss_update_start(wpa_s);
+ return 0;
+ }
+
+ if (os_strcmp(param, "END") == 0) {
+ wpa_bss_update_end(wpa_s, NULL, 1);
+ return 0;
+ }
+
+ if (os_strncmp(param, "BSS ", 4) != 0)
+ return -1;
+ param += 3;
+
+ res = os_zalloc(sizeof(*res) + os_strlen(param) / 2);
+ if (!res)
+ return -1;
+
+ pos = os_strstr(param, " flags=");
+ if (pos)
+ res->flags = strtol(pos + 7, NULL, 16);
+
+ pos = os_strstr(param, " bssid=");
+ if (pos && hwaddr_aton(pos + 7, res->bssid))
+ goto fail;
+
+ pos = os_strstr(param, " freq=");
+ if (pos)
+ res->freq = atoi(pos + 6);
+
+ pos = os_strstr(param, " beacon_int=");
+ if (pos)
+ res->beacon_int = atoi(pos + 12);
+
+ pos = os_strstr(param, " caps=");
+ if (pos)
+ res->caps = strtol(pos + 6, NULL, 16);
+
+ pos = os_strstr(param, " qual=");
+ if (pos)
+ res->qual = atoi(pos + 6);
+
+ pos = os_strstr(param, " noise=");
+ if (pos)
+ res->noise = atoi(pos + 7);
+
+ pos = os_strstr(param, " level=");
+ if (pos)
+ res->level = atoi(pos + 7);
+
+ pos = os_strstr(param, " tsf=");
+ if (pos)
+ res->tsf = strtoll(pos + 5, NULL, 16);
+
+ pos = os_strstr(param, " age=");
+ if (pos)
+ res->age = atoi(pos + 5);
+
+ pos = os_strstr(param, " est_throughput=");
+ if (pos)
+ res->est_throughput = atoi(pos + 16);
+
+ pos = os_strstr(param, " snr=");
+ if (pos)
+ res->snr = atoi(pos + 5);
+
+ pos = os_strstr(param, " parent_tsf=");
+ if (pos)
+ res->parent_tsf = strtoll(pos + 7, NULL, 16);
+
+ pos = os_strstr(param, " tsf_bssid=");
+ if (pos && hwaddr_aton(pos + 11, res->tsf_bssid))
+ goto fail;
+
+ pos = os_strstr(param, " ie=");
+ if (pos) {
+ pos += 4;
+ end = os_strchr(pos, ' ');
+ if (!end)
+ end = pos + os_strlen(pos);
+ res->ie_len = (end - pos) / 2;
+ if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len))
+ goto fail;
+ }
+
+ pos = os_strstr(param, " beacon_ie=");
+ if (pos) {
+ pos += 11;
+ end = os_strchr(pos, ' ');
+ if (!end)
+ end = pos + os_strlen(pos);
+ res->beacon_ie_len = (end - pos) / 2;
+ if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len,
+ res->beacon_ie_len))
+ goto fail;
+ }
+
+ os_get_reltime(&now);
+ wpa_bss_update_scan_res(wpa_s, res, &now);
+ ret = 0;
+fail:
+ os_free(res);
+
+ return ret;
+}
+
+
static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
{
char *pos, *param;
@@ -7854,6 +8781,8 @@ static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
wpa_supplicant_event(wpa_s, ev, &event);
os_free(event.freq_range.range);
return 0;
+ } else if (os_strcmp(cmd, "SCAN_RES") == 0) {
+ return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
} else {
wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
cmd);
@@ -7931,26 +8860,39 @@ static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
struct iphdr ip;
const u8 *pos;
unsigned int i;
+ char extra[30];
- if (len != HWSIM_PACKETLEN)
+ if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
+ wpa_printf(MSG_DEBUG,
+ "test data: RX - ignore unexpected length %d",
+ (int) len);
return;
+ }
eth = (const struct ether_header *) buf;
os_memcpy(&ip, eth + 1, sizeof(ip));
pos = &buf[sizeof(*eth) + sizeof(ip)];
if (ip.ihl != 5 || ip.version != 4 ||
- ntohs(ip.tot_len) != HWSIM_IP_LEN)
+ ntohs(ip.tot_len) > HWSIM_IP_LEN) {
+ wpa_printf(MSG_DEBUG,
+ "test data: RX - ignore unexpect IP header");
return;
+ }
- for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) {
- if (*pos != (u8) i)
+ for (i = 0; i < ntohs(ip.tot_len) - sizeof(ip); i++) {
+ if (*pos != (u8) i) {
+ wpa_printf(MSG_DEBUG,
+ "test data: RX - ignore mismatching payload");
return;
+ }
pos++;
}
-
- wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
- MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
+ extra[0] = '\0';
+ if (ntohs(ip.tot_len) != HWSIM_IP_LEN)
+ os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.tot_len));
+ wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
+ MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
}
@@ -7994,7 +8936,7 @@ static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
{
u8 dst[ETH_ALEN], src[ETH_ALEN];
- char *pos;
+ char *pos, *pos2;
int used;
long int val;
u8 tos;
@@ -8003,11 +8945,12 @@ static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
struct iphdr *ip;
u8 *dpos;
unsigned int i;
+ size_t send_len = HWSIM_IP_LEN;
if (wpa_s->l2_test == NULL)
return -1;
- /* format: <dst> <src> <tos> */
+ /* format: <dst> <src> <tos> [len=<length>] */
pos = cmd;
used = hwaddr_aton2(pos, dst);
@@ -8021,11 +8964,19 @@ static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
return -1;
pos += used;
- val = strtol(pos, NULL, 0);
+ val = strtol(pos, &pos2, 0);
if (val < 0 || val > 0xff)
return -1;
tos = val;
+ pos = os_strstr(pos2, " len=");
+ if (pos) {
+ i = atoi(pos + 5);
+ if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
+ return -1;
+ send_len = i;
+ }
+
eth = (struct ether_header *) &buf[2];
os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
os_memcpy(eth->ether_shost, src, ETH_ALEN);
@@ -8036,17 +8987,17 @@ static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
ip->version = 4;
ip->ttl = 64;
ip->tos = tos;
- ip->tot_len = htons(HWSIM_IP_LEN);
+ ip->tot_len = htons(send_len);
ip->protocol = 1;
ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
dpos = (u8 *) (ip + 1);
- for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
+ for (i = 0; i < send_len - sizeof(*ip); i++)
*dpos++ = i;
if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2],
- HWSIM_PACKETLEN) < 0)
+ sizeof(struct ether_header) + send_len) < 0)
return -1;
wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
@@ -8218,6 +9169,79 @@ static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
return 0;
}
+
+static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
+{
+ u8 zero[WPA_TK_MAX_LEN];
+
+ if (wpa_s->last_tk_alg == WPA_ALG_NONE)
+ return -1;
+
+ wpa_printf(MSG_INFO, "TESTING: Reset PN");
+ os_memset(zero, 0, sizeof(zero));
+
+ /* First, use a zero key to avoid any possible duplicate key avoidance
+ * in the driver. */
+ if (wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
+ wpa_s->last_tk_key_idx, 1, zero, 6,
+ zero, wpa_s->last_tk_len) < 0)
+ return -1;
+
+ /* Set the previously configured key to reset its TSC/RSC */
+ return wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
+ wpa_s->last_tk_key_idx, 1, zero, 6,
+ wpa_s->last_tk, wpa_s->last_tk_len);
+}
+
+
+static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ const char *pos = cmd;
+ int error, pairwise;
+
+ error = atoi(pos);
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ return -1;
+ pairwise = atoi(pos);
+ wpa_sm_key_request(wpa_s->wpa, error, pairwise);
+ return 0;
+}
+
+
+static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_SME
+ struct wpa_driver_associate_params params;
+ int ret;
+
+ os_memset(&params, 0, sizeof(params));
+ params.bssid = wpa_s->bssid;
+ params.ssid = wpa_s->sme.ssid;
+ params.ssid_len = wpa_s->sme.ssid_len;
+ params.freq.freq = wpa_s->sme.freq;
+ if (wpa_s->last_assoc_req_wpa_ie) {
+ params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie);
+ params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie);
+ }
+ params.pairwise_suite = wpa_s->pairwise_cipher;
+ params.group_suite = wpa_s->group_cipher;
+ params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
+ params.key_mgmt_suite = wpa_s->key_mgmt;
+ params.wpa_proto = wpa_s->wpa_proto;
+ params.mgmt_frame_protection = wpa_s->sme.mfp;
+ params.rrm_used = wpa_s->rrm.rrm_used;
+ if (wpa_s->sme.prev_bssid_set)
+ params.prev_bssid = wpa_s->sme.prev_bssid;
+ wpa_printf(MSG_INFO, "TESTING: Resend association request");
+ ret = wpa_drv_associate(wpa_s, &params);
+ wpa_s->testing_resend_assoc = 1;
+ return ret;
+#else /* CONFIG_SME */
+ return -1;
+#endif /* CONFIG_SME */
+}
+
#endif /* CONFIG_TESTING_OPTIONS */
@@ -8553,13 +9577,6 @@ static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
return -1;
}
- if ((wpa_s->mac_addr_rand_supported & type) != type) {
- wpa_printf(MSG_INFO,
- "CTRL: MAC_RAND_SCAN types=%u != supported=%u",
- type, wpa_s->mac_addr_rand_supported);
- return -1;
- }
-
if (enable > 1) {
wpa_printf(MSG_INFO,
"CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
@@ -8593,21 +9610,25 @@ static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
}
if (type & MAC_ADDR_RAND_SCAN) {
- wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
- addr, mask);
+ if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
+ addr, mask))
+ return -1;
}
if (type & MAC_ADDR_RAND_SCHED_SCAN) {
- wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
- addr, mask);
+ if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
+ addr, mask))
+ return -1;
if (wpa_s->sched_scanning && !wpa_s->pno)
wpas_scan_restart_sched_scan(wpa_s);
}
if (type & MAC_ADDR_RAND_PNO) {
- wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
- addr, mask);
+ if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
+ addr, mask))
+ return -1;
+
if (wpa_s->pno) {
wpas_stop_pno(wpa_s);
wpas_start_pno(wpa_s);
@@ -8641,6 +9662,248 @@ static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
}
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+
+static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s,
+ const char *cmd, char *buf, size_t buflen)
+{
+ struct rsn_pmksa_cache_entry *entry;
+ struct wpa_ssid *ssid;
+ char *pos, *pos2, *end;
+ int ret;
+ struct os_reltime now;
+
+ ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
+ if (!ssid)
+ return -1;
+
+ pos = buf;
+ end = buf + buflen;
+
+ os_get_reltime(&now);
+
+ /*
+ * Entry format:
+ * <BSSID> <PMKID> <PMK> <reauth_time in seconds>
+ * <expiration in seconds> <akmp> <opportunistic>
+ * [FILS Cache Identifier]
+ */
+
+ for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry;
+ entry = entry->next) {
+ if (entry->network_ctx != ssid)
+ continue;
+
+ pos2 = pos;
+ ret = os_snprintf(pos2, end - pos2, MACSTR " ",
+ MAC2STR(entry->aa));
+ if (os_snprintf_error(end - pos2, ret))
+ break;
+ pos2 += ret;
+
+ pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid,
+ PMKID_LEN);
+
+ ret = os_snprintf(pos2, end - pos2, " ");
+ if (os_snprintf_error(end - pos2, ret))
+ break;
+ pos2 += ret;
+
+ pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk,
+ entry->pmk_len);
+
+ ret = os_snprintf(pos2, end - pos2, " %d %d %d %d",
+ (int) (entry->reauth_time - now.sec),
+ (int) (entry->expiration - now.sec),
+ entry->akmp,
+ entry->opportunistic);
+ if (os_snprintf_error(end - pos2, ret))
+ break;
+ pos2 += ret;
+
+ if (entry->fils_cache_id_set) {
+ ret = os_snprintf(pos2, end - pos2, " %02x%02x",
+ entry->fils_cache_id[0],
+ entry->fils_cache_id[1]);
+ if (os_snprintf_error(end - pos2, ret))
+ break;
+ pos2 += ret;
+ }
+
+ ret = os_snprintf(pos2, end - pos2, "\n");
+ if (os_snprintf_error(end - pos2, ret))
+ break;
+ pos2 += ret;
+
+ pos = pos2;
+ }
+
+ return pos - buf;
+}
+
+
+static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ struct rsn_pmksa_cache_entry *entry;
+ struct wpa_ssid *ssid;
+ char *pos, *pos2;
+ int ret = -1;
+ struct os_reltime now;
+ int reauth_time = 0, expiration = 0, i;
+
+ /*
+ * Entry format:
+ * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds>
+ * <expiration in seconds> <akmp> <opportunistic>
+ * [FILS Cache Identifier]
+ */
+
+ ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
+ if (!ssid)
+ return -1;
+
+ pos = os_strchr(cmd, ' ');
+ if (!pos)
+ return -1;
+ pos++;
+
+ entry = os_zalloc(sizeof(*entry));
+ if (!entry)
+ return -1;
+
+ if (hwaddr_aton(pos, entry->aa))
+ goto fail;
+
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ goto fail;
+ pos++;
+
+ if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0)
+ goto fail;
+
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ goto fail;
+ pos++;
+
+ pos2 = os_strchr(pos, ' ');
+ if (!pos2)
+ goto fail;
+ entry->pmk_len = (pos2 - pos) / 2;
+ if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX ||
+ hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0)
+ goto fail;
+
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ goto fail;
+ pos++;
+
+ if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration,
+ &entry->akmp, &entry->opportunistic) != 4)
+ goto fail;
+ for (i = 0; i < 4; i++) {
+ pos = os_strchr(pos, ' ');
+ if (!pos) {
+ if (i < 3)
+ goto fail;
+ break;
+ }
+ pos++;
+ }
+ if (pos) {
+ if (hexstr2bin(pos, entry->fils_cache_id,
+ FILS_CACHE_ID_LEN) < 0)
+ goto fail;
+ entry->fils_cache_id_set = 1;
+ }
+ os_get_reltime(&now);
+ entry->expiration = now.sec + expiration;
+ entry->reauth_time = now.sec + reauth_time;
+
+ entry->network_ctx = ssid;
+
+ wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
+ entry = NULL;
+ ret = 0;
+fail:
+ os_free(entry);
+ return ret;
+}
+
+
+#ifdef CONFIG_MESH
+
+static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s,
+ const char *cmd, char *buf,
+ size_t buflen)
+{
+ u8 spa[ETH_ALEN];
+
+ if (!wpa_s->ifmsh)
+ return -1;
+
+ if (os_strcasecmp(cmd, "any") == 0)
+ return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen);
+
+ if (hwaddr_aton(cmd, spa))
+ return -1;
+
+ return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen);
+}
+
+
+static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ /*
+ * We do not check mesh interface existance because PMKSA should be
+ * stored before wpa_s->ifmsh creation to suppress commit message
+ * creation.
+ */
+ return wpas_ap_pmksa_cache_add_external(wpa_s, cmd);
+}
+
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
+
+#ifdef CONFIG_FILS
+static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ struct fils_hlp_req *req;
+ const char *pos;
+
+ /* format: <dst> <packet starting from ethertype> */
+
+ req = os_zalloc(sizeof(*req));
+ if (!req)
+ return -1;
+
+ if (hwaddr_aton(cmd, req->dst))
+ goto fail;
+
+ pos = os_strchr(cmd, ' ');
+ if (!pos)
+ goto fail;
+ pos++;
+ req->pkt = wpabuf_parse_bin(pos);
+ if (!req->pkt)
+ goto fail;
+
+ dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
+ return 0;
+fail:
+ wpabuf_free(req->pkt);
+ os_free(req);
+ return -1;
+}
+#endif /* CONFIG_FILS */
+
+
static int wpas_ctrl_cmd_debug_level(const char *cmd)
{
if (os_strcmp(cmd, "PING") == 0 ||
@@ -8662,7 +9925,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
int reply_len;
if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
- os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
+ os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
+ os_strncmp(buf, "PMKSA_ADD ", 10) == 0 ||
+ os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
if (wpa_debug_show_keys)
wpa_dbg(wpa_s, MSG_DEBUG,
"Control interface command '%s'", buf);
@@ -8671,7 +9936,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
"Control interface command '%s [REMOVED]'",
os_strncmp(buf, WPA_CTRL_RSP,
os_strlen(WPA_CTRL_RSP)) == 0 ?
- WPA_CTRL_RSP : "SET_NETWORK");
+ WPA_CTRL_RSP :
+ (os_strncmp(buf, "SET_NETWORK ", 12) == 0 ?
+ "SET_NETWORK" : "key-add"));
} else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
@@ -8707,6 +9974,11 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
reply_len += eapol_sm_get_mib(wpa_s->eapol,
reply + reply_len,
reply_size - reply_len);
+#ifdef CONFIG_MACSEC
+ reply_len += ieee802_1x_kay_get_mib(
+ wpa_s->kay, reply + reply_len,
+ reply_size - reply_len);
+#endif /* CONFIG_MACSEC */
}
} else if (os_strncmp(buf, "STATUS", 6) == 0) {
reply_len = wpa_supplicant_ctrl_iface_status(
@@ -8715,6 +9987,22 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size);
} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
wpas_ctrl_iface_pmksa_flush(wpa_s);
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+ } else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) {
+ reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10,
+ reply, reply_size);
+ } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
+ if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0)
+ reply_len = -1;
+#ifdef CONFIG_MESH
+ } else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) {
+ reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15,
+ reply, reply_size);
+ } else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
+ if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0)
+ reply_len = -1;
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
} else if (os_strncmp(buf, "SET ", 4) == 0) {
if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
reply_len = -1;
@@ -8751,11 +10039,6 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
reply_len = -1;
#endif /* IEEE8021X_EAPOL */
-#ifdef CONFIG_PEERKEY
- } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
- if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
- reply_len = -1;
-#endif /* CONFIG_PEERKEY */
#ifdef CONFIG_IEEE80211R
} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
@@ -9286,6 +10569,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
reply_len = -1;
+ } else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) {
+ if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
+ reply_len = -1;
#endif /* CONFIG_WNM */
} else if (os_strcmp(buf, "FLUSH") == 0) {
wpa_supplicant_ctrl_iface_flush(wpa_s);
@@ -9332,6 +10618,21 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
reply_len = -1;
+ } else if (os_strcmp(buf, "RESET_PN") == 0) {
+ if (wpas_ctrl_reset_pn(wpa_s) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) {
+ if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "RESEND_ASSOC") == 0) {
+ if (wpas_ctrl_resend_assoc(wpa_s) < 0)
+ reply_len = -1;
+#ifdef CONFIG_IEEE80211W
+ } else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) {
+ sme_event_unprot_disconnect(
+ wpa_s, wpa_s->bssid, NULL,
+ WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
+#endif /* CONFIG_IEEE80211W */
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
@@ -9353,6 +10654,98 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) {
reply_len = wpas_ctrl_iface_get_pref_freq_list(
wpa_s, buf + 19, reply, reply_size);
+#ifdef CONFIG_FILS
+ } else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) {
+ if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17))
+ reply_len = -1;
+ } else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) {
+ wpas_flush_fils_hlp_req(wpa_s);
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_DPP
+ } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
+ int res;
+
+ res = wpas_dpp_qr_code(wpa_s, buf + 12);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
+ } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
+ int res;
+
+ res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
+ } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
+ if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
+ const char *uri;
+
+ uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22));
+ if (!uri) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%s", uri);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
+ } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
+ reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19),
+ reply, reply_size);
+ } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
+ if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
+ if (wpas_dpp_listen(wpa_s, buf + 11) < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
+ wpas_dpp_stop(wpa_s);
+ wpas_dpp_listen_stop(wpa_s);
+ } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
+ int res;
+
+ res = dpp_configurator_add(wpa_s->dpp, buf + 20);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
+ } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
+ if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
+ if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
+ reply_len = dpp_configurator_get_key_id(wpa_s->dpp,
+ atoi(buf + 25),
+ reply, reply_size);
+ } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
+ int res;
+
+ res = wpas_dpp_pkex_add(wpa_s, buf + 12);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
+ } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
+ if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0)
+ reply_len = -1;
+#endif /* CONFIG_DPP */
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
@@ -9662,12 +11055,16 @@ static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
"P2P_CANCEL",
"P2P_PRESENCE_REQ",
"P2P_EXT_LISTEN",
+#ifdef CONFIG_AP
+ "STA-FIRST",
+#endif /* CONFIG_AP */
NULL
};
static const char * prefix[] = {
#ifdef ANDROID
"DRIVER ",
#endif /* ANDROID */
+ "GET_CAPABILITY ",
"GET_NETWORK ",
"REMOVE_NETWORK ",
"P2P_FIND ",
@@ -9699,6 +11096,10 @@ static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
"NFC_REPORT_HANDOVER ",
"P2P_ASP_PROVISION ",
"P2P_ASP_PROVISION_RESP ",
+#ifdef CONFIG_AP
+ "STA ",
+ "STA-NEXT ",
+#endif /* CONFIG_AP */
NULL
};
int found = 0;
diff --git a/contrib/wpa/wpa_supplicant/ctrl_iface_named_pipe.c b/contrib/wpa/wpa_supplicant/ctrl_iface_named_pipe.c
index 54e0e2fac583..9c0a47e63936 100644
--- a/contrib/wpa/wpa_supplicant/ctrl_iface_named_pipe.c
+++ b/contrib/wpa/wpa_supplicant/ctrl_iface_named_pipe.c
@@ -319,13 +319,12 @@ static void wpa_supplicant_ctrl_iface_rx(struct wpa_ctrl_dst *dst, size_t len)
}
os_free(dst->rsp_buf);
- dst->rsp_buf = os_malloc(send_len);
+ dst->rsp_buf = os_memdup(send_buf, send_len);
if (dst->rsp_buf == NULL) {
ctrl_close_pipe(dst);
os_free(reply);
return;
}
- os_memcpy(dst->rsp_buf, send_buf, send_len);
os_free(reply);
if (!WriteFileEx(dst->pipe, dst->rsp_buf, send_len, &dst->overlap,
@@ -739,13 +738,12 @@ static void wpa_supplicant_global_iface_rx(struct wpa_global_dst *dst,
}
os_free(dst->rsp_buf);
- dst->rsp_buf = os_malloc(send_len);
+ dst->rsp_buf = os_memdup(send_buf, send_len);
if (dst->rsp_buf == NULL) {
global_close_pipe(dst);
os_free(reply);
return;
}
- os_memcpy(dst->rsp_buf, send_buf, send_len);
os_free(reply);
if (!WriteFileEx(dst->pipe, dst->rsp_buf, send_len, &dst->overlap,
diff --git a/contrib/wpa/wpa_supplicant/ctrl_iface_udp.c b/contrib/wpa/wpa_supplicant/ctrl_iface_udp.c
index 0dc0937ff0aa..8a6057a82bfe 100644
--- a/contrib/wpa/wpa_supplicant/ctrl_iface_udp.c
+++ b/contrib/wpa/wpa_supplicant/ctrl_iface_udp.c
@@ -219,7 +219,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
{
struct wpa_supplicant *wpa_s = eloop_ctx;
struct ctrl_iface_priv *priv = sock_ctx;
- char buf[256], *pos;
+ char buf[4096], *pos;
int res;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
struct sockaddr_in6 from;
@@ -600,7 +600,7 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
{
struct wpa_global *global = eloop_ctx;
struct ctrl_iface_global_priv *priv = sock_ctx;
- char buf[256], *pos;
+ char buf[4096], *pos;
int res;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
struct sockaddr_in6 from;
diff --git a/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c b/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c
index 4db712fff7bb..71fe7ed6bef5 100644
--- a/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c
+++ b/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c
@@ -103,7 +103,7 @@ static int wpa_supplicant_ctrl_iface_attach(struct dl_list *ctrl_dst,
struct sockaddr_storage *from,
socklen_t fromlen, int global)
{
- return ctrl_iface_attach(ctrl_dst, from, fromlen);
+ return ctrl_iface_attach(ctrl_dst, from, fromlen, NULL);
}
@@ -570,8 +570,8 @@ static int wpas_ctrl_iface_open_sock(struct wpa_supplicant *wpa_s,
}
}
- if (gid_set && chown(dir, -1, gid) < 0) {
- wpa_printf(MSG_ERROR, "chown[ctrl_interface=%s,gid=%d]: %s",
+ if (gid_set && lchown(dir, -1, gid) < 0) {
+ wpa_printf(MSG_ERROR, "lchown[ctrl_interface=%s,gid=%d]: %s",
dir, (int) gid, strerror(errno));
goto fail;
}
@@ -638,8 +638,8 @@ static int wpas_ctrl_iface_open_sock(struct wpa_supplicant *wpa_s,
}
}
- if (gid_set && chown(fname, -1, gid) < 0) {
- wpa_printf(MSG_ERROR, "chown[ctrl_interface=%s,gid=%d]: %s",
+ if (gid_set && lchown(fname, -1, gid) < 0) {
+ wpa_printf(MSG_ERROR, "lchown[ctrl_interface=%s,gid=%d]: %s",
fname, (int) gid, strerror(errno));
goto fail;
}
@@ -1235,9 +1235,9 @@ static int wpas_global_ctrl_iface_open_sock(struct wpa_global *global,
wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
(int) gid);
}
- if (chown(ctrl, -1, gid) < 0) {
+ if (lchown(ctrl, -1, gid) < 0) {
wpa_printf(MSG_ERROR,
- "chown[global_ctrl_interface=%s,gid=%d]: %s",
+ "lchown[global_ctrl_interface=%s,gid=%d]: %s",
ctrl, (int) gid, strerror(errno));
goto fail;
}
diff --git a/contrib/wpa/wpa_supplicant/dbus/Makefile b/contrib/wpa/wpa_supplicant/dbus/Makefile
index f355ebef51d2..4d8700428dcb 100644
--- a/contrib/wpa/wpa_supplicant/dbus/Makefile
+++ b/contrib/wpa/wpa_supplicant/dbus/Makefile
@@ -36,7 +36,6 @@ CFLAGS += -DCONFIG_WPS
endif
CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_NEW
-CFLAGS += -DCONFIG_CTRL_IFACE_DBUS
ifndef DBUS_LIBS
DBUS_LIBS := $(shell $(PKG_CONFIG) --libs dbus-1)
@@ -54,8 +53,6 @@ CFLAGS += $(DBUS_INCLUDE)
LIB_OBJS= \
dbus_common.o \
- dbus_old.o \
- dbus_old_handlers.o \
dbus_new.o \
dbus_new_handlers.o \
dbus_new_helpers.o \
@@ -63,7 +60,6 @@ LIB_OBJS= \
dbus_dict_helpers.o
ifdef CONFIG_WPS
-LIB_OBJS += dbus_old_handlers_wps.o
LIB_OBJS += dbus_new_handlers_wps.o
endif
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus-wpa_supplicant.conf b/contrib/wpa/wpa_supplicant/dbus/dbus-wpa_supplicant.conf
index 382dcb34318c..e81b495f4b99 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus-wpa_supplicant.conf
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus-wpa_supplicant.conf
@@ -3,11 +3,6 @@
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="root">
- <allow own="fi.epitest.hostap.WPASupplicant"/>
-
- <allow send_destination="fi.epitest.hostap.WPASupplicant"/>
- <allow send_interface="fi.epitest.hostap.WPASupplicant"/>
-
<allow own="fi.w1.wpa_supplicant1"/>
<allow send_destination="fi.w1.wpa_supplicant1"/>
@@ -15,9 +10,6 @@
<allow receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
</policy>
<policy context="default">
- <deny own="fi.epitest.hostap.WPASupplicant"/>
- <deny send_destination="fi.epitest.hostap.WPASupplicant"/>
-
<deny own="fi.w1.wpa_supplicant1"/>
<deny send_destination="fi.w1.wpa_supplicant1"/>
<deny receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_common.c b/contrib/wpa/wpa_supplicant/dbus/dbus_common.c
index 7ef6cad62aaf..efa6c7b20595 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_common.c
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus_common.c
@@ -16,7 +16,6 @@
#include "dbus_common.h"
#include "dbus_common_i.h"
#include "dbus_new.h"
-#include "dbus_old.h"
#include "../wpa_supplicant_i.h"
@@ -351,9 +350,6 @@ struct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global)
#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
wpas_dbus_ctrl_iface_init(priv) < 0 ||
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
-#ifdef CONFIG_CTRL_IFACE_DBUS
- wpa_supplicant_dbus_ctrl_iface_init(priv) < 0 ||
-#endif /* CONFIG_CTRL_IFACE_DBUS */
wpas_dbus_init_common_finish(priv) < 0) {
wpas_dbus_deinit(priv);
return NULL;
@@ -372,9 +368,5 @@ void wpas_dbus_deinit(struct wpas_dbus_priv *priv)
wpas_dbus_ctrl_iface_deinit(priv);
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
-#ifdef CONFIG_CTRL_IFACE_DBUS
- /* TODO: is any deinit needed? */
-#endif /* CONFIG_CTRL_IFACE_DBUS */
-
wpas_dbus_deinit_common(priv);
}
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new.c b/contrib/wpa/wpa_supplicant/dbus/dbus_new.c
index 27b3012aede8..fc2fc2ef1b96 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_new.c
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new.c
@@ -13,6 +13,7 @@
#include "common.h"
#include "common/ieee802_11_defs.h"
#include "wps/wps.h"
+#include "ap/sta_info.h"
#include "../config.h"
#include "../wpa_supplicant_i.h"
#include "../bss.h"
@@ -128,7 +129,8 @@ void wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv *priv)
* Notify listeners about event related with interface
*/
static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
- const char *sig_name, int properties)
+ const char *sig_name,
+ dbus_bool_t properties)
{
struct wpas_dbus_priv *iface;
DBusMessage *msg;
@@ -230,7 +232,7 @@ void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success)
*/
static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
const char *bss_obj_path,
- const char *sig_name, int properties)
+ const char *sig_name, dbus_bool_t properties)
{
struct wpas_dbus_priv *iface;
DBusMessage *msg;
@@ -364,7 +366,7 @@ void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
*/
static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
int id, const char *sig_name,
- int properties)
+ dbus_bool_t properties)
{
struct wpas_dbus_priv *iface;
DBusMessage *msg;
@@ -793,6 +795,144 @@ nomem:
#endif /* CONFIG_WPS */
+
+#ifdef CONFIG_MESH
+
+void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+ DBusMessageIter iter, dict_iter;
+
+ iface = wpa_s->global->dbus;
+
+ /* Do nothing if the control interface is not turned on */
+ if (!iface || !wpa_s->dbus_new_path)
+ return;
+
+ msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_MESH,
+ "MeshGroupStarted");
+ if (!msg)
+ return;
+
+ dbus_message_iter_init_append(msg, &iter);
+ if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
+ !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
+ (const char *) ssid->ssid,
+ ssid->ssid_len) ||
+ !wpa_dbus_dict_close_write(&iter, &dict_iter))
+ wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+ else
+ dbus_connection_send(iface->con, msg, NULL);
+ dbus_message_unref(msg);
+}
+
+
+void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s,
+ const u8 *meshid, u8 meshid_len,
+ int reason)
+{
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+ DBusMessageIter iter, dict_iter;
+
+ iface = wpa_s->global->dbus;
+
+ /* Do nothing if the control interface is not turned on */
+ if (!iface || !wpa_s->dbus_new_path)
+ return;
+
+ msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_MESH,
+ "MeshGroupRemoved");
+ if (!msg)
+ return;
+
+ dbus_message_iter_init_append(msg, &iter);
+ if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
+ !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
+ (const char *) meshid,
+ meshid_len) ||
+ !wpa_dbus_dict_append_int32(&dict_iter, "DisconnectReason",
+ reason) ||
+ !wpa_dbus_dict_close_write(&iter, &dict_iter))
+ wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+ else
+ dbus_connection_send(iface->con, msg, NULL);
+ dbus_message_unref(msg);
+}
+
+
+void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr)
+{
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+ DBusMessageIter iter, dict_iter;
+
+ iface = wpa_s->global->dbus;
+
+ /* Do nothing if the control interface is not turned on */
+ if (!iface || !wpa_s->dbus_new_path)
+ return;
+
+ msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_MESH,
+ "MeshPeerConnected");
+ if (!msg)
+ return;
+
+ dbus_message_iter_init_append(msg, &iter);
+ if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
+ !wpa_dbus_dict_append_byte_array(&dict_iter, "PeerAddress",
+ (const char *) peer_addr,
+ ETH_ALEN) ||
+ !wpa_dbus_dict_close_write(&iter, &dict_iter))
+ wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+ else
+ dbus_connection_send(iface->con, msg, NULL);
+ dbus_message_unref(msg);
+}
+
+
+void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr, int reason)
+{
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+ DBusMessageIter iter, dict_iter;
+
+ iface = wpa_s->global->dbus;
+
+ /* Do nothing if the control interface is not turned on */
+ if (!iface || !wpa_s->dbus_new_path)
+ return;
+
+ msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_MESH,
+ "MeshPeerDisconnected");
+ if (!msg)
+ return;
+
+ dbus_message_iter_init_append(msg, &iter);
+ if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
+ !wpa_dbus_dict_append_byte_array(&dict_iter, "PeerAddress",
+ (const char *) peer_addr,
+ ETH_ALEN) ||
+ !wpa_dbus_dict_append_int32(&dict_iter, "DisconnectReason",
+ reason) ||
+ !wpa_dbus_dict_close_write(&iter, &dict_iter))
+ wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+ else
+ dbus_connection_send(iface->con, msg, NULL);
+ dbus_message_unref(msg);
+}
+
+#endif /* CONFIG_MESH */
+
+
void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
int depth, const char *subject,
const char *altsubject[],
@@ -939,6 +1079,79 @@ void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
}
+/**
+ * wpas_dbus_signal_station - Send an event signal related to a station object
+ * @wpa_s: %wpa_supplicant network interface data
+ * @station_obj_path: Station object path
+ * @sig_name: signal name - StationAdded or StationRemoved
+ * @properties: Whether to add second argument with object properties
+ *
+ * Notify listeners about event related with station.
+ */
+static void wpas_dbus_signal_station(struct wpa_supplicant *wpa_s,
+ const char *station_obj_path,
+ const char *sig_name,
+ dbus_bool_t properties)
+{
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+ DBusMessageIter iter;
+
+ iface = wpa_s->global->dbus;
+
+ /* Do nothing if the control interface is not turned on */
+ if (!iface || !wpa_s->dbus_new_path)
+ return;
+
+ wpa_printf(MSG_DEBUG, "dbus: STA signal %s", sig_name);
+ msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
+ if (!msg)
+ return;
+
+ dbus_message_iter_init_append(msg, &iter);
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+ &station_obj_path) ||
+ (properties &&
+ !wpa_dbus_get_object_properties(iface, station_obj_path,
+ WPAS_DBUS_NEW_IFACE_STA,
+ &iter)))
+ wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+ else
+ dbus_connection_send(iface->con, msg, NULL);
+ dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_station_added - Send a Station added signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @station_obj_path: new Station object path
+ *
+ * Notify listeners about adding new Station
+ */
+static void wpas_dbus_signal_station_added(struct wpa_supplicant *wpa_s,
+ const char *station_obj_path)
+{
+ wpas_dbus_signal_station(wpa_s, station_obj_path, "StationAdded", TRUE);
+}
+
+
+/**
+ * wpas_dbus_signal_station_removed - Send a Station removed signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @station_obj_path: Station object path
+ *
+ * Notify listeners about removing Station
+ */
+static void wpas_dbus_signal_station_removed(struct wpa_supplicant *wpa_s,
+ const char *station_obj_path)
+{
+ wpas_dbus_signal_station(wpa_s, station_obj_path, "StationRemoved",
+ FALSE);
+}
+
+
#ifdef CONFIG_P2P
/**
@@ -1256,9 +1469,12 @@ static void peer_groups_changed(struct wpa_supplicant *wpa_s)
* @wpa_s: %wpa_supplicant network interface data
* @client: this device is P2P client
* @persistent: 0 - non persistent group, 1 - persistent group
+ * @ip: When group role is client, it contains local IP address, netmask, and
+ * GO's IP address, if assigned; otherwise, NULL
*/
void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
- int client, int persistent)
+ int client, int persistent,
+ const u8 *ip)
{
DBusMessage *msg;
DBusMessageIter iter, dict_iter;
@@ -1300,6 +1516,13 @@ void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
!wpa_dbus_dict_append_bool(&dict_iter, "persistent", persistent) ||
!wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
wpa_s->dbus_groupobj_path) ||
+ (ip &&
+ (!wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddr",
+ (char *) ip, 4) ||
+ !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
+ (char *) ip + 4, 4) ||
+ !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
+ (char *) ip + 8, 4))) ||
!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
} else {
@@ -1734,7 +1957,7 @@ void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
*/
static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
int id, const char *sig_name,
- int properties)
+ dbus_bool_t properties)
{
struct wpas_dbus_priv *iface;
DBusMessage *msg;
@@ -1879,6 +2102,9 @@ void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
if (iface == NULL)
return;
+ if (wpa_s->p2p_mgmt)
+ wpa_s = wpa_s->parent;
+
msg = dbus_message_new_signal(wpa_s->dbus_new_path,
WPAS_DBUS_NEW_IFACE_P2PDEVICE,
"GroupFormationFailure");
@@ -1920,6 +2146,9 @@ void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
if (iface == NULL)
return;
+ if (wpa_s->p2p_mgmt)
+ wpa_s = wpa_s->parent;
+
msg = dbus_message_new_signal(wpa_s->dbus_new_path,
WPAS_DBUS_NEW_IFACE_P2PDEVICE,
"InvitationReceived");
@@ -1992,6 +2221,9 @@ void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
case WPAS_DBUS_PROP_BSSS:
prop = "BSSs";
break;
+ case WPAS_DBUS_PROP_STATIONS:
+ prop = "Stations";
+ break;
case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
prop = "CurrentAuthMode";
break;
@@ -1999,10 +2231,26 @@ void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
prop = "DisconnectReason";
flush = TRUE;
break;
+ case WPAS_DBUS_PROP_AUTH_STATUS_CODE:
+ prop = "AuthStatusCode";
+ flush = TRUE;
+ break;
case WPAS_DBUS_PROP_ASSOC_STATUS_CODE:
prop = "AssocStatusCode";
flush = TRUE;
break;
+ case WPAS_DBUS_PROP_ROAM_TIME:
+ prop = "RoamTime";
+ break;
+ case WPAS_DBUS_PROP_ROAM_COMPLETE:
+ prop = "RoamComplete";
+ break;
+ case WPAS_DBUS_PROP_SESSION_LENGTH:
+ prop = "SessionLength";
+ break;
+ case WPAS_DBUS_PROP_BSS_TM_STATUS:
+ prop = "BSSTMStatus";
+ break;
default:
wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
__func__, property);
@@ -2085,6 +2333,41 @@ void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
/**
+ * wpas_dbus_sta_signal_prop_changed - Signals change of STA property
+ * @wpa_s: %wpa_supplicant network interface data
+ * @property: indicates which property has changed
+ * @address: unique BSS identifier
+ *
+ * Sends PropertyChanged signals with path, interface, and arguments depending
+ * on which property has changed.
+ */
+void wpas_dbus_sta_signal_prop_changed(struct wpa_supplicant *wpa_s,
+ enum wpas_dbus_bss_prop property,
+ u8 address[ETH_ALEN])
+{
+ char path[WPAS_DBUS_OBJECT_PATH_MAX];
+ char *prop;
+
+ switch (property) {
+ case WPAS_DBUS_STA_PROP_ADDRESS:
+ prop = "Address";
+ break;
+ default:
+ wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
+ __func__, property);
+ return;
+ }
+
+ os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
+ "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
+ wpa_s->dbus_new_path, MAC2STR(address));
+
+ wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
+ WPAS_DBUS_NEW_IFACE_STA, prop);
+}
+
+
+/**
* wpas_dbus_signal_debug_level_changed - Signals change of debug param
* @global: wpa_global structure
*
@@ -2572,6 +2855,30 @@ static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
NULL,
NULL
},
+ {
+ "RoamTime", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+ wpas_dbus_getter_roam_time,
+ NULL,
+ NULL
+ },
+ {
+ "RoamComplete", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
+ wpas_dbus_getter_roam_complete,
+ NULL,
+ NULL
+ },
+ {
+ "SessionLength", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+ wpas_dbus_getter_session_length,
+ NULL,
+ NULL
+ },
+ {
+ "BSSTMStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+ wpas_dbus_getter_bss_tm_status,
+ NULL,
+ NULL
+ },
{ NULL, NULL, NULL, NULL, NULL, NULL }
};
@@ -2698,6 +3005,157 @@ err:
}
+static const struct wpa_dbus_property_desc wpas_dbus_sta_properties[] = {
+ { "Address", WPAS_DBUS_NEW_IFACE_STA, "ay",
+ wpas_dbus_getter_sta_address,
+ NULL, NULL
+ },
+ { "AID", WPAS_DBUS_NEW_IFACE_STA, "q",
+ wpas_dbus_getter_sta_aid,
+ NULL, NULL
+ },
+ { "Capabilities", WPAS_DBUS_NEW_IFACE_STA, "q",
+ wpas_dbus_getter_sta_caps,
+ NULL, NULL
+ },
+ { "RxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
+ wpas_dbus_getter_sta_rx_packets,
+ NULL, NULL
+ },
+ { "TxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
+ wpas_dbus_getter_sta_tx_packets,
+ NULL, NULL
+ },
+ { "RxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
+ wpas_dbus_getter_sta_rx_bytes,
+ NULL, NULL
+ },
+ { "TxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
+ wpas_dbus_getter_sta_tx_bytes,
+ NULL, NULL
+ },
+ { NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
+
+static const struct wpa_dbus_signal_desc wpas_dbus_sta_signals[] = {
+ /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
+ { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_STA,
+ {
+ { "properties", "a{sv}", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { NULL, NULL, { END_ARGS } }
+};
+
+
+/**
+ * wpas_dbus_unregister_sta - Unregister a connected station from dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @sta: station MAC address
+ * Returns: 0 on success, -1 on failure
+ *
+ * Unregisters STA representing object from dbus.
+ */
+int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
+{
+ struct wpas_dbus_priv *ctrl_iface;
+ char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+
+ /* Do nothing if the control interface is not turned on */
+ if (!wpa_s || !wpa_s->global)
+ return 0;
+ ctrl_iface = wpa_s->global->dbus;
+ if (!ctrl_iface)
+ return 0;
+
+ os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+ "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
+ wpa_s->dbus_new_path, MAC2STR(sta));
+
+ wpa_printf(MSG_DEBUG, "dbus: Unregister STA object '%s'",
+ station_obj_path);
+ if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
+ station_obj_path)) {
+ wpa_printf(MSG_ERROR, "dbus: Cannot unregister STA object %s",
+ station_obj_path);
+ return -1;
+ }
+
+ wpas_dbus_signal_station_removed(wpa_s, station_obj_path);
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
+
+ return 0;
+}
+
+
+/**
+ * wpas_dbus_register_sta - Register a connected station with dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @sta: station MAC address
+ * Returns: 0 on success, -1 on failure
+ *
+ * Registers STA representing object with dbus.
+ */
+int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
+{
+ struct wpas_dbus_priv *ctrl_iface;
+ struct wpa_dbus_object_desc *obj_desc;
+ char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+ struct sta_handler_args *arg;
+
+ /* Do nothing if the control interface is not turned on */
+ if (!wpa_s || !wpa_s->global)
+ return 0;
+ ctrl_iface = wpa_s->global->dbus;
+ if (!ctrl_iface)
+ return 0;
+
+ os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+ "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
+ wpa_s->dbus_new_path, MAC2STR(sta));
+
+ obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
+ if (!obj_desc) {
+ wpa_printf(MSG_ERROR,
+ "Not enough memory to create object description");
+ goto err;
+ }
+
+ arg = os_zalloc(sizeof(struct sta_handler_args));
+ if (!arg) {
+ wpa_printf(MSG_ERROR,
+ "Not enough memory to create arguments for handler");
+ goto err;
+ }
+ arg->wpa_s = wpa_s;
+ arg->sta = sta;
+
+ wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
+ wpas_dbus_sta_properties, wpas_dbus_sta_signals);
+
+ wpa_printf(MSG_DEBUG, "dbus: Register STA object '%s'",
+ station_obj_path);
+ if (wpa_dbus_register_object_per_iface(ctrl_iface, station_obj_path,
+ wpa_s->ifname, obj_desc)) {
+ wpa_printf(MSG_ERROR,
+ "Cannot register STA dbus object %s",
+ station_obj_path);
+ goto err;
+ }
+
+ wpas_dbus_signal_station_added(wpa_s, station_obj_path);
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
+
+ return 0;
+
+err:
+ free_dbus_object_desc(obj_desc);
+ return -1;
+}
+
+
static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
{ "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
(WPADBusMethodHandler) wpas_dbus_handler_scan,
@@ -3071,6 +3529,20 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
END_ARGS
}
},
+ { "TDLSChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_tdls_channel_switch,
+ {
+ { "args", "a{sv}", ARG_IN },
+ END_ARGS
+ }
+ },
+ { "TDLSCancelChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_tdls_cancel_channel_switch,
+ {
+ { "peer_address", "s", ARG_IN },
+ END_ARGS
+ }
+ },
#endif /* CONFIG_TDLS */
{ "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
(WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
@@ -3104,6 +3576,12 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
}
},
#endif /* CONFIG_NO_CONFIG_WRITE */
+ { "AbortScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_abort_scan,
+ {
+ END_ARGS
+ }
+ },
{ NULL, NULL, NULL, { END_ARGS } }
};
@@ -3224,6 +3702,42 @@ static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
wpas_dbus_setter_config_methods,
NULL
},
+ {
+ "DeviceName", WPAS_DBUS_NEW_IFACE_WPS, "s",
+ wpas_dbus_getter_wps_device_name,
+ wpas_dbus_setter_wps_device_name,
+ NULL
+ },
+ {
+ "Manufacturer", WPAS_DBUS_NEW_IFACE_WPS, "s",
+ wpas_dbus_getter_wps_manufacturer,
+ wpas_dbus_setter_wps_manufacturer,
+ NULL
+ },
+ {
+ "ModelName", WPAS_DBUS_NEW_IFACE_WPS, "s",
+ wpas_dbus_getter_wps_device_model_name,
+ wpas_dbus_setter_wps_device_model_name,
+ NULL
+ },
+ {
+ "ModelNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
+ wpas_dbus_getter_wps_device_model_number,
+ wpas_dbus_setter_wps_device_model_number,
+ NULL
+ },
+ {
+ "SerialNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
+ wpas_dbus_getter_wps_device_serial_number,
+ wpas_dbus_setter_wps_device_serial_number,
+ NULL
+ },
+ {
+ "DeviceType", WPAS_DBUS_NEW_IFACE_WPS, "ay",
+ wpas_dbus_getter_wps_device_device_type,
+ wpas_dbus_setter_wps_device_device_type,
+ NULL
+ },
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
{ "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
@@ -3262,11 +3776,33 @@ static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
NULL,
NULL
},
+ { "AuthStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
+ wpas_dbus_getter_auth_status_code,
+ NULL,
+ NULL
+ },
{ "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
wpas_dbus_getter_assoc_status_code,
NULL,
NULL
},
+#ifdef CONFIG_MESH
+ { "MeshPeers", WPAS_DBUS_NEW_IFACE_MESH, "aay",
+ wpas_dbus_getter_mesh_peers,
+ NULL,
+ NULL
+ },
+ { "MeshGroup", WPAS_DBUS_NEW_IFACE_MESH, "ay",
+ wpas_dbus_getter_mesh_group,
+ NULL,
+ NULL
+ },
+#endif /* CONFIG_MESH */
+ { "Stations", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
+ wpas_dbus_getter_stas,
+ NULL,
+ NULL
+ },
{ NULL, NULL, NULL, NULL, NULL, NULL }
};
@@ -3536,6 +4072,19 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
END_ARGS
}
},
+ { "StationAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ {
+ { "path", "o", ARG_OUT },
+ { "properties", "a{sv}", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { "StationRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ {
+ { "path", "o", ARG_OUT },
+ END_ARGS
+ }
+ },
{ "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
{
{ "path", "o", ARG_OUT },
@@ -3544,6 +4093,32 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
END_ARGS
}
},
+#ifdef CONFIG_MESH
+ { "MeshGroupStarted", WPAS_DBUS_NEW_IFACE_MESH,
+ {
+ { "args", "a{sv}", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { "MeshGroupRemoved", WPAS_DBUS_NEW_IFACE_MESH,
+ {
+ { "args", "a{sv}", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { "MeshPeerConnected", WPAS_DBUS_NEW_IFACE_MESH,
+ {
+ { "args", "a{sv}", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { "MeshPeerDisconnected", WPAS_DBUS_NEW_IFACE_MESH,
+ {
+ { "args", "a{sv}", ARG_OUT },
+ END_ARGS
+ }
+ },
+#endif /* CONFIG_MESH */
{ NULL, NULL, { END_ARGS } }
};
@@ -3790,6 +4365,11 @@ static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
NULL,
NULL
},
+ { "VSIE", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
+ wpas_dbus_getter_p2p_peer_vsie,
+ NULL,
+ NULL
+ },
{ NULL, NULL, NULL, NULL, NULL, NULL }
};
@@ -3818,7 +4398,7 @@ static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
*/
static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
const u8 *dev_addr, const char *interface,
- const char *sig_name, int properties)
+ const char *sig_name, dbus_bool_t properties)
{
struct wpas_dbus_priv *iface;
DBusMessage *msg;
@@ -4012,7 +4592,13 @@ void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
iface = wpa_s->global->dbus;
/* Do nothing if the control interface is not turned on */
- if (iface == NULL || !wpa_s->dbus_new_path)
+ if (iface == NULL)
+ return;
+
+ if (wpa_s->p2p_mgmt)
+ wpa_s = wpa_s->parent;
+
+ if (!wpa_s->dbus_new_path)
return;
msg = dbus_message_new_signal(wpa_s->dbus_new_path,
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new.h b/contrib/wpa/wpa_supplicant/dbus/dbus_new.h
index d64fceef718c..42db3892ed77 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_new.h
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new.h
@@ -28,8 +28,14 @@ enum wpas_dbus_prop {
WPAS_DBUS_PROP_CURRENT_NETWORK,
WPAS_DBUS_PROP_CURRENT_AUTH_MODE,
WPAS_DBUS_PROP_BSSS,
+ WPAS_DBUS_PROP_STATIONS,
WPAS_DBUS_PROP_DISCONNECT_REASON,
+ WPAS_DBUS_PROP_AUTH_STATUS_CODE,
WPAS_DBUS_PROP_ASSOC_STATUS_CODE,
+ WPAS_DBUS_PROP_ROAM_TIME,
+ WPAS_DBUS_PROP_ROAM_COMPLETE,
+ WPAS_DBUS_PROP_SESSION_LENGTH,
+ WPAS_DBUS_PROP_BSS_TM_STATUS,
};
enum wpas_dbus_bss_prop {
@@ -45,6 +51,10 @@ enum wpas_dbus_bss_prop {
WPAS_DBUS_BSS_PROP_AGE,
};
+enum wpas_dbus_sta_prop {
+ WPAS_DBUS_STA_PROP_ADDRESS,
+};
+
#define WPAS_DBUS_OBJECT_PATH_MAX 150
#define WPAS_DBUS_NEW_SERVICE "fi.w1.wpa_supplicant1"
@@ -61,9 +71,14 @@ enum wpas_dbus_bss_prop {
#define WPAS_DBUS_NEW_BSSIDS_PART "BSSs"
#define WPAS_DBUS_NEW_IFACE_BSS WPAS_DBUS_NEW_INTERFACE ".BSS"
+#define WPAS_DBUS_NEW_STAS_PART "Stations"
+#define WPAS_DBUS_NEW_IFACE_STA WPAS_DBUS_NEW_INTERFACE ".Station"
+
#define WPAS_DBUS_NEW_IFACE_P2PDEVICE \
WPAS_DBUS_NEW_IFACE_INTERFACE ".P2PDevice"
+#define WPAS_DBUS_NEW_IFACE_MESH WPAS_DBUS_NEW_IFACE_INTERFACE ".Mesh"
+
/*
* Groups correspond to P2P groups where this device is a GO (owner)
*/
@@ -161,6 +176,8 @@ int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
u8 bssid[ETH_ALEN], unsigned int id);
int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
u8 bssid[ETH_ALEN], unsigned int id);
+int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta);
+int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta);
void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
const char *name);
void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
@@ -190,7 +207,8 @@ void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
const u8 *src, u16 dev_passwd_id,
u8 go_intent);
void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
- int client, int persistent);
+ int client, int persistent,
+ const u8 *ip);
void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
const char *reason);
void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
@@ -237,6 +255,15 @@ void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
const u8 *sa, const u8 *dev_addr,
const u8 *bssid, int id,
int op_freq);
+void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
+void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s,
+ const u8 *meshid, u8 meshid_len,
+ int reason);
+void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr);
+void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr, int reason);
#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
@@ -333,6 +360,18 @@ static inline int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
return 0;
}
+static inline int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s,
+ const u8 *sta)
+{
+ return 0;
+}
+
+static inline int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s,
+ const u8 *sta)
+{
+ return 0;
+}
+
static inline void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
const char *name)
{
@@ -400,7 +439,8 @@ static inline void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
static inline void
wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
- int client, int persistent)
+ int client, int persistent,
+ const u8 *ip)
{
}
@@ -551,6 +591,31 @@ void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
{
}
+static inline
+void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+}
+
+static inline
+void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s,
+ const u8 *meshid, u8 meshid_len,
+ int reason)
+{
+}
+
+static inline
+void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr)
+{
+}
+
+static inline
+void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr, int reason)
+{
+}
+
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
#endif /* CTRL_IFACE_DBUS_H_NEW */
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c
index e11dd36ca23c..6c36d91a0cf8 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -15,6 +15,9 @@
#include "eap_peer/eap_methods.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "rsn_supp/wpa.h"
+#include "ap/hostapd.h"
+#include "ap/sta_info.h"
+#include "ap/ap_drv_ops.h"
#include "../config.h"
#include "../wpa_supplicant_i.h"
#include "../driver_i.h"
@@ -22,12 +25,17 @@
#include "../bss.h"
#include "../scan.h"
#include "../autoscan.h"
+#include "../ap.h"
#include "dbus_new_helpers.h"
#include "dbus_new.h"
#include "dbus_new_handlers.h"
#include "dbus_dict_helpers.h"
#include "dbus_common_i.h"
#include "drivers/driver.h"
+#ifdef CONFIG_MESH
+#include "ap/hostapd.h"
+#include "ap/sta_info.h"
+#endif /* CONFIG_MESH */
static const char * const debug_strings[] = {
"excessive", "msgdump", "debug", "info", "warning", "error", NULL
@@ -517,6 +525,27 @@ dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
/**
+ * wpas_dbus_string_property_getter - Get string type property
+ * @iter: Message iter to use when appending arguments
+ * @val: Pointer to place holding property value, can be %NULL
+ * @error: On failure an error describing the failure
+ * Returns: TRUE if the request was successful, FALSE if it failed
+ *
+ * Generic getter for string type properties. %NULL is converted to an empty
+ * string.
+ */
+dbus_bool_t wpas_dbus_string_property_getter(DBusMessageIter *iter,
+ const void *val,
+ DBusError *error)
+{
+ if (!val)
+ val = "";
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
+ &val, error);
+}
+
+
+/**
* wpas_dbus_handler_create_interface - Request registration of a network iface
* @message: Pointer to incoming dbus message
* @global: %wpa_supplicant global data structure
@@ -955,8 +984,21 @@ dbus_bool_t wpas_dbus_getter_global_capabilities(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
- const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
+ const char *capabilities[10] = { NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL };
size_t num_items = 0;
+#ifdef CONFIG_FILS
+ struct wpa_global *global = user_data;
+ struct wpa_supplicant *wpa_s;
+ int fils_supported = 0, fils_sk_pfs_supported = 0;
+
+ for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+ if (wpa_is_fils_supported(wpa_s))
+ fils_supported = 1;
+ if (wpa_is_fils_sk_pfs_supported(wpa_s))
+ fils_sk_pfs_supported = 1;
+ }
+#endif /* CONFIG_FILS */
#ifdef CONFIG_AP
capabilities[num_items++] = "ap";
@@ -970,6 +1012,24 @@ dbus_bool_t wpas_dbus_getter_global_capabilities(
#ifdef CONFIG_INTERWORKING
capabilities[num_items++] = "interworking";
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_IEEE80211W
+ capabilities[num_items++] = "pmf";
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_MESH
+ capabilities[num_items++] = "mesh";
+#endif /* CONFIG_MESH */
+#ifdef CONFIG_FILS
+ if (fils_supported)
+ capabilities[num_items++] = "fils";
+ if (fils_sk_pfs_supported)
+ capabilities[num_items++] = "fils_sk_pfs";
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211R
+ capabilities[num_items++] = "ft";
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_SHA384
+ capabilities[num_items++] = "sha384";
+#endif /* CONFIG_SHA384 */
return wpas_dbus_simple_array_property_getter(iter,
DBUS_TYPE_STRING,
@@ -1052,12 +1112,11 @@ static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
}
if (len != 0) {
- ssid = os_malloc(len);
+ ssid = os_memdup(val, len);
if (ssid == NULL) {
*reply = wpas_dbus_error_no_memory(message);
return -1;
}
- os_memcpy(ssid, val, len);
} else {
/* Allow zero-length SSIDs */
ssid = NULL;
@@ -1396,6 +1455,27 @@ out:
}
+/*
+ * wpas_dbus_handler_abort_scan - Request an ongoing scan to be aborted
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: Abort failed or no scan in progress DBus error message on failure
+ * or NULL otherwise.
+ *
+ * Handler function for "AbortScan" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ if (wpas_abort_ongoing_scan(wpa_s) < 0)
+ return dbus_message_new_error(
+ message, WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
+ "Abort failed or no scan in progress");
+
+ return NULL;
+}
+
+
/**
* wpas_dbus_handler_signal_poll - Request immediate signal properties
* @message: Pointer to incoming dbus message
@@ -1903,13 +1983,12 @@ DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
goto err;
}
- blob->data = os_malloc(blob_len);
+ blob->data = os_memdup(blob_data, blob_len);
blob->name = os_strdup(blob_name);
if (!blob->data || !blob->name) {
reply = wpas_dbus_error_no_memory(message);
goto err;
}
- os_memcpy(blob->data, blob_data, blob_len);
blob->len = blob_len;
wpa_config_set_blob(wpa_s->conf, blob);
@@ -2270,6 +2349,156 @@ DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
return NULL;
}
+/*
+ * wpas_dbus_handler_tdls_channel_switch - Enable channel switching with TDLS peer
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL indicating success or DBus error message on failure
+ *
+ * Handler function for "TDLSChannelSwitch" method call of network interface.
+ */
+DBusMessage *
+wpas_dbus_handler_tdls_channel_switch(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ DBusMessageIter iter, iter_dict;
+ struct wpa_dbus_dict_entry entry;
+ u8 peer[ETH_ALEN];
+ struct hostapd_freq_params freq_params;
+ u8 oper_class = 0;
+ int ret;
+ int is_peer_present = 0;
+
+ if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
+ wpa_printf(MSG_INFO,
+ "tdls_chanswitch: Only supported with external setup");
+ return wpas_dbus_error_unknown_error(message, "TDLS is not using external setup");
+ }
+
+ os_memset(&freq_params, 0, sizeof(freq_params));
+
+ dbus_message_iter_init(message, &iter);
+
+ if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
+ return wpas_dbus_error_invalid_args(message, NULL);
+
+ while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+ if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+ return wpas_dbus_error_invalid_args(message, NULL);
+
+ if (os_strcmp(entry.key, "PeerAddress") == 0 &&
+ entry.type == DBUS_TYPE_STRING) {
+ if (hwaddr_aton(entry.str_value, peer)) {
+ wpa_printf(MSG_DEBUG,
+ "tdls_chanswitch: Invalid address '%s'",
+ entry.str_value);
+ wpa_dbus_dict_entry_clear(&entry);
+ return wpas_dbus_error_invalid_args(message,
+ NULL);
+ }
+
+ is_peer_present = 1;
+ } else if (os_strcmp(entry.key, "OperClass") == 0 &&
+ entry.type == DBUS_TYPE_BYTE) {
+ oper_class = entry.byte_value;
+ } else if (os_strcmp(entry.key, "Frequency") == 0 &&
+ entry.type == DBUS_TYPE_UINT32) {
+ freq_params.freq = entry.uint32_value;
+ } else if (os_strcmp(entry.key, "SecChannelOffset") == 0 &&
+ entry.type == DBUS_TYPE_UINT32) {
+ freq_params.sec_channel_offset = entry.uint32_value;
+ } else if (os_strcmp(entry.key, "CenterFrequency1") == 0 &&
+ entry.type == DBUS_TYPE_UINT32) {
+ freq_params.center_freq1 = entry.uint32_value;
+ } else if (os_strcmp(entry.key, "CenterFrequency2") == 0 &&
+ entry.type == DBUS_TYPE_UINT32) {
+ freq_params.center_freq2 = entry.uint32_value;
+ } else if (os_strcmp(entry.key, "Bandwidth") == 0 &&
+ entry.type == DBUS_TYPE_UINT32) {
+ freq_params.bandwidth = entry.uint32_value;
+ } else if (os_strcmp(entry.key, "HT") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ freq_params.ht_enabled = entry.bool_value;
+ } else if (os_strcmp(entry.key, "VHT") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ freq_params.vht_enabled = entry.bool_value;
+ } else {
+ wpa_dbus_dict_entry_clear(&entry);
+ return wpas_dbus_error_invalid_args(message, NULL);
+ }
+
+ wpa_dbus_dict_entry_clear(&entry);
+ }
+
+ if (oper_class == 0) {
+ wpa_printf(MSG_INFO,
+ "tdls_chanswitch: Invalid op class provided");
+ return wpas_dbus_error_invalid_args(
+ message, "Invalid op class provided");
+ }
+
+ if (freq_params.freq == 0) {
+ wpa_printf(MSG_INFO,
+ "tdls_chanswitch: Invalid freq provided");
+ return wpas_dbus_error_invalid_args(message,
+ "Invalid freq provided");
+ }
+
+ if (is_peer_present == 0) {
+ wpa_printf(MSG_DEBUG,
+ "tdls_chanswitch: peer address not provided");
+ return wpas_dbus_error_invalid_args(
+ message, "peer address not provided");
+ }
+
+ wpa_printf(MSG_DEBUG, "dbus: TDLS_CHAN_SWITCH " MACSTR
+ " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
+ MAC2STR(peer), oper_class, freq_params.freq,
+ freq_params.center_freq1, freq_params.center_freq2,
+ freq_params.bandwidth, freq_params.sec_channel_offset,
+ freq_params.ht_enabled ? " HT" : "",
+ freq_params.vht_enabled ? " VHT" : "");
+
+ ret = wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
+ &freq_params);
+ if (ret)
+ return wpas_dbus_error_unknown_error(
+ message, "error processing TDLS channel switch");
+
+ return NULL;
+}
+
+/*
+ * wpas_dbus_handler_tdls_cancel_channel_switch - Disable channel switching with TDLS peer
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL indicating success or DBus error message on failure
+ *
+ * Handler function for "TDLSCancelChannelSwitch" method call of network
+ * interface.
+ */
+DBusMessage *
+wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ u8 peer[ETH_ALEN];
+ DBusMessage *error_reply;
+ int ret;
+
+ if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
+ return error_reply;
+
+ wpa_printf(MSG_DEBUG, "dbus: TDLS_CANCEL_CHAN_SWITCH " MACSTR,
+ MAC2STR(peer));
+
+ ret = wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
+ if (ret)
+ return wpas_dbus_error_unknown_error(
+ message, "error canceling TDLS channel switch");
+
+ return NULL;
+}
+
#endif /* CONFIG_TDLS */
@@ -2468,6 +2697,28 @@ dbus_bool_t wpas_dbus_getter_capabilities(
goto nomem;
}
+ if (!wpa_dbus_dict_begin_string_array(&iter_dict, "GroupMgmt",
+ &iter_dict_entry,
+ &iter_dict_val,
+ &iter_array) ||
+ (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP) &&
+ !wpa_dbus_dict_string_array_add_element(
+ &iter_array, "aes-128-cmac")) ||
+ (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_128) &&
+ !wpa_dbus_dict_string_array_add_element(
+ &iter_array, "bip-gmac-128")) ||
+ (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_256) &&
+ !wpa_dbus_dict_string_array_add_element(
+ &iter_array, "bip-gmac-256")) ||
+ (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_CMAC_256) &&
+ !wpa_dbus_dict_string_array_add_element(
+ &iter_array, "bip-cmac-256")) ||
+ !wpa_dbus_dict_end_string_array(&iter_dict,
+ &iter_dict_entry,
+ &iter_dict_val,
+ &iter_array))
+ goto nomem;
+
/***** key management */
if (res < 0) {
const char *args[] = {
@@ -2627,6 +2878,11 @@ dbus_bool_t wpas_dbus_getter_capabilities(
!wpa_s->conf->p2p_disabled &&
!wpa_dbus_dict_string_array_add_element(
&iter_array, "p2p")) ||
+#ifdef CONFIG_MESH
+ (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_MESH) &&
+ !wpa_dbus_dict_string_array_add_element(
+ &iter_array, "mesh")) ||
+#endif /* CONFIG_MESH */
!wpa_dbus_dict_end_string_array(&iter_dict,
&iter_dict_entry,
&iter_dict_val,
@@ -2837,6 +3093,27 @@ dbus_bool_t wpas_dbus_getter_disconnect_reason(
/**
+ * wpas_dbus_getter_auth_status_code - Get most recent auth status code
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "AuthStatusCode" property.
+ */
+dbus_bool_t wpas_dbus_getter_auth_status_code(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ dbus_int32_t reason = wpa_s->auth_status_code;
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
+ &reason, error);
+}
+
+
+/**
* wpas_dbus_getter_assoc_status_code - Get most recent failed assoc status code
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
@@ -2858,6 +3135,97 @@ dbus_bool_t wpas_dbus_getter_assoc_status_code(
/**
+ * wpas_dbus_getter_roam_time - Get most recent roam time
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "RoamTime" property.
+ */
+dbus_bool_t wpas_dbus_getter_roam_time(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ dbus_uint32_t roam_time = wpa_s->roam_time.sec * 1000 +
+ wpa_s->roam_time.usec / 1000;
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
+ &roam_time, error);
+}
+
+
+/**
+ * wpas_dbus_getter_roam_complete - Get most recent roam success or failure
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "RoamComplete" property.
+ */
+dbus_bool_t wpas_dbus_getter_roam_complete(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ dbus_bool_t roam_complete = os_reltime_initialized(&wpa_s->roam_time);
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
+ &roam_complete, error);
+}
+
+
+/**
+ * wpas_dbus_getter_session_length - Get most recent BSS session length
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "SessionLength" property.
+ */
+dbus_bool_t wpas_dbus_getter_session_length(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ dbus_uint32_t session_length = wpa_s->session_length.sec * 1000 +
+ wpa_s->session_length.usec / 1000;
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
+ &session_length, error);
+}
+
+
+/**
+ * wpas_dbus_getter_bss_tm_status - Get most BSS Transition Management request
+ * status code
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "BSSTMStatus" property.
+ */
+dbus_bool_t wpas_dbus_getter_bss_tm_status(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_WNM
+ struct wpa_supplicant *wpa_s = user_data;
+ dbus_uint32_t bss_tm_status = wpa_s->bss_tm_status;
+#else /* CONFIG_WNM */
+ dbus_uint32_t bss_tm_status = 0;
+#endif /* CONFIG_WNM */
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
+ &bss_tm_status, error);
+}
+
+
+/**
* wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
@@ -3086,10 +3454,8 @@ dbus_bool_t wpas_dbus_getter_ifname(
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
- const char *ifname = wpa_s->ifname;
- return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
- &ifname, error);
+ return wpas_dbus_string_property_getter(iter, wpa_s->ifname, error);
}
@@ -3107,7 +3473,6 @@ dbus_bool_t wpas_dbus_getter_driver(
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
- const char *driver;
if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set",
@@ -3117,9 +3482,8 @@ dbus_bool_t wpas_dbus_getter_driver(
return FALSE;
}
- driver = wpa_s->driver->name;
- return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
- &driver, error);
+ return wpas_dbus_string_property_getter(iter, wpa_s->driver->name,
+ error);
}
@@ -3232,10 +3596,9 @@ dbus_bool_t wpas_dbus_getter_bridge_ifname(
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
- const char *bridge_ifname = wpa_s->bridge_ifname;
- return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
- &bridge_ifname, error);
+ return wpas_dbus_string_property_getter(iter, wpa_s->bridge_ifname,
+ error);
}
@@ -3253,13 +3616,8 @@ dbus_bool_t wpas_dbus_getter_config_file(
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
- char *confname = "";
-
- if (wpa_s->confname)
- confname = wpa_s->confname;
- return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
- &confname, error);
+ return wpas_dbus_string_property_getter(iter, wpa_s->confname, error);
}
@@ -3399,14 +3757,10 @@ dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
- const char *pkcs11_engine_path;
- if (wpa_s->conf->pkcs11_engine_path == NULL)
- pkcs11_engine_path = "";
- else
- pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
- return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
- &pkcs11_engine_path, error);
+ return wpas_dbus_string_property_getter(iter,
+ wpa_s->conf->pkcs11_engine_path,
+ error);
}
@@ -3424,14 +3778,10 @@ dbus_bool_t wpas_dbus_getter_pkcs11_module_path(
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
- const char *pkcs11_module_path;
- if (wpa_s->conf->pkcs11_module_path == NULL)
- pkcs11_module_path = "";
- else
- pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
- return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
- &pkcs11_module_path, error);
+ return wpas_dbus_string_property_getter(iter,
+ wpa_s->conf->pkcs11_module_path,
+ error);
}
@@ -3571,6 +3921,320 @@ dbus_bool_t wpas_dbus_setter_iface_global(
}
+/**
+ * wpas_dbus_getter_stas - Get connected stations for an interface
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: a list of stations
+ *
+ * Getter for "Stations" property.
+ */
+dbus_bool_t wpas_dbus_getter_stas(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ struct sta_info *sta = NULL;
+ char **paths = NULL;
+ unsigned int i = 0, num = 0;
+ dbus_bool_t success = FALSE;
+
+ if (!wpa_s->dbus_new_path) {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "%s: no D-Bus interface", __func__);
+ return FALSE;
+ }
+
+#ifdef CONFIG_AP
+ if (wpa_s->ap_iface) {
+ struct hostapd_data *hapd;
+
+ hapd = wpa_s->ap_iface->bss[0];
+ sta = hapd->sta_list;
+ num = hapd->num_sta;
+ }
+#endif /* CONFIG_AP */
+
+ paths = os_calloc(num, sizeof(char *));
+ if (!paths) {
+ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
+ return FALSE;
+ }
+
+ /* Loop through scan results and append each result's object path */
+ for (; sta; sta = sta->next) {
+ paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
+ if (!paths[i]) {
+ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
+ "no memory");
+ goto out;
+ }
+ /* Construct the object path for this BSS. */
+ os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
+ "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
+ wpa_s->dbus_new_path, MAC2STR(sta->addr));
+ }
+
+ success = wpas_dbus_simple_array_property_getter(iter,
+ DBUS_TYPE_OBJECT_PATH,
+ paths, num,
+ error);
+
+out:
+ while (i)
+ os_free(paths[--i]);
+ os_free(paths);
+ return success;
+}
+
+
+/**
+ * wpas_dbus_getter_sta_address - Return the address of a connected station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "Address" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_address(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+ struct sta_handler_args *args = user_data;
+ struct sta_info *sta;
+
+ sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
+ if (!sta)
+ return FALSE;
+
+ return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
+ sta->addr, ETH_ALEN,
+ error);
+#else /* CONFIG_AP */
+ return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
+/**
+ * wpas_dbus_getter_sta_aid - Return the AID of a connected station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "AID" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_aid(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+ struct sta_handler_args *args = user_data;
+ struct sta_info *sta;
+
+ sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
+ if (!sta)
+ return FALSE;
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
+ &sta->aid,
+ error);
+#else /* CONFIG_AP */
+ return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
+/**
+ * wpas_dbus_getter_sta_caps - Return the capabilities of a station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "Capabilities" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_caps(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+ struct sta_handler_args *args = user_data;
+ struct sta_info *sta;
+
+ sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta);
+ if (!sta)
+ return FALSE;
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
+ &sta->capability,
+ error);
+#else /* CONFIG_AP */
+ return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
+/**
+ * wpas_dbus_getter_rx_packets - Return the received packets for a station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "RxPackets" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_rx_packets(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+ struct sta_handler_args *args = user_data;
+ struct sta_info *sta;
+ struct hostap_sta_driver_data data;
+ struct hostapd_data *hapd;
+
+ if (!args->wpa_s->ap_iface)
+ return FALSE;
+
+ hapd = args->wpa_s->ap_iface->bss[0];
+ sta = ap_get_sta(hapd, args->sta);
+ if (!sta)
+ return FALSE;
+
+ if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
+ return FALSE;
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
+ &data.rx_packets,
+ error);
+#else /* CONFIG_AP */
+ return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
+/**
+ * wpas_dbus_getter_tx_packets - Return the transmitted packets for a station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "TxPackets" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_tx_packets(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+ struct sta_handler_args *args = user_data;
+ struct sta_info *sta;
+ struct hostap_sta_driver_data data;
+ struct hostapd_data *hapd;
+
+ if (!args->wpa_s->ap_iface)
+ return FALSE;
+
+ hapd = args->wpa_s->ap_iface->bss[0];
+ sta = ap_get_sta(hapd, args->sta);
+ if (!sta)
+ return FALSE;
+
+ if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
+ return FALSE;
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
+ &data.tx_packets,
+ error);
+#else /* CONFIG_AP */
+ return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
+/**
+ * wpas_dbus_getter_tx_bytes - Return the transmitted bytes for a station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "TxBytes" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_tx_bytes(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+ struct sta_handler_args *args = user_data;
+ struct sta_info *sta;
+ struct hostap_sta_driver_data data;
+ struct hostapd_data *hapd;
+
+ if (!args->wpa_s->ap_iface)
+ return FALSE;
+
+ hapd = args->wpa_s->ap_iface->bss[0];
+ sta = ap_get_sta(hapd, args->sta);
+ if (!sta)
+ return FALSE;
+
+ if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
+ return FALSE;
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
+ &data.tx_bytes,
+ error);
+#else /* CONFIG_AP */
+ return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
+/**
+ * wpas_dbus_getter_rx_bytes - Return the received bytes for a station
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "RxBytes" property.
+ */
+dbus_bool_t wpas_dbus_getter_sta_rx_bytes(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+#ifdef CONFIG_AP
+ struct sta_handler_args *args = user_data;
+ struct sta_info *sta;
+ struct hostap_sta_driver_data data;
+ struct hostapd_data *hapd;
+
+ if (!args->wpa_s->ap_iface)
+ return FALSE;
+
+ hapd = args->wpa_s->ap_iface->bss[0];
+ sta = ap_get_sta(hapd, args->sta);
+ if (!sta)
+ return FALSE;
+
+ if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
+ return FALSE;
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64,
+ &data.rx_bytes,
+ error);
+#else /* CONFIG_AP */
+ return FALSE;
+#endif /* CONFIG_AP */
+}
+
+
static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
DBusError *error, const char *func_name)
{
@@ -3683,6 +4347,7 @@ dbus_bool_t wpas_dbus_getter_bss_mode(
struct bss_handler_args *args = user_data;
struct wpa_bss *res;
const char *mode;
+ const u8 *mesh;
res = get_bss_helper(args, error, __func__);
if (!res)
@@ -3696,9 +4361,15 @@ dbus_bool_t wpas_dbus_getter_bss_mode(
case IEEE80211_CAP_DMG_AP:
mode = "infrastructure";
break;
+ default:
+ mode = "";
+ break;
}
} else {
- if (res->caps & IEEE80211_CAP_IBSS)
+ mesh = wpa_bss_get_ie(res, WLAN_EID_MESH_ID);
+ if (mesh)
+ mode = "mesh";
+ else if (res->caps & IEEE80211_CAP_IBSS)
mode = "ad-hoc";
else
mode = "infrastructure";
@@ -3826,7 +4497,7 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop(
DBusMessageIter iter_dict, variant_iter;
const char *group;
const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
- const char *key_mgmt[9]; /* max 9 key managements may be supported */
+ const char *key_mgmt[15]; /* max 15 key managements may be supported */
int n;
if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
@@ -3836,7 +4507,12 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop(
if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
goto nomem;
- /* KeyMgmt */
+ /*
+ * KeyMgmt
+ *
+ * When adding a new entry here, please take care to extend key_mgmt[]
+ * and keep documentation in doc/dbus.doxygen up to date.
+ */
n = 0;
if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
key_mgmt[n++] = "wpa-psk";
@@ -3858,6 +4534,22 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop(
if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
key_mgmt[n++] = "wpa-eap-suite-b-192";
#endif /* CONFIG_SUITEB192 */
+#ifdef CONFIG_FILS
+ if (ie_data->key_mgmt & WPA_KEY_MGMT_FILS_SHA256)
+ key_mgmt[n++] = "wpa-fils-sha256";
+ if (ie_data->key_mgmt & WPA_KEY_MGMT_FILS_SHA384)
+ key_mgmt[n++] = "wpa-fils-sha384";
+ if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256)
+ key_mgmt[n++] = "wpa-ft-fils-sha256";
+ if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384)
+ key_mgmt[n++] = "wpa-ft-fils-sha384";
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_SAE
+ if (ie_data->key_mgmt & WPA_KEY_MGMT_SAE)
+ key_mgmt[n++] = "sae";
+ if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_SAE)
+ key_mgmt[n++] = "ft-sae";
+#endif /* CONFIG_SAE */
if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
key_mgmt[n++] = "wpa-none";
@@ -4534,3 +5226,100 @@ DBusMessage * wpas_dbus_handler_vendor_elem_remove(DBusMessage *message,
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Not found");
}
+
+
+#ifdef CONFIG_MESH
+
+/**
+ * wpas_dbus_getter_mesh_peers - Get connected mesh peers
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "MeshPeers" property.
+ */
+dbus_bool_t wpas_dbus_getter_mesh_peers(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ struct hostapd_data *hapd;
+ struct sta_info *sta;
+ DBusMessageIter variant_iter, array_iter;
+ int i;
+ DBusMessageIter inner_array_iter;
+
+ if (!wpa_s->ifmsh)
+ return FALSE;
+ hapd = wpa_s->ifmsh->bss[0];
+
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_TYPE_BYTE_AS_STRING,
+ &variant_iter) ||
+ !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_TYPE_BYTE_AS_STRING,
+ &array_iter))
+ return FALSE;
+
+ for (sta = hapd->sta_list; sta; sta = sta->next) {
+ if (!dbus_message_iter_open_container(
+ &array_iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_BYTE_AS_STRING,
+ &inner_array_iter))
+ return FALSE;
+
+ for (i = 0; i < ETH_ALEN; i++) {
+ if (!dbus_message_iter_append_basic(&inner_array_iter,
+ DBUS_TYPE_BYTE,
+ &(sta->addr[i])))
+ return FALSE;
+ }
+
+ if (!dbus_message_iter_close_container(
+ &array_iter, &inner_array_iter))
+ return FALSE;
+ }
+
+ if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
+ !dbus_message_iter_close_container(iter, &variant_iter))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/**
+ * wpas_dbus_getter_mesh_group - Get mesh group
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "MeshGroup" property.
+ */
+dbus_bool_t wpas_dbus_getter_mesh_group(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+
+ if (!wpa_s->ifmsh || !ssid)
+ return FALSE;
+
+ if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
+ (char *) ssid->ssid,
+ ssid->ssid_len, error)) {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "%s: error constructing reply", __func__);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#endif /* CONFIG_MESH */
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h
index 1d6235d6f3e4..d922ce1b4189 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -22,6 +22,11 @@ struct bss_handler_args {
unsigned int id;
};
+struct sta_handler_args {
+ struct wpa_supplicant *wpa_s;
+ const u8 *sta;
+};
+
dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
const int type,
const void *val,
@@ -43,6 +48,10 @@ dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
size_t array_len,
DBusError *error);
+dbus_bool_t wpas_dbus_string_property_getter(DBusMessageIter *iter,
+ const void *val,
+ DBusError *error);
+
DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
struct wpa_global *global);
@@ -70,6 +79,9 @@ DECLARE_ACCESSOR(wpas_dbus_setter_iface_global);
DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
struct wpa_supplicant *wpa_s);
+DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message,
+ struct wpa_supplicant *wpa_s);
+
DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
struct wpa_supplicant *wpa_s);
@@ -138,7 +150,12 @@ DECLARE_ACCESSOR(wpas_dbus_getter_fast_reauth);
DECLARE_ACCESSOR(wpas_dbus_setter_fast_reauth);
DECLARE_ACCESSOR(wpas_dbus_getter_disconnect_reason);
DECLARE_ACCESSOR(wpas_dbus_getter_disassociate_reason);
+DECLARE_ACCESSOR(wpas_dbus_getter_auth_status_code);
DECLARE_ACCESSOR(wpas_dbus_getter_assoc_status_code);
+DECLARE_ACCESSOR(wpas_dbus_getter_roam_time);
+DECLARE_ACCESSOR(wpas_dbus_getter_roam_complete);
+DECLARE_ACCESSOR(wpas_dbus_getter_session_length);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_tm_status);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_expire_age);
DECLARE_ACCESSOR(wpas_dbus_setter_bss_expire_age);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_expire_count);
@@ -159,6 +176,14 @@ DECLARE_ACCESSOR(wpas_dbus_getter_networks);
DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_engine_path);
DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_module_path);
DECLARE_ACCESSOR(wpas_dbus_getter_blobs);
+DECLARE_ACCESSOR(wpas_dbus_getter_stas);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_address);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_aid);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_caps);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_rx_packets);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_tx_packets);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_tx_bytes);
+DECLARE_ACCESSOR(wpas_dbus_getter_sta_rx_bytes);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_bssid);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_ssid);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_privacy);
@@ -186,6 +211,21 @@ DECLARE_ACCESSOR(wpas_dbus_getter_process_credentials);
DECLARE_ACCESSOR(wpas_dbus_setter_process_credentials);
DECLARE_ACCESSOR(wpas_dbus_getter_config_methods);
DECLARE_ACCESSOR(wpas_dbus_setter_config_methods);
+DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_name);
+DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_name);
+DECLARE_ACCESSOR(wpas_dbus_getter_wps_manufacturer);
+DECLARE_ACCESSOR(wpas_dbus_setter_wps_manufacturer);
+DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_model_name);
+DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_model_name);
+DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_model_number);
+DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_model_number);
+DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_serial_number);
+DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_serial_number);
+DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_device_type);
+DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_device_type);
+
+DECLARE_ACCESSOR(wpas_dbus_getter_mesh_peers);
+DECLARE_ACCESSOR(wpas_dbus_getter_mesh_group);
DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
struct wpa_supplicant *wpa_s);
@@ -195,6 +235,12 @@ DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
struct wpa_supplicant *wpa_s);
+DBusMessage *
+wpas_dbus_handler_tdls_channel_switch(DBusMessage *message,
+ struct wpa_supplicant *wpa_s);
+DBusMessage *
+wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage *message,
+ struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
struct wpa_supplicant *wpa_s);
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 73b9e20c20b0..8cdd885644af 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -28,6 +28,18 @@
#include "../p2p_supplicant.h"
#include "../wifi_display.h"
+
+static int wpas_dbus_validate_dbus_ipaddr(struct wpa_dbus_dict_entry entry)
+{
+ if (entry.type != DBUS_TYPE_ARRAY ||
+ entry.array_type != DBUS_TYPE_BYTE ||
+ entry.array_len != 4)
+ return 0;
+
+ return 1;
+}
+
+
/**
* Parses out the mac address from the peer object path.
* @peer_path - object path of the form
@@ -78,6 +90,7 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
int num_req_dev_types = 0;
unsigned int i;
u8 *req_dev_types = NULL;
+ unsigned int freq = 0;
dbus_message_iter_init(message, &iter);
entry.key = NULL;
@@ -122,6 +135,10 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
type = P2P_FIND_PROGRESSIVE;
else
goto error_clear;
+ } else if (os_strcmp(entry.key, "freq") == 0 &&
+ (entry.type == DBUS_TYPE_INT32 ||
+ entry.type == DBUS_TYPE_UINT32)) {
+ freq = entry.uint32_value;
} else
goto error_clear;
wpa_dbus_dict_entry_clear(&entry);
@@ -129,8 +146,11 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
wpa_s = wpa_s->global->p2p_init_wpa_s;
- wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types,
- NULL, 0, 0, NULL, 0);
+ if (wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types,
+ req_dev_types, NULL, 0, 0, NULL, freq))
+ reply = wpas_dbus_error_unknown_error(
+ message, "Could not start P2P find");
+
os_free(req_dev_types);
return reply;
@@ -364,14 +384,14 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
goto inv_args;
if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
- 0, 0, NULL, 0, 0)) {
+ 0, 0, 0, NULL, 0, 0)) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
goto out;
}
} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0,
- 0))
+ 0, 0))
goto inv_args;
out:
@@ -485,6 +505,7 @@ DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
wpa_s = wpa_s->global->p2p_init_wpa_s;
+ wpas_p2p_stop_find(wpa_s);
os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
wpa_s->force_long_sd = 0;
p2p_flush(wpa_s->global->p2p);
@@ -512,6 +533,7 @@ DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
int new_pin;
char *err_msg = NULL;
char *iface = NULL;
+ int ret;
if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
return reply;
@@ -583,13 +605,19 @@ DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
persistent_group, 0, join, authorize_only,
- go_intent, freq, 0, -1, 0, 0, 0, 0, NULL, 0);
+ go_intent, freq, 0, -1, 0, 0, 0, 0, 0,
+ NULL, 0);
if (new_pin >= 0) {
char npin[9];
char *generated_pin;
- os_snprintf(npin, sizeof(npin), "%08d", new_pin);
+ ret = os_snprintf(npin, sizeof(npin), "%08d", new_pin);
+ if (os_snprintf_error(sizeof(npin), ret)) {
+ reply = wpas_dbus_error_unknown_error(message,
+ "invalid PIN");
+ goto out;
+ }
generated_pin = npin;
reply = dbus_message_new_method_return(message);
dbus_message_append_args(reply, DBUS_TYPE_STRING,
@@ -735,7 +763,7 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
goto err;
if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
- 0) < 0) {
+ 0, 0) < 0) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
@@ -867,6 +895,35 @@ dbus_bool_t wpas_dbus_getter_p2p_device_config(
goto err_no_mem;
}
+ /* GO IP address */
+ if (WPA_GET_BE32(wpa_s->conf->ip_addr_go) &&
+ !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
+ (char *) wpa_s->conf->ip_addr_go,
+ 4))
+ goto err_no_mem;
+
+ /* IP address mask */
+ if (WPA_GET_BE32(wpa_s->conf->ip_addr_mask) &&
+ !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
+ (char *) wpa_s->conf->ip_addr_mask,
+ 4))
+ goto err_no_mem;
+
+ /* IP address start */
+ if (WPA_GET_BE32(wpa_s->conf->ip_addr_start) &&
+ !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrStart",
+ (char *)
+ wpa_s->conf->ip_addr_start,
+ 4))
+ goto err_no_mem;
+
+ /* IP address end */
+ if (WPA_GET_BE32(wpa_s->conf->ip_addr_end) &&
+ !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrEnd",
+ (char *) wpa_s->conf->ip_addr_end,
+ 4))
+ goto err_no_mem;
+
/* Vendor Extensions */
for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
if (wpa_s->conf->wps_vendor_ext[i] == NULL)
@@ -1051,6 +1108,26 @@ dbus_bool_t wpas_dbus_setter_p2p_device_config(
wpa_s->conf->p2p_intra_bss = entry.bool_value;
wpa_s->conf->changed_parameters |=
CFG_CHANGED_P2P_INTRA_BSS;
+ } else if (os_strcmp(entry.key, "IpAddrGo") == 0) {
+ if (!wpas_dbus_validate_dbus_ipaddr(entry))
+ goto error;
+ os_memcpy(wpa_s->conf->ip_addr_go,
+ entry.bytearray_value, 4);
+ } else if (os_strcmp(entry.key, "IpAddrMask") == 0) {
+ if (!wpas_dbus_validate_dbus_ipaddr(entry))
+ goto error;
+ os_memcpy(wpa_s->conf->ip_addr_mask,
+ entry.bytearray_value, 4);
+ } else if (os_strcmp(entry.key, "IpAddrStart") == 0) {
+ if (!wpas_dbus_validate_dbus_ipaddr(entry))
+ goto error;
+ os_memcpy(wpa_s->conf->ip_addr_start,
+ entry.bytearray_value, 4);
+ } else if (os_strcmp(entry.key, "IpAddrEnd") == 0) {
+ if (!wpas_dbus_validate_dbus_ipaddr(entry))
+ goto error;
+ os_memcpy(wpa_s->conf->ip_addr_end,
+ entry.bytearray_value, 4);
} else if (os_strcmp(entry.key, "GroupIdle") == 0 &&
entry.type == DBUS_TYPE_UINT32)
wpa_s->conf->p2p_group_idle = entry.uint32_value;
@@ -1841,6 +1918,30 @@ out:
return success;
}
+dbus_bool_t wpas_dbus_getter_p2p_peer_vsie(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct peer_handler_args *peer_args = user_data;
+ const struct p2p_peer_info *info;
+
+ info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+ peer_args->p2p_device_addr, 0);
+ if (!info) {
+ dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
+ return FALSE;
+ }
+
+ if (!info->vendor_elems)
+ return wpas_dbus_simple_array_property_getter(iter,
+ DBUS_TYPE_BYTE,
+ NULL, 0, error);
+
+ return wpas_dbus_simple_array_property_getter(
+ iter, DBUS_TYPE_BYTE, (char *) info->vendor_elems->buf,
+ info->vendor_elems->used, error);
+}
+
/**
* wpas_dbus_getter_persistent_groups - Get array of persistent group objects
@@ -2286,19 +2387,12 @@ dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
- char *p_pass;
struct wpa_ssid *ssid = wpa_s->current_ssid;
if (ssid == NULL)
return FALSE;
- p_pass = ssid->passphrase;
- if (!p_pass)
- p_pass = "";
-
- return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
- &p_pass, error);
-
+ return wpas_dbus_string_property_getter(iter, ssid->passphrase, error);
}
@@ -2599,7 +2693,7 @@ DBusMessage * wpas_dbus_handler_p2p_delete_service(
if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
goto error;
- if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+ while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
goto error;
@@ -2611,26 +2705,27 @@ DBusMessage * wpas_dbus_handler_p2p_delete_service(
bonjour = 1;
else
goto error_clear;
- wpa_dbus_dict_entry_clear(&entry);
- }
- }
- if (upnp == 1) {
- while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
- if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
- goto error;
- if (os_strcmp(entry.key, "version") == 0 &&
- entry.type == DBUS_TYPE_INT32)
- version = entry.uint32_value;
- else if (os_strcmp(entry.key, "service") == 0 &&
- entry.type == DBUS_TYPE_STRING) {
- os_free(service);
- service = os_strdup(entry.str_value);
- } else
+ } else if (os_strcmp(entry.key, "version") == 0 &&
+ entry.type == DBUS_TYPE_INT32) {
+ version = entry.uint32_value;
+ } else if (os_strcmp(entry.key, "service") == 0 &&
+ entry.type == DBUS_TYPE_STRING) {
+ os_free(service);
+ service = os_strdup(entry.str_value);
+ } else if (os_strcmp(entry.key, "query") == 0) {
+ if (entry.type != DBUS_TYPE_ARRAY ||
+ entry.array_type != DBUS_TYPE_BYTE)
goto error_clear;
-
- wpa_dbus_dict_entry_clear(&entry);
+ wpabuf_free(query);
+ query = wpabuf_alloc_copy(entry.bytearray_value,
+ entry.array_len);
+ } else {
+ goto error_clear;
}
+ wpa_dbus_dict_entry_clear(&entry);
+ }
+ if (upnp == 1) {
if (version <= 0 || service == NULL)
goto error;
@@ -2638,24 +2733,6 @@ DBusMessage * wpas_dbus_handler_p2p_delete_service(
if (ret != 0)
goto error;
} else if (bonjour == 1) {
- while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
- if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
- goto error;
-
- if (os_strcmp(entry.key, "query") == 0) {
- if (entry.type != DBUS_TYPE_ARRAY ||
- entry.array_type != DBUS_TYPE_BYTE)
- goto error_clear;
- wpabuf_free(query);
- query = wpabuf_alloc_copy(
- entry.bytearray_value,
- entry.array_len);
- } else
- goto error_clear;
-
- wpa_dbus_dict_entry_clear(&entry);
- }
-
if (query == NULL)
goto error;
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.h b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
index c4c02615dbc3..b3c45c11012c 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
@@ -114,6 +114,7 @@ DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_vendor_extension);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_ies);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_device_address);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_groups);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_vsie);
/*
* P2P Group properties
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_wps.c b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_wps.c
index f16e2290c7ed..1594dafc7bb5 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_wps.c
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_wps.c
@@ -286,10 +286,14 @@ DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message,
ret = wpas_wps_start_pin(wpa_s, params.bssid,
params.pin, 0,
DEV_PW_DEFAULT);
- if (ret > 0)
- os_snprintf(npin, sizeof(npin), "%08d", ret);
+ if (ret > 0) {
+ ret = os_snprintf(npin, sizeof(npin), "%08d", ret);
+ if (os_snprintf_error(sizeof(npin), ret))
+ return wpas_dbus_error_unknown_error(
+ message, "invalid PIN");
+ }
} else {
- ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0);
+ ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0, 0);
}
if (ret < 0) {
@@ -412,12 +416,10 @@ dbus_bool_t wpas_dbus_getter_config_methods(
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
- char *methods = wpa_s->conf->config_methods;
- if (methods == NULL)
- methods = "";
- return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
- &methods, error);
+ return wpas_dbus_string_property_getter(iter,
+ wpa_s->conf->config_methods,
+ error);
}
@@ -454,3 +456,349 @@ dbus_bool_t wpas_dbus_setter_config_methods(
return TRUE;
}
+
+
+/**
+ * wpas_dbus_getter_wps_device_name - Get current WPS device name
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "DeviceName" property.
+ */
+dbus_bool_t wpas_dbus_getter_wps_device_name(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+
+ return wpas_dbus_string_property_getter(iter, wpa_s->conf->device_name,
+ error);
+}
+
+
+/**
+ * wpas_dbus_setter_wps_device_name - Set current WPS device name
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Setter for "DeviceName" property.
+ */
+dbus_bool_t wpas_dbus_setter_wps_device_name(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ char *methods, *devname;
+
+ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
+ &methods))
+ return FALSE;
+
+ if (os_strlen(methods) > WPS_DEV_NAME_MAX_LEN)
+ return FALSE;
+
+ devname = os_strdup(methods);
+ if (!devname)
+ return FALSE;
+
+ os_free(wpa_s->conf->device_name);
+ wpa_s->conf->device_name = devname;
+ wpa_s->conf->changed_parameters |= CFG_CHANGED_DEVICE_NAME;
+ wpa_supplicant_update_config(wpa_s);
+
+ return TRUE;
+}
+
+
+/**
+ * wpas_dbus_getter_wps_manufacturer - Get current manufacturer name
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "Manufacturer" property.
+ */
+dbus_bool_t wpas_dbus_getter_wps_manufacturer(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+
+ return wpas_dbus_string_property_getter(iter, wpa_s->conf->manufacturer,
+ error);
+}
+
+
+/**
+ * wpas_dbus_setter_wps_manufacturer - Set current manufacturer name
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Setter for "Manufacturer" property.
+ */
+dbus_bool_t wpas_dbus_setter_wps_manufacturer(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ char *methods, *manufacturer;
+
+ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
+ &methods))
+ return FALSE;
+
+ if (os_strlen(methods) > WPS_MANUFACTURER_MAX_LEN)
+ return FALSE;
+
+ manufacturer = os_strdup(methods);
+ if (!manufacturer)
+ return FALSE;
+
+ os_free(wpa_s->conf->manufacturer);
+ wpa_s->conf->manufacturer = manufacturer;
+ wpa_s->conf->changed_parameters |= CFG_CHANGED_WPS_STRING;
+ wpa_supplicant_update_config(wpa_s);
+
+ return TRUE;
+}
+
+
+/**
+ * wpas_dbus_getter_wps_device_model_name - Get current device model name
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "ModelName" property.
+ */
+dbus_bool_t wpas_dbus_getter_wps_device_model_name(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+
+ return wpas_dbus_string_property_getter(iter, wpa_s->conf->model_name,
+ error);
+}
+
+
+/**
+ * wpas_dbus_setter_wps_device_model_name - Set current device model name
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Setter for "ModelName" property.
+ */
+dbus_bool_t wpas_dbus_setter_wps_device_model_name(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ char *methods, *model_name;
+
+ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
+ &methods))
+ return FALSE;
+
+ if (os_strlen(methods) > WPS_MODEL_NAME_MAX_LEN)
+ return FALSE;
+
+ model_name = os_strdup(methods);
+ if (!model_name)
+ return FALSE;
+ os_free(wpa_s->conf->model_name);
+ wpa_s->conf->model_name = model_name;
+ wpa_s->conf->changed_parameters |= CFG_CHANGED_WPS_STRING;
+ wpa_supplicant_update_config(wpa_s);
+
+ return TRUE;
+}
+
+
+/**
+ * wpas_dbus_getter_wps_device_model_number - Get current device model number
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "ModelNumber" property.
+ */
+dbus_bool_t wpas_dbus_getter_wps_device_model_number(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+
+ return wpas_dbus_string_property_getter(iter, wpa_s->conf->model_number,
+ error);
+}
+
+
+/**
+ * wpas_dbus_setter_wps_device_model_number - Set current device model number
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Setter for "ModelNumber" property.
+ */
+dbus_bool_t wpas_dbus_setter_wps_device_model_number(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ char *methods, *model_number;
+
+ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
+ &methods))
+ return FALSE;
+
+ if (os_strlen(methods) > WPS_MODEL_NUMBER_MAX_LEN)
+ return FALSE;
+
+ model_number = os_strdup(methods);
+ if (!model_number)
+ return FALSE;
+
+ os_free(wpa_s->conf->model_number);
+ wpa_s->conf->model_number = model_number;
+ wpa_s->conf->changed_parameters |= CFG_CHANGED_WPS_STRING;
+ wpa_supplicant_update_config(wpa_s);
+
+ return TRUE;
+}
+
+
+/**
+ * wpas_dbus_getter_wps_device_serial_number - Get current device serial number
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "SerialNumber" property.
+ */
+dbus_bool_t wpas_dbus_getter_wps_device_serial_number(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+
+ return wpas_dbus_string_property_getter(iter,
+ wpa_s->conf->serial_number,
+ error);
+}
+
+
+/**
+ * wpas_dbus_setter_wps_device_serial_number - Set current device serial number
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Setter for "SerialNumber" property.
+ */
+dbus_bool_t wpas_dbus_setter_wps_device_serial_number(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ char *methods, *serial_number;
+
+ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
+ &methods))
+ return FALSE;
+
+ if (os_strlen(methods) > WPS_SERIAL_NUMBER_MAX_LEN)
+ return FALSE;
+
+ serial_number = os_strdup(methods);
+ if (!serial_number)
+ return FALSE;
+ os_free(wpa_s->conf->serial_number);
+ wpa_s->conf->serial_number = serial_number;
+ wpa_s->conf->changed_parameters |= CFG_CHANGED_WPS_STRING;
+ wpa_supplicant_update_config(wpa_s);
+
+ return TRUE;
+}
+
+
+/**
+ * wpas_dbus_getter_wps_device_device_type - Get current device type
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "DeviceType" property.
+ */
+dbus_bool_t wpas_dbus_getter_wps_device_device_type(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+
+ if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
+ (char *)
+ wpa_s->conf->device_type,
+ WPS_DEV_TYPE_LEN, error)) {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "%s: error constructing reply", __func__);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * wpas_dbus_setter_wps_device_device_type - Set current device type
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Setter for "DeviceType" property.
+ */
+dbus_bool_t wpas_dbus_setter_wps_device_device_type(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ u8 *dev_type;
+ int dev_len;
+ DBusMessageIter variant, array_iter;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
+ return FALSE;
+
+ dbus_message_iter_recurse(iter, &variant);
+ if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
+ return FALSE;
+
+ dbus_message_iter_recurse(&variant, &array_iter);
+ dbus_message_iter_get_fixed_array(&array_iter, &dev_type, &dev_len);
+
+ if (dev_len != WPS_DEV_TYPE_LEN)
+ return FALSE;
+
+ os_memcpy(wpa_s->conf->device_type, dev_type, WPS_DEV_TYPE_LEN);
+ wpa_s->conf->changed_parameters |= CFG_CHANGED_DEVICE_TYPE;
+ wpa_supplicant_update_config(wpa_s);
+
+ return TRUE;
+}
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_old.c b/contrib/wpa/wpa_supplicant/dbus/dbus_old.c
deleted file mode 100644
index 88227af7c03b..000000000000
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_old.c
+++ /dev/null
@@ -1,745 +0,0 @@
-/*
- * WPA Supplicant / dbus-based control interface
- * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-#include <dbus/dbus.h>
-
-#include "common.h"
-#include "eloop.h"
-#include "wps/wps.h"
-#include "../config.h"
-#include "../wpa_supplicant_i.h"
-#include "../bss.h"
-#include "dbus_old.h"
-#include "dbus_old_handlers.h"
-#include "dbus_common_i.h"
-
-
-/**
- * wpas_dbus_decompose_object_path - Decompose an interface object path into parts
- * @path: The dbus object path
- * @network: (out) the configured network this object path refers to, if any
- * @bssid: (out) the scanned bssid this object path refers to, if any
- * Returns: The object path of the network interface this path refers to
- *
- * For a given object path, decomposes the object path into object id, network,
- * and BSSID parts, if those parts exist.
- */
-char * wpas_dbus_decompose_object_path(const char *path, char **network,
- char **bssid)
-{
- const unsigned int dev_path_prefix_len =
- strlen(WPAS_DBUS_PATH_INTERFACES "/");
- char *obj_path_only;
- char *next_sep;
-
- /* Be a bit paranoid about path */
- if (!path || strncmp(path, WPAS_DBUS_PATH_INTERFACES "/",
- dev_path_prefix_len))
- return NULL;
-
- /* Ensure there's something at the end of the path */
- if ((path + dev_path_prefix_len)[0] == '\0')
- return NULL;
-
- obj_path_only = os_strdup(path);
- if (obj_path_only == NULL)
- return NULL;
-
- next_sep = strchr(obj_path_only + dev_path_prefix_len, '/');
- if (next_sep != NULL) {
- const char *net_part = strstr(next_sep,
- WPAS_DBUS_NETWORKS_PART "/");
- const char *bssid_part = strstr(next_sep,
- WPAS_DBUS_BSSIDS_PART "/");
-
- if (network && net_part) {
- /* Deal with a request for a configured network */
- const char *net_name = net_part +
- strlen(WPAS_DBUS_NETWORKS_PART "/");
- *network = NULL;
- if (strlen(net_name))
- *network = os_strdup(net_name);
- } else if (bssid && bssid_part) {
- /* Deal with a request for a scanned BSSID */
- const char *bssid_name = bssid_part +
- strlen(WPAS_DBUS_BSSIDS_PART "/");
- if (strlen(bssid_name))
- *bssid = os_strdup(bssid_name);
- else
- *bssid = NULL;
- }
-
- /* Cut off interface object path before "/" */
- *next_sep = '\0';
- }
-
- return obj_path_only;
-}
-
-
-/**
- * wpas_dbus_new_invalid_iface_error - Return a new invalid interface error message
- * @message: Pointer to incoming dbus message this error refers to
- * Returns: A dbus error message
- *
- * Convenience function to create and return an invalid interface error
- */
-DBusMessage * wpas_dbus_new_invalid_iface_error(DBusMessage *message)
-{
- return dbus_message_new_error(
- message, WPAS_ERROR_INVALID_IFACE,
- "wpa_supplicant knows nothing about this interface.");
-}
-
-
-/**
- * wpas_dbus_new_invalid_network_error - Return a new invalid network error message
- * @message: Pointer to incoming dbus message this error refers to
- * Returns: a dbus error message
- *
- * Convenience function to create and return an invalid network error
- */
-DBusMessage * wpas_dbus_new_invalid_network_error(DBusMessage *message)
-{
- return dbus_message_new_error(message, WPAS_ERROR_INVALID_NETWORK,
- "The requested network does not exist.");
-}
-
-
-/**
- * wpas_dbus_new_invalid_bssid_error - Return a new invalid bssid error message
- * @message: Pointer to incoming dbus message this error refers to
- * Returns: a dbus error message
- *
- * Convenience function to create and return an invalid bssid error
- */
-static DBusMessage * wpas_dbus_new_invalid_bssid_error(DBusMessage *message)
-{
- return dbus_message_new_error(message, WPAS_ERROR_INVALID_BSSID,
- "The BSSID requested was invalid.");
-}
-
-
-/**
- * wpas_dispatch_network_method - dispatch messages for configured networks
- * @message: the incoming dbus message
- * @wpa_s: a network interface's data
- * @network_id: id of the configured network we're interested in
- * Returns: a reply dbus message, or a dbus error message
- *
- * This function dispatches all incoming dbus messages for configured networks.
- */
-static DBusMessage * wpas_dispatch_network_method(DBusMessage *message,
- struct wpa_supplicant *wpa_s,
- int network_id)
-{
- DBusMessage *reply = NULL;
- const char *method = dbus_message_get_member(message);
- struct wpa_ssid *ssid;
-
- ssid = wpa_config_get_network(wpa_s->conf, network_id);
- if (ssid == NULL)
- return wpas_dbus_new_invalid_network_error(message);
-
- if (!strcmp(method, "set"))
- reply = wpas_dbus_iface_set_network(message, wpa_s, ssid);
- else if (!strcmp(method, "enable"))
- reply = wpas_dbus_iface_enable_network(message, wpa_s, ssid);
- else if (!strcmp(method, "disable"))
- reply = wpas_dbus_iface_disable_network(message, wpa_s, ssid);
-
- return reply;
-}
-
-
-/**
- * wpas_dispatch_bssid_method - dispatch messages for scanned networks
- * @message: the incoming dbus message
- * @wpa_s: a network interface's data
- * @bssid: bssid of the scanned network we're interested in
- * Returns: a reply dbus message, or a dbus error message
- *
- * This function dispatches all incoming dbus messages for scanned networks.
- */
-static DBusMessage * wpas_dispatch_bssid_method(DBusMessage *message,
- struct wpa_supplicant *wpa_s,
- const char *bssid_txt)
-{
- u8 bssid[ETH_ALEN];
- struct wpa_bss *bss;
-
- if (hexstr2bin(bssid_txt, bssid, ETH_ALEN) < 0)
- return wpas_dbus_new_invalid_bssid_error(message);
-
- bss = wpa_bss_get_bssid(wpa_s, bssid);
- if (bss == NULL)
- return wpas_dbus_new_invalid_bssid_error(message);
-
- /* Dispatch the method call against the scanned bssid */
- if (os_strcmp(dbus_message_get_member(message), "properties") == 0)
- return wpas_dbus_bssid_properties(message, wpa_s, bss);
-
- return NULL;
-}
-
-
-/**
- * wpas_iface_message_handler - Dispatch messages for interfaces or networks
- * @connection: Connection to the system message bus
- * @message: An incoming dbus message
- * @user_data: A pointer to a dbus control interface data structure
- * Returns: Whether or not the message was handled
- *
- * This function dispatches all incoming dbus messages for network interfaces,
- * or objects owned by them, such as scanned BSSIDs and configured networks.
- */
-static DBusHandlerResult wpas_iface_message_handler(DBusConnection *connection,
- DBusMessage *message,
- void *user_data)
-{
- struct wpa_supplicant *wpa_s = user_data;
- const char *method = dbus_message_get_member(message);
- const char *path = dbus_message_get_path(message);
- const char *msg_interface = dbus_message_get_interface(message);
- char *iface_obj_path = NULL;
- char *network = NULL;
- char *bssid = NULL;
- DBusMessage *reply = NULL;
-
- /* Caller must specify a message interface */
- if (!msg_interface)
- goto out;
-
- wpa_printf(MSG_MSGDUMP, "dbus[old/iface]: %s.%s (%s) [%s]",
- msg_interface, method, path,
- dbus_message_get_signature(message));
-
- iface_obj_path = wpas_dbus_decompose_object_path(path, &network,
- &bssid);
- if (iface_obj_path == NULL) {
- reply = wpas_dbus_new_invalid_iface_error(message);
- goto out;
- }
-
- /* Make sure the message's object path actually refers to the
- * wpa_supplicant structure it's supposed to (which is wpa_s)
- */
- if (wpa_supplicant_get_iface_by_dbus_path(wpa_s->global,
- iface_obj_path) != wpa_s) {
- reply = wpas_dbus_new_invalid_iface_error(message);
- goto out;
- }
-
- if (network && !strcmp(msg_interface, WPAS_DBUS_IFACE_NETWORK)) {
- /* A method for one of this interface's configured networks */
- int nid = strtoul(network, NULL, 10);
-
- if (errno != EINVAL)
- reply = wpas_dispatch_network_method(message, wpa_s,
- nid);
- else
- reply = wpas_dbus_new_invalid_network_error(message);
- } else if (bssid && !strcmp(msg_interface, WPAS_DBUS_IFACE_BSSID)) {
- /* A method for one of this interface's scanned BSSIDs */
- reply = wpas_dispatch_bssid_method(message, wpa_s, bssid);
- } else if (!strcmp(msg_interface, WPAS_DBUS_IFACE_INTERFACE)) {
- /* A method for an interface only. */
- if (!strcmp(method, "scan"))
- reply = wpas_dbus_iface_scan(message, wpa_s);
- else if (!strcmp(method, "scanResults"))
- reply = wpas_dbus_iface_scan_results(message, wpa_s);
- else if (!strcmp(method, "addNetwork"))
- reply = wpas_dbus_iface_add_network(message, wpa_s);
- else if (!strcmp(method, "removeNetwork"))
- reply = wpas_dbus_iface_remove_network(message, wpa_s);
- else if (!strcmp(method, "selectNetwork"))
- reply = wpas_dbus_iface_select_network(message, wpa_s);
- else if (!strcmp(method, "capabilities"))
- reply = wpas_dbus_iface_capabilities(message, wpa_s);
- else if (!strcmp(method, "disconnect"))
- reply = wpas_dbus_iface_disconnect(message, wpa_s);
- else if (!strcmp(method, "setAPScan"))
- reply = wpas_dbus_iface_set_ap_scan(message, wpa_s);
- else if (!strcmp(method, "setSmartcardModules"))
- reply = wpas_dbus_iface_set_smartcard_modules(message,
- wpa_s);
- else if (!strcmp(method, "state"))
- reply = wpas_dbus_iface_get_state(message, wpa_s);
- else if (!strcmp(method, "scanning"))
- reply = wpas_dbus_iface_get_scanning(message, wpa_s);
-#ifndef CONFIG_NO_CONFIG_BLOBS
- else if (!strcmp(method, "setBlobs"))
- reply = wpas_dbus_iface_set_blobs(message, wpa_s);
- else if (!strcmp(method, "removeBlobs"))
- reply = wpas_dbus_iface_remove_blobs(message, wpa_s);
-#endif /* CONFIG_NO_CONFIG_BLOBS */
-#ifdef CONFIG_WPS
- else if (os_strcmp(method, "wpsPbc") == 0)
- reply = wpas_dbus_iface_wps_pbc(message, wpa_s);
- else if (os_strcmp(method, "wpsPin") == 0)
- reply = wpas_dbus_iface_wps_pin(message, wpa_s);
- else if (os_strcmp(method, "wpsReg") == 0)
- reply = wpas_dbus_iface_wps_reg(message, wpa_s);
-#endif /* CONFIG_WPS */
- else if (os_strcmp(method, "flush") == 0)
- reply = wpas_dbus_iface_flush(message, wpa_s);
- }
-
- /* If the message was handled, send back the reply */
-out:
- if (reply) {
- if (!dbus_message_get_no_reply(message))
- dbus_connection_send(connection, reply, NULL);
- dbus_message_unref(reply);
- }
-
- os_free(iface_obj_path);
- os_free(network);
- os_free(bssid);
- return reply ? DBUS_HANDLER_RESULT_HANDLED :
- DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-
-/**
- * wpas_message_handler - dispatch incoming dbus messages
- * @connection: connection to the system message bus
- * @message: an incoming dbus message
- * @user_data: a pointer to a dbus control interface data structure
- * Returns: whether or not the message was handled
- *
- * This function dispatches all incoming dbus messages to the correct
- * handlers, depending on what the message's target object path is,
- * and what the method call is.
- */
-static DBusHandlerResult wpas_message_handler(DBusConnection *connection,
- DBusMessage *message, void *user_data)
-{
- struct wpas_dbus_priv *ctrl_iface = user_data;
- const char *method;
- const char *path;
- const char *msg_interface;
- DBusMessage *reply = NULL;
-
- method = dbus_message_get_member(message);
- path = dbus_message_get_path(message);
- msg_interface = dbus_message_get_interface(message);
- if (!method || !path || !ctrl_iface || !msg_interface)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- wpa_printf(MSG_MSGDUMP, "dbus[old]: %s.%s (%s) [%s]",
- msg_interface, method, path,
- dbus_message_get_signature(message));
-
- /* Validate the method interface */
- if (strcmp(msg_interface, WPAS_DBUS_INTERFACE) != 0)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- if (!strcmp(path, WPAS_DBUS_PATH)) {
- /* dispatch methods against our global dbus interface here */
- if (!strcmp(method, "addInterface")) {
- reply = wpas_dbus_global_add_interface(
- message, ctrl_iface->global);
- } else if (!strcmp(method, "removeInterface")) {
- reply = wpas_dbus_global_remove_interface(
- message, ctrl_iface->global);
- } else if (!strcmp(method, "getInterface")) {
- reply = wpas_dbus_global_get_interface(
- message, ctrl_iface->global);
- } else if (!strcmp(method, "setDebugParams")) {
- reply = wpas_dbus_global_set_debugparams(
- message, ctrl_iface->global);
- }
- }
-
- /* If the message was handled, send back the reply */
- if (reply) {
- if (!dbus_message_get_no_reply(message))
- dbus_connection_send(connection, reply, NULL);
- dbus_message_unref(reply);
- }
-
- return reply ? DBUS_HANDLER_RESULT_HANDLED :
- DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-
-/**
- * wpa_supplicant_dbus_notify_scan_results - Send a scan results signal
- * @wpa_s: %wpa_supplicant network interface data
- * Returns: 0 on success, -1 on failure
- *
- * Notify listeners that this interface has updated scan results.
- */
-void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s)
-{
- struct wpas_dbus_priv *iface = wpa_s->global->dbus;
- DBusMessage *_signal;
-
- /* Do nothing if the control interface is not turned on */
- if (iface == NULL || !wpa_s->dbus_path)
- return;
-
- _signal = dbus_message_new_signal(wpa_s->dbus_path,
- WPAS_DBUS_IFACE_INTERFACE,
- "ScanResultsAvailable");
- if (_signal == NULL) {
- wpa_printf(MSG_ERROR,
- "dbus: Not enough memory to send scan results signal");
- return;
- }
- dbus_connection_send(iface->con, _signal, NULL);
- dbus_message_unref(_signal);
-}
-
-
-/**
- * wpa_supplicant_dbus_notify_state_change - Send a state change signal
- * @wpa_s: %wpa_supplicant network interface data
- * @new_state: new state wpa_supplicant is entering
- * @old_state: old state wpa_supplicant is leaving
- * Returns: 0 on success, -1 on failure
- *
- * Notify listeners that wpa_supplicant has changed state
- */
-void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
- enum wpa_states new_state,
- enum wpa_states old_state)
-{
- struct wpas_dbus_priv *iface;
- DBusMessage *_signal = NULL;
- const char *new_state_str, *old_state_str;
-
- if (wpa_s->dbus_path == NULL)
- return; /* Skip signal since D-Bus setup is not yet ready */
-
- /* Do nothing if the control interface is not turned on */
- if (wpa_s->global == NULL)
- return;
- iface = wpa_s->global->dbus;
- if (iface == NULL)
- return;
-
- /* Only send signal if state really changed */
- if (new_state == old_state)
- return;
-
- _signal = dbus_message_new_signal(wpa_s->dbus_path,
- WPAS_DBUS_IFACE_INTERFACE,
- "StateChange");
- if (_signal == NULL) {
- wpa_printf(MSG_ERROR,
- "dbus: %s: could not create dbus signal; likely out of memory",
- __func__);
- return;
- }
-
- new_state_str = wpa_supplicant_state_txt(new_state);
- old_state_str = wpa_supplicant_state_txt(old_state);
-
- if (!dbus_message_append_args(_signal,
- DBUS_TYPE_STRING, &new_state_str,
- DBUS_TYPE_STRING, &old_state_str,
- DBUS_TYPE_INVALID)) {
- wpa_printf(MSG_ERROR,
- "dbus: %s: Not enough memory to construct state change signal",
- __func__);
- goto out;
- }
-
- dbus_connection_send(iface->con, _signal, NULL);
-
-out:
- dbus_message_unref(_signal);
-}
-
-
-/**
- * wpa_supplicant_dbus_notify_scanning - send scanning status
- * @wpa_s: %wpa_supplicant network interface data
- * Returns: 0 on success, -1 on failure
- *
- * Notify listeners of interface scanning state changes
- */
-void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s)
-{
- struct wpas_dbus_priv *iface = wpa_s->global->dbus;
- DBusMessage *_signal;
- dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
-
- /* Do nothing if the control interface is not turned on */
- if (iface == NULL || !wpa_s->dbus_path)
- return;
-
- _signal = dbus_message_new_signal(wpa_s->dbus_path,
- WPAS_DBUS_IFACE_INTERFACE,
- "Scanning");
- if (_signal == NULL) {
- wpa_printf(MSG_ERROR,
- "dbus: Not enough memory to send scan results signal");
- return;
- }
-
- if (dbus_message_append_args(_signal,
- DBUS_TYPE_BOOLEAN, &scanning,
- DBUS_TYPE_INVALID)) {
- dbus_connection_send(iface->con, _signal, NULL);
- } else {
- wpa_printf(MSG_ERROR,
- "dbus: Not enough memory to construct signal");
- }
- dbus_message_unref(_signal);
-}
-
-
-#ifdef CONFIG_WPS
-void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
- const struct wps_credential *cred)
-{
- struct wpas_dbus_priv *iface;
- DBusMessage *_signal = NULL;
-
- /* Do nothing if the control interface is not turned on */
- if (wpa_s->global == NULL)
- return;
- iface = wpa_s->global->dbus;
- if (iface == NULL || !wpa_s->dbus_path)
- return;
-
- _signal = dbus_message_new_signal(wpa_s->dbus_path,
- WPAS_DBUS_IFACE_INTERFACE,
- "WpsCred");
- if (_signal == NULL) {
- wpa_printf(MSG_ERROR,
- "dbus: %s: Could not create dbus signal; likely out of memory",
- __func__);
- return;
- }
-
- if (!dbus_message_append_args(_signal,
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &cred->cred_attr, cred->cred_attr_len,
- DBUS_TYPE_INVALID)) {
- wpa_printf(MSG_ERROR,
- "dbus: %s: Not enough memory to construct signal",
- __func__);
- goto out;
- }
-
- dbus_connection_send(iface->con, _signal, NULL);
-
-out:
- dbus_message_unref(_signal);
-}
-#else /* CONFIG_WPS */
-void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
- const struct wps_credential *cred)
-{
-}
-#endif /* CONFIG_WPS */
-
-void wpa_supplicant_dbus_notify_certification(struct wpa_supplicant *wpa_s,
- int depth, const char *subject,
- const char *cert_hash,
- const struct wpabuf *cert)
-{
- struct wpas_dbus_priv *iface;
- DBusMessage *_signal = NULL;
- const char *hash;
- const char *cert_hex;
- int cert_hex_len;
-
- /* Do nothing if the control interface is not turned on */
- if (wpa_s->global == NULL)
- return;
- iface = wpa_s->global->dbus;
- if (iface == NULL || !wpa_s->dbus_path)
- return;
-
- _signal = dbus_message_new_signal(wpa_s->dbus_path,
- WPAS_DBUS_IFACE_INTERFACE,
- "Certification");
- if (_signal == NULL) {
- wpa_printf(MSG_ERROR,
- "dbus: %s: Could not create dbus signal; likely out of memory",
- __func__);
- return;
- }
-
- hash = cert_hash ? cert_hash : "";
- cert_hex = cert ? wpabuf_head(cert) : "";
- cert_hex_len = cert ? wpabuf_len(cert) : 0;
-
- if (!dbus_message_append_args(_signal,
- DBUS_TYPE_INT32, &depth,
- DBUS_TYPE_STRING, &subject,
- DBUS_TYPE_STRING, &hash,
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &cert_hex, cert_hex_len,
- DBUS_TYPE_INVALID)) {
- wpa_printf(MSG_ERROR,
- "dbus: %s: Not enough memory to construct signal",
- __func__);
- goto out;
- }
-
- dbus_connection_send(iface->con, _signal, NULL);
-
-out:
- dbus_message_unref(_signal);
-
-}
-
-
-/**
- * wpa_supplicant_dbus_ctrl_iface_init - Initialize dbus control interface
- * @global: Pointer to global data from wpa_supplicant_init()
- * Returns: 0 on success, -1 on failure
- *
- * Initialize the dbus control interface and start receiving commands from
- * external programs over the bus.
- */
-int wpa_supplicant_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface)
-{
- DBusError error;
- int ret = -1;
- DBusObjectPathVTable wpas_vtable = {
- NULL, &wpas_message_handler, NULL, NULL, NULL, NULL
- };
-
- /* Register the message handler for the global dbus interface */
- if (!dbus_connection_register_object_path(iface->con,
- WPAS_DBUS_PATH, &wpas_vtable,
- iface)) {
- wpa_printf(MSG_ERROR, "dbus: Could not set up message handler");
- return -1;
- }
-
- /* Register our service with the message bus */
- dbus_error_init(&error);
- switch (dbus_bus_request_name(iface->con, WPAS_DBUS_SERVICE,
- 0, &error)) {
- case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
- ret = 0;
- break;
- case DBUS_REQUEST_NAME_REPLY_EXISTS:
- case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
- case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
- wpa_printf(MSG_ERROR,
- "dbus: Could not request service name: already registered");
- break;
- default:
- wpa_printf(MSG_ERROR,
- "dbus: Could not request service name: %s %s",
- error.name, error.message);
- break;
- }
- dbus_error_free(&error);
-
- if (ret != 0)
- return -1;
-
- wpa_printf(MSG_DEBUG, "Providing DBus service '" WPAS_DBUS_SERVICE
- "'.");
-
- return 0;
-}
-
-
-/**
- * wpas_dbus_register_new_iface - Register a new interface with dbus
- * @wpa_s: %wpa_supplicant interface description structure to register
- * Returns: 0 on success, -1 on error
- *
- * Registers a new interface with dbus and assigns it a dbus object path.
- */
-int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
-{
- struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
- DBusConnection * con;
- u32 next;
- DBusObjectPathVTable vtable = {
- NULL, &wpas_iface_message_handler, NULL, NULL, NULL, NULL
- };
-
- /* Do nothing if the control interface is not turned on */
- if (ctrl_iface == NULL)
- return 0;
-
- con = ctrl_iface->con;
- next = ctrl_iface->next_objid++;
-
- /* Create and set the interface's object path */
- wpa_s->dbus_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
- if (wpa_s->dbus_path == NULL)
- return -1;
- os_snprintf(wpa_s->dbus_path, WPAS_DBUS_OBJECT_PATH_MAX,
- WPAS_DBUS_PATH_INTERFACES "/%u",
- next);
-
- /* Register the message handler for the interface functions */
- if (!dbus_connection_register_fallback(con, wpa_s->dbus_path, &vtable,
- wpa_s)) {
- wpa_printf(MSG_ERROR,
- "dbus: Could not set up message handler for interface %s",
- wpa_s->ifname);
- return -1;
- }
-
- return 0;
-}
-
-
-/**
- * wpas_dbus_unregister_iface - Unregister an interface from dbus
- * @wpa_s: wpa_supplicant interface structure
- * Returns: 0 on success, -1 on failure
- *
- * Unregisters the interface with dbus
- */
-int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s)
-{
- struct wpas_dbus_priv *ctrl_iface;
- DBusConnection *con;
-
- /* Do nothing if the control interface is not turned on */
- if (wpa_s == NULL || wpa_s->global == NULL)
- return 0;
- ctrl_iface = wpa_s->global->dbus;
- if (ctrl_iface == NULL || wpa_s->dbus_path == NULL)
- return 0;
-
- con = ctrl_iface->con;
- if (!dbus_connection_unregister_object_path(con, wpa_s->dbus_path))
- return -1;
-
- os_free(wpa_s->dbus_path);
- wpa_s->dbus_path = NULL;
-
- return 0;
-}
-
-
-/**
- * wpa_supplicant_get_iface_by_dbus_path - Get a new network interface
- * @global: Pointer to global data from wpa_supplicant_init()
- * @path: Pointer to a dbus object path representing an interface
- * Returns: Pointer to the interface or %NULL if not found
- */
-struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path(
- struct wpa_global *global, const char *path)
-{
- struct wpa_supplicant *wpa_s;
-
- for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
- if (wpa_s->dbus_path && strcmp(wpa_s->dbus_path, path) == 0)
- return wpa_s;
- }
- return NULL;
-}
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_old.h b/contrib/wpa/wpa_supplicant/dbus/dbus_old.h
deleted file mode 100644
index 451a9f827aa9..000000000000
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_old.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * WPA Supplicant / dbus-based control interface
- * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef CTRL_IFACE_DBUS_H
-#define CTRL_IFACE_DBUS_H
-
-struct wps_credential;
-
-#ifdef CONFIG_CTRL_IFACE_DBUS
-
-#define WPAS_DBUS_OBJECT_PATH_MAX 150
-
-#define WPAS_DBUS_SERVICE "fi.epitest.hostap.WPASupplicant"
-#define WPAS_DBUS_PATH "/fi/epitest/hostap/WPASupplicant"
-#define WPAS_DBUS_INTERFACE "fi.epitest.hostap.WPASupplicant"
-
-#define WPAS_DBUS_PATH_INTERFACES WPAS_DBUS_PATH "/Interfaces"
-#define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface"
-
-#define WPAS_DBUS_NETWORKS_PART "Networks"
-#define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network"
-
-#define WPAS_DBUS_BSSIDS_PART "BSSIDs"
-#define WPAS_DBUS_IFACE_BSSID WPAS_DBUS_INTERFACE ".BSSID"
-
-
-/* Errors */
-#define WPAS_ERROR_INVALID_NETWORK \
- WPAS_DBUS_IFACE_INTERFACE ".InvalidNetwork"
-#define WPAS_ERROR_INVALID_BSSID \
- WPAS_DBUS_IFACE_INTERFACE ".InvalidBSSID"
-
-#define WPAS_ERROR_INVALID_OPTS \
- WPAS_DBUS_INTERFACE ".InvalidOptions"
-#define WPAS_ERROR_INVALID_IFACE \
- WPAS_DBUS_INTERFACE ".InvalidInterface"
-
-#define WPAS_ERROR_ADD_ERROR \
- WPAS_DBUS_INTERFACE ".AddError"
-#define WPAS_ERROR_EXISTS_ERROR \
- WPAS_DBUS_INTERFACE ".ExistsError"
-#define WPAS_ERROR_REMOVE_ERROR \
- WPAS_DBUS_INTERFACE ".RemoveError"
-
-#define WPAS_ERROR_SCAN_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".ScanError"
-#define WPAS_ERROR_ADD_NETWORK_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".AddNetworkError"
-#define WPAS_ERROR_INTERNAL_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".InternalError"
-#define WPAS_ERROR_REMOVE_NETWORK_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".RemoveNetworkError"
-
-#define WPAS_ERROR_WPS_PBC_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".WpsPbcError"
-#define WPAS_ERROR_WPS_PIN_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".WpsPinError"
-#define WPAS_ERROR_WPS_REG_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".WpsRegError"
-
-#define WPAS_DBUS_BSSID_FORMAT "%02x%02x%02x%02x%02x%02x"
-
-struct wpa_global;
-struct wpa_supplicant;
-
-int wpa_supplicant_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface);
-void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s);
-void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s);
-void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
- enum wpa_states new_state,
- enum wpa_states old_state);
-void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
- const struct wps_credential *cred);
-void wpa_supplicant_dbus_notify_certification(struct wpa_supplicant *wpa_s,
- int depth, const char *subject,
- const char *cert_hash,
- const struct wpabuf *cert);
-
-char * wpas_dbus_decompose_object_path(const char *path, char **network,
- char **bssid);
-
-int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s);
-int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s);
-
-
-/* Methods internal to the dbus control interface */
-struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path(
- struct wpa_global *global, const char *path);
-
-#else /* CONFIG_CTRL_IFACE_DBUS */
-
-static inline void
-wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s)
-{
-}
-
-static inline void
-wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s)
-{
-}
-
-static inline void
-wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
- enum wpa_states new_state,
- enum wpa_states old_state)
-{
-}
-
-static inline void
-wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
- const struct wps_credential *cred)
-{
-}
-
-static inline void
-wpa_supplicant_dbus_notify_certification(struct wpa_supplicant *wpa_s,
- int depth, const char *subject,
- const char *cert_hash,
- const struct wpabuf *cert)
-{
-}
-
-static inline int
-wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
-{
- return 0;
-}
-
-static inline int
-wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s)
-{
- return 0;
-}
-
-#endif /* CONFIG_CTRL_IFACE_DBUS */
-
-#endif /* CTRL_IFACE_DBUS_H */
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_old_handlers.c b/contrib/wpa/wpa_supplicant/dbus/dbus_old_handlers.c
deleted file mode 100644
index e540832f254b..000000000000
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_old_handlers.c
+++ /dev/null
@@ -1,1393 +0,0 @@
-/*
- * WPA Supplicant / dbus-based control interface
- * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-#include <dbus/dbus.h>
-
-#include "common.h"
-#include "eap_peer/eap_methods.h"
-#include "common/ieee802_11_defs.h"
-#include "eapol_supp/eapol_supp_sm.h"
-#include "rsn_supp/wpa.h"
-#include "../config.h"
-#include "../wpa_supplicant_i.h"
-#include "../driver_i.h"
-#include "../notify.h"
-#include "../wpas_glue.h"
-#include "../bss.h"
-#include "../scan.h"
-#include "dbus_old.h"
-#include "dbus_old_handlers.h"
-#include "dbus_dict_helpers.h"
-
-/**
- * wpas_dbus_new_invalid_opts_error - Return a new invalid options error message
- * @message: Pointer to incoming dbus message this error refers to
- * Returns: a dbus error message
- *
- * Convenience function to create and return an invalid options error
- */
-DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message,
- const char *arg)
-{
- DBusMessage *reply;
-
- reply = dbus_message_new_error(
- message, WPAS_ERROR_INVALID_OPTS,
- "Did not receive correct message arguments.");
- if (arg != NULL)
- dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
- DBUS_TYPE_INVALID);
-
- return reply;
-}
-
-
-/**
- * wpas_dbus_new_success_reply - Return a new success reply message
- * @message: Pointer to incoming dbus message this reply refers to
- * Returns: a dbus message containing a single UINT32 that indicates
- * success (ie, a value of 1)
- *
- * Convenience function to create and return a success reply message
- */
-DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message)
-{
- DBusMessage *reply;
- unsigned int success = 1;
-
- reply = dbus_message_new_method_return(message);
- dbus_message_append_args(reply, DBUS_TYPE_UINT32, &success,
- DBUS_TYPE_INVALID);
- return reply;
-}
-
-
-/**
- * wpas_dbus_global_add_interface - Request registration of a network interface
- * @message: Pointer to incoming dbus message
- * @global: %wpa_supplicant global data structure
- * Returns: The object path of the new interface object,
- * or a dbus error message with more information
- *
- * Handler function for "addInterface" method call. Handles requests
- * by dbus clients to register a network interface that wpa_supplicant
- * will manage.
- */
-DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message,
- struct wpa_global *global)
-{
- char *ifname = NULL;
- char *driver = NULL;
- char *driver_param = NULL;
- char *confname = NULL;
- char *bridge_ifname = NULL;
- DBusMessage *reply = NULL;
- DBusMessageIter iter;
-
- dbus_message_iter_init(message, &iter);
-
- /* First argument: interface name (DBUS_TYPE_STRING)
- * Required; must be non-zero length
- */
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- goto error;
- dbus_message_iter_get_basic(&iter, &ifname);
- if (!os_strlen(ifname))
- goto error;
-
- /* Second argument: dict of options */
- if (dbus_message_iter_next(&iter)) {
- DBusMessageIter iter_dict;
- struct wpa_dbus_dict_entry entry;
-
- if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
- goto error;
- while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
- if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
- goto error;
- if (!strcmp(entry.key, "driver") &&
- entry.type == DBUS_TYPE_STRING) {
- os_free(driver);
- driver = os_strdup(entry.str_value);
- wpa_dbus_dict_entry_clear(&entry);
- if (driver == NULL)
- goto error;
- } else if (!strcmp(entry.key, "driver-params") &&
- entry.type == DBUS_TYPE_STRING) {
- os_free(driver_param);
- driver_param = os_strdup(entry.str_value);
- wpa_dbus_dict_entry_clear(&entry);
- if (driver_param == NULL)
- goto error;
- } else if (!strcmp(entry.key, "config-file") &&
- entry.type == DBUS_TYPE_STRING) {
- os_free(confname);
- confname = os_strdup(entry.str_value);
- wpa_dbus_dict_entry_clear(&entry);
- if (confname == NULL)
- goto error;
- } else if (!strcmp(entry.key, "bridge-ifname") &&
- entry.type == DBUS_TYPE_STRING) {
- os_free(bridge_ifname);
- bridge_ifname = os_strdup(entry.str_value);
- wpa_dbus_dict_entry_clear(&entry);
- if (bridge_ifname == NULL)
- goto error;
- } else {
- wpa_dbus_dict_entry_clear(&entry);
- goto error;
- }
- }
- }
-
- /*
- * Try to get the wpa_supplicant record for this iface, return
- * an error if we already control it.
- */
- if (wpa_supplicant_get_iface(global, ifname) != NULL) {
- reply = dbus_message_new_error(
- message, WPAS_ERROR_EXISTS_ERROR,
- "wpa_supplicant already controls this interface.");
- } else {
- struct wpa_supplicant *wpa_s;
- struct wpa_interface iface;
-
- os_memset(&iface, 0, sizeof(iface));
- iface.ifname = ifname;
- iface.driver = driver;
- iface.driver_param = driver_param;
- iface.confname = confname;
- iface.bridge_ifname = bridge_ifname;
- /* Otherwise, have wpa_supplicant attach to it. */
- wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
- if (wpa_s && wpa_s->dbus_path) {
- const char *path = wpa_s->dbus_path;
-
- reply = dbus_message_new_method_return(message);
- dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
- &path, DBUS_TYPE_INVALID);
- } else {
- reply = dbus_message_new_error(
- message, WPAS_ERROR_ADD_ERROR,
- "wpa_supplicant couldn't grab this interface.");
- }
- }
-
-out:
- os_free(driver);
- os_free(driver_param);
- os_free(confname);
- os_free(bridge_ifname);
- return reply;
-
-error:
- reply = wpas_dbus_new_invalid_opts_error(message, NULL);
- goto out;
-}
-
-
-/**
- * wpas_dbus_global_remove_interface - Request deregistration of an interface
- * @message: Pointer to incoming dbus message
- * @global: wpa_supplicant global data structure
- * Returns: a dbus message containing a UINT32 indicating success (1) or
- * failure (0), or returns a dbus error message with more information
- *
- * Handler function for "removeInterface" method call. Handles requests
- * by dbus clients to deregister a network interface that wpa_supplicant
- * currently manages.
- */
-DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message,
- struct wpa_global *global)
-{
- struct wpa_supplicant *wpa_s;
- char *path;
- DBusMessage *reply = NULL;
-
- if (!dbus_message_get_args(message, NULL,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID)) {
- reply = wpas_dbus_new_invalid_opts_error(message, NULL);
- goto out;
- }
-
- wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path);
- if (wpa_s == NULL) {
- reply = wpas_dbus_new_invalid_iface_error(message);
- goto out;
- }
-
- if (!wpa_supplicant_remove_iface(global, wpa_s, 0)) {
- reply = wpas_dbus_new_success_reply(message);
- } else {
- reply = dbus_message_new_error(
- message, WPAS_ERROR_REMOVE_ERROR,
- "wpa_supplicant couldn't remove this interface.");
- }
-
-out:
- return reply;
-}
-
-
-/**
- * wpas_dbus_global_get_interface - Get the object path for an interface name
- * @message: Pointer to incoming dbus message
- * @global: %wpa_supplicant global data structure
- * Returns: The object path of the interface object,
- * or a dbus error message with more information
- *
- * Handler function for "getInterface" method call. Handles requests
- * by dbus clients for the object path of an specific network interface.
- */
-DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message,
- struct wpa_global *global)
-{
- DBusMessage *reply = NULL;
- const char *ifname;
- const char *path;
- struct wpa_supplicant *wpa_s;
-
- if (!dbus_message_get_args(message, NULL,
- DBUS_TYPE_STRING, &ifname,
- DBUS_TYPE_INVALID)) {
- reply = wpas_dbus_new_invalid_opts_error(message, NULL);
- goto out;
- }
-
- wpa_s = wpa_supplicant_get_iface(global, ifname);
- if (wpa_s == NULL || !wpa_s->dbus_path) {
- reply = wpas_dbus_new_invalid_iface_error(message);
- goto out;
- }
-
- path = wpa_s->dbus_path;
- reply = dbus_message_new_method_return(message);
- dbus_message_append_args(reply,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID);
-
-out:
- return reply;
-}
-
-
-/**
- * wpas_dbus_global_set_debugparams- Set the debug params
- * @message: Pointer to incoming dbus message
- * @global: %wpa_supplicant global data structure
- * Returns: a dbus message containing a UINT32 indicating success (1) or
- * failure (0), or returns a dbus error message with more information
- *
- * Handler function for "setDebugParams" method call. Handles requests
- * by dbus clients for the object path of an specific network interface.
- */
-DBusMessage * wpas_dbus_global_set_debugparams(DBusMessage *message,
- struct wpa_global *global)
-{
- DBusMessage *reply = NULL;
- int debug_level;
- dbus_bool_t debug_timestamp;
- dbus_bool_t debug_show_keys;
-
- if (!dbus_message_get_args(message, NULL,
- DBUS_TYPE_INT32, &debug_level,
- DBUS_TYPE_BOOLEAN, &debug_timestamp,
- DBUS_TYPE_BOOLEAN, &debug_show_keys,
- DBUS_TYPE_INVALID)) {
- return wpas_dbus_new_invalid_opts_error(message, NULL);
- }
-
- if (wpa_supplicant_set_debug_params(global, debug_level,
- debug_timestamp ? 1 : 0,
- debug_show_keys ? 1 : 0)) {
- return wpas_dbus_new_invalid_opts_error(message, NULL);
- }
-
- reply = wpas_dbus_new_success_reply(message);
-
- return reply;
-}
-
-
-/**
- * wpas_dbus_iface_scan - Request a wireless scan on an interface
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * Returns: a dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Handler function for "scan" method call of a network device. Requests
- * that wpa_supplicant perform a wireless scan as soon as possible
- * on a particular wireless interface.
- */
-DBusMessage * wpas_dbus_iface_scan(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- wpa_s->scan_req = MANUAL_SCAN_REQ;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- return wpas_dbus_new_success_reply(message);
-}
-
-
-/**
- * wpas_dbus_iface_scan_results - Get the results of a recent scan request
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * Returns: a dbus message containing a dbus array of objects paths, or returns
- * a dbus error message if not scan results could be found
- *
- * Handler function for "scanResults" method call of a network device. Returns
- * a dbus message containing the object paths of wireless networks found.
- */
-DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- DBusMessage *reply;
- DBusMessageIter iter;
- DBusMessageIter sub_iter;
- struct wpa_bss *bss;
-
- if (!wpa_s->dbus_path)
- return dbus_message_new_error(message,
- WPAS_ERROR_INTERNAL_ERROR,
- "no D-Bus interface available");
-
- /* Create and initialize the return message */
- reply = dbus_message_new_method_return(message);
- dbus_message_iter_init_append(reply, &iter);
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_TYPE_OBJECT_PATH_AS_STRING,
- &sub_iter))
- goto error;
-
- /* Loop through scan results and append each result's object path */
- dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
- char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
- char *path = path_buf;
-
- /* Construct the object path for this network. Note that ':'
- * is not a valid character in dbus object paths.
- */
- os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
- "%s/" WPAS_DBUS_BSSIDS_PART "/"
- WPAS_DBUS_BSSID_FORMAT,
- wpa_s->dbus_path, MAC2STR(bss->bssid));
- if (!dbus_message_iter_append_basic(&sub_iter,
- DBUS_TYPE_OBJECT_PATH,
- &path))
- goto error;
- }
-
- if (!dbus_message_iter_close_container(&iter, &sub_iter))
- goto error;
-
- return reply;
-
-error:
- dbus_message_unref(reply);
- return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
- "an internal error occurred returning scan results");
-}
-
-
-/**
- * wpas_dbus_bssid_properties - Return the properties of a scanned network
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * @res: wpa_supplicant scan result for which to get properties
- * Returns: a dbus message containing the properties for the requested network
- *
- * Handler function for "properties" method call of a scanned network.
- * Returns a dbus message containing the the properties.
- */
-DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message,
- struct wpa_supplicant *wpa_s,
- struct wpa_bss *bss)
-{
- DBusMessage *reply;
- DBusMessageIter iter, iter_dict;
- const u8 *wpa_ie, *rsn_ie, *wps_ie;
-
- /* Dump the properties into a dbus message */
- reply = dbus_message_new_method_return(message);
-
- wpa_ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
- rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
- wps_ie = wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE);
-
- dbus_message_iter_init_append(reply, &iter);
- if (!wpa_dbus_dict_open_write(&iter, &iter_dict) ||
- !wpa_dbus_dict_append_byte_array(&iter_dict, "bssid",
- (const char *) bss->bssid,
- ETH_ALEN) ||
- !wpa_dbus_dict_append_byte_array(&iter_dict, "ssid",
- (const char *) bss->ssid,
- bss->ssid_len) ||
- (wpa_ie &&
- !wpa_dbus_dict_append_byte_array(&iter_dict, "wpaie",
- (const char *) wpa_ie,
- wpa_ie[1] + 2)) ||
- (rsn_ie &&
- !wpa_dbus_dict_append_byte_array(&iter_dict, "rsnie",
- (const char *) rsn_ie,
- rsn_ie[1] + 2)) ||
- (wps_ie &&
- !wpa_dbus_dict_append_byte_array(&iter_dict, "wpsie",
- (const char *) wps_ie,
- wps_ie[1] + 2)) ||
- (bss->freq &&
- !wpa_dbus_dict_append_int32(&iter_dict, "frequency", bss->freq)) ||
- !wpa_dbus_dict_append_uint16(&iter_dict, "capabilities",
- bss->caps) ||
- (!(bss->flags & WPA_BSS_QUAL_INVALID) &&
- !wpa_dbus_dict_append_int32(&iter_dict, "quality", bss->qual)) ||
- (!(bss->flags & WPA_BSS_NOISE_INVALID) &&
- !wpa_dbus_dict_append_int32(&iter_dict, "noise", bss->noise)) ||
- (!(bss->flags & WPA_BSS_LEVEL_INVALID) &&
- !wpa_dbus_dict_append_int32(&iter_dict, "level", bss->level)) ||
- !wpa_dbus_dict_append_int32(&iter_dict, "maxrate",
- wpa_bss_get_max_rate(bss) * 500000) ||
- !wpa_dbus_dict_close_write(&iter, &iter_dict)) {
- if (reply)
- dbus_message_unref(reply);
- reply = dbus_message_new_error(
- message, WPAS_ERROR_INTERNAL_ERROR,
- "an internal error occurred returning BSSID properties.");
- }
-
- return reply;
-}
-
-
-/**
- * wpas_dbus_iface_capabilities - Return interface capabilities
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * Returns: A dbus message containing a dict of strings
- *
- * Handler function for "capabilities" method call of an interface.
- */
-DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- DBusMessage *reply = NULL;
- struct wpa_driver_capa capa;
- int res;
- DBusMessageIter iter, iter_dict;
- char **eap_methods;
- size_t num_items;
- dbus_bool_t strict = FALSE;
- DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
-
- if (!dbus_message_get_args(message, NULL,
- DBUS_TYPE_BOOLEAN, &strict,
- DBUS_TYPE_INVALID))
- strict = FALSE;
-
- reply = dbus_message_new_method_return(message);
-
- dbus_message_iter_init_append(reply, &iter);
- if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
- goto error;
-
- /* EAP methods */
- eap_methods = eap_get_names_as_string_array(&num_items);
- if (eap_methods) {
- dbus_bool_t success;
- size_t i = 0;
-
- success = wpa_dbus_dict_append_string_array(
- &iter_dict, "eap", (const char **) eap_methods,
- num_items);
-
- /* free returned method array */
- while (eap_methods[i])
- os_free(eap_methods[i++]);
- os_free(eap_methods);
-
- if (!success)
- goto error;
- }
-
- res = wpa_drv_get_capa(wpa_s, &capa);
-
- /***** pairwise cipher */
- if (res < 0) {
- if (!strict) {
- const char *args[] = {"CCMP", "TKIP", "NONE"};
-
- if (!wpa_dbus_dict_append_string_array(
- &iter_dict, "pairwise", args,
- ARRAY_SIZE(args)))
- goto error;
- }
- } else {
- if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise",
- &iter_dict_entry,
- &iter_dict_val,
- &iter_array) ||
- ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "CCMP")) ||
- ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "TKIP")) ||
- ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "NONE")) ||
- !wpa_dbus_dict_end_string_array(&iter_dict,
- &iter_dict_entry,
- &iter_dict_val,
- &iter_array))
- goto error;
- }
-
- /***** group cipher */
- if (res < 0) {
- if (!strict) {
- const char *args[] = {
- "CCMP", "TKIP", "WEP104", "WEP40"
- };
-
- if (!wpa_dbus_dict_append_string_array(
- &iter_dict, "group", args,
- ARRAY_SIZE(args)))
- goto error;
- }
- } else {
- if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group",
- &iter_dict_entry,
- &iter_dict_val,
- &iter_array))
- goto error;
-
- if (((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "CCMP")) ||
- ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "TKIP")) ||
- ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "WEP104")) ||
- ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "WEP40")) ||
- !wpa_dbus_dict_end_string_array(&iter_dict,
- &iter_dict_entry,
- &iter_dict_val,
- &iter_array))
- goto error;
- }
-
- /***** key management */
- if (res < 0) {
- if (!strict) {
- const char *args[] = {
- "WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE",
- "NONE"
- };
- if (!wpa_dbus_dict_append_string_array(
- &iter_dict, "key_mgmt", args,
- ARRAY_SIZE(args)))
- goto error;
- }
- } else {
- if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt",
- &iter_dict_entry,
- &iter_dict_val,
- &iter_array) ||
- !wpa_dbus_dict_string_array_add_element(&iter_array,
- "NONE") ||
- !wpa_dbus_dict_string_array_add_element(&iter_array,
- "IEEE8021X") ||
- ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
- WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "WPA-EAP")) ||
- ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
- WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "WPA-PSK")) ||
- ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "WPA-NONE")) ||
- !wpa_dbus_dict_end_string_array(&iter_dict,
- &iter_dict_entry,
- &iter_dict_val,
- &iter_array))
- goto error;
- }
-
- /***** WPA protocol */
- if (res < 0) {
- if (!strict) {
- const char *args[] = { "RSN", "WPA" };
-
- if (!wpa_dbus_dict_append_string_array(
- &iter_dict, "proto", args,
- ARRAY_SIZE(args)))
- goto error;
- }
- } else {
- if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto",
- &iter_dict_entry,
- &iter_dict_val,
- &iter_array) ||
- ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
- WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "RSN")) ||
- ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
- WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "WPA")) ||
- !wpa_dbus_dict_end_string_array(&iter_dict,
- &iter_dict_entry,
- &iter_dict_val,
- &iter_array))
- goto error;
- }
-
- /***** auth alg */
- if (res < 0) {
- if (!strict) {
- const char *args[] = { "OPEN", "SHARED", "LEAP" };
-
- if (!wpa_dbus_dict_append_string_array(
- &iter_dict, "auth_alg", args,
- ARRAY_SIZE(args)))
- goto error;
- }
- } else {
- if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg",
- &iter_dict_entry,
- &iter_dict_val,
- &iter_array) ||
- ((capa.auth & WPA_DRIVER_AUTH_OPEN) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "OPEN")) ||
- ((capa.auth & WPA_DRIVER_AUTH_SHARED) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "SHARED")) ||
- ((capa.auth & WPA_DRIVER_AUTH_LEAP) &&
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "LEAP")) ||
- !wpa_dbus_dict_end_string_array(&iter_dict,
- &iter_dict_entry,
- &iter_dict_val,
- &iter_array))
- goto error;
- }
-
- if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
- goto error;
-
- return reply;
-
-error:
- if (reply)
- dbus_message_unref(reply);
- return dbus_message_new_error(
- message, WPAS_ERROR_INTERNAL_ERROR,
- "an internal error occurred returning interface capabilities.");
-}
-
-
-/**
- * wpas_dbus_iface_add_network - Add a new configured network
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * Returns: A dbus message containing the object path of the new network
- *
- * Handler function for "addNetwork" method call of a network interface.
- */
-DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- DBusMessage *reply = NULL;
- struct wpa_ssid *ssid = NULL;
- char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
-
- if (wpa_s->dbus_path)
- ssid = wpa_supplicant_add_network(wpa_s);
- if (ssid == NULL) {
- reply = dbus_message_new_error(
- message, WPAS_ERROR_ADD_NETWORK_ERROR,
- "wpa_supplicant could not add a network on this interface.");
- goto out;
- }
-
- /* Construct the object path for this network. */
- os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
- "%s/" WPAS_DBUS_NETWORKS_PART "/%d",
- wpa_s->dbus_path, ssid->id);
-
- reply = dbus_message_new_method_return(message);
- dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
- &path, DBUS_TYPE_INVALID);
-
-out:
- return reply;
-}
-
-
-/**
- * wpas_dbus_iface_remove_network - Remove a configured network
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * Returns: A dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Handler function for "removeNetwork" method call of a network interface.
- */
-DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- DBusMessage *reply = NULL;
- const char *op;
- char *iface = NULL, *net_id = NULL;
- int id;
- int result;
-
- if (!dbus_message_get_args(message, NULL,
- DBUS_TYPE_OBJECT_PATH, &op,
- DBUS_TYPE_INVALID)) {
- reply = wpas_dbus_new_invalid_opts_error(message, NULL);
- goto out;
- }
-
- /* Extract the network ID */
- iface = wpas_dbus_decompose_object_path(op, &net_id, NULL);
- if (iface == NULL || net_id == NULL) {
- reply = wpas_dbus_new_invalid_network_error(message);
- goto out;
- }
-
- /* Ensure the network is actually a child of this interface */
- if (!wpa_s->dbus_path || os_strcmp(iface, wpa_s->dbus_path) != 0) {
- reply = wpas_dbus_new_invalid_network_error(message);
- goto out;
- }
-
- id = strtoul(net_id, NULL, 10);
- result = wpa_supplicant_remove_network(wpa_s, id);
- if (result == -1) {
- reply = wpas_dbus_new_invalid_network_error(message);
- goto out;
- }
- if (result == -2) {
- reply = dbus_message_new_error(
- message, WPAS_ERROR_REMOVE_NETWORK_ERROR,
- "error removing the specified on this interface.");
- goto out;
- }
-
- reply = wpas_dbus_new_success_reply(message);
-
-out:
- os_free(iface);
- os_free(net_id);
- return reply;
-}
-
-
-static const char * const dont_quote[] = {
- "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
- "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
- "bssid", "scan_freq", "freq_list", NULL
-};
-
-
-static dbus_bool_t should_quote_opt(const char *key)
-{
- int i = 0;
-
- while (dont_quote[i] != NULL) {
- if (os_strcmp(key, dont_quote[i]) == 0)
- return FALSE;
- i++;
- }
- return TRUE;
-}
-
-
-/**
- * wpas_dbus_iface_set_network - Set options for a configured network
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * @ssid: wpa_ssid structure for a configured network
- * Returns: a dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Handler function for "set" method call of a configured network.
- */
-DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message,
- struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid)
-{
- DBusMessage *reply = NULL;
- struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
- DBusMessageIter iter, iter_dict;
-
- dbus_message_iter_init(message, &iter);
-
- if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) {
- reply = wpas_dbus_new_invalid_opts_error(message, NULL);
- goto out;
- }
-
- while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
- char *value = NULL;
- size_t size = 50;
- int ret;
-
- if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
- reply = wpas_dbus_new_invalid_opts_error(message,
- NULL);
- goto out;
- }
-
- /* Type conversions, since wpa_supplicant wants strings */
- if (entry.type == DBUS_TYPE_ARRAY &&
- entry.array_type == DBUS_TYPE_BYTE) {
- if (entry.array_len <= 0)
- goto error;
-
- size = entry.array_len * 2 + 1;
- value = os_zalloc(size);
- if (value == NULL)
- goto error;
- ret = wpa_snprintf_hex(value, size,
- (u8 *) entry.bytearray_value,
- entry.array_len);
- if (ret <= 0)
- goto error;
- } else if (entry.type == DBUS_TYPE_STRING) {
- if (should_quote_opt(entry.key)) {
- size = os_strlen(entry.str_value);
- /* Zero-length option check */
- if (size == 0)
- goto error;
- size += 3; /* For quotes and terminator */
- value = os_zalloc(size);
- if (value == NULL)
- goto error;
- ret = os_snprintf(value, size, "\"%s\"",
- entry.str_value);
- if (os_snprintf_error(size, ret))
- goto error;
- } else {
- value = os_strdup(entry.str_value);
- if (value == NULL)
- goto error;
- }
- } else if (entry.type == DBUS_TYPE_UINT32) {
- value = os_zalloc(size);
- if (value == NULL)
- goto error;
- ret = os_snprintf(value, size, "%u",
- entry.uint32_value);
- if (os_snprintf_error(size, ret))
- goto error;
- } else if (entry.type == DBUS_TYPE_INT32) {
- value = os_zalloc(size);
- if (value == NULL)
- goto error;
- ret = os_snprintf(value, size, "%d",
- entry.int32_value);
- if (os_snprintf_error(size, ret))
- goto error;
- } else
- goto error;
-
- if (wpa_config_set(ssid, entry.key, value, 0) < 0)
- goto error;
-
- if ((os_strcmp(entry.key, "psk") == 0 &&
- value[0] == '"' && ssid->ssid_len) ||
- (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
- wpa_config_update_psk(ssid);
- else if (os_strcmp(entry.key, "priority") == 0)
- wpa_config_update_prio_list(wpa_s->conf);
-
- os_free(value);
- wpa_dbus_dict_entry_clear(&entry);
- continue;
-
- error:
- os_free(value);
- reply = wpas_dbus_new_invalid_opts_error(message, entry.key);
- wpa_dbus_dict_entry_clear(&entry);
- break;
- }
-
- if (!reply)
- reply = wpas_dbus_new_success_reply(message);
-
-out:
- return reply;
-}
-
-
-/**
- * wpas_dbus_iface_enable_network - Mark a configured network as enabled
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * @ssid: wpa_ssid structure for a configured network
- * Returns: A dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Handler function for "enable" method call of a configured network.
- */
-DBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message,
- struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid)
-{
- wpa_supplicant_enable_network(wpa_s, ssid);
- return wpas_dbus_new_success_reply(message);
-}
-
-
-/**
- * wpas_dbus_iface_disable_network - Mark a configured network as disabled
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * @ssid: wpa_ssid structure for a configured network
- * Returns: A dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Handler function for "disable" method call of a configured network.
- */
-DBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message,
- struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid)
-{
- wpa_supplicant_disable_network(wpa_s, ssid);
- return wpas_dbus_new_success_reply(message);
-}
-
-
-/**
- * wpas_dbus_iface_select_network - Attempt association with a configured network
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * Returns: A dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Handler function for "selectNetwork" method call of network interface.
- */
-DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- DBusMessage *reply = NULL;
- const char *op;
- struct wpa_ssid *ssid;
- char *iface_obj_path = NULL;
- char *network = NULL;
-
- if (os_strlen(dbus_message_get_signature(message)) == 0) {
- /* Any network */
- ssid = NULL;
- } else {
- int nid;
-
- if (!dbus_message_get_args(message, NULL,
- DBUS_TYPE_OBJECT_PATH, &op,
- DBUS_TYPE_INVALID)) {
- reply = wpas_dbus_new_invalid_opts_error(message,
- NULL);
- goto out;
- }
-
- /* Extract the network number */
- iface_obj_path = wpas_dbus_decompose_object_path(op,
- &network,
- NULL);
- if (iface_obj_path == NULL) {
- reply = wpas_dbus_new_invalid_iface_error(message);
- goto out;
- }
- /* Ensure the object path really points to this interface */
- if (network == NULL || !wpa_s->dbus_path ||
- os_strcmp(iface_obj_path, wpa_s->dbus_path) != 0) {
- reply = wpas_dbus_new_invalid_network_error(message);
- goto out;
- }
-
- nid = strtoul(network, NULL, 10);
- if (errno == EINVAL) {
- reply = wpas_dbus_new_invalid_network_error(message);
- goto out;
- }
-
- ssid = wpa_config_get_network(wpa_s->conf, nid);
- if (ssid == NULL) {
- reply = wpas_dbus_new_invalid_network_error(message);
- goto out;
- }
- }
-
- /* Finally, associate with the network */
- wpa_supplicant_select_network(wpa_s, ssid);
-
- reply = wpas_dbus_new_success_reply(message);
-
-out:
- os_free(iface_obj_path);
- os_free(network);
- return reply;
-}
-
-
-/**
- * wpas_dbus_iface_disconnect - Terminate the current connection
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * Returns: A dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Handler function for "disconnect" method call of network interface.
- */
-DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- wpas_request_disconnection(wpa_s);
-
- return wpas_dbus_new_success_reply(message);
-}
-
-
-/**
- * wpas_dbus_iface_set_ap_scan - Control roaming mode
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * Returns: A dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Handler function for "setAPScan" method call.
- */
-DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- DBusMessage *reply = NULL;
- dbus_uint32_t ap_scan = 1;
-
- if (!dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ap_scan,
- DBUS_TYPE_INVALID)) {
- reply = wpas_dbus_new_invalid_opts_error(message, NULL);
- goto out;
- }
-
- if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
- reply = wpas_dbus_new_invalid_opts_error(message, NULL);
- goto out;
- }
-
- reply = wpas_dbus_new_success_reply(message);
-
-out:
- return reply;
-}
-
-
-/**
- * wpas_dbus_iface_set_smartcard_modules - Set smartcard related module paths
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * Returns: A dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Handler function for "setSmartcardModules" method call.
- */
-DBusMessage * wpas_dbus_iface_set_smartcard_modules(
- DBusMessage *message, struct wpa_supplicant *wpa_s)
-{
- DBusMessageIter iter, iter_dict;
- char *opensc_engine_path = NULL;
- char *pkcs11_engine_path = NULL;
- char *pkcs11_module_path = NULL;
- struct wpa_dbus_dict_entry entry;
-
- if (!dbus_message_iter_init(message, &iter))
- goto error;
-
- if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
- goto error;
-
- while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
- if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
- goto error;
- if (!strcmp(entry.key, "opensc_engine_path") &&
- entry.type == DBUS_TYPE_STRING) {
- os_free(opensc_engine_path);
- opensc_engine_path = os_strdup(entry.str_value);
- wpa_dbus_dict_entry_clear(&entry);
- if (opensc_engine_path == NULL)
- goto error;
- } else if (!strcmp(entry.key, "pkcs11_engine_path") &&
- entry.type == DBUS_TYPE_STRING) {
- os_free(pkcs11_engine_path);
- pkcs11_engine_path = os_strdup(entry.str_value);
- wpa_dbus_dict_entry_clear(&entry);
- if (pkcs11_engine_path == NULL)
- goto error;
- } else if (!strcmp(entry.key, "pkcs11_module_path") &&
- entry.type == DBUS_TYPE_STRING) {
- os_free(pkcs11_module_path);
- pkcs11_module_path = os_strdup(entry.str_value);
- wpa_dbus_dict_entry_clear(&entry);
- if (pkcs11_module_path == NULL)
- goto error;
- } else {
- wpa_dbus_dict_entry_clear(&entry);
- goto error;
- }
- }
-
- os_free(wpa_s->conf->opensc_engine_path);
- wpa_s->conf->opensc_engine_path = opensc_engine_path;
- os_free(wpa_s->conf->pkcs11_engine_path);
- wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path;
- os_free(wpa_s->conf->pkcs11_module_path);
- wpa_s->conf->pkcs11_module_path = pkcs11_module_path;
-
- wpa_sm_set_eapol(wpa_s->wpa, NULL);
- eapol_sm_deinit(wpa_s->eapol);
- wpa_s->eapol = NULL;
- wpa_supplicant_init_eapol(wpa_s);
- wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
-
- return wpas_dbus_new_success_reply(message);
-
-error:
- os_free(opensc_engine_path);
- os_free(pkcs11_engine_path);
- os_free(pkcs11_module_path);
- return wpas_dbus_new_invalid_opts_error(message, NULL);
-}
-
-
-/**
- * wpas_dbus_iface_get_state - Get interface state
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * Returns: A dbus message containing a STRING representing the current
- * interface state
- *
- * Handler function for "state" method call.
- */
-DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- DBusMessage *reply = NULL;
- const char *str_state;
-
- reply = dbus_message_new_method_return(message);
- if (reply != NULL) {
- str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
- dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_state,
- DBUS_TYPE_INVALID);
- }
-
- return reply;
-}
-
-
-/**
- * wpas_dbus_iface_get_scanning - Get interface scanning state
- * @message: Pointer to incoming dbus message
- * @wpa_s: wpa_supplicant structure for a network interface
- * Returns: A dbus message containing whether the interface is scanning
- *
- * Handler function for "scanning" method call.
- */
-DBusMessage * wpas_dbus_iface_get_scanning(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- DBusMessage *reply = NULL;
- dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
-
- reply = dbus_message_new_method_return(message);
- if (reply != NULL) {
- dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &scanning,
- DBUS_TYPE_INVALID);
- } else {
- wpa_printf(MSG_ERROR,
- "dbus: Not enough memory to return scanning state");
- }
-
- return reply;
-}
-
-
-#ifndef CONFIG_NO_CONFIG_BLOBS
-
-/**
- * wpas_dbus_iface_set_blobs - Store named binary blobs (ie, for certificates)
- * @message: Pointer to incoming dbus message
- * @wpa_s: %wpa_supplicant data structure
- * Returns: A dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Asks wpa_supplicant to internally store a one or more binary blobs.
- */
-DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- DBusMessage *reply = NULL;
- struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
- DBusMessageIter iter, iter_dict;
-
- dbus_message_iter_init(message, &iter);
-
- if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
- return wpas_dbus_new_invalid_opts_error(message, NULL);
-
- while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
- struct wpa_config_blob *blob;
-
- if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
- reply = wpas_dbus_new_invalid_opts_error(message,
- NULL);
- break;
- }
-
- if (entry.type != DBUS_TYPE_ARRAY ||
- entry.array_type != DBUS_TYPE_BYTE) {
- reply = wpas_dbus_new_invalid_opts_error(
- message, "Byte array expected.");
- break;
- }
-
- if ((entry.array_len <= 0) || (entry.array_len > 65536) ||
- !strlen(entry.key)) {
- reply = wpas_dbus_new_invalid_opts_error(
- message, "Invalid array size.");
- break;
- }
-
- blob = os_zalloc(sizeof(*blob));
- if (blob == NULL) {
- reply = dbus_message_new_error(
- message, WPAS_ERROR_ADD_ERROR,
- "Not enough memory to add blob.");
- break;
- }
- blob->data = os_zalloc(entry.array_len);
- if (blob->data == NULL) {
- reply = dbus_message_new_error(
- message, WPAS_ERROR_ADD_ERROR,
- "Not enough memory to add blob data.");
- os_free(blob);
- break;
- }
-
- blob->name = os_strdup(entry.key);
- blob->len = entry.array_len;
- os_memcpy(blob->data, (u8 *) entry.bytearray_value,
- entry.array_len);
- if (blob->name == NULL) {
- wpa_config_free_blob(blob);
- reply = dbus_message_new_error(
- message, WPAS_ERROR_ADD_ERROR,
- "Error adding blob.");
- break;
- }
-
- /* Success */
- if (!wpa_config_remove_blob(wpa_s->conf, blob->name))
- wpas_notify_blob_removed(wpa_s, blob->name);
- wpa_config_set_blob(wpa_s->conf, blob);
- wpas_notify_blob_added(wpa_s, blob->name);
-
- wpa_dbus_dict_entry_clear(&entry);
- }
- wpa_dbus_dict_entry_clear(&entry);
-
- return reply ? reply : wpas_dbus_new_success_reply(message);
-}
-
-
-/**
- * wpas_dbus_iface_remove_blob - Remove named binary blobs
- * @message: Pointer to incoming dbus message
- * @wpa_s: %wpa_supplicant data structure
- * Returns: A dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Asks wpa_supplicant to remove one or more previously stored binary blobs.
- */
-DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- DBusMessageIter iter, array;
- char *err_msg = NULL;
-
- dbus_message_iter_init(message, &iter);
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRING)
- return wpas_dbus_new_invalid_opts_error(message, NULL);
-
- dbus_message_iter_recurse(&iter, &array);
- while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
- const char *name;
-
- dbus_message_iter_get_basic(&array, &name);
- if (!os_strlen(name))
- err_msg = "Invalid blob name.";
- else if (wpa_config_remove_blob(wpa_s->conf, name) != 0)
- err_msg = "Error removing blob.";
- else
- wpas_notify_blob_removed(wpa_s, name);
- dbus_message_iter_next(&array);
- }
-
- if (err_msg)
- return dbus_message_new_error(message, WPAS_ERROR_REMOVE_ERROR,
- err_msg);
-
- return wpas_dbus_new_success_reply(message);
-}
-
-#endif /* CONFIG_NO_CONFIG_BLOBS */
-
-
-/**
- * wpas_dbus_iface_flush - Clear BSS of old or all inactive entries
- * @message: Pointer to incoming dbus message
- * @wpa_s: %wpa_supplicant data structure
- * Returns: a dbus message containing a UINT32 indicating success (1) or
- * failure (0), or returns a dbus error message with more information
- *
- * Handler function for "flush" method call. Handles requests for an
- * interface with an optional "age" parameter that specifies the minimum
- * age of a BSS to be flushed.
- */
-DBusMessage * wpas_dbus_iface_flush(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- int flush_age = 0;
-
- if (os_strlen(dbus_message_get_signature(message)) != 0 &&
- !dbus_message_get_args(message, NULL,
- DBUS_TYPE_INT32, &flush_age,
- DBUS_TYPE_INVALID)) {
- return wpas_dbus_new_invalid_opts_error(message, NULL);
- }
-
- if (flush_age == 0)
- wpa_bss_flush(wpa_s);
- else
- wpa_bss_flush_by_age(wpa_s, flush_age);
-
- return wpas_dbus_new_success_reply(message);
-}
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_old_handlers.h b/contrib/wpa/wpa_supplicant/dbus/dbus_old_handlers.h
deleted file mode 100644
index e60ad06a032e..000000000000
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_old_handlers.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * WPA Supplicant / dbus-based control interface
- * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef CTRL_IFACE_DBUS_HANDLERS_H
-#define CTRL_IFACE_DBUS_HANDLERS_H
-
-struct wpa_bss;
-
-DBusMessage * wpas_dbus_new_invalid_iface_error(DBusMessage *message);
-DBusMessage * wpas_dbus_new_invalid_network_error(DBusMessage *message);
-
-DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message,
- struct wpa_global *global);
-
-DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message,
- struct wpa_global *global);
-
-DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message,
- struct wpa_global *global);
-
-DBusMessage * wpas_dbus_global_set_debugparams(DBusMessage *message,
- struct wpa_global *global);
-
-DBusMessage * wpas_dbus_iface_scan(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message,
- struct wpa_supplicant *wpa_s,
- struct wpa_bss *bss);
-
-DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message,
- struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid);
-
-DBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message,
- struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid);
-
-DBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message,
- struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid);
-
-DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_set_smartcard_modules(
- DBusMessage *message, struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_get_scanning(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_wps_pbc(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_wps_pin(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_wps_reg(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_iface_flush(DBusMessage *message,
- struct wpa_supplicant *wpa_s);
-
-DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message);
-DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message,
- const char *arg);
-
-#endif /* CTRL_IFACE_DBUS_HANDLERS_H */
-
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_old_handlers_wps.c b/contrib/wpa/wpa_supplicant/dbus/dbus_old_handlers_wps.c
deleted file mode 100644
index 5309a5301fc2..000000000000
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_old_handlers_wps.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * WPA Supplicant / dbus-based control interface (WPS)
- * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-#include <dbus/dbus.h>
-
-#include "common.h"
-#include "../config.h"
-#include "../wpa_supplicant_i.h"
-#include "../wps_supplicant.h"
-#include "dbus_old.h"
-#include "dbus_old_handlers.h"
-
-/**
- * wpas_dbus_iface_wps_pbc - Request credentials using WPS PBC method
- * @message: Pointer to incoming dbus message
- * @wpa_s: %wpa_supplicant data structure
- * Returns: A dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Handler function for "wpsPbc" method call
- */
-DBusMessage * wpas_dbus_iface_wps_pbc(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- char *arg_bssid = NULL;
- u8 bssid[ETH_ALEN];
- int ret = 0;
-
- if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg_bssid,
- DBUS_TYPE_INVALID))
- return wpas_dbus_new_invalid_opts_error(message, NULL);
-
- if (os_strcmp(arg_bssid, "any") == 0)
- ret = wpas_wps_start_pbc(wpa_s, NULL, 0);
- else if (!hwaddr_aton(arg_bssid, bssid))
- ret = wpas_wps_start_pbc(wpa_s, bssid, 0);
- else {
- return wpas_dbus_new_invalid_opts_error(message,
- "Invalid BSSID");
- }
-
- if (ret < 0) {
- return dbus_message_new_error(
- message, WPAS_ERROR_WPS_PBC_ERROR,
- "Could not start PBC negotiation");
- }
-
- return wpas_dbus_new_success_reply(message);
-}
-
-
-/**
- * wpas_dbus_iface_wps_pin - Establish the PIN number of the enrollee
- * @message: Pointer to incoming dbus message
- * @wpa_s: %wpa_supplicant data structure
- * Returns: A dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Handler function for "wpsPin" method call
- */
-DBusMessage * wpas_dbus_iface_wps_pin(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- DBusMessage *reply = NULL;
- char *arg_bssid;
- char *pin = NULL;
- u8 bssid[ETH_ALEN], *_bssid = NULL;
- int ret = 0;
- char npin[9];
-
- if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg_bssid,
- DBUS_TYPE_STRING, &pin, DBUS_TYPE_INVALID))
- return wpas_dbus_new_invalid_opts_error(message, NULL);
-
- if (os_strcmp(arg_bssid, "any") == 0)
- _bssid = NULL;
- else if (!hwaddr_aton(arg_bssid, bssid))
- _bssid = bssid;
- else {
- return wpas_dbus_new_invalid_opts_error(message,
- "Invalid BSSID");
- }
-
- if (os_strlen(pin) > 0)
- ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
- DEV_PW_DEFAULT);
- else
- ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0,
- DEV_PW_DEFAULT);
-
- if (ret < 0) {
- return dbus_message_new_error(message,
- WPAS_ERROR_WPS_PIN_ERROR,
- "Could not init PIN");
- }
-
- reply = dbus_message_new_method_return(message);
- if (reply == NULL)
- return NULL;
-
- if (ret > 0) {
- os_snprintf(npin, sizeof(npin), "%08d", ret);
- pin = npin;
- }
- dbus_message_append_args(reply, DBUS_TYPE_STRING, &pin,
- DBUS_TYPE_INVALID);
- return reply;
-}
-
-
-/**
- * wpas_dbus_iface_wps_reg - Request credentials using the PIN of the AP
- * @message: Pointer to incoming dbus message
- * @wpa_s: %wpa_supplicant data structure
- * Returns: A dbus message containing a UINT32 indicating success (1) or
- * failure (0)
- *
- * Handler function for "wpsReg" method call
- */
-DBusMessage * wpas_dbus_iface_wps_reg(DBusMessage *message,
- struct wpa_supplicant *wpa_s)
-{
- char *arg_bssid;
- char *pin = NULL;
- u8 bssid[ETH_ALEN];
- int ret = 0;
-
- if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg_bssid,
- DBUS_TYPE_STRING, &pin, DBUS_TYPE_INVALID))
- return wpas_dbus_new_invalid_opts_error(message, NULL);
-
- if (!hwaddr_aton(arg_bssid, bssid))
- ret = wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
- else {
- return wpas_dbus_new_invalid_opts_error(message,
- "Invalid BSSID");
- }
-
- if (ret < 0) {
- return dbus_message_new_error(message,
- WPAS_ERROR_WPS_REG_ERROR,
- "Could not request credentials");
- }
-
- return wpas_dbus_new_success_reply(message);
-}
diff --git a/contrib/wpa/wpa_supplicant/dbus/fi.epitest.hostap.WPASupplicant.service.in b/contrib/wpa/wpa_supplicant/dbus/fi.epitest.hostap.WPASupplicant.service.in
deleted file mode 100644
index a75918f9380b..000000000000
--- a/contrib/wpa/wpa_supplicant/dbus/fi.epitest.hostap.WPASupplicant.service.in
+++ /dev/null
@@ -1,5 +0,0 @@
-[D-BUS Service]
-Name=fi.epitest.hostap.WPASupplicant
-Exec=@BINDIR@/wpa_supplicant -u
-User=root
-SystemdService=wpa_supplicant.service
diff --git a/contrib/wpa/wpa_supplicant/defconfig b/contrib/wpa/wpa_supplicant/defconfig
index 1d05198f849a..88cd79085f6d 100644
--- a/contrib/wpa/wpa_supplicant/defconfig
+++ b/contrib/wpa/wpa_supplicant/defconfig
@@ -1,9 +1,9 @@
# Example wpa_supplicant build time configuration
#
# This file lists the configuration options that are used when building the
-# hostapd binary. All lines starting with # are ignored. Configuration option
-# lines must be commented out complete, if they are not to be included, i.e.,
-# just setting VARIABLE=n is not disabling that variable.
+# wpa_supplicant binary. All lines starting with # are ignored. Configuration
+# option lines must be commented out complete, if they are not to be included,
+# i.e., just setting VARIABLE=n is not disabling that variable.
#
# This file is included in Makefile, so variables like CFLAGS and LIBS can also
# be modified from here. In most cases, these lines should use += in order not
@@ -44,7 +44,7 @@ CONFIG_DRIVER_NL80211=y
#CONFIG_LIBNL20=y
# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
-#CONFIG_LIBNL32=y
+CONFIG_LIBNL32=y
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
@@ -73,6 +73,12 @@ CONFIG_DRIVER_NL80211=y
# Driver interface for wired Ethernet drivers
CONFIG_DRIVER_WIRED=y
+# Driver interface for MACsec capable Qualcomm Atheros drivers
+#CONFIG_DRIVER_MACSEC_QCA=y
+
+# Driver interface for Linux MACsec drivers
+#CONFIG_DRIVER_MACSEC_LINUX=y
+
# Driver interface for the Broadcom RoboSwitch family
#CONFIG_DRIVER_ROBOSWITCH=y
@@ -83,8 +89,8 @@ CONFIG_DRIVER_WIRED=y
#LIBS += -lsocket -ldlpi -lnsl
#LIBS_c += -lsocket
-# Enable IEEE 802.1X Supplicant (automatically included if any EAP method is
-# included)
+# Enable IEEE 802.1X Supplicant (automatically included if any EAP method or
+# MACsec is included)
CONFIG_IEEE8021X_EAPOL=y
# EAP-MD5
@@ -103,10 +109,7 @@ CONFIG_EAP_PEAP=y
CONFIG_EAP_TTLS=y
# EAP-FAST
-# Note: If OpenSSL is used as the TLS library, OpenSSL 1.0 or newer is needed
-# for EAP-FAST support. Older OpenSSL releases would need to be patched, e.g.,
-# with openssl-0.9.8x-tls-extensions.patch, to add the needed functions.
-#CONFIG_EAP_FAST=y
+CONFIG_EAP_FAST=y
# EAP-GTC
CONFIG_EAP_GTC=y
@@ -121,10 +124,10 @@ CONFIG_EAP_OTP=y
#CONFIG_EAP_PSK=y
# EAP-pwd (secure authentication using only a password)
-#CONFIG_EAP_PWD=y
+CONFIG_EAP_PWD=y
# EAP-PAX
-#CONFIG_EAP_PAX=y
+CONFIG_EAP_PAX=y
# LEAP
CONFIG_EAP_LEAP=y
@@ -140,18 +143,18 @@ CONFIG_EAP_LEAP=y
#CONFIG_USIM_SIMULATOR=y
# EAP-SAKE
-#CONFIG_EAP_SAKE=y
+CONFIG_EAP_SAKE=y
# EAP-GPSK
-#CONFIG_EAP_GPSK=y
+CONFIG_EAP_GPSK=y
# Include support for optional SHA256 cipher suite in EAP-GPSK
-#CONFIG_EAP_GPSK_SHA256=y
+CONFIG_EAP_GPSK_SHA256=y
# EAP-TNC and related Trusted Network Connect support (experimental)
-#CONFIG_EAP_TNC=y
+CONFIG_EAP_TNC=y
# Wi-Fi Protected Setup (WPS)
-#CONFIG_WPS=y
+CONFIG_WPS=y
# Enable WPS external registrar functionality
#CONFIG_WPS_ER=y
# Disable credentials for an open network by default when acting as a WPS
@@ -161,11 +164,14 @@ CONFIG_EAP_LEAP=y
#CONFIG_WPS_NFC=y
# EAP-IKEv2
-#CONFIG_EAP_IKEV2=y
+CONFIG_EAP_IKEV2=y
# EAP-EKE
#CONFIG_EAP_EKE=y
+# MACsec
+#CONFIG_MACSEC=y
+
# PKCS#12 (PFX) support (used to read private key and certificate file from
# a file that usually has extension .p12 or .pfx)
CONFIG_PKCS12=y
@@ -226,6 +232,9 @@ CONFIG_CTRL_IFACE=y
# wpa_passphrase). This saves about 0.5 kB in code size.
#CONFIG_NO_WPA_PASSPHRASE=y
+# Simultaneous Authentication of Equals (SAE), WPA3-Personal
+CONFIG_SAE=y
+
# Disable scan result processing (ap_mode=1) to save code size by about 1 kB.
# This can be used if ap_scan=1 mode is never enabled.
#CONFIG_NO_SCAN_PROCESSING=y
@@ -288,17 +297,18 @@ CONFIG_BACKEND=file
# bridge interfaces (commit 'bridge: respect RFC2863 operational state')').
#CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
-# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
-CONFIG_PEERKEY=y
-
# IEEE 802.11w (management frame protection), also known as PMF
# Driver support is also needed for IEEE 802.11w.
-#CONFIG_IEEE80211W=y
+CONFIG_IEEE80211W=y
+
+# Support Operating Channel Validation
+#CONFIG_OCV=y
# Select TLS implementation
# openssl = OpenSSL (default)
# gnutls = GnuTLS
# internal = Internal TLSv1 implementation (experimental)
+# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
# none = Empty template
#CONFIG_TLS=openssl
@@ -316,6 +326,10 @@ CONFIG_PEERKEY=y
# will be used)
#CONFIG_TLSV12=y
+# Select which ciphers to use by default with OpenSSL if the user does not
+# specify them.
+#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
+
# 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
@@ -338,16 +352,12 @@ CONFIG_PEERKEY=y
#CONFIG_NDIS_EVENTS_INTEGRATED=y
#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
-# Add support for old DBus control interface
-# (fi.epitest.hostap.WPASupplicant)
-#CONFIG_CTRL_IFACE_DBUS=y
-
# Add support for new DBus control interface
# (fi.w1.hostap.wpa_supplicant1)
-#CONFIG_CTRL_IFACE_DBUS_NEW=y
+CONFIG_CTRL_IFACE_DBUS_NEW=y
# Add introspection support for new DBus control interface
-#CONFIG_CTRL_IFACE_DBUS_INTRO=y
+CONFIG_CTRL_IFACE_DBUS_INTRO=y
# Add support for loading EAP methods dynamically as shared libraries.
# When this option is enabled, each EAP method can be either included
@@ -370,14 +380,14 @@ CONFIG_PEERKEY=y
# amount of memory/flash.
#CONFIG_DYNAMIC_EAP_METHODS=y
-# IEEE Std 802.11r-2008 (Fast BSS Transition)
-#CONFIG_IEEE80211R=y
+# IEEE Std 802.11r-2008 (Fast BSS Transition) for station mode
+CONFIG_IEEE80211R=y
# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)
-#CONFIG_DEBUG_FILE=y
+CONFIG_DEBUG_FILE=y
# Send debug messages to syslog instead of stdout
-#CONFIG_DEBUG_SYSLOG=y
+CONFIG_DEBUG_SYSLOG=y
# Set syslog facility for debug messages
#CONFIG_DEBUG_SYSLOG_FACILITY=LOG_DAEMON
@@ -447,12 +457,17 @@ CONFIG_PEERKEY=y
# that meet the requirements described above.
#CONFIG_NO_RANDOM_POOL=y
+# Should we attempt to use the getrandom(2) call that provides more reliable
+# yet secure randomness source than /dev/random on Linux 3.17 and newer.
+# Requires glibc 2.25 to build, falls back to /dev/random if unavailable.
+#CONFIG_GETRANDOM=y
+
# IEEE 802.11n (High Throughput) support (mainly for AP mode)
-#CONFIG_IEEE80211N=y
+CONFIG_IEEE80211N=y
# IEEE 802.11ac (Very High Throughput) support (mainly for AP mode)
# (depends on CONFIG_IEEE80211N)
-#CONFIG_IEEE80211AC=y
+CONFIG_IEEE80211AC=y
# Wireless Network Management (IEEE Std 802.11v-2011)
# Note: This is experimental and not complete implementation.
@@ -462,10 +477,10 @@ CONFIG_PEERKEY=y
# This can be used to enable functionality to improve interworking with
# external networks (GAS/ANQP to learn more about the networks and network
# selection based on available credentials).
-#CONFIG_INTERWORKING=y
+CONFIG_INTERWORKING=y
# Hotspot 2.0
-#CONFIG_HS20=y
+CONFIG_HS20=y
# Enable interface matching in wpa_supplicant
#CONFIG_MATCH_IFACE=y
@@ -478,20 +493,20 @@ CONFIG_PEERKEY=y
# should be noted that this is mainly aimed at simple cases like
# WPA2-Personal while more complex configurations like WPA2-Enterprise with an
# external RADIUS server can be supported with hostapd.
-#CONFIG_AP=y
+CONFIG_AP=y
# P2P (Wi-Fi Direct)
# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
# more information on P2P operations.
-#CONFIG_P2P=y
+CONFIG_P2P=y
# Enable TDLS support
#CONFIG_TDLS=y
-# Wi-Fi Direct
-# This can be used to enable Wi-Fi Direct extensions for P2P using an external
+# Wi-Fi Display
+# This can be used to enable Wi-Fi Display extensions for P2P using an external
# program to control the additional information exchanges in the messages.
-#CONFIG_WIFI_DISPLAY=y
+CONFIG_WIFI_DISPLAY=y
# Autoscan
# This can be used to enable automatic scan support in wpa_supplicant.
@@ -548,3 +563,40 @@ CONFIG_PEERKEY=y
# Support Multi Band Operation
#CONFIG_MBO=y
+
+# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
+#CONFIG_FILS=y
+# FILS shared key authentication with PFS
+#CONFIG_FILS_SK_PFS=y
+
+# Support RSN on IBSS networks
+# This is needed to be able to use mode=1 network profile with proto=RSN and
+# key_mgmt=WPA-PSK (i.e., full key management instead of WPA-None).
+CONFIG_IBSS_RSN=y
+
+# External PMKSA cache control
+# This can be used to enable control interface commands that allow the current
+# PMKSA cache entries to be fetched and new entries to be added.
+#CONFIG_PMKSA_CACHE_EXTERNAL=y
+
+# Mesh Networking (IEEE 802.11s)
+#CONFIG_MESH=y
+
+# Background scanning modules
+# These can be used to request wpa_supplicant to perform background scanning
+# operations for roaming within an ESS (same SSID). See the bgscan parameter in
+# the wpa_supplicant.conf file for more details.
+# Periodic background scans based on signal strength
+CONFIG_BGSCAN_SIMPLE=y
+# Learn channels used by the network and try to avoid bgscans on other
+# channels (experimental)
+#CONFIG_BGSCAN_LEARN=y
+
+# Opportunistic Wireless Encryption (OWE)
+# Experimental implementation of draft-harkins-owe-07.txt
+#CONFIG_OWE=y
+
+# Device Provisioning Protocol (DPP)
+# This requires CONFIG_IEEE80211W=y to be enabled, too. (see
+# wpa_supplicant/README-DPP for details)
+CONFIG_DPP=y
diff --git a/contrib/wpa/wpa_supplicant/dpp_supplicant.c b/contrib/wpa/wpa_supplicant/dpp_supplicant.c
new file mode 100644
index 000000000000..e003a8514edb
--- /dev/null
+++ b/contrib/wpa/wpa_supplicant/dpp_supplicant.c
@@ -0,0 +1,2246 @@
+/*
+ * wpa_supplicant - DPP
+ * Copyright (c) 2017, Qualcomm Atheros, Inc.
+ * Copyright (c) 2018-2019, The Linux Foundation
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "common/dpp.h"
+#include "common/gas.h"
+#include "common/gas_server.h"
+#include "rsn_supp/wpa.h"
+#include "rsn_supp/pmksa_cache.h"
+#include "wpa_supplicant_i.h"
+#include "config.h"
+#include "driver_i.h"
+#include "offchannel.h"
+#include "gas_query.h"
+#include "bss.h"
+#include "scan.h"
+#include "notify.h"
+#include "dpp_supplicant.h"
+
+
+static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
+ unsigned int freq);
+static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
+static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator);
+static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
+ unsigned int freq, const u8 *dst,
+ const u8 *src, const u8 *bssid,
+ const u8 *data, size_t data_len,
+ enum offchannel_send_action_result result);
+static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
+static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s);
+static void
+wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
+ unsigned int freq, const u8 *dst,
+ const u8 *src, const u8 *bssid,
+ const u8 *data, size_t data_len,
+ enum offchannel_send_action_result result);
+
+static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+/* Use a hardcoded Transaction ID 1 in Peer Discovery frames since there is only
+ * a single transaction in progress at any point in time. */
+static const u8 TRANSACTION_ID = 1;
+
+
+/**
+ * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @cmd: DPP URI read from a QR Code
+ * Returns: Identifier of the stored info or -1 on failure
+ */
+int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ struct dpp_bootstrap_info *bi;
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+ bi = dpp_add_qr_code(wpa_s->dpp, cmd);
+ if (!bi)
+ return -1;
+
+ if (auth && auth->response_pending &&
+ dpp_notify_new_qr_code(auth, bi) == 1) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Sending out pending authentication response");
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
+ " freq=%u type=%d",
+ MAC2STR(auth->peer_mac_addr), auth->curr_freq,
+ DPP_PA_AUTHENTICATION_RESP);
+ offchannel_send_action(wpa_s, auth->curr_freq,
+ auth->peer_mac_addr, wpa_s->own_addr,
+ broadcast,
+ wpabuf_head(auth->resp_msg),
+ wpabuf_len(auth->resp_msg),
+ 500, wpas_dpp_tx_status, 0);
+ }
+
+ return bi->id;
+}
+
+
+static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+ if (!auth || !auth->resp_msg)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "DPP: Retry Authentication Response after timeout");
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
+ " freq=%u type=%d",
+ MAC2STR(auth->peer_mac_addr), auth->curr_freq,
+ DPP_PA_AUTHENTICATION_RESP);
+ offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr,
+ wpa_s->own_addr, broadcast,
+ wpabuf_head(auth->resp_msg),
+ wpabuf_len(auth->resp_msg),
+ 500, wpas_dpp_tx_status, 0);
+}
+
+
+static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s)
+{
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+ unsigned int wait_time, max_tries;
+
+ if (!auth || !auth->resp_msg)
+ return;
+
+ if (wpa_s->dpp_resp_max_tries)
+ max_tries = wpa_s->dpp_resp_max_tries;
+ else
+ max_tries = 5;
+ auth->auth_resp_tries++;
+ if (auth->auth_resp_tries >= max_tries) {
+ wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange");
+ offchannel_send_action_done(wpa_s);
+ dpp_auth_deinit(wpa_s->dpp_auth);
+ wpa_s->dpp_auth = NULL;
+ return;
+ }
+
+ if (wpa_s->dpp_resp_retry_time)
+ wait_time = wpa_s->dpp_resp_retry_time;
+ else
+ wait_time = 1000;
+ wpa_printf(MSG_DEBUG,
+ "DPP: Schedule retransmission of Authentication Response frame in %u ms",
+ wait_time);
+ eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
+ eloop_register_timeout(wait_time / 1000,
+ (wait_time % 1000) * 1000,
+ wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
+}
+
+
+static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s)
+{
+ wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
+ wpa_s->disconnected = 0;
+ wpa_s->reassociate = 1;
+ wpa_s->scan_runs = 0;
+ wpa_s->normal_scans = 0;
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+}
+
+
+static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
+ unsigned int freq, const u8 *dst,
+ const u8 *src, const u8 *bssid,
+ const u8 *data, size_t data_len,
+ enum offchannel_send_action_result result)
+{
+ const char *res_txt;
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+ res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
+ (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
+ "FAILED");
+ wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
+ " result=%s", freq, MAC2STR(dst), res_txt);
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
+ " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
+
+ if (!wpa_s->dpp_auth) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Ignore TX status since there is no ongoing authentication exchange");
+ return;
+ }
+
+#ifdef CONFIG_DPP2
+ if (auth->connect_on_tx_status) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Try to connect after completed configuration result");
+ wpas_dpp_try_to_connect(wpa_s);
+ dpp_auth_deinit(wpa_s->dpp_auth);
+ wpa_s->dpp_auth = NULL;
+ return;
+ }
+#endif /* CONFIG_DPP2 */
+
+ if (wpa_s->dpp_auth->remove_on_tx_status) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Terminate authentication exchange due to an earlier error");
+ eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
+ NULL);
+ offchannel_send_action_done(wpa_s);
+ dpp_auth_deinit(wpa_s->dpp_auth);
+ wpa_s->dpp_auth = NULL;
+ return;
+ }
+
+ if (wpa_s->dpp_auth_ok_on_ack)
+ wpas_dpp_auth_success(wpa_s, 1);
+
+ if (!is_broadcast_ether_addr(dst) &&
+ result != OFFCHANNEL_SEND_ACTION_SUCCESS) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Unicast DPP Action frame was not ACKed");
+ if (auth->waiting_auth_resp) {
+ /* In case of DPP Authentication Request frame, move to
+ * the next channel immediately. */
+ offchannel_send_action_done(wpa_s);
+ wpas_dpp_auth_init_next(wpa_s);
+ return;
+ }
+ if (auth->waiting_auth_conf) {
+ wpas_dpp_auth_resp_retry(wpa_s);
+ return;
+ }
+ }
+
+ if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
+ result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
+ /* Allow timeout handling to stop iteration if no response is
+ * received from a peer that has ACKed a request. */
+ auth->auth_req_ack = 1;
+ }
+
+ if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
+ wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
+ wpa_s->dpp_auth->curr_freq,
+ wpa_s->dpp_auth->neg_freq);
+ offchannel_send_action_done(wpa_s);
+ wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
+ }
+
+ if (wpa_s->dpp_auth_ok_on_ack)
+ wpa_s->dpp_auth_ok_on_ack = 0;
+}
+
+
+static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+ unsigned int freq;
+ struct os_reltime now, diff;
+ unsigned int wait_time, diff_ms;
+
+ if (!auth || !auth->waiting_auth_resp)
+ return;
+
+ wait_time = wpa_s->dpp_resp_wait_time ?
+ wpa_s->dpp_resp_wait_time : 2000;
+ os_get_reltime(&now);
+ os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff);
+ diff_ms = diff.sec * 1000 + diff.usec / 1000;
+ wpa_printf(MSG_DEBUG,
+ "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
+ wait_time, diff_ms);
+
+ if (auth->auth_req_ack && diff_ms >= wait_time) {
+ /* Peer ACK'ed Authentication Request frame, but did not reply
+ * with Authentication Response frame within two seconds. */
+ wpa_printf(MSG_INFO,
+ "DPP: No response received from responder - stopping initiation attempt");
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
+ offchannel_send_action_done(wpa_s);
+ wpas_dpp_listen_stop(wpa_s);
+ dpp_auth_deinit(auth);
+ wpa_s->dpp_auth = NULL;
+ return;
+ }
+
+ if (diff_ms >= wait_time) {
+ /* Authentication Request frame was not ACK'ed and no reply
+ * was receiving within two seconds. */
+ wpa_printf(MSG_DEBUG,
+ "DPP: Continue Initiator channel iteration");
+ offchannel_send_action_done(wpa_s);
+ wpas_dpp_listen_stop(wpa_s);
+ wpas_dpp_auth_init_next(wpa_s);
+ return;
+ }
+
+ /* Driver did not support 2000 ms long wait_time with TX command, so
+ * schedule listen operation to continue waiting for the response.
+ *
+ * DPP listen operations continue until stopped, so simply schedule a
+ * new call to this function at the point when the two second reply
+ * wait has expired. */
+ wait_time -= diff_ms;
+
+ freq = auth->curr_freq;
+ if (auth->neg_freq > 0)
+ freq = auth->neg_freq;
+ wpa_printf(MSG_DEBUG,
+ "DPP: Continue reply wait on channel %u MHz for %u ms",
+ freq, wait_time);
+ wpa_s->dpp_in_response_listen = 1;
+ wpas_dpp_listen_start(wpa_s, freq);
+
+ eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
+ wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+}
+
+
+static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
+ struct dpp_authentication *auth)
+{
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->dpp_config_obj_override)
+ auth->config_obj_override =
+ os_strdup(wpa_s->dpp_config_obj_override);
+ if (wpa_s->dpp_discovery_override)
+ auth->discovery_override =
+ os_strdup(wpa_s->dpp_discovery_override);
+ if (wpa_s->dpp_groups_override)
+ auth->groups_override =
+ os_strdup(wpa_s->dpp_groups_override);
+ auth->ignore_netaccesskey_mismatch =
+ wpa_s->dpp_ignore_netaccesskey_mismatch;
+#endif /* CONFIG_TESTING_OPTIONS */
+}
+
+
+static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+
+ if (!wpa_s->dpp_auth)
+ return;
+ wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
+ wpas_dpp_auth_init_next(wpa_s);
+}
+
+
+static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
+{
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+ const u8 *dst;
+ unsigned int wait_time, max_wait_time, freq, max_tries, used;
+ struct os_reltime now, diff;
+
+ wpa_s->dpp_in_response_listen = 0;
+ if (!auth)
+ return -1;
+
+ if (auth->freq_idx == 0)
+ os_get_reltime(&wpa_s->dpp_init_iter_start);
+
+ if (auth->freq_idx >= auth->num_freq) {
+ auth->num_freq_iters++;
+ if (wpa_s->dpp_init_max_tries)
+ max_tries = wpa_s->dpp_init_max_tries;
+ else
+ max_tries = 5;
+ if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
+ wpa_printf(MSG_INFO,
+ "DPP: No response received from responder - stopping initiation attempt");
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
+ eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
+ wpa_s, NULL);
+ offchannel_send_action_done(wpa_s);
+ dpp_auth_deinit(wpa_s->dpp_auth);
+ wpa_s->dpp_auth = NULL;
+ return -1;
+ }
+ auth->freq_idx = 0;
+ eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
+ if (wpa_s->dpp_init_retry_time)
+ wait_time = wpa_s->dpp_init_retry_time;
+ else
+ wait_time = 10000;
+ os_get_reltime(&now);
+ os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
+ used = diff.sec * 1000 + diff.usec / 1000;
+ if (used > wait_time)
+ wait_time = 0;
+ else
+ wait_time -= used;
+ wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
+ wait_time);
+ eloop_register_timeout(wait_time / 1000,
+ (wait_time % 1000) * 1000,
+ wpas_dpp_init_timeout, wpa_s,
+ NULL);
+ return 0;
+ }
+ freq = auth->freq[auth->freq_idx++];
+ auth->curr_freq = freq;
+
+ if (is_zero_ether_addr(auth->peer_bi->mac_addr))
+ dst = broadcast;
+ else
+ dst = auth->peer_bi->mac_addr;
+ wpa_s->dpp_auth_ok_on_ack = 0;
+ eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+ wait_time = wpa_s->max_remain_on_chan;
+ max_wait_time = wpa_s->dpp_resp_wait_time ?
+ wpa_s->dpp_resp_wait_time : 2000;
+ if (wait_time > max_wait_time)
+ wait_time = max_wait_time;
+ wait_time += 10; /* give the driver some extra time to complete */
+ eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
+ wpas_dpp_reply_wait_timeout,
+ wpa_s, NULL);
+ wait_time -= 10;
+ if (auth->neg_freq > 0 && freq != auth->neg_freq) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
+ freq, auth->neg_freq);
+ }
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
+ MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
+ auth->auth_req_ack = 0;
+ os_get_reltime(&wpa_s->dpp_last_init);
+ return offchannel_send_action(wpa_s, freq, dst,
+ wpa_s->own_addr, broadcast,
+ wpabuf_head(auth->req_msg),
+ wpabuf_len(auth->req_msg),
+ wait_time, wpas_dpp_tx_status, 0);
+}
+
+
+int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ const char *pos;
+ struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
+ u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
+ unsigned int neg_freq = 0;
+
+ wpa_s->dpp_gas_client = 0;
+
+ pos = os_strstr(cmd, " peer=");
+ if (!pos)
+ return -1;
+ pos += 6;
+ peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
+ if (!peer_bi) {
+ wpa_printf(MSG_INFO,
+ "DPP: Could not find bootstrapping info for the identified peer");
+ return -1;
+ }
+
+ pos = os_strstr(cmd, " own=");
+ if (pos) {
+ pos += 5;
+ own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
+ if (!own_bi) {
+ wpa_printf(MSG_INFO,
+ "DPP: Could not find bootstrapping info for the identified local entry");
+ return -1;
+ }
+
+ if (peer_bi->curve != own_bi->curve) {
+ wpa_printf(MSG_INFO,
+ "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
+ peer_bi->curve->name, own_bi->curve->name);
+ return -1;
+ }
+ }
+
+ pos = os_strstr(cmd, " role=");
+ if (pos) {
+ pos += 6;
+ if (os_strncmp(pos, "configurator", 12) == 0)
+ allowed_roles = DPP_CAPAB_CONFIGURATOR;
+ else if (os_strncmp(pos, "enrollee", 8) == 0)
+ allowed_roles = DPP_CAPAB_ENROLLEE;
+ else if (os_strncmp(pos, "either", 6) == 0)
+ allowed_roles = DPP_CAPAB_CONFIGURATOR |
+ DPP_CAPAB_ENROLLEE;
+ else
+ goto fail;
+ }
+
+ pos = os_strstr(cmd, " netrole=");
+ if (pos) {
+ pos += 9;
+ wpa_s->dpp_netrole_ap = os_strncmp(pos, "ap", 2) == 0;
+ }
+
+ pos = os_strstr(cmd, " neg_freq=");
+ if (pos)
+ neg_freq = atoi(pos + 10);
+
+ if (wpa_s->dpp_auth) {
+ eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
+ NULL);
+ offchannel_send_action_done(wpa_s);
+ dpp_auth_deinit(wpa_s->dpp_auth);
+ }
+ wpa_s->dpp_auth = dpp_auth_init(wpa_s, peer_bi, own_bi, allowed_roles,
+ neg_freq,
+ wpa_s->hw.modes, wpa_s->hw.num_modes);
+ if (!wpa_s->dpp_auth)
+ goto fail;
+ wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
+ if (dpp_set_configurator(wpa_s->dpp, wpa_s, wpa_s->dpp_auth, cmd) < 0) {
+ dpp_auth_deinit(wpa_s->dpp_auth);
+ wpa_s->dpp_auth = NULL;
+ goto fail;
+ }
+
+ wpa_s->dpp_auth->neg_freq = neg_freq;
+
+ if (!is_zero_ether_addr(peer_bi->mac_addr))
+ os_memcpy(wpa_s->dpp_auth->peer_mac_addr, peer_bi->mac_addr,
+ ETH_ALEN);
+
+ return wpas_dpp_auth_init_next(wpa_s);
+fail:
+ return -1;
+}
+
+
+struct wpas_dpp_listen_work {
+ unsigned int freq;
+ unsigned int duration;
+ struct wpabuf *probe_resp_ie;
+};
+
+
+static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
+{
+ if (!lwork)
+ return;
+ os_free(lwork);
+}
+
+
+static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_dpp_listen_work *lwork;
+
+ if (!wpa_s->dpp_listen_work)
+ return;
+
+ lwork = wpa_s->dpp_listen_work->ctx;
+ wpas_dpp_listen_work_free(lwork);
+ radio_work_done(wpa_s->dpp_listen_work);
+ wpa_s->dpp_listen_work = NULL;
+}
+
+
+static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
+{
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ struct wpas_dpp_listen_work *lwork = work->ctx;
+
+ if (deinit) {
+ if (work->started) {
+ wpa_s->dpp_listen_work = NULL;
+ wpas_dpp_listen_stop(wpa_s);
+ }
+ wpas_dpp_listen_work_free(lwork);
+ return;
+ }
+
+ wpa_s->dpp_listen_work = work;
+
+ wpa_s->dpp_pending_listen_freq = lwork->freq;
+
+ if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
+ wpa_s->max_remain_on_chan) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
+ lwork->freq);
+ wpa_s->dpp_listen_freq = 0;
+ wpas_dpp_listen_work_done(wpa_s);
+ wpa_s->dpp_pending_listen_freq = 0;
+ return;
+ }
+ wpa_s->off_channel_freq = 0;
+ wpa_s->roc_waiting_drv_freq = lwork->freq;
+}
+
+
+static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
+ unsigned int freq)
+{
+ struct wpas_dpp_listen_work *lwork;
+
+ if (wpa_s->dpp_listen_work) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Reject start_listen since dpp_listen_work already exists");
+ return -1;
+ }
+
+ if (wpa_s->dpp_listen_freq)
+ wpas_dpp_listen_stop(wpa_s);
+ wpa_s->dpp_listen_freq = freq;
+
+ lwork = os_zalloc(sizeof(*lwork));
+ if (!lwork)
+ return -1;
+ lwork->freq = freq;
+
+ if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
+ lwork) < 0) {
+ wpas_dpp_listen_work_free(lwork);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ int freq;
+
+ freq = atoi(cmd);
+ if (freq <= 0)
+ return -1;
+
+ if (os_strstr(cmd, " role=configurator"))
+ wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
+ else if (os_strstr(cmd, " role=enrollee"))
+ wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
+ else
+ wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
+ DPP_CAPAB_ENROLLEE;
+ wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
+ wpa_s->dpp_netrole_ap = os_strstr(cmd, " netrole=ap") != NULL;
+ if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
+ wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
+ freq);
+ return 0;
+ }
+
+ return wpas_dpp_listen_start(wpa_s, freq);
+}
+
+
+void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
+{
+ wpa_s->dpp_in_response_listen = 0;
+ if (!wpa_s->dpp_listen_freq)
+ return;
+
+ wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
+ wpa_s->dpp_listen_freq);
+ wpa_drv_cancel_remain_on_channel(wpa_s);
+ wpa_s->dpp_listen_freq = 0;
+ wpas_dpp_listen_work_done(wpa_s);
+}
+
+
+void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+ unsigned int freq)
+{
+ wpas_dpp_listen_work_done(wpa_s);
+
+ if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
+ unsigned int new_freq;
+
+ /* Continue listen with a new remain-on-channel */
+ if (wpa_s->dpp_auth->neg_freq > 0)
+ new_freq = wpa_s->dpp_auth->neg_freq;
+ else
+ new_freq = wpa_s->dpp_auth->curr_freq;
+ wpa_printf(MSG_DEBUG,
+ "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
+ new_freq);
+ wpas_dpp_listen_start(wpa_s, new_freq);
+ return;
+ }
+
+ if (wpa_s->dpp_listen_freq) {
+ /* Continue listen with a new remain-on-channel */
+ wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
+ }
+}
+
+
+static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *hdr, const u8 *buf, size_t len,
+ unsigned int freq)
+{
+ const u8 *r_bootstrap, *i_bootstrap;
+ u16 r_bootstrap_len, i_bootstrap_len;
+ struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
+
+ if (!wpa_s->dpp)
+ return;
+
+ wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
+ MAC2STR(src));
+
+ r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
+ &r_bootstrap_len);
+ if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
+ "Missing or invalid required Responder Bootstrapping Key Hash attribute");
+ return;
+ }
+ wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
+ r_bootstrap, r_bootstrap_len);
+
+ i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
+ &i_bootstrap_len);
+ if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
+ "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
+ return;
+ }
+ wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
+ i_bootstrap, i_bootstrap_len);
+
+ /* Try to find own and peer bootstrapping key matches based on the
+ * received hash values */
+ dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
+ &own_bi, &peer_bi);
+ if (!own_bi) {
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
+ "No matching own bootstrapping key found - ignore message");
+ return;
+ }
+
+ if (wpa_s->dpp_auth) {
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
+ "Already in DPP authentication exchange - ignore new one");
+ return;
+ }
+
+ wpa_s->dpp_gas_client = 0;
+ wpa_s->dpp_auth_ok_on_ack = 0;
+ wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s, wpa_s->dpp_allowed_roles,
+ wpa_s->dpp_qr_mutual,
+ peer_bi, own_bi, freq, hdr, buf, len);
+ if (!wpa_s->dpp_auth) {
+ wpa_printf(MSG_DEBUG, "DPP: No response generated");
+ return;
+ }
+ wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
+ if (dpp_set_configurator(wpa_s->dpp, wpa_s, wpa_s->dpp_auth,
+ wpa_s->dpp_configurator_params) < 0) {
+ dpp_auth_deinit(wpa_s->dpp_auth);
+ wpa_s->dpp_auth = NULL;
+ return;
+ }
+ os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
+
+ if (wpa_s->dpp_listen_freq &&
+ wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
+ wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
+ wpas_dpp_listen_stop(wpa_s);
+ }
+
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
+ MAC2STR(src), wpa_s->dpp_auth->curr_freq,
+ DPP_PA_AUTHENTICATION_RESP);
+ offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
+ src, wpa_s->own_addr, broadcast,
+ wpabuf_head(wpa_s->dpp_auth->resp_msg),
+ wpabuf_len(wpa_s->dpp_auth->resp_msg),
+ 500, wpas_dpp_tx_status, 0);
+}
+
+
+static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
+{
+ /* TODO: stop wait and start ROC */
+}
+
+
+static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
+ struct dpp_authentication *auth)
+{
+ struct wpa_ssid *ssid;
+
+#ifdef CONFIG_DPP2
+ if (auth->akm == DPP_AKM_SAE) {
+#ifdef CONFIG_SAE
+ struct wpa_driver_capa capa;
+ int res;
+
+ res = wpa_drv_get_capa(wpa_s, &capa);
+ if (res == 0 &&
+ !(capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: SAE not supported by the driver");
+ return NULL;
+ }
+#else /* CONFIG_SAE */
+ wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
+ return NULL;
+#endif /* CONFIG_SAE */
+ }
+#endif /* CONFIG_DPP2 */
+
+ ssid = wpa_config_add_network(wpa_s->conf);
+ if (!ssid)
+ return NULL;
+ wpas_notify_network_added(wpa_s, ssid);
+ wpa_config_set_network_defaults(ssid);
+ ssid->disabled = 1;
+
+ ssid->ssid = os_malloc(auth->ssid_len);
+ if (!ssid->ssid)
+ goto fail;
+ os_memcpy(ssid->ssid, auth->ssid, auth->ssid_len);
+ ssid->ssid_len = auth->ssid_len;
+
+ if (auth->connector) {
+ ssid->key_mgmt = WPA_KEY_MGMT_DPP;
+ ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+ ssid->dpp_connector = os_strdup(auth->connector);
+ if (!ssid->dpp_connector)
+ goto fail;
+ }
+
+ if (auth->c_sign_key) {
+ ssid->dpp_csign = os_malloc(wpabuf_len(auth->c_sign_key));
+ if (!ssid->dpp_csign)
+ goto fail;
+ os_memcpy(ssid->dpp_csign, wpabuf_head(auth->c_sign_key),
+ wpabuf_len(auth->c_sign_key));
+ ssid->dpp_csign_len = wpabuf_len(auth->c_sign_key);
+ }
+
+ if (auth->net_access_key) {
+ ssid->dpp_netaccesskey =
+ os_malloc(wpabuf_len(auth->net_access_key));
+ if (!ssid->dpp_netaccesskey)
+ goto fail;
+ os_memcpy(ssid->dpp_netaccesskey,
+ wpabuf_head(auth->net_access_key),
+ wpabuf_len(auth->net_access_key));
+ ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
+ ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
+ }
+
+ if (!auth->connector || dpp_akm_psk(auth->akm) ||
+ dpp_akm_sae(auth->akm)) {
+ if (!auth->connector)
+ ssid->key_mgmt = 0;
+ if (dpp_akm_psk(auth->akm))
+ ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
+ WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
+ if (dpp_akm_sae(auth->akm))
+ ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
+ WPA_KEY_MGMT_FT_SAE;
+ ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
+ if (auth->passphrase[0]) {
+ if (wpa_config_set_quoted(ssid, "psk",
+ auth->passphrase) < 0)
+ goto fail;
+ wpa_config_update_psk(ssid);
+ ssid->export_keys = 1;
+ } else {
+ ssid->psk_set = auth->psk_set;
+ os_memcpy(ssid->psk, auth->psk, PMK_LEN);
+ }
+ }
+
+ return ssid;
+fail:
+ wpas_notify_network_removed(wpa_s, ssid);
+ wpa_config_remove_network(wpa_s->conf, ssid->id);
+ return NULL;
+}
+
+
+static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
+ struct dpp_authentication *auth)
+{
+ struct wpa_ssid *ssid;
+
+ if (wpa_s->conf->dpp_config_processing < 1)
+ return 0;
+
+ ssid = wpas_dpp_add_network(wpa_s, auth);
+ if (!ssid)
+ return -1;
+
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
+ if (wpa_s->conf->dpp_config_processing == 2)
+ ssid->disabled = 0;
+
+#ifndef CONFIG_NO_CONFIG_WRITE
+ if (wpa_s->conf->update_config &&
+ wpa_config_write(wpa_s->confname, wpa_s->conf))
+ wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
+#endif /* CONFIG_NO_CONFIG_WRITE */
+
+ if (wpa_s->conf->dpp_config_processing < 2)
+ return 0;
+
+#ifdef CONFIG_DPP2
+ if (auth->peer_version >= 2) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
+ auth->connect_on_tx_status = 1;
+ return 0;
+ }
+#endif /* CONFIG_DPP2 */
+
+ wpas_dpp_try_to_connect(wpa_s);
+ return 0;
+}
+
+
+static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
+ struct dpp_authentication *auth)
+{
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
+ if (auth->ssid_len)
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
+ wpa_ssid_txt(auth->ssid, auth->ssid_len));
+ if (auth->connector) {
+ /* TODO: Save the Connector and consider using a command
+ * to fetch the value instead of sending an event with
+ * it. The Connector could end up being larger than what
+ * most clients are ready to receive as an event
+ * message. */
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
+ auth->connector);
+ }
+ if (auth->c_sign_key) {
+ char *hex;
+ size_t hexlen;
+
+ hexlen = 2 * wpabuf_len(auth->c_sign_key) + 1;
+ hex = os_malloc(hexlen);
+ if (hex) {
+ wpa_snprintf_hex(hex, hexlen,
+ wpabuf_head(auth->c_sign_key),
+ wpabuf_len(auth->c_sign_key));
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
+ hex);
+ os_free(hex);
+ }
+ }
+ if (auth->net_access_key) {
+ char *hex;
+ size_t hexlen;
+
+ hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
+ hex = os_malloc(hexlen);
+ if (hex) {
+ wpa_snprintf_hex(hex, hexlen,
+ wpabuf_head(auth->net_access_key),
+ wpabuf_len(auth->net_access_key));
+ if (auth->net_access_key_expiry)
+ wpa_msg(wpa_s, MSG_INFO,
+ DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
+ (long unsigned)
+ auth->net_access_key_expiry);
+ else
+ wpa_msg(wpa_s, MSG_INFO,
+ DPP_EVENT_NET_ACCESS_KEY "%s", hex);
+ os_free(hex);
+ }
+ }
+
+ return wpas_dpp_process_config(wpa_s, auth);
+}
+
+
+static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
+ enum gas_query_result result,
+ const struct wpabuf *adv_proto,
+ const struct wpabuf *resp, u16 status_code)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ const u8 *pos;
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+ int res;
+ enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
+
+ wpa_s->dpp_gas_dialog_token = -1;
+
+ if (!auth || !auth->auth_success) {
+ wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
+ return;
+ }
+ if (result != GAS_QUERY_SUCCESS ||
+ !resp || status_code != WLAN_STATUS_SUCCESS) {
+ wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
+ goto fail;
+ }
+
+ wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
+ adv_proto);
+ wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
+ resp);
+
+ if (wpabuf_len(adv_proto) != 10 ||
+ !(pos = wpabuf_head(adv_proto)) ||
+ pos[0] != WLAN_EID_ADV_PROTO ||
+ pos[1] != 8 ||
+ pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
+ pos[4] != 5 ||
+ WPA_GET_BE24(&pos[5]) != OUI_WFA ||
+ pos[8] != 0x1a ||
+ pos[9] != 1) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Not a DPP Advertisement Protocol ID");
+ goto fail;
+ }
+
+ if (dpp_conf_resp_rx(auth, resp) < 0) {
+ wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
+ goto fail;
+ }
+
+ res = wpas_dpp_handle_config_obj(wpa_s, auth);
+ if (res < 0)
+ goto fail;
+
+ status = DPP_STATUS_OK;
+#ifdef CONFIG_TESTING_OPTIONS
+ if (dpp_test == DPP_TEST_REJECT_CONFIG) {
+ wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
+ status = DPP_STATUS_CONFIG_REJECTED;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+fail:
+ if (status != DPP_STATUS_OK)
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
+#ifdef CONFIG_DPP2
+ if (auth->peer_version >= 2 &&
+ auth->conf_resp_status == DPP_STATUS_OK) {
+ struct wpabuf *msg;
+
+ wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
+ msg = dpp_build_conf_result(auth, status);
+ if (!msg)
+ goto fail2;
+
+ wpa_msg(wpa_s, MSG_INFO,
+ DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
+ MAC2STR(addr), auth->curr_freq,
+ DPP_PA_CONFIGURATION_RESULT);
+ offchannel_send_action(wpa_s, auth->curr_freq,
+ addr, wpa_s->own_addr, broadcast,
+ wpabuf_head(msg),
+ wpabuf_len(msg),
+ 500, wpas_dpp_tx_status, 0);
+ wpabuf_free(msg);
+
+ /* This exchange will be terminated in the TX status handler */
+ return;
+ }
+fail2:
+#endif /* CONFIG_DPP2 */
+ dpp_auth_deinit(wpa_s->dpp_auth);
+ wpa_s->dpp_auth = NULL;
+}
+
+
+static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
+{
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+ struct wpabuf *buf;
+ char json[100];
+ int res;
+
+ wpa_s->dpp_gas_client = 1;
+ os_snprintf(json, sizeof(json),
+ "{\"name\":\"Test\","
+ "\"wi-fi_tech\":\"infra\","
+ "\"netRole\":\"%s\"}",
+ wpa_s->dpp_netrole_ap ? "ap" : "sta");
+#ifdef CONFIG_TESTING_OPTIONS
+ if (dpp_test == DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ) {
+ wpa_printf(MSG_INFO, "DPP: TESTING - invalid Config Attr");
+ json[29] = 'k'; /* replace "infra" with "knfra" */
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+ wpa_printf(MSG_DEBUG, "DPP: GAS Config Attributes: %s", json);
+
+ offchannel_send_action_done(wpa_s);
+ wpas_dpp_listen_stop(wpa_s);
+
+ buf = dpp_build_conf_req(auth, json);
+ if (!buf) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: No configuration request data available");
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
+ MAC2STR(auth->peer_mac_addr), auth->curr_freq);
+
+ res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
+ 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
+ if (res < 0) {
+ wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
+ wpabuf_free(buf);
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "DPP: GAS query started with dialog token %u", res);
+ wpa_s->dpp_gas_dialog_token = res;
+ }
+}
+
+
+static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
+{
+ wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
+#ifdef CONFIG_TESTING_OPTIONS
+ if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
+ wpa_printf(MSG_INFO,
+ "DPP: TESTING - stop at Authentication Confirm");
+ if (wpa_s->dpp_auth->configurator) {
+ /* Prevent GAS response */
+ wpa_s->dpp_auth->auth_success = 0;
+ }
+ return;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
+ if (wpa_s->dpp_auth->configurator)
+ wpas_dpp_start_gas_server(wpa_s);
+ else
+ wpas_dpp_start_gas_client(wpa_s);
+}
+
+
+static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *hdr, const u8 *buf, size_t len,
+ unsigned int freq)
+{
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+ struct wpabuf *msg;
+
+ wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
+ " (freq %u MHz)", MAC2STR(src), freq);
+
+ if (!auth) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: No DPP Authentication in progress - drop");
+ return;
+ }
+
+ if (!is_zero_ether_addr(auth->peer_mac_addr) &&
+ os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
+ wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
+ MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
+ return;
+ }
+
+ eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+
+ if (auth->curr_freq != freq && auth->neg_freq == freq) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Responder accepted request for different negotiation channel");
+ auth->curr_freq = freq;
+ }
+
+ eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
+ msg = dpp_auth_resp_rx(auth, hdr, buf, len);
+ if (!msg) {
+ if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Start wait for full response");
+ offchannel_send_action_done(wpa_s);
+ wpas_dpp_listen_start(wpa_s, auth->curr_freq);
+ return;
+ }
+ wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
+ return;
+ }
+ os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
+
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
+ MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
+ offchannel_send_action(wpa_s, auth->curr_freq,
+ src, wpa_s->own_addr, broadcast,
+ wpabuf_head(msg), wpabuf_len(msg),
+ 500, wpas_dpp_tx_status, 0);
+ wpabuf_free(msg);
+ wpa_s->dpp_auth_ok_on_ack = 1;
+}
+
+
+static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *hdr, const u8 *buf, size_t len)
+{
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+ wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
+ MAC2STR(src));
+
+ if (!auth) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: No DPP Authentication in progress - drop");
+ return;
+ }
+
+ if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
+ wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
+ MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
+ return;
+ }
+
+ if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
+ wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
+ return;
+ }
+
+ wpas_dpp_auth_success(wpa_s, 0);
+}
+
+
+#ifdef CONFIG_DPP2
+
+static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
+ void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+ if (!auth || !auth->waiting_conf_result)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "DPP: Timeout while waiting for Configuration Result");
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
+ dpp_auth_deinit(auth);
+ wpa_s->dpp_auth = NULL;
+}
+
+
+static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *hdr, const u8 *buf, size_t len)
+{
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+ enum dpp_status_error status;
+
+ wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
+ MAC2STR(src));
+
+ if (!auth || !auth->waiting_conf_result) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: No DPP Configuration waiting for result - drop");
+ return;
+ }
+
+ if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
+ wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
+ MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
+ return;
+ }
+
+ status = dpp_conf_result_rx(auth, hdr, buf, len);
+
+ offchannel_send_action_done(wpa_s);
+ wpas_dpp_listen_stop(wpa_s);
+ if (status == DPP_STATUS_OK)
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
+ else
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
+ dpp_auth_deinit(auth);
+ wpa_s->dpp_auth = NULL;
+ eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
+}
+
+#endif /* CONFIG_DPP2 */
+
+
+static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
+ const u8 *src,
+ const u8 *buf, size_t len)
+{
+ struct wpa_ssid *ssid;
+ const u8 *connector, *trans_id, *status;
+ u16 connector_len, trans_id_len, status_len;
+ struct dpp_introduction intro;
+ struct rsn_pmksa_cache_entry *entry;
+ struct os_time now;
+ struct os_reltime rnow;
+ os_time_t expiry;
+ unsigned int seconds;
+ enum dpp_status_error res;
+
+ wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
+ MAC2STR(src));
+ if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
+ os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
+ wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
+ MACSTR " - drop", MAC2STR(src));
+ return;
+ }
+ offchannel_send_action_done(wpa_s);
+
+ for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+ if (ssid == wpa_s->dpp_intro_network)
+ break;
+ }
+ if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
+ !ssid->dpp_csign) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Profile not found for network introduction");
+ return;
+ }
+
+ trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
+ &trans_id_len);
+ if (!trans_id || trans_id_len != 1) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Peer did not include Transaction ID");
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+ " fail=missing_transaction_id", MAC2STR(src));
+ goto fail;
+ }
+ if (trans_id[0] != TRANSACTION_ID) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Ignore frame with unexpected Transaction ID %u",
+ trans_id[0]);
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+ " fail=transaction_id_mismatch", MAC2STR(src));
+ goto fail;
+ }
+
+ status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
+ if (!status || status_len != 1) {
+ wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+ " fail=missing_status", MAC2STR(src));
+ goto fail;
+ }
+ if (status[0] != DPP_STATUS_OK) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Peer rejected network introduction: Status %u",
+ status[0]);
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+ " status=%u", MAC2STR(src), status[0]);
+ goto fail;
+ }
+
+ connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
+ if (!connector) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Peer did not include its Connector");
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+ " fail=missing_connector", MAC2STR(src));
+ goto fail;
+ }
+
+ res = dpp_peer_intro(&intro, ssid->dpp_connector,
+ ssid->dpp_netaccesskey,
+ ssid->dpp_netaccesskey_len,
+ ssid->dpp_csign,
+ ssid->dpp_csign_len,
+ connector, connector_len, &expiry);
+ if (res != DPP_STATUS_OK) {
+ wpa_printf(MSG_INFO,
+ "DPP: Network Introduction protocol resulted in failure");
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+ " fail=peer_connector_validation_failed", MAC2STR(src));
+ goto fail;
+ }
+
+ entry = os_zalloc(sizeof(*entry));
+ if (!entry)
+ goto fail;
+ os_memcpy(entry->aa, src, ETH_ALEN);
+ os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
+ os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
+ entry->pmk_len = intro.pmk_len;
+ entry->akmp = WPA_KEY_MGMT_DPP;
+ if (expiry) {
+ os_get_time(&now);
+ seconds = expiry - now.sec;
+ } else {
+ seconds = 86400 * 7;
+ }
+ os_get_reltime(&rnow);
+ entry->expiration = rnow.sec + seconds;
+ entry->reauth_time = rnow.sec + seconds;
+ entry->network_ctx = ssid;
+ wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
+
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
+ " status=%u", MAC2STR(src), status[0]);
+
+ wpa_printf(MSG_DEBUG,
+ "DPP: Try connection again after successful network introduction");
+ if (wpa_supplicant_fast_associate(wpa_s) != 1) {
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ }
+fail:
+ os_memset(&intro, 0, sizeof(intro));
+}
+
+
+static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
+{
+ int i, j;
+
+ if (!wpa_s->hw.modes)
+ return -1;
+
+ for (i = 0; i < wpa_s->hw.num_modes; i++) {
+ struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
+
+ for (j = 0; j < mode->num_channels; j++) {
+ struct hostapd_channel_data *chan = &mode->channels[j];
+
+ if (chan->freq != (int) freq)
+ continue;
+
+ if (chan->flag & (HOSTAPD_CHAN_DISABLED |
+ HOSTAPD_CHAN_NO_IR |
+ HOSTAPD_CHAN_RADAR))
+ continue;
+
+ return 1;
+ }
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
+ freq);
+
+ return 0;
+}
+
+
+static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
+ struct dpp_pkex *pkex)
+{
+ if (pkex->freq == 2437)
+ pkex->freq = 5745;
+ else if (pkex->freq == 5745)
+ pkex->freq = 5220;
+ else if (pkex->freq == 5220)
+ pkex->freq = 60480;
+ else
+ return -1; /* no more channels to try */
+
+ if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
+ wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
+ pkex->freq);
+ return 0;
+ }
+
+ /* Could not use this channel - try the next one */
+ return wpas_dpp_pkex_next_channel(wpa_s, pkex);
+}
+
+
+static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct dpp_pkex *pkex = wpa_s->dpp_pkex;
+
+ if (!pkex || !pkex->exchange_req)
+ return;
+ if (pkex->exch_req_tries >= 5) {
+ if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
+ "No response from PKEX peer");
+ dpp_pkex_free(pkex);
+ wpa_s->dpp_pkex = NULL;
+ return;
+ }
+ pkex->exch_req_tries = 0;
+ }
+
+ pkex->exch_req_tries++;
+ wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
+ pkex->exch_req_tries);
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
+ MAC2STR(broadcast), pkex->freq, DPP_PA_PKEX_EXCHANGE_REQ);
+ offchannel_send_action(wpa_s, pkex->freq, broadcast,
+ wpa_s->own_addr, broadcast,
+ wpabuf_head(pkex->exchange_req),
+ wpabuf_len(pkex->exchange_req),
+ pkex->exch_req_wait_time,
+ wpas_dpp_tx_pkex_status, 0);
+}
+
+
+static void
+wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
+ unsigned int freq, const u8 *dst,
+ const u8 *src, const u8 *bssid,
+ const u8 *data, size_t data_len,
+ enum offchannel_send_action_result result)
+{
+ const char *res_txt;
+ struct dpp_pkex *pkex = wpa_s->dpp_pkex;
+
+ res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
+ (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
+ "FAILED");
+ wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
+ " result=%s (PKEX)",
+ freq, MAC2STR(dst), res_txt);
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
+ " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
+
+ if (!pkex) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Ignore TX status since there is no ongoing PKEX exchange");
+ return;
+ }
+
+ if (pkex->failed) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Terminate PKEX exchange due to an earlier error");
+ if (pkex->t > pkex->own_bi->pkex_t)
+ pkex->own_bi->pkex_t = pkex->t;
+ dpp_pkex_free(pkex);
+ wpa_s->dpp_pkex = NULL;
+ return;
+ }
+
+ if (pkex->exch_req_wait_time && pkex->exchange_req) {
+ /* Wait for PKEX Exchange Response frame and retry request if
+ * no response is seen. */
+ eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
+ eloop_register_timeout(pkex->exch_req_wait_time / 1000,
+ (pkex->exch_req_wait_time % 1000) * 1000,
+ wpas_dpp_pkex_retry_timeout, wpa_s,
+ NULL);
+ }
+}
+
+
+static void
+wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *buf, size_t len, unsigned int freq)
+{
+ struct wpabuf *msg;
+ unsigned int wait_time;
+
+ wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
+ MAC2STR(src));
+
+ /* TODO: Support multiple PKEX codes by iterating over all the enabled
+ * values here */
+
+ if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: No PKEX code configured - ignore request");
+ return;
+ }
+
+ if (wpa_s->dpp_pkex) {
+ /* TODO: Support parallel operations */
+ wpa_printf(MSG_DEBUG,
+ "DPP: Already in PKEX session - ignore new request");
+ return;
+ }
+
+ wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
+ wpa_s->own_addr, src,
+ wpa_s->dpp_pkex_identifier,
+ wpa_s->dpp_pkex_code,
+ buf, len);
+ if (!wpa_s->dpp_pkex) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Failed to process the request - ignore it");
+ return;
+ }
+
+ msg = wpa_s->dpp_pkex->exchange_resp;
+ wait_time = wpa_s->max_remain_on_chan;
+ if (wait_time > 2000)
+ wait_time = 2000;
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
+ MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
+ offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
+ broadcast,
+ wpabuf_head(msg), wpabuf_len(msg),
+ wait_time, wpas_dpp_tx_pkex_status, 0);
+}
+
+
+static void
+wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *buf, size_t len, unsigned int freq)
+{
+ struct wpabuf *msg;
+ unsigned int wait_time;
+
+ wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
+ MAC2STR(src));
+
+ /* TODO: Support multiple PKEX codes by iterating over all the enabled
+ * values here */
+
+ if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
+ wpa_s->dpp_pkex->exchange_done) {
+ wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
+ return;
+ }
+
+ eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
+ wpa_s->dpp_pkex->exch_req_wait_time = 0;
+
+ msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
+ if (!msg) {
+ wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
+ MAC2STR(src));
+
+ wait_time = wpa_s->max_remain_on_chan;
+ if (wait_time > 2000)
+ wait_time = 2000;
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
+ MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
+ offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
+ broadcast,
+ wpabuf_head(msg), wpabuf_len(msg),
+ wait_time, wpas_dpp_tx_pkex_status, 0);
+ wpabuf_free(msg);
+}
+
+
+static struct dpp_bootstrap_info *
+wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
+ unsigned int freq)
+{
+ struct dpp_bootstrap_info *bi;
+
+ bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
+ if (!bi)
+ return NULL;
+ wpa_s->dpp_pkex = NULL;
+ return bi;
+}
+
+
+static void
+wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *hdr, const u8 *buf, size_t len,
+ unsigned int freq)
+{
+ struct wpabuf *msg;
+ unsigned int wait_time;
+ struct dpp_pkex *pkex = wpa_s->dpp_pkex;
+
+ wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
+ MAC2STR(src));
+
+ if (!pkex || pkex->initiator || !pkex->exchange_done) {
+ wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
+ return;
+ }
+
+ msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
+ if (!msg) {
+ wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
+ if (pkex->failed) {
+ wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
+ if (pkex->t > pkex->own_bi->pkex_t)
+ pkex->own_bi->pkex_t = pkex->t;
+ dpp_pkex_free(wpa_s->dpp_pkex);
+ wpa_s->dpp_pkex = NULL;
+ }
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
+ MACSTR, MAC2STR(src));
+
+ wait_time = wpa_s->max_remain_on_chan;
+ if (wait_time > 2000)
+ wait_time = 2000;
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
+ MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
+ offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
+ broadcast,
+ wpabuf_head(msg), wpabuf_len(msg),
+ wait_time, wpas_dpp_tx_pkex_status, 0);
+ wpabuf_free(msg);
+
+ wpas_dpp_pkex_finish(wpa_s, src, freq);
+}
+
+
+static void
+wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *hdr, const u8 *buf, size_t len,
+ unsigned int freq)
+{
+ int res;
+ struct dpp_bootstrap_info *bi;
+ struct dpp_pkex *pkex = wpa_s->dpp_pkex;
+ char cmd[500];
+
+ wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
+ MAC2STR(src));
+
+ if (!pkex || !pkex->initiator || !pkex->exchange_done) {
+ wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
+ return;
+ }
+
+ res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
+ if (res < 0) {
+ wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
+ return;
+ }
+
+ bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
+ if (!bi)
+ return;
+
+ os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
+ bi->id,
+ wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
+ wpa_printf(MSG_DEBUG,
+ "DPP: Start authentication after PKEX with parameters: %s",
+ cmd);
+ if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Authentication initialization failed");
+ return;
+ }
+}
+
+
+void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *buf, size_t len, unsigned int freq)
+{
+ u8 crypto_suite;
+ enum dpp_public_action_frame_type type;
+ const u8 *hdr;
+ unsigned int pkex_t;
+
+ if (len < DPP_HDR_LEN)
+ return;
+ if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
+ return;
+ hdr = buf;
+ buf += 4;
+ len -= 4;
+ crypto_suite = *buf++;
+ type = *buf++;
+ len -= 2;
+
+ wpa_printf(MSG_DEBUG,
+ "DPP: Received DPP Public Action frame crypto suite %u type %d from "
+ MACSTR " freq=%u",
+ crypto_suite, type, MAC2STR(src), freq);
+ if (crypto_suite != 1) {
+ wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
+ crypto_suite);
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
+ " freq=%u type=%d ignore=unsupported-crypto-suite",
+ MAC2STR(src), freq, type);
+ return;
+ }
+ wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
+ if (dpp_check_attrs(buf, len) < 0) {
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
+ " freq=%u type=%d ignore=invalid-attributes",
+ MAC2STR(src), freq, type);
+ return;
+ }
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
+ MAC2STR(src), freq, type);
+
+ switch (type) {
+ case DPP_PA_AUTHENTICATION_REQ:
+ wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
+ break;
+ case DPP_PA_AUTHENTICATION_RESP:
+ wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
+ break;
+ case DPP_PA_AUTHENTICATION_CONF:
+ wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
+ break;
+ case DPP_PA_PEER_DISCOVERY_RESP:
+ wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
+ break;
+ case DPP_PA_PKEX_EXCHANGE_REQ:
+ wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq);
+ break;
+ case DPP_PA_PKEX_EXCHANGE_RESP:
+ wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
+ break;
+ case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
+ wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
+ freq);
+ break;
+ case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
+ wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
+ freq);
+ break;
+#ifdef CONFIG_DPP2
+ case DPP_PA_CONFIGURATION_RESULT:
+ wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
+ break;
+#endif /* CONFIG_DPP2 */
+ default:
+ wpa_printf(MSG_DEBUG,
+ "DPP: Ignored unsupported frame subtype %d", type);
+ break;
+ }
+
+ if (wpa_s->dpp_pkex)
+ pkex_t = wpa_s->dpp_pkex->t;
+ else if (wpa_s->dpp_pkex_bi)
+ pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
+ else
+ pkex_t = 0;
+ if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
+ wpas_dpp_pkex_remove(wpa_s, "*");
+ }
+}
+
+
+static struct wpabuf *
+wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query,
+ size_t query_len)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+ struct wpabuf *resp;
+
+ wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
+ MAC2STR(sa));
+ if (!auth || !auth->auth_success ||
+ os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
+ wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
+ return NULL;
+ }
+ wpa_hexdump(MSG_DEBUG,
+ "DPP: Received Configuration Request (GAS Query Request)",
+ query, query_len);
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
+ MAC2STR(sa));
+ resp = dpp_conf_req_rx(auth, query, query_len);
+ if (!resp)
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
+ auth->conf_resp = resp;
+ return resp;
+}
+
+
+static void
+wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+ if (!auth) {
+ wpabuf_free(resp);
+ return;
+ }
+ if (auth->conf_resp != resp) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Ignore GAS status report (ok=%d) for unknown response",
+ ok);
+ wpabuf_free(resp);
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
+ ok);
+ eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
+#ifdef CONFIG_DPP2
+ if (ok && auth->peer_version >= 2 &&
+ auth->conf_resp_status == DPP_STATUS_OK) {
+ wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
+ auth->waiting_conf_result = 1;
+ auth->conf_resp = NULL;
+ wpabuf_free(resp);
+ eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
+ wpa_s, NULL);
+ eloop_register_timeout(2, 0,
+ wpas_dpp_config_result_wait_timeout,
+ wpa_s, NULL);
+ return;
+ }
+#endif /* CONFIG_DPP2 */
+ offchannel_send_action_done(wpa_s);
+ wpas_dpp_listen_stop(wpa_s);
+ if (ok)
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
+ else
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
+ dpp_auth_deinit(wpa_s->dpp_auth);
+ wpa_s->dpp_auth = NULL;
+ wpabuf_free(resp);
+}
+
+
+int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ struct dpp_authentication *auth;
+ int ret = -1;
+ char *curve = NULL;
+
+ auth = os_zalloc(sizeof(*auth));
+ if (!auth)
+ return -1;
+
+ curve = get_param(cmd, " curve=");
+ wpas_dpp_set_testing_options(wpa_s, auth);
+ if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) == 0 &&
+ dpp_configurator_own_config(auth, curve, 0) == 0)
+ ret = wpas_dpp_handle_config_obj(wpa_s, auth);
+
+ dpp_auth_deinit(auth);
+ os_free(curve);
+
+ return ret;
+}
+
+
+static void
+wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
+ unsigned int freq, const u8 *dst,
+ const u8 *src, const u8 *bssid,
+ const u8 *data, size_t data_len,
+ enum offchannel_send_action_result result)
+{
+ const char *res_txt;
+
+ res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
+ (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
+ "FAILED");
+ wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
+ " result=%s (DPP Peer Discovery Request)",
+ freq, MAC2STR(dst), res_txt);
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
+ " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
+ /* TODO: Time out wait for response more quickly in error cases? */
+}
+
+
+int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ struct wpa_bss *bss)
+{
+ struct os_time now;
+ struct wpabuf *msg;
+ unsigned int wait_time;
+ const u8 *rsn;
+ struct wpa_ie_data ied;
+
+ if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
+ return 0; /* Not using DPP AKM - continue */
+ rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+ if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
+ !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
+ return 0; /* AP does not support DPP AKM - continue */
+ if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
+ return 0; /* PMKSA exists for DPP AKM - continue */
+
+ if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
+ !ssid->dpp_csign) {
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
+ "missing %s",
+ !ssid->dpp_connector ? "Connector" :
+ (!ssid->dpp_netaccesskey ? "netAccessKey" :
+ "C-sign-key"));
+ return -1;
+ }
+
+ os_get_time(&now);
+
+ if (ssid->dpp_netaccesskey_expiry &&
+ (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
+ "netAccessKey expired");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "DPP: Starting network introduction protocol to derive PMKSA for "
+ MACSTR, MAC2STR(bss->bssid));
+
+ msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ,
+ 5 + 4 + os_strlen(ssid->dpp_connector));
+ if (!msg)
+ return -1;
+
+#ifdef CONFIG_TESTING_OPTIONS
+ if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
+ wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
+ goto skip_trans_id;
+ }
+ if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
+ wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
+ wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
+ wpabuf_put_le16(msg, 0);
+ goto skip_trans_id;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
+ /* Transaction ID */
+ wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
+ wpabuf_put_le16(msg, 1);
+ wpabuf_put_u8(msg, TRANSACTION_ID);
+
+#ifdef CONFIG_TESTING_OPTIONS
+skip_trans_id:
+ if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
+ wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
+ goto skip_connector;
+ }
+ if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
+ char *connector;
+
+ wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
+ connector = dpp_corrupt_connector_signature(
+ ssid->dpp_connector);
+ if (!connector) {
+ wpabuf_free(msg);
+ return -1;
+ }
+ wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
+ wpabuf_put_le16(msg, os_strlen(connector));
+ wpabuf_put_str(msg, connector);
+ os_free(connector);
+ goto skip_connector;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
+ /* DPP Connector */
+ wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
+ wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
+ wpabuf_put_str(msg, ssid->dpp_connector);
+
+#ifdef CONFIG_TESTING_OPTIONS
+skip_connector:
+#endif /* CONFIG_TESTING_OPTIONS */
+
+ /* TODO: Timeout on AP response */
+ wait_time = wpa_s->max_remain_on_chan;
+ if (wait_time > 2000)
+ wait_time = 2000;
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
+ MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
+ offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
+ broadcast,
+ wpabuf_head(msg), wpabuf_len(msg),
+ wait_time, wpas_dpp_tx_introduction_status, 0);
+ wpabuf_free(msg);
+
+ /* Request this connection attempt to terminate - new one will be
+ * started when network introduction protocol completes */
+ os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
+ wpa_s->dpp_intro_network = ssid;
+ return 1;
+}
+
+
+int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ struct dpp_bootstrap_info *own_bi;
+ const char *pos, *end;
+ unsigned int wait_time;
+
+ pos = os_strstr(cmd, " own=");
+ if (!pos)
+ return -1;
+ pos += 5;
+ own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
+ if (!own_bi) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Identified bootstrap info not found");
+ return -1;
+ }
+ if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Identified bootstrap info not for PKEX");
+ return -1;
+ }
+ wpa_s->dpp_pkex_bi = own_bi;
+ own_bi->pkex_t = 0; /* clear pending errors on new code */
+
+ os_free(wpa_s->dpp_pkex_identifier);
+ wpa_s->dpp_pkex_identifier = NULL;
+ pos = os_strstr(cmd, " identifier=");
+ if (pos) {
+ pos += 12;
+ end = os_strchr(pos, ' ');
+ if (!end)
+ return -1;
+ wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
+ if (!wpa_s->dpp_pkex_identifier)
+ return -1;
+ os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
+ wpa_s->dpp_pkex_identifier[end - pos] = '\0';
+ }
+
+ pos = os_strstr(cmd, " code=");
+ if (!pos)
+ return -1;
+ os_free(wpa_s->dpp_pkex_code);
+ wpa_s->dpp_pkex_code = os_strdup(pos + 6);
+ if (!wpa_s->dpp_pkex_code)
+ return -1;
+
+ if (os_strstr(cmd, " init=1")) {
+ struct dpp_pkex *pkex;
+ struct wpabuf *msg;
+
+ wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
+ dpp_pkex_free(wpa_s->dpp_pkex);
+ wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr,
+ wpa_s->dpp_pkex_identifier,
+ wpa_s->dpp_pkex_code);
+ pkex = wpa_s->dpp_pkex;
+ if (!pkex)
+ return -1;
+
+ msg = pkex->exchange_req;
+ wait_time = wpa_s->max_remain_on_chan;
+ if (wait_time > 2000)
+ wait_time = 2000;
+ pkex->freq = 2437;
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
+ " freq=%u type=%d",
+ MAC2STR(broadcast), pkex->freq,
+ DPP_PA_PKEX_EXCHANGE_REQ);
+ offchannel_send_action(wpa_s, pkex->freq, broadcast,
+ wpa_s->own_addr, broadcast,
+ wpabuf_head(msg), wpabuf_len(msg),
+ wait_time, wpas_dpp_tx_pkex_status, 0);
+ if (wait_time == 0)
+ wait_time = 2000;
+ pkex->exch_req_wait_time = wait_time;
+ pkex->exch_req_tries = 1;
+ }
+
+ /* TODO: Support multiple PKEX info entries */
+
+ os_free(wpa_s->dpp_pkex_auth_cmd);
+ wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
+
+ return 1;
+}
+
+
+int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
+{
+ unsigned int id_val;
+
+ if (os_strcmp(id, "*") == 0) {
+ id_val = 0;
+ } else {
+ id_val = atoi(id);
+ if (id_val == 0)
+ return -1;
+ }
+
+ if ((id_val != 0 && id_val != 1) || !wpa_s->dpp_pkex_code)
+ return -1;
+
+ /* TODO: Support multiple PKEX entries */
+ os_free(wpa_s->dpp_pkex_code);
+ wpa_s->dpp_pkex_code = NULL;
+ os_free(wpa_s->dpp_pkex_identifier);
+ wpa_s->dpp_pkex_identifier = NULL;
+ os_free(wpa_s->dpp_pkex_auth_cmd);
+ wpa_s->dpp_pkex_auth_cmd = NULL;
+ wpa_s->dpp_pkex_bi = NULL;
+ /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
+ dpp_pkex_free(wpa_s->dpp_pkex);
+ wpa_s->dpp_pkex = NULL;
+ return 0;
+}
+
+
+void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
+{
+ dpp_auth_deinit(wpa_s->dpp_auth);
+ wpa_s->dpp_auth = NULL;
+ dpp_pkex_free(wpa_s->dpp_pkex);
+ wpa_s->dpp_pkex = NULL;
+ if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
+ gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
+}
+
+
+int wpas_dpp_init(struct wpa_supplicant *wpa_s)
+{
+ u8 adv_proto_id[7];
+
+ adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
+ adv_proto_id[1] = 5;
+ WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
+ adv_proto_id[5] = DPP_OUI_TYPE;
+ adv_proto_id[6] = 0x01;
+
+ if (gas_server_register(wpa_s->gas_server, adv_proto_id,
+ sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
+ wpas_dpp_gas_status_handler, wpa_s) < 0)
+ return -1;
+ wpa_s->dpp = dpp_global_init();
+ return wpa_s->dpp ? 0 : -1;
+}
+
+
+void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_TESTING_OPTIONS
+ os_free(wpa_s->dpp_config_obj_override);
+ wpa_s->dpp_config_obj_override = NULL;
+ os_free(wpa_s->dpp_discovery_override);
+ wpa_s->dpp_discovery_override = NULL;
+ os_free(wpa_s->dpp_groups_override);
+ wpa_s->dpp_groups_override = NULL;
+ wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
+#endif /* CONFIG_TESTING_OPTIONS */
+ if (!wpa_s->dpp)
+ return;
+ dpp_global_clear(wpa_s->dpp);
+ eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
+#ifdef CONFIG_DPP2
+ eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
+ dpp_pfs_free(wpa_s->dpp_pfs);
+ wpa_s->dpp_pfs = NULL;
+#endif /* CONFIG_DPP2 */
+ offchannel_send_action_done(wpa_s);
+ wpas_dpp_listen_stop(wpa_s);
+ wpas_dpp_stop(wpa_s);
+ wpas_dpp_pkex_remove(wpa_s, "*");
+ os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
+ os_free(wpa_s->dpp_configurator_params);
+ wpa_s->dpp_configurator_params = NULL;
+}
diff --git a/contrib/wpa/wpa_supplicant/dpp_supplicant.h b/contrib/wpa/wpa_supplicant/dpp_supplicant.h
new file mode 100644
index 000000000000..ecb7a7d684fa
--- /dev/null
+++ b/contrib/wpa/wpa_supplicant/dpp_supplicant.h
@@ -0,0 +1,29 @@
+/*
+ * wpa_supplicant - DPP
+ * Copyright (c) 2017, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef DPP_SUPPLICANT_H
+#define DPP_SUPPLICANT_H
+
+int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd);
+int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd);
+int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd);
+void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s);
+void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+ unsigned int freq);
+void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *buf, size_t len, unsigned int freq);
+int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd);
+int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd);
+int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id);
+void wpas_dpp_stop(struct wpa_supplicant *wpa_s);
+int wpas_dpp_init(struct wpa_supplicant *wpa_s);
+void wpas_dpp_deinit(struct wpa_supplicant *wpa_s);
+int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ struct wpa_bss *bss);
+
+#endif /* DPP_SUPPLICANT_H */
diff --git a/contrib/wpa/wpa_supplicant/driver_i.h b/contrib/wpa/wpa_supplicant/driver_i.h
index 220b7ba3ddca..4a9f472e84ee 100644
--- a/contrib/wpa/wpa_supplicant/driver_i.h
+++ b/contrib/wpa/wpa_supplicant/driver_i.h
@@ -189,20 +189,19 @@ static inline int wpa_drv_deauthenticate(struct wpa_supplicant *wpa_s,
}
static inline int wpa_drv_add_pmkid(struct wpa_supplicant *wpa_s,
- const u8 *bssid, const u8 *pmkid)
+ struct wpa_pmkid_params *params)
{
if (wpa_s->driver->add_pmkid) {
- return wpa_s->driver->add_pmkid(wpa_s->drv_priv, bssid, pmkid);
+ return wpa_s->driver->add_pmkid(wpa_s->drv_priv, params);
}
return -1;
}
static inline int wpa_drv_remove_pmkid(struct wpa_supplicant *wpa_s,
- const u8 *bssid, const u8 *pmkid)
+ struct wpa_pmkid_params *params)
{
if (wpa_s->driver->remove_pmkid) {
- return wpa_s->driver->remove_pmkid(wpa_s->drv_priv, bssid,
- pmkid);
+ return wpa_s->driver->remove_pmkid(wpa_s->drv_priv, params);
}
return -1;
}
@@ -276,11 +275,12 @@ static inline int wpa_drv_mlme_setprotection(struct wpa_supplicant *wpa_s,
static inline struct hostapd_hw_modes *
wpa_drv_get_hw_feature_data(struct wpa_supplicant *wpa_s, u16 *num_modes,
- u16 *flags)
+ u16 *flags, u8 *dfs_domain)
{
if (wpa_s->driver->get_hw_feature_data)
return wpa_s->driver->get_hw_feature_data(wpa_s->drv_priv,
- num_modes, flags);
+ num_modes, flags,
+ dfs_domain);
return NULL;
}
@@ -492,6 +492,14 @@ static inline int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
return -1;
}
+static inline int wpa_drv_channel_info(struct wpa_supplicant *wpa_s,
+ struct wpa_channel_info *ci)
+{
+ if (wpa_s->driver->channel_info)
+ return wpa_s->driver->channel_info(wpa_s->drv_priv, ci);
+ return -1;
+}
+
static inline int wpa_drv_pktcnt_poll(struct wpa_supplicant *wpa_s,
struct hostap_sta_driver_data *sta)
{
@@ -689,6 +697,14 @@ static inline int wpa_drv_roaming(struct wpa_supplicant *wpa_s, int allowed,
return wpa_s->driver->roaming(wpa_s->drv_priv, allowed, bssid);
}
+static inline int wpa_drv_disable_fils(struct wpa_supplicant *wpa_s,
+ int disable)
+{
+ if (!wpa_s->driver->disable_fils)
+ return -1;
+ return wpa_s->driver->disable_fils(wpa_s->drv_priv, disable);
+}
+
static inline int wpa_drv_set_mac_addr(struct wpa_supplicant *wpa_s,
const u8 *addr)
{
@@ -715,6 +731,14 @@ static inline int wpa_drv_macsec_deinit(struct wpa_supplicant *wpa_s)
return wpa_s->driver->macsec_deinit(wpa_s->drv_priv);
}
+static inline int wpa_drv_macsec_get_capability(struct wpa_supplicant *wpa_s,
+ enum macsec_cap *cap)
+{
+ if (!wpa_s->driver->macsec_get_capability)
+ return -1;
+ return wpa_s->driver->macsec_get_capability(wpa_s->drv_priv, cap);
+}
+
static inline int wpa_drv_enable_protect_frames(struct wpa_supplicant *wpa_s,
Boolean enabled)
{
@@ -723,6 +747,14 @@ static inline int wpa_drv_enable_protect_frames(struct wpa_supplicant *wpa_s,
return wpa_s->driver->enable_protect_frames(wpa_s->drv_priv, enabled);
}
+static inline int wpa_drv_enable_encrypt(struct wpa_supplicant *wpa_s,
+ Boolean enabled)
+{
+ if (!wpa_s->driver->enable_encrypt)
+ return -1;
+ return wpa_s->driver->enable_encrypt(wpa_s->drv_priv, enabled);
+}
+
static inline int wpa_drv_set_replay_protect(struct wpa_supplicant *wpa_s,
Boolean enabled, u32 window)
{
@@ -749,145 +781,135 @@ static inline int wpa_drv_enable_controlled_port(struct wpa_supplicant *wpa_s,
}
static inline int wpa_drv_get_receive_lowest_pn(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an,
- u32 *lowest_pn)
+ struct receive_sa *sa)
{
if (!wpa_s->driver->get_receive_lowest_pn)
return -1;
- return wpa_s->driver->get_receive_lowest_pn(wpa_s->drv_priv, channel,
- an, lowest_pn);
+ return wpa_s->driver->get_receive_lowest_pn(wpa_s->drv_priv, sa);
}
static inline int wpa_drv_get_transmit_next_pn(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an,
- u32 *next_pn)
+ struct transmit_sa *sa)
{
if (!wpa_s->driver->get_transmit_next_pn)
return -1;
- return wpa_s->driver->get_transmit_next_pn(wpa_s->drv_priv, channel,
- an, next_pn);
+ return wpa_s->driver->get_transmit_next_pn(wpa_s->drv_priv, sa);
}
static inline int wpa_drv_set_transmit_next_pn(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an,
- u32 next_pn)
+ struct transmit_sa *sa)
{
if (!wpa_s->driver->set_transmit_next_pn)
return -1;
- return wpa_s->driver->set_transmit_next_pn(wpa_s->drv_priv, channel,
- an, next_pn);
+ return wpa_s->driver->set_transmit_next_pn(wpa_s->drv_priv, sa);
}
-static inline int wpa_drv_get_available_receive_sc(struct wpa_supplicant *wpa_s,
- u32 *channel)
+static inline int wpa_drv_set_receive_lowest_pn(struct wpa_supplicant *wpa_s,
+ struct receive_sa *sa)
{
- if (!wpa_s->driver->get_available_receive_sc)
+ if (!wpa_s->driver->set_receive_lowest_pn)
return -1;
- return wpa_s->driver->get_available_receive_sc(wpa_s->drv_priv,
- channel);
+ return wpa_s->driver->set_receive_lowest_pn(wpa_s->drv_priv, sa);
}
static inline int
-wpa_drv_create_receive_sc(struct wpa_supplicant *wpa_s, u32 channel,
- const u8 *sci_addr, u16 sci_port,
+wpa_drv_create_receive_sc(struct wpa_supplicant *wpa_s, struct receive_sc *sc,
unsigned int conf_offset, int validation)
{
if (!wpa_s->driver->create_receive_sc)
return -1;
- return wpa_s->driver->create_receive_sc(wpa_s->drv_priv, channel,
- sci_addr, sci_port, conf_offset,
- validation);
+ return wpa_s->driver->create_receive_sc(wpa_s->drv_priv, sc,
+ conf_offset, validation);
}
static inline int wpa_drv_delete_receive_sc(struct wpa_supplicant *wpa_s,
- u32 channel)
+ struct receive_sc *sc)
{
if (!wpa_s->driver->delete_receive_sc)
return -1;
- return wpa_s->driver->delete_receive_sc(wpa_s->drv_priv, channel);
+ return wpa_s->driver->delete_receive_sc(wpa_s->drv_priv, sc);
}
static inline int wpa_drv_create_receive_sa(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an,
- u32 lowest_pn, const u8 *sak)
+ struct receive_sa *sa)
{
if (!wpa_s->driver->create_receive_sa)
return -1;
- return wpa_s->driver->create_receive_sa(wpa_s->drv_priv, channel, an,
- lowest_pn, sak);
+ return wpa_s->driver->create_receive_sa(wpa_s->drv_priv, sa);
}
-static inline int wpa_drv_enable_receive_sa(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an)
+static inline int wpa_drv_delete_receive_sa(struct wpa_supplicant *wpa_s,
+ struct receive_sa *sa)
{
- if (!wpa_s->driver->enable_receive_sa)
+ if (!wpa_s->driver->delete_receive_sa)
return -1;
- return wpa_s->driver->enable_receive_sa(wpa_s->drv_priv, channel, an);
+ return wpa_s->driver->delete_receive_sa(wpa_s->drv_priv, sa);
}
-static inline int wpa_drv_disable_receive_sa(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an)
+static inline int wpa_drv_enable_receive_sa(struct wpa_supplicant *wpa_s,
+ struct receive_sa *sa)
{
- if (!wpa_s->driver->disable_receive_sa)
+ if (!wpa_s->driver->enable_receive_sa)
return -1;
- return wpa_s->driver->disable_receive_sa(wpa_s->drv_priv, channel, an);
+ return wpa_s->driver->enable_receive_sa(wpa_s->drv_priv, sa);
}
-static inline int
-wpa_drv_get_available_transmit_sc(struct wpa_supplicant *wpa_s, u32 *channel)
+static inline int wpa_drv_disable_receive_sa(struct wpa_supplicant *wpa_s,
+ struct receive_sa *sa)
{
- if (!wpa_s->driver->get_available_transmit_sc)
+ if (!wpa_s->driver->disable_receive_sa)
return -1;
- return wpa_s->driver->get_available_transmit_sc(wpa_s->drv_priv,
- channel);
+ return wpa_s->driver->disable_receive_sa(wpa_s->drv_priv, sa);
}
static inline int
-wpa_drv_create_transmit_sc(struct wpa_supplicant *wpa_s, u32 channel,
- const u8 *sci_addr, u16 sci_port,
+wpa_drv_create_transmit_sc(struct wpa_supplicant *wpa_s, struct transmit_sc *sc,
unsigned int conf_offset)
{
if (!wpa_s->driver->create_transmit_sc)
return -1;
- return wpa_s->driver->create_transmit_sc(wpa_s->drv_priv, channel,
- sci_addr, sci_port,
+ return wpa_s->driver->create_transmit_sc(wpa_s->drv_priv, sc,
conf_offset);
}
static inline int wpa_drv_delete_transmit_sc(struct wpa_supplicant *wpa_s,
- u32 channel)
+ struct transmit_sc *sc)
{
if (!wpa_s->driver->delete_transmit_sc)
return -1;
- return wpa_s->driver->delete_transmit_sc(wpa_s->drv_priv, channel);
+ return wpa_s->driver->delete_transmit_sc(wpa_s->drv_priv, sc);
}
static inline int wpa_drv_create_transmit_sa(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an,
- u32 next_pn,
- Boolean confidentiality,
- const u8 *sak)
+ struct transmit_sa *sa)
{
if (!wpa_s->driver->create_transmit_sa)
return -1;
- return wpa_s->driver->create_transmit_sa(wpa_s->drv_priv, channel, an,
- next_pn, confidentiality, sak);
+ return wpa_s->driver->create_transmit_sa(wpa_s->drv_priv, sa);
+}
+
+static inline int wpa_drv_delete_transmit_sa(struct wpa_supplicant *wpa_s,
+ struct transmit_sa *sa)
+{
+ if (!wpa_s->driver->delete_transmit_sa)
+ return -1;
+ return wpa_s->driver->delete_transmit_sa(wpa_s->drv_priv, sa);
}
static inline int wpa_drv_enable_transmit_sa(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an)
+ struct transmit_sa *sa)
{
if (!wpa_s->driver->enable_transmit_sa)
return -1;
- return wpa_s->driver->enable_transmit_sa(wpa_s->drv_priv, channel, an);
+ return wpa_s->driver->enable_transmit_sa(wpa_s->drv_priv, sa);
}
static inline int wpa_drv_disable_transmit_sa(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an)
+ struct transmit_sa *sa)
{
if (!wpa_s->driver->disable_transmit_sa)
return -1;
- return wpa_s->driver->disable_transmit_sa(wpa_s->drv_priv, channel, an);
+ return wpa_s->driver->disable_transmit_sa(wpa_s->drv_priv, sa);
}
#endif /* CONFIG_MACSEC */
@@ -904,6 +926,11 @@ static inline int wpa_drv_get_pref_freq_list(struct wpa_supplicant *wpa_s,
unsigned int *num,
unsigned int *freq_list)
{
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->get_pref_freq_list_override)
+ return wpas_ctrl_iface_get_pref_freq_list_override(
+ wpa_s, if_type, num, freq_list);
+#endif /* CONFIG_TESTING_OPTIONS */
if (!wpa_s->driver->get_pref_freq_list)
return -1;
return wpa_s->driver->get_pref_freq_list(wpa_s->drv_priv, if_type,
@@ -918,11 +945,12 @@ static inline int wpa_drv_set_prob_oper_freq(struct wpa_supplicant *wpa_s,
return wpa_s->driver->set_prob_oper_freq(wpa_s->drv_priv, freq);
}
-static inline int wpa_drv_abort_scan(struct wpa_supplicant *wpa_s)
+static inline int wpa_drv_abort_scan(struct wpa_supplicant *wpa_s,
+ u64 scan_cookie)
{
if (!wpa_s->driver->abort_scan)
return -1;
- return wpa_s->driver->abort_scan(wpa_s->drv_priv);
+ return wpa_s->driver->abort_scan(wpa_s->drv_priv, scan_cookie);
}
static inline int wpa_drv_configure_frame_filters(struct wpa_supplicant *wpa_s,
@@ -976,4 +1004,70 @@ static inline int wpa_drv_set_default_scan_ies(struct wpa_supplicant *wpa_s,
return wpa_s->driver->set_default_scan_ies(wpa_s->drv_priv, ies, len);
}
+static inline int wpa_drv_set_tdls_mode(struct wpa_supplicant *wpa_s,
+ int tdls_external_control)
+{
+ if (!wpa_s->driver->set_tdls_mode)
+ return -1;
+ return wpa_s->driver->set_tdls_mode(wpa_s->drv_priv,
+ tdls_external_control);
+}
+
+static inline struct wpa_bss_candidate_info *
+wpa_drv_get_bss_trans_status(struct wpa_supplicant *wpa_s,
+ struct wpa_bss_trans_info *params)
+{
+ if (!wpa_s->driver->get_bss_transition_status)
+ return NULL;
+ return wpa_s->driver->get_bss_transition_status(wpa_s->drv_priv,
+ params);
+}
+
+static inline int wpa_drv_ignore_assoc_disallow(struct wpa_supplicant *wpa_s,
+ int val)
+{
+ if (!wpa_s->driver->ignore_assoc_disallow)
+ return -1;
+ return wpa_s->driver->ignore_assoc_disallow(wpa_s->drv_priv, val);
+}
+
+static inline int wpa_drv_set_bssid_blacklist(struct wpa_supplicant *wpa_s,
+ unsigned int num_bssid,
+ const u8 *bssids)
+{
+ if (!wpa_s->driver->set_bssid_blacklist)
+ return -1;
+ return wpa_s->driver->set_bssid_blacklist(wpa_s->drv_priv, num_bssid,
+ bssids);
+}
+
+static inline int wpa_drv_update_connect_params(
+ struct wpa_supplicant *wpa_s,
+ struct wpa_driver_associate_params *params,
+ enum wpa_drv_update_connect_params_mask mask)
+{
+ if (!wpa_s->driver->update_connect_params)
+ return -1;
+ return wpa_s->driver->update_connect_params(wpa_s->drv_priv, params,
+ mask);
+}
+
+static inline int
+wpa_drv_send_external_auth_status(struct wpa_supplicant *wpa_s,
+ struct external_auth *params)
+{
+ if (!wpa_s->driver->send_external_auth_status)
+ return -1;
+ return wpa_s->driver->send_external_auth_status(wpa_s->drv_priv,
+ params);
+}
+
+static inline int wpa_drv_set_4addr_mode(struct wpa_supplicant *wpa_s, int val)
+{
+ if (!wpa_s->driver->set_4addr_mode)
+ return -1;
+ return wpa_s->driver->set_4addr_mode(wpa_s->drv_priv,
+ wpa_s->bridge_ifname, val);
+}
+
#endif /* DRIVER_I_H */
diff --git a/contrib/wpa/wpa_supplicant/eapol_test.c b/contrib/wpa/wpa_supplicant/eapol_test.c
index 6548bd17b11f..3fd4ce61a1c2 100644
--- a/contrib/wpa/wpa_supplicant/eapol_test.c
+++ b/contrib/wpa/wpa_supplicant/eapol_test.c
@@ -711,7 +711,8 @@ static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx)
eap = (struct eap_hdr *) (hdr + 1);
eap->code = EAP_CODE_REQUEST;
- eap->identifier = 0;
+ if (os_get_random((u8 *) &eap->identifier, sizeof(eap->identifier)) < 0)
+ eap->identifier = os_random() & 0xff;
eap->length = htons(5);
pos = (u8 *) (eap + 1);
*pos = EAP_TYPE_IDENTITY;
diff --git a/contrib/wpa/wpa_supplicant/eapol_test.py b/contrib/wpa/wpa_supplicant/eapol_test.py
index 80e7dfcf531d..734428d29e66 100755
--- a/contrib/wpa/wpa_supplicant/eapol_test.py
+++ b/contrib/wpa/wpa_supplicant/eapol_test.py
@@ -136,7 +136,7 @@ def main():
results = res[i].get(False)
except:
results = "N/A"
- print "%d: %s" % (i, results)
+ print("%d: %s" % (i, results))
if __name__ == "__main__":
main()
diff --git a/contrib/wpa/wpa_supplicant/events.c b/contrib/wpa/wpa_supplicant/events.c
index abe3b476773d..f6ec111b77b6 100644
--- a/contrib/wpa/wpa_supplicant/events.c
+++ b/contrib/wpa/wpa_supplicant/events.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant - Driver event processing
- * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -28,6 +28,8 @@
#include "notify.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
+#include "common/gas_server.h"
+#include "common/dpp.h"
#include "crypto/random.h"
#include "blacklist.h"
#include "wpas_glue.h"
@@ -46,6 +48,10 @@
#include "mesh.h"
#include "mesh_mpm.h"
#include "wmm_ac.h"
+#include "dpp_supplicant.h"
+
+
+#define MAX_OWE_TRANSITION_BSS_SELECT_COUNT 5
#ifndef CONFIG_NO_SCAN_PROCESSING
@@ -54,8 +60,7 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_NO_SCAN_PROCESSING */
-static int wpas_temp_disabled(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid)
+int wpas_temp_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
{
struct os_reltime now;
@@ -289,6 +294,13 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
return;
+ if (os_reltime_initialized(&wpa_s->session_start)) {
+ os_reltime_age(&wpa_s->session_start, &wpa_s->session_length);
+ wpa_s->session_start.sec = 0;
+ wpa_s->session_start.usec = 0;
+ wpas_notify_session_length(wpa_s);
+ }
+
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
os_memset(wpa_s->bssid, 0, ETH_ALEN);
@@ -302,7 +314,9 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
- if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt))
+ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_DPP)
eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
wpa_s->ap_ies_from_associnfo = 0;
wpa_s->current_ssid = NULL;
@@ -311,6 +325,16 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
wpas_rrm_reset(wpa_s);
wpa_s->wnmsleep_used = 0;
+ wnm_clear_coloc_intf_reporting(wpa_s);
+
+#ifdef CONFIG_TESTING_OPTIONS
+ wpa_s->last_tk_alg = WPA_ALG_NONE;
+ os_memset(wpa_s->last_tk, 0, sizeof(wpa_s->last_tk));
+#endif /* CONFIG_TESTING_OPTIONS */
+ wpa_s->ieee80211ac = 0;
+
+ if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
+ wpa_s->enabled_4addr_mode = 0;
}
@@ -327,7 +351,7 @@ static void wpa_find_assoc_pmkid(struct wpa_supplicant *wpa_s)
for (i = 0; i < ie.num_pmkid; i++) {
pmksa_set = pmksa_cache_set_current(wpa_s->wpa,
ie.pmkid + i * PMKID_LEN,
- NULL, NULL, 0);
+ NULL, NULL, 0, NULL, 0);
if (pmksa_set == 0) {
eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
break;
@@ -479,6 +503,11 @@ static int wpa_supplicant_match_privacy(struct wpa_bss *bss,
return 1;
#endif /* CONFIG_WPS */
+#ifdef CONFIG_OWE
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) && !ssid->owe_only)
+ return 1;
+#endif /* CONFIG_OWE */
+
if (has_wep_key(ssid))
privacy = 1;
@@ -503,7 +532,7 @@ static int wpa_supplicant_match_privacy(struct wpa_bss *bss,
static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
- struct wpa_bss *bss)
+ struct wpa_bss *bss, int debug_print)
{
struct wpa_ie_data ie;
int proto_match = 0;
@@ -522,44 +551,63 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA));
rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
- while ((ssid->proto & WPA_PROTO_RSN) && rsn_ie) {
+ while ((ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)) && rsn_ie) {
proto_match++;
if (wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - parse "
- "failed");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - parse failed");
break;
}
+ if (!ie.has_pairwise)
+ ie.pairwise_cipher = wpa_default_rsn_cipher(bss->freq);
+ if (!ie.has_group)
+ ie.group_cipher = wpa_default_rsn_cipher(bss->freq);
if (wep_ok &&
(ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)))
{
- wpa_dbg(wpa_s, MSG_DEBUG, " selected based on TSN "
- "in RSN IE");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " selected based on TSN in RSN IE");
return 1;
}
- if (!(ie.proto & ssid->proto)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - proto "
- "mismatch");
+ if (!(ie.proto & ssid->proto) &&
+ !(ssid->proto & WPA_PROTO_OSEN)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - proto mismatch");
break;
}
if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - PTK "
- "cipher mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - PTK cipher mismatch");
break;
}
if (!(ie.group_cipher & ssid->group_cipher)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - GTK "
- "cipher mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - GTK cipher mismatch");
+ break;
+ }
+
+ if (ssid->group_mgmt_cipher &&
+ !(ie.mgmt_group_cipher & ssid->group_mgmt_cipher)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - group mgmt cipher mismatch");
break;
}
if (!(ie.key_mgmt & ssid->key_mgmt)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - key mgmt "
- "mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - key mgmt mismatch");
break;
}
@@ -567,16 +615,18 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
wpas_get_ssid_pmf(wpa_s, ssid) ==
MGMT_FRAME_PROTECTION_REQUIRED) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - no mgmt "
- "frame protection");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - no mgmt frame protection");
break;
}
#endif /* CONFIG_IEEE80211W */
if ((ie.capabilities & WPA_CAPABILITY_MFPR) &&
wpas_get_ssid_pmf(wpa_s, ssid) ==
NO_MGMT_FRAME_PROTECTION) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip RSN IE - no mgmt frame protection enabled but AP requires it");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - no mgmt frame protection enabled but AP requires it");
break;
}
#ifdef CONFIG_MBO
@@ -584,20 +634,25 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
wpas_mbo_get_bss_attr(bss, MBO_ATTR_ID_AP_CAPA_IND) &&
wpas_get_ssid_pmf(wpa_s, ssid) !=
NO_MGMT_FRAME_PROTECTION) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip RSN IE - no mgmt frame protection enabled on MBO AP");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - no mgmt frame protection enabled on MBO AP");
break;
}
#endif /* CONFIG_MBO */
- wpa_dbg(wpa_s, MSG_DEBUG, " selected based on RSN IE");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " selected based on RSN IE");
return 1;
}
#ifdef CONFIG_IEEE80211W
- if (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - MFP Required but network not MFP Capable");
+ if (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED &&
+ (!(ssid->key_mgmt & WPA_KEY_MGMT_OWE) || ssid->owe_only)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - MFP Required but network not MFP Capable");
return 0;
}
#endif /* CONFIG_IEEE80211W */
@@ -607,72 +662,110 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
proto_match++;
if (wpa_parse_wpa_ie(wpa_ie, 2 + wpa_ie[1], &ie)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - parse "
- "failed");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip WPA IE - parse failed");
break;
}
if (wep_ok &&
(ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)))
{
- wpa_dbg(wpa_s, MSG_DEBUG, " selected based on TSN "
- "in WPA IE");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " selected based on TSN in WPA IE");
return 1;
}
if (!(ie.proto & ssid->proto)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - proto "
- "mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip WPA IE - proto mismatch");
break;
}
if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - PTK "
- "cipher mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip WPA IE - PTK cipher mismatch");
break;
}
if (!(ie.group_cipher & ssid->group_cipher)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - GTK "
- "cipher mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip WPA IE - GTK cipher mismatch");
break;
}
if (!(ie.key_mgmt & ssid->key_mgmt)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - key mgmt "
- "mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip WPA IE - key mgmt mismatch");
break;
}
- wpa_dbg(wpa_s, MSG_DEBUG, " selected based on WPA IE");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " selected based on WPA IE");
return 1;
}
if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && !wpa_ie &&
!rsn_ie) {
- wpa_dbg(wpa_s, MSG_DEBUG, " allow for non-WPA IEEE 802.1X");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " allow for non-WPA IEEE 802.1X");
return 1;
}
+#ifdef CONFIG_OWE
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) && !ssid->owe_only &&
+ !wpa_ie && !rsn_ie) {
+ if (wpa_s->owe_transition_select &&
+ wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE) &&
+ ssid->owe_transition_bss_select_count + 1 <=
+ MAX_OWE_TRANSITION_BSS_SELECT_COUNT) {
+ ssid->owe_transition_bss_select_count++;
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip OWE transition BSS (selection count %d does not exceed %d)",
+ ssid->owe_transition_bss_select_count,
+ MAX_OWE_TRANSITION_BSS_SELECT_COUNT);
+ wpa_s->owe_transition_search = 1;
+ return 0;
+ }
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " allow in OWE transition mode");
+ return 1;
+ }
+#endif /* CONFIG_OWE */
+
if ((ssid->proto & (WPA_PROTO_WPA | WPA_PROTO_RSN)) &&
wpa_key_mgmt_wpa(ssid->key_mgmt) && proto_match == 0) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - no WPA/RSN proto match");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - no WPA/RSN proto match");
return 0;
}
if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) &&
wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " allow in OSEN");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG, " allow in OSEN");
return 1;
}
if (!wpa_key_mgmt_wpa(ssid->key_mgmt)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " allow in non-WPA/WPA2");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG, " allow in non-WPA/WPA2");
return 1;
}
- wpa_dbg(wpa_s, MSG_DEBUG, " reject due to mismatch with "
- "WPA/WPA2");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " reject due to mismatch with WPA/WPA2");
return 0;
}
@@ -692,7 +785,8 @@ static int freq_allowed(int *freqs, int freq)
}
-static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
+static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ int debug_print)
{
const struct hostapd_hw_modes *mode = NULL, *modes;
const u8 scan_ie[2] = { WLAN_EID_SUPP_RATES, WLAN_EID_EXT_SUPP_RATES };
@@ -749,9 +843,9 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
if (flagged && ((rate_ie[j] & 0x7f) ==
BSS_MEMBERSHIP_SELECTOR_HT_PHY)) {
if (!ht_supported(mode)) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " hardware does not support "
- "HT PHY");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " hardware does not support HT PHY");
return 0;
}
continue;
@@ -761,9 +855,9 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
if (flagged && ((rate_ie[j] & 0x7f) ==
BSS_MEMBERSHIP_SELECTOR_VHT_PHY)) {
if (!vht_supported(mode)) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " hardware does not support "
- "VHT PHY");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " hardware does not support VHT PHY");
return 0;
}
continue;
@@ -783,10 +877,11 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
* order to join a BSS all required rates
* have to be supported by the hardware.
*/
- wpa_dbg(wpa_s, MSG_DEBUG,
- " hardware does not support required rate %d.%d Mbps (freq=%d mode==%d num_rates=%d)",
- r / 10, r % 10,
- bss->freq, mode->mode, mode->num_rates);
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " hardware does not support required rate %d.%d Mbps (freq=%d mode==%d num_rates=%d)",
+ r / 10, r % 10,
+ bss->freq, mode->mode, mode->num_rates);
return 0;
}
}
@@ -839,39 +934,124 @@ static int addr_in_list(const u8 *addr, const u8 *list, size_t num)
}
+static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ const u8 **ret_ssid, size_t *ret_ssid_len)
+{
+#ifdef CONFIG_OWE
+ const u8 *owe, *pos, *end, *bssid;
+ u8 ssid_len;
+ struct wpa_bss *open_bss;
+
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+ if (!owe || !wpa_bss_get_ie(bss, WLAN_EID_RSN))
+ return;
+
+ pos = owe + 6;
+ end = owe + 2 + owe[1];
+
+ if (end - pos < ETH_ALEN + 1)
+ return;
+ bssid = pos;
+ pos += ETH_ALEN;
+ ssid_len = *pos++;
+ if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
+ return;
+
+ /* Match the profile SSID against the OWE transition mode SSID on the
+ * open network. */
+ wpa_dbg(wpa_s, MSG_DEBUG, "OWE: transition mode BSSID: " MACSTR
+ " SSID: %s", MAC2STR(bssid), wpa_ssid_txt(pos, ssid_len));
+ *ret_ssid = pos;
+ *ret_ssid_len = ssid_len;
+
+ if (bss->ssid_len > 0)
+ return;
+
+ open_bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
+ if (!open_bss)
+ return;
+ if (ssid_len != open_bss->ssid_len ||
+ os_memcmp(pos, open_bss->ssid, ssid_len) != 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "OWE: transition mode SSID mismatch: %s",
+ wpa_ssid_txt(open_bss->ssid, open_bss->ssid_len));
+ return;
+ }
+
+ owe = wpa_bss_get_vendor_ie(open_bss, OWE_IE_VENDOR_TYPE);
+ if (!owe || wpa_bss_get_ie(open_bss, WLAN_EID_RSN)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "OWE: transition mode open BSS unexpected info");
+ return;
+ }
+
+ pos = owe + 6;
+ end = owe + 2 + owe[1];
+
+ if (end - pos < ETH_ALEN + 1)
+ return;
+ if (os_memcmp(pos, bss->bssid, ETH_ALEN) != 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "OWE: transition mode BSSID mismatch: " MACSTR,
+ MAC2STR(pos));
+ return;
+ }
+ pos += ETH_ALEN;
+ ssid_len = *pos++;
+ if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
+ return;
+ wpa_dbg(wpa_s, MSG_DEBUG, "OWE: learned transition mode OWE SSID: %s",
+ wpa_ssid_txt(pos, ssid_len));
+ os_memcpy(bss->ssid, pos, ssid_len);
+ bss->ssid_len = ssid_len;
+#endif /* CONFIG_OWE */
+}
+
+
struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
int i, struct wpa_bss *bss,
struct wpa_ssid *group,
- int only_first_ssid)
+ int only_first_ssid, int debug_print)
{
u8 wpa_ie_len, rsn_ie_len;
int wpa;
struct wpa_blacklist *e;
const u8 *ie;
struct wpa_ssid *ssid;
- int osen;
+ int osen, rsn_osen = 0;
#ifdef CONFIG_MBO
const u8 *assoc_disallow;
#endif /* CONFIG_MBO */
+ const u8 *match_ssid;
+ size_t match_ssid_len;
+ struct wpa_ie_data data;
ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
wpa_ie_len = ie ? ie[1] : 0;
ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
rsn_ie_len = ie ? ie[1] : 0;
+ if (ie && wpa_parse_wpa_ie_rsn(ie, 2 + ie[1], &data) == 0 &&
+ (data.key_mgmt & WPA_KEY_MGMT_OSEN))
+ rsn_osen = 1;
ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
osen = ie != NULL;
- wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' "
- "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d freq=%d %s%s%s",
- i, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len),
- wpa_ie_len, rsn_ie_len, bss->caps, bss->level, bss->freq,
- wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : "",
- (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
- wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) ?
- " p2p" : "",
- osen ? " osen=1" : "");
+ if (debug_print) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR
+ " ssid='%s' wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d freq=%d %s%s%s",
+ i, MAC2STR(bss->bssid),
+ wpa_ssid_txt(bss->ssid, bss->ssid_len),
+ wpa_ie_len, rsn_ie_len, bss->caps, bss->level,
+ bss->freq,
+ wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ?
+ " wps" : "",
+ (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
+ wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE))
+ ? " p2p" : "",
+ osen ? " osen=1" : "");
+ }
e = wpa_blacklist_get(wpa_s, bss->bssid);
if (e) {
@@ -888,24 +1068,34 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
limit = 0;
}
if (e->count > limit) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted "
- "(count=%d limit=%d)", e->count, limit);
+ if (debug_print) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - blacklisted (count=%d limit=%d)",
+ e->count, limit);
+ }
return NULL;
}
}
- if (bss->ssid_len == 0) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known");
+ match_ssid = bss->ssid;
+ match_ssid_len = bss->ssid_len;
+ owe_trans_ssid(wpa_s, bss, &match_ssid, &match_ssid_len);
+
+ if (match_ssid_len == 0) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known");
return NULL;
}
if (disallowed_bssid(wpa_s, bss->bssid)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID disallowed");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID disallowed");
return NULL;
}
- if (disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID disallowed");
+ if (disallowed_ssid(wpa_s, match_ssid, match_ssid_len)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID disallowed");
return NULL;
}
@@ -916,21 +1106,25 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
int res;
if (wpas_network_disabled(wpa_s, ssid)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled");
continue;
}
res = wpas_temp_disabled(wpa_s, ssid);
if (res > 0) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled "
- "temporarily for %d second(s)", res);
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - disabled temporarily for %d second(s)",
+ res);
continue;
}
#ifdef CONFIG_WPS
if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && e && e->count > 0) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted "
- "(WPS)");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - blacklisted (WPS)");
continue;
}
@@ -954,15 +1148,19 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
check_ssid = 0;
if (check_ssid &&
- (bss->ssid_len != ssid->ssid_len ||
- os_memcmp(bss->ssid, ssid->ssid, bss->ssid_len) != 0)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID mismatch");
+ (match_ssid_len != ssid->ssid_len ||
+ os_memcmp(match_ssid, ssid->ssid, match_ssid_len) != 0)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - SSID mismatch");
continue;
}
if (ssid->bssid_set &&
os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - BSSID mismatch");
continue;
}
@@ -970,8 +1168,9 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
if (ssid->num_bssid_blacklist &&
addr_in_list(bss->bssid, ssid->bssid_blacklist,
ssid->num_bssid_blacklist)) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - BSSID blacklisted");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - BSSID blacklisted");
continue;
}
@@ -979,79 +1178,108 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
if (ssid->num_bssid_whitelist &&
!addr_in_list(bss->bssid, ssid->bssid_whitelist,
ssid->num_bssid_whitelist)) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - BSSID not in whitelist");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - BSSID not in whitelist");
continue;
}
- if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss))
+ if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss,
+ debug_print))
continue;
if (!osen && !wpa &&
!(ssid->key_mgmt & WPA_KEY_MGMT_NONE) &&
!(ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
+ !(ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
!(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - non-WPA network "
- "not allowed");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - non-WPA network not allowed");
continue;
}
if (wpa && !wpa_key_mgmt_wpa(ssid->key_mgmt) &&
has_wep_key(ssid)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - ignore WPA/WPA2 AP for WEP network block");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - ignore WPA/WPA2 AP for WEP network block");
continue;
}
- if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - non-OSEN network "
- "not allowed");
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen &&
+ !rsn_osen) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - non-OSEN network not allowed");
continue;
}
if (!wpa_supplicant_match_privacy(bss, ssid)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - privacy "
- "mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - privacy mismatch");
continue;
}
if (ssid->mode != IEEE80211_MODE_MESH && !bss_is_ess(bss) &&
!bss_is_pbss(bss)) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - not ESS, PBSS, or MBSS");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - not ESS, PBSS, or MBSS");
continue;
}
if (ssid->pbss != 2 && ssid->pbss != bss_is_pbss(bss)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - PBSS mismatch (ssid %d bss %d)",
- ssid->pbss, bss_is_pbss(bss));
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - PBSS mismatch (ssid %d bss %d)",
+ ssid->pbss, bss_is_pbss(bss));
continue;
}
if (!freq_allowed(ssid->freq_list, bss->freq)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - frequency not "
- "allowed");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - frequency not allowed");
continue;
}
#ifdef CONFIG_MESH
if (ssid->mode == IEEE80211_MODE_MESH && ssid->frequency > 0 &&
ssid->frequency != bss->freq) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - frequency not allowed (mesh)");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - frequency not allowed (mesh)");
continue;
}
#endif /* CONFIG_MESH */
- if (!rate_match(wpa_s, bss)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - rate sets do "
- "not match");
+ if (!rate_match(wpa_s, bss, debug_print)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - rate sets do not match");
continue;
}
+#ifndef CONFIG_IBSS_RSN
+ if (ssid->mode == WPAS_MODE_IBSS &&
+ !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE |
+ WPA_KEY_MGMT_WPA_NONE))) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - IBSS RSN not supported in the build");
+ continue;
+ }
+#endif /* !CONFIG_IBSS_RSN */
+
#ifdef CONFIG_P2P
if (ssid->p2p_group &&
!wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) &&
!wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - no P2P IE seen");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - no P2P IE seen");
continue;
}
@@ -1061,20 +1289,26 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
ie = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
if (ie == NULL) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - no P2P element");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - no P2P element");
continue;
}
p2p_ie = wpa_bss_get_vendor_ie_multi(
bss, P2P_IE_VENDOR_TYPE);
if (p2p_ie == NULL) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - could not fetch P2P element");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - could not fetch P2P element");
continue;
}
if (p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr) < 0
|| os_memcmp(dev_addr, ssid->go_p2p_dev_addr,
ETH_ALEN) != 0) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - no matching GO P2P Device Address in P2P element");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - no matching GO P2P Device Address in P2P element");
wpabuf_free(p2p_ie);
continue;
}
@@ -1094,8 +1328,9 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
os_reltime_sub(&wpa_s->scan_min_time,
&bss->last_update, &diff);
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - scan result not recent enough (%u.%06u seconds too old)",
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - scan result not recent enough (%u.%06u seconds too old)",
(unsigned int) diff.sec,
(unsigned int) diff.usec);
continue;
@@ -1108,15 +1343,17 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
assoc_disallow = wpas_mbo_get_bss_attr(
bss, MBO_ATTR_ID_ASSOC_DISALLOW);
if (assoc_disallow && assoc_disallow[1] >= 1) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - MBO association disallowed (reason %u)",
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - MBO association disallowed (reason %u)",
assoc_disallow[2]);
continue;
}
- if (wpa_is_bss_tmp_disallowed(wpa_s, bss->bssid)) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - MBO retry delay has not passed yet");
+ if (wpa_is_bss_tmp_disallowed(wpa_s, bss)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - AP temporarily disallowed");
continue;
}
#ifdef CONFIG_TESTING_OPTIONS
@@ -1124,6 +1361,19 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_MBO */
+#ifdef CONFIG_DPP
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
+ !wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid) &&
+ (!ssid->dpp_connector ||
+ !ssid->dpp_netaccesskey ||
+ !ssid->dpp_csign)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - no PMKSA entry for DPP");
+ continue;
+ }
+#endif /* CONFIG_DPP */
+
/* Matching configuration found */
return ssid;
}
@@ -1141,6 +1391,25 @@ wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
{
unsigned int i;
+ if (wpa_s->current_ssid) {
+ struct wpa_ssid *ssid;
+
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Scan results matching the currently selected network");
+ for (i = 0; i < wpa_s->last_scan_res_used; i++) {
+ struct wpa_bss *bss = wpa_s->last_scan_res[i];
+
+ ssid = wpa_scan_res_match(wpa_s, i, bss, group,
+ only_first_ssid, 0);
+ if (ssid != wpa_s->current_ssid)
+ continue;
+ wpa_dbg(wpa_s, MSG_DEBUG, "%u: " MACSTR
+ " freq=%d level=%d snr=%d est_throughput=%u",
+ i, MAC2STR(bss->bssid), bss->freq, bss->level,
+ bss->snr, bss->est_throughput);
+ }
+ }
+
if (only_first_ssid)
wpa_dbg(wpa_s, MSG_DEBUG, "Try to find BSS matching pre-selected network id=%d",
group->id);
@@ -1150,8 +1419,11 @@ wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
for (i = 0; i < wpa_s->last_scan_res_used; i++) {
struct wpa_bss *bss = wpa_s->last_scan_res[i];
+
+ wpa_s->owe_transition_select = 1;
*selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group,
- only_first_ssid);
+ only_first_ssid, 1);
+ wpa_s->owe_transition_select = 0;
if (!*selected_ssid)
continue;
wpa_dbg(wpa_s, MSG_DEBUG, " selected BSS " MACSTR
@@ -1332,6 +1604,17 @@ wpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s)
{
if (wpas_network_disabled(wpa_s, ssid))
continue;
+#ifndef CONFIG_IBSS_RSN
+ if (ssid->mode == WPAS_MODE_IBSS &&
+ !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE |
+ WPA_KEY_MGMT_WPA_NONE))) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "IBSS RSN not supported in the build - cannot use the profile for SSID '%s'",
+ wpa_ssid_txt(ssid->ssid,
+ ssid->ssid_len));
+ continue;
+ }
+#endif /* !CONFIG_IBSS_RSN */
if (ssid->mode == IEEE80211_MODE_IBSS ||
ssid->mode == IEEE80211_MODE_AP ||
ssid->mode == IEEE80211_MODE_MESH)
@@ -1375,8 +1658,9 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
{
struct wpa_bss *current_bss = NULL;
#ifndef CONFIG_NO_ROAMING
- int min_diff;
+ int min_diff, diff;
int to_5ghz;
+ int cur_est, sel_est;
#endif /* CONFIG_NO_ROAMING */
if (wpa_s->reassociate)
@@ -1410,12 +1694,13 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
#ifndef CONFIG_NO_ROAMING
wpa_dbg(wpa_s, MSG_DEBUG, "Considering within-ESS reassociation");
wpa_dbg(wpa_s, MSG_DEBUG, "Current BSS: " MACSTR
- " level=%d snr=%d est_throughput=%u",
- MAC2STR(current_bss->bssid), current_bss->level,
+ " freq=%d level=%d snr=%d est_throughput=%u",
+ MAC2STR(current_bss->bssid),
+ current_bss->freq, current_bss->level,
current_bss->snr, current_bss->est_throughput);
wpa_dbg(wpa_s, MSG_DEBUG, "Selected BSS: " MACSTR
- " level=%d snr=%d est_throughput=%u",
- MAC2STR(selected->bssid), selected->level,
+ " freq=%d level=%d snr=%d est_throughput=%u",
+ MAC2STR(selected->bssid), selected->freq, selected->level,
selected->snr, selected->est_throughput);
if (wpa_s->current_ssid->bssid_set &&
@@ -1441,6 +1726,14 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
return 0;
}
+ if (current_bss->est_throughput > selected->est_throughput + 5000) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Skip roam - Current BSS has better estimated throughput");
+ return 0;
+ }
+
+ cur_est = current_bss->est_throughput;
+ sel_est = selected->est_throughput;
min_diff = 2;
if (current_bss->level < 0) {
if (current_bss->level < -85)
@@ -1453,20 +1746,42 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
min_diff = 4;
else
min_diff = 5;
+ if (cur_est > sel_est * 1.5)
+ min_diff += 10;
+ else if (cur_est > sel_est * 1.2)
+ min_diff += 5;
+ else if (cur_est > sel_est * 1.1)
+ min_diff += 2;
+ else if (cur_est > sel_est)
+ min_diff++;
}
if (to_5ghz) {
+ int reduce = 2;
+
/* Make it easier to move to 5 GHz band */
- if (min_diff > 2)
- min_diff -= 2;
+ if (sel_est > cur_est * 1.5)
+ reduce = 5;
+ else if (sel_est > cur_est * 1.2)
+ reduce = 4;
+ else if (sel_est > cur_est * 1.1)
+ reduce = 3;
+
+ if (min_diff > reduce)
+ min_diff -= reduce;
else
min_diff = 0;
}
- if (abs(current_bss->level - selected->level) < min_diff) {
- wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - too small difference "
- "in signal level");
+ diff = abs(current_bss->level - selected->level);
+ if (diff < min_diff) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Skip roam - too small difference in signal level (%d < %d)",
+ diff, min_diff);
return 0;
}
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Allow reassociation due to difference in signal level (%d >= %d)",
+ diff, min_diff);
return 1;
#else /* CONFIG_NO_ROAMING */
return 0;
@@ -1474,11 +1789,18 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
}
-/* Return != 0 if no scan results could be fetched or if scan results should not
- * be shared with other virtual interfaces. */
+/*
+ * Return a negative value if no scan results could be fetched or if scan
+ * results should not be shared with other virtual interfaces.
+ * Return 0 if scan results were fetched and may be shared with other
+ * interfaces.
+ * Return 1 if scan results may be shared with other virtual interfaces but may
+ * not trigger any operations.
+ * Return 2 if the interface was removed and cannot be used.
+ */
static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
union wpa_event_data *data,
- int own_request)
+ int own_request, int update_only)
{
struct wpa_scan_results *scan_res = NULL;
int ret = 0;
@@ -1528,6 +1850,11 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_NO_RANDOM_POOL */
+ if (update_only) {
+ ret = 1;
+ goto scan_work_done;
+ }
+
if (own_request && wpa_s->scan_res_handler &&
!(data && data->scan_info.external_scan)) {
void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
@@ -1536,7 +1863,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
scan_res_handler = wpa_s->scan_res_handler;
wpa_s->scan_res_handler = NULL;
scan_res_handler(wpa_s, scan_res);
- ret = -2;
+ ret = 1;
goto scan_work_done;
}
@@ -1577,6 +1904,10 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
if (sme_proc_obss_scan(wpa_s) > 0)
goto scan_work_done;
+ if (own_request && data &&
+ wpas_beacon_rep_scan_process(wpa_s, scan_res, &data->scan_info) > 0)
+ goto scan_work_done;
+
if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s)))
goto scan_work_done;
@@ -1639,6 +1970,7 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
if (wpa_s->p2p_mgmt)
return 0; /* no normal connection on p2p_mgmt interface */
+ wpa_s->owe_transition_search = 0;
selected = wpa_supplicant_pick_network(wpa_s, &ssid);
#ifdef CONFIG_MESH
@@ -1672,8 +2004,9 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
if (new_scan)
wpa_supplicant_rsn_preauth_scan_results(wpa_s);
/*
- * Do not notify other virtual radios of scan results since we do not
- * want them to start other associations at the same time.
+ * Do not allow other virtual radios to trigger operations based
+ * on these scan results since we do not want them to start
+ * other associations at the same time.
*/
return 1;
} else {
@@ -1739,6 +2072,17 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
return 0;
}
#endif /* CONFIG_WPS */
+#ifdef CONFIG_OWE
+ if (wpa_s->owe_transition_search) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "OWE: Use shorter wait during transition mode search");
+ timeout_sec = 0;
+ timeout_usec = 500000;
+ wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
+ timeout_usec);
+ return 0;
+ }
+#endif /* CONFIG_OWE */
if (wpa_supplicant_req_sched_scan(wpa_s))
wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
timeout_usec);
@@ -1757,7 +2101,7 @@ static int wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
struct wpa_supplicant *ifs;
int res;
- res = _wpa_supplicant_event_scan_results(wpa_s, data, 1);
+ res = _wpa_supplicant_event_scan_results(wpa_s, data, 1, 0);
if (res == 2) {
/*
* Interface may have been removed, so must not dereference
@@ -1765,7 +2109,8 @@ static int wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
*/
return 1;
}
- if (res != 0) {
+
+ if (res < 0) {
/*
* If no scan results could be fetched, then no need to
* notify those interfaces that did not actually request
@@ -1785,7 +2130,10 @@ static int wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
if (ifs != wpa_s) {
wpa_printf(MSG_DEBUG, "%s: Updating scan results from "
"sibling", ifs->ifname);
- _wpa_supplicant_event_scan_results(ifs, data, 0);
+ res = _wpa_supplicant_event_scan_results(ifs, data, 0,
+ res > 0);
+ if (res < 0)
+ return 0;
}
}
@@ -1802,6 +2150,8 @@ int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s)
#else /* CONFIG_NO_SCAN_PROCESSING */
struct os_reltime now;
+ wpa_s->ignore_post_flush_scan_res = 0;
+
if (wpa_s->last_scan_res_used == 0)
return -1;
@@ -1932,6 +2282,57 @@ static void interworking_process_assoc_resp(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_INTERWORKING */
+static void multi_ap_process_assoc_resp(struct wpa_supplicant *wpa_s,
+ const u8 *ies, size_t ies_len)
+{
+ struct ieee802_11_elems elems;
+ const u8 *map_sub_elem, *pos;
+ size_t len;
+
+ if (!wpa_s->current_ssid ||
+ !wpa_s->current_ssid->multi_ap_backhaul_sta ||
+ !ies ||
+ ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed)
+ return;
+
+ if (!elems.multi_ap || elems.multi_ap_len < 7) {
+ wpa_printf(MSG_INFO, "AP doesn't support Multi-AP protocol");
+ goto fail;
+ }
+
+ pos = elems.multi_ap + 4;
+ len = elems.multi_ap_len - 4;
+
+ map_sub_elem = get_ie(pos, len, MULTI_AP_SUB_ELEM_TYPE);
+ if (!map_sub_elem || map_sub_elem[1] < 1) {
+ wpa_printf(MSG_INFO, "invalid Multi-AP sub elem type");
+ goto fail;
+ }
+
+ if (!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS)) {
+ if ((map_sub_elem[2] & MULTI_AP_FRONTHAUL_BSS) &&
+ wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
+ wpa_printf(MSG_INFO,
+ "WPS active, accepting fronthaul-only BSS");
+ /* Don't set 4addr mode in this case, so just return */
+ return;
+ }
+ wpa_printf(MSG_INFO, "AP doesn't support backhaul BSS");
+ goto fail;
+ }
+
+ if (wpa_drv_set_4addr_mode(wpa_s, 1) < 0) {
+ wpa_printf(MSG_ERROR, "Failed to set 4addr mode");
+ goto fail;
+ }
+ wpa_s->enabled_4addr_mode = 1;
+ return;
+
+fail:
+ wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+}
+
+
#ifdef CONFIG_FST
static int wpas_fst_update_mbie(struct wpa_supplicant *wpa_s,
const u8 *ie, size_t ie_len)
@@ -1981,9 +2382,9 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
{
int l, len, found = 0, wpa_found, rsn_found;
const u8 *p;
-#ifdef CONFIG_IEEE80211R
+#if defined(CONFIG_IEEE80211R) || defined(CONFIG_OWE)
u8 bssid[ETH_ALEN];
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R || CONFIG_OWE */
wpa_dbg(wpa_s, MSG_DEBUG, "Association info event");
if (data->assoc_info.req_ies)
@@ -2004,6 +2405,13 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len);
#endif /* CONFIG_INTERWORKING */
+ if (wpa_s->hw_capab == CAPAB_VHT &&
+ get_ie(data->assoc_info.resp_ies,
+ data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP))
+ wpa_s->ieee80211ac = 1;
+
+ multi_ap_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
+ data->assoc_info.resp_ies_len);
}
if (data->assoc_info.beacon_ies)
wpa_hexdump(MSG_DEBUG, "beacon_ies",
@@ -2013,6 +2421,26 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG, "freq=%u MHz",
data->assoc_info.freq);
+ wpa_s->connection_set = 0;
+ if (data->assoc_info.req_ies && data->assoc_info.resp_ies) {
+ struct ieee802_11_elems req_elems, resp_elems;
+
+ if (ieee802_11_parse_elems(data->assoc_info.req_ies,
+ data->assoc_info.req_ies_len,
+ &req_elems, 0) != ParseFailed &&
+ ieee802_11_parse_elems(data->assoc_info.resp_ies,
+ data->assoc_info.resp_ies_len,
+ &resp_elems, 0) != ParseFailed) {
+ wpa_s->connection_set = 1;
+ wpa_s->connection_ht = req_elems.ht_capabilities &&
+ resp_elems.ht_capabilities;
+ wpa_s->connection_vht = req_elems.vht_capabilities &&
+ resp_elems.vht_capabilities;
+ wpa_s->connection_he = req_elems.he_capabilities &&
+ resp_elems.he_capabilities;
+ }
+ }
+
p = data->assoc_info.req_ies;
l = data->assoc_info.req_ies_len;
@@ -2041,6 +2469,58 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
if (!found && data->assoc_info.req_ies)
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
+#ifdef CONFIG_FILS
+#ifdef CONFIG_SME
+ if ((wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
+ wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS_SK_PFS) &&
+ (!data->assoc_info.resp_frame ||
+ fils_process_assoc_resp(wpa_s->wpa,
+ data->assoc_info.resp_frame,
+ data->assoc_info.resp_frame_len) < 0)) {
+ wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
+ return -1;
+ }
+#endif /* CONFIG_SME */
+
+ /* Additional processing for FILS when SME is in driver */
+ if (wpa_s->auth_alg == WPA_AUTH_ALG_FILS &&
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
+ wpa_sm_set_reset_fils_completed(wpa_s->wpa, 1);
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_OWE
+ if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE &&
+ (wpa_drv_get_bssid(wpa_s, bssid) < 0 ||
+ owe_process_assoc_resp(wpa_s->wpa, bssid,
+ data->assoc_info.resp_ies,
+ data->assoc_info.resp_ies_len) < 0)) {
+ wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
+ return -1;
+ }
+#endif /* CONFIG_OWE */
+
+#ifdef CONFIG_DPP2
+ wpa_sm_set_dpp_z(wpa_s->wpa, NULL);
+ if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->dpp_pfs) {
+ struct ieee802_11_elems elems;
+
+ if (ieee802_11_parse_elems(data->assoc_info.resp_ies,
+ data->assoc_info.resp_ies_len,
+ &elems, 0) == ParseFailed ||
+ !elems.owe_dh)
+ goto no_pfs;
+ if (dpp_pfs_process(wpa_s->dpp_pfs, elems.owe_dh,
+ elems.owe_dh_len) < 0) {
+ wpa_supplicant_deauthenticate(wpa_s,
+ WLAN_REASON_UNSPECIFIED);
+ return -1;
+ }
+
+ wpa_sm_set_dpp_z(wpa_s->wpa, wpa_s->dpp_pfs->secret);
+ }
+no_pfs:
+#endif /* CONFIG_DPP2 */
+
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_SME
if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) {
@@ -2262,6 +2742,13 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
ft_completed = wpa_ft_is_completed(wpa_s->wpa);
if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0)
return;
+ /*
+ * FILS authentication can share the same mechanism to mark the
+ * connection fully authenticated, so set ft_completed also based on
+ * FILS result.
+ */
+ if (!ft_completed)
+ ft_completed = wpa_fils_is_completed(wpa_s->wpa);
if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
wpa_dbg(wpa_s, MSG_ERROR, "Failed to get BSSID");
@@ -2272,6 +2759,16 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED);
if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) {
+ if (os_reltime_initialized(&wpa_s->session_start)) {
+ os_reltime_age(&wpa_s->session_start,
+ &wpa_s->session_length);
+ wpa_s->session_start.sec = 0;
+ wpa_s->session_start.usec = 0;
+ wpas_notify_session_length(wpa_s);
+ } else {
+ wpas_notify_auth_changed(wpa_s);
+ os_get_reltime(&wpa_s->session_start);
+ }
wpa_dbg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID="
MACSTR, MAC2STR(bssid));
new_bss = 1;
@@ -2331,7 +2828,9 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
}
- if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed ||
+ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_DPP ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || ft_completed ||
already_authorized)
eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
/* 802.1X::portControl = Auto */
@@ -2360,8 +2859,17 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
}
wpa_supplicant_cancel_scan(wpa_s);
- if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
- wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
+ if (ft_completed) {
+ /*
+ * FT protocol completed - make sure EAPOL state machine ends
+ * up in authenticated.
+ */
+ wpa_supplicant_cancel_auth_timeout(wpa_s);
+ wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+ eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
+ eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
+ } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
+ wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
/*
* We are done; the driver will take care of RSN 4-way
* handshake.
@@ -2370,7 +2878,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
- } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
+ } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
/*
* The driver will take care of RSN 4-way handshake, so we need
@@ -2378,15 +2886,6 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
* waiting for WPA supplicant.
*/
eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
- } else if (ft_completed) {
- /*
- * FT protocol completed - make sure EAPOL state machine ends
- * up in authenticated.
- */
- wpa_supplicant_cancel_auth_timeout(wpa_s);
- wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
- eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
- eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
}
wpa_s->last_eapol_matches_bssid = 0;
@@ -2395,7 +2894,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
struct os_reltime now, age;
os_get_reltime(&now);
os_reltime_sub(&now, &wpa_s->pending_eapol_rx_time, &age);
- if (age.sec == 0 && age.usec < 100000 &&
+ if (age.sec == 0 && age.usec < 200000 &&
os_memcmp(wpa_s->pending_eapol_rx_src, bssid, ETH_ALEN) ==
0) {
wpa_dbg(wpa_s, MSG_DEBUG, "Process pending EAPOL "
@@ -2446,6 +2945,16 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
if (wpa_s->reassoc_same_bss)
wmm_ac_restore_tspecs(wpa_s);
}
+
+#ifdef CONFIG_FILS
+ if (wpa_key_mgmt_fils(wpa_s->key_mgmt)) {
+ struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, bssid);
+ const u8 *fils_cache_id = wpa_bss_get_fils_cache_id(bss);
+
+ if (fils_cache_id)
+ wpa_sm_set_fils_cache_id(wpa_s->wpa, fils_cache_id);
+ }
+#endif /* CONFIG_FILS */
}
@@ -2622,7 +3131,7 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
!disallowed_ssid(wpa_s, fast_reconnect->ssid,
fast_reconnect->ssid_len) &&
!wpas_temp_disabled(wpa_s, fast_reconnect_ssid) &&
- !wpa_is_bss_tmp_disallowed(wpa_s, fast_reconnect->bssid)) {
+ !wpa_is_bss_tmp_disallowed(wpa_s, fast_reconnect)) {
#ifndef CONFIG_NO_SCAN_PROCESSING
wpa_dbg(wpa_s, MSG_DEBUG, "Try to reconnect to the same BSS");
if (wpa_supplicant_connect(wpa_s, fast_reconnect,
@@ -2837,18 +3346,6 @@ wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s,
}
-#ifdef CONFIG_PEERKEY
-static void
-wpa_supplicant_event_stkstart(struct wpa_supplicant *wpa_s,
- union wpa_event_data *data)
-{
- if (data == NULL)
- return;
- wpa_sm_stkstart(wpa_s->wpa, data->stkstart.peer);
-}
-#endif /* CONFIG_PEERKEY */
-
-
#ifdef CONFIG_TDLS
static void wpa_supplicant_event_tdls(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
@@ -3207,10 +3704,11 @@ static const char * reg_type_str(enum reg_type type)
}
-static void wpa_supplicant_update_channel_list(
- struct wpa_supplicant *wpa_s, struct channel_list_changed *info)
+void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s,
+ struct channel_list_changed *info)
{
struct wpa_supplicant *ifs;
+ u8 dfs_domain;
/*
* To allow backwards compatibility with higher level layers that
@@ -3221,10 +3719,13 @@ static void wpa_supplicant_update_channel_list(
for (ifs = wpa_s; ifs->parent && ifs != ifs->parent; ifs = ifs->parent)
;
- wpa_msg(ifs, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
- reg_init_str(info->initiator), reg_type_str(info->type),
- info->alpha2[0] ? " alpha2=" : "",
- info->alpha2[0] ? info->alpha2 : "");
+ if (info) {
+ wpa_msg(ifs, MSG_INFO,
+ WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
+ reg_init_str(info->initiator), reg_type_str(info->type),
+ info->alpha2[0] ? " alpha2=" : "",
+ info->alpha2[0] ? info->alpha2 : "");
+ }
if (wpa_s->drv_priv == NULL)
return; /* Ignore event during drv initialization */
@@ -3235,7 +3736,7 @@ static void wpa_supplicant_update_channel_list(
ifs->ifname);
free_hw_features(ifs);
ifs->hw.modes = wpa_drv_get_hw_feature_data(
- ifs, &ifs->hw.num_modes, &ifs->hw.flags);
+ ifs, &ifs->hw.num_modes, &ifs->hw.flags, &dfs_domain);
/* Restart PNO/sched_scan with updated channel list */
if (ifs->pno) {
@@ -3310,6 +3811,15 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
return;
#endif /* CONFIG_GAS */
+#ifdef CONFIG_GAS_SERVER
+ if ((mgmt->u.action.category == WLAN_ACTION_PUBLIC ||
+ mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL) &&
+ gas_server_rx(wpa_s->gas_server, mgmt->da, mgmt->sa, mgmt->bssid,
+ mgmt->u.action.category,
+ payload, plen, freq) == 0)
+ return;
+#endif /* CONFIG_GAS_SERVER */
+
#ifdef CONFIG_TDLS
if (category == WLAN_ACTION_PUBLIC && plen >= 4 &&
payload[0] == WLAN_TDLS_DISCOVERY_RESPONSE) {
@@ -3338,6 +3848,7 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
if (category == WLAN_ACTION_RADIO_MEASUREMENT &&
payload[0] == WLAN_RRM_RADIO_MEASUREMENT_REQUEST) {
wpas_rrm_handle_radio_measurement_request(wpa_s, mgmt->sa,
+ mgmt->da,
payload + 1,
plen - 1);
return;
@@ -3364,6 +3875,18 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_FST */
+#ifdef CONFIG_DPP
+ if (category == WLAN_ACTION_PUBLIC && plen >= 5 &&
+ payload[0] == WLAN_PA_VENDOR_SPECIFIC &&
+ WPA_GET_BE24(&payload[1]) == OUI_WFA &&
+ payload[4] == DPP_OUI_TYPE) {
+ payload++;
+ plen--;
+ wpas_dpp_rx_action(wpa_s, mgmt->sa, payload, plen, freq);
+ return;
+ }
+#endif /* CONFIG_DPP */
+
wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
category, payload, plen, freq);
if (wpa_s->ifmsh)
@@ -3404,23 +3927,252 @@ static void wpa_supplicant_notify_avoid_freq(struct wpa_supplicant *wpa_s,
}
-static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s,
- union wpa_event_data *data)
+static void wpa_supplicant_event_port_authorized(struct wpa_supplicant *wpa_s)
{
- wpa_dbg(wpa_s, MSG_DEBUG,
- "Connection authorized by device, previous state %d",
- wpa_s->wpa_state);
if (wpa_s->wpa_state == WPA_ASSOCIATED) {
wpa_supplicant_cancel_auth_timeout(wpa_s);
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
}
+}
+
+
+static unsigned int wpas_event_cac_ms(const struct wpa_supplicant *wpa_s,
+ int freq)
+{
+ size_t i;
+ int j;
+
+ for (i = 0; i < wpa_s->hw.num_modes; i++) {
+ const struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
+
+ for (j = 0; j < mode->num_channels; j++) {
+ const struct hostapd_channel_data *chan;
+
+ chan = &mode->channels[j];
+ if (chan->freq == freq)
+ return chan->dfs_cac_ms;
+ }
+ }
+
+ return 0;
+}
+
+
+static void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
+{
+#if defined(NEED_AP_MLME) && defined(CONFIG_AP)
+ if (wpa_s->ap_iface || wpa_s->ifmsh) {
+ wpas_ap_event_dfs_cac_started(wpa_s, radar);
+ } else
+#endif /* NEED_AP_MLME && CONFIG_AP */
+ {
+ unsigned int cac_time = wpas_event_cac_ms(wpa_s, radar->freq);
+
+ cac_time /= 1000; /* convert from ms to sec */
+ if (!cac_time)
+ cac_time = 10 * 60; /* max timeout: 10 minutes */
+
+ /* Restart auth timeout: CAC time added to initial timeout */
+ wpas_auth_timeout_restart(wpa_s, cac_time);
+ }
+}
+
+
+static void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
+{
+#if defined(NEED_AP_MLME) && defined(CONFIG_AP)
+ if (wpa_s->ap_iface || wpa_s->ifmsh) {
+ wpas_ap_event_dfs_cac_finished(wpa_s, radar);
+ } else
+#endif /* NEED_AP_MLME && CONFIG_AP */
+ {
+ /* Restart auth timeout with original value after CAC is
+ * finished */
+ wpas_auth_timeout_restart(wpa_s, 0);
+ }
+}
+
+
+static void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
+{
+#if defined(NEED_AP_MLME) && defined(CONFIG_AP)
+ if (wpa_s->ap_iface || wpa_s->ifmsh) {
+ wpas_ap_event_dfs_cac_aborted(wpa_s, radar);
+ } else
+#endif /* NEED_AP_MLME && CONFIG_AP */
+ {
+ /* Restart auth timeout with original value after CAC is
+ * aborted */
+ wpas_auth_timeout_restart(wpa_s, 0);
+ }
+}
+
+
+static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Connection authorized by device, previous state %d",
+ wpa_s->wpa_state);
+
+ wpa_supplicant_event_port_authorized(wpa_s);
+
wpa_sm_set_rx_replay_ctr(wpa_s->wpa, data->assoc_info.key_replay_ctr);
wpa_sm_set_ptk_kck_kek(wpa_s->wpa, data->assoc_info.ptk_kck,
data->assoc_info.ptk_kck_len,
data->assoc_info.ptk_kek,
data->assoc_info.ptk_kek_len);
+#ifdef CONFIG_FILS
+ if (wpa_s->auth_alg == WPA_AUTH_ALG_FILS) {
+ struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid);
+ const u8 *fils_cache_id = wpa_bss_get_fils_cache_id(bss);
+
+ /* Update ERP next sequence number */
+ eapol_sm_update_erp_next_seq_num(
+ wpa_s->eapol, data->assoc_info.fils_erp_next_seq_num);
+
+ if (data->assoc_info.fils_pmk && data->assoc_info.fils_pmkid) {
+ /* Add the new PMK and PMKID to the PMKSA cache */
+ wpa_sm_pmksa_cache_add(wpa_s->wpa,
+ data->assoc_info.fils_pmk,
+ data->assoc_info.fils_pmk_len,
+ data->assoc_info.fils_pmkid,
+ wpa_s->bssid, fils_cache_id);
+ } else if (data->assoc_info.fils_pmkid) {
+ /* Update the current PMKSA used for this connection */
+ pmksa_cache_set_current(wpa_s->wpa,
+ data->assoc_info.fils_pmkid,
+ NULL, NULL, 0, NULL, 0);
+ }
+ }
+#endif /* CONFIG_FILS */
+}
+
+
+static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ const u8 *bssid = data->assoc_reject.bssid;
+
+ if (!bssid || is_zero_ether_addr(bssid))
+ bssid = wpa_s->pending_bssid;
+
+ if (data->assoc_reject.bssid)
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
+ "bssid=" MACSTR " status_code=%u%s%s%s",
+ MAC2STR(data->assoc_reject.bssid),
+ data->assoc_reject.status_code,
+ data->assoc_reject.timed_out ? " timeout" : "",
+ data->assoc_reject.timeout_reason ? "=" : "",
+ data->assoc_reject.timeout_reason ?
+ data->assoc_reject.timeout_reason : "");
+ else
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
+ "status_code=%u%s%s%s",
+ data->assoc_reject.status_code,
+ data->assoc_reject.timed_out ? " timeout" : "",
+ data->assoc_reject.timeout_reason ? "=" : "",
+ data->assoc_reject.timeout_reason ?
+ data->assoc_reject.timeout_reason : "");
+ wpa_s->assoc_status_code = data->assoc_reject.status_code;
+ wpas_notify_assoc_status_code(wpa_s);
+
+#ifdef CONFIG_OWE
+ if (data->assoc_reject.status_code ==
+ WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
+ wpa_s->key_mgmt == WPA_KEY_MGMT_OWE &&
+ wpa_s->current_ssid &&
+ wpa_s->current_ssid->owe_group == 0 &&
+ wpa_s->last_owe_group != 21) {
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ struct wpa_bss *bss = wpa_s->current_bss;
+
+ if (!bss) {
+ bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
+ if (!bss) {
+ wpas_connection_failed(wpa_s, bssid);
+ wpa_supplicant_mark_disassoc(wpa_s);
+ return;
+ }
+ }
+ wpa_printf(MSG_DEBUG, "OWE: Try next supported DH group");
+ wpas_connect_work_done(wpa_s);
+ wpa_supplicant_mark_disassoc(wpa_s);
+ wpa_supplicant_connect(wpa_s, bss, ssid);
+ return;
+ }
+#endif /* CONFIG_OWE */
+
+#ifdef CONFIG_MBO
+ if (data->assoc_reject.status_code ==
+ WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS &&
+ wpa_s->current_bss && data->assoc_reject.bssid &&
+ data->assoc_reject.resp_ies) {
+ const u8 *rssi_rej;
+
+ rssi_rej = mbo_get_attr_from_ies(
+ data->assoc_reject.resp_ies,
+ data->assoc_reject.resp_ies_len,
+ OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT);
+ if (rssi_rej && rssi_rej[1] == 2) {
+ wpa_printf(MSG_DEBUG,
+ "OCE: RSSI-based association rejection from "
+ MACSTR " (Delta RSSI: %u, Retry Delay: %u)",
+ MAC2STR(data->assoc_reject.bssid),
+ rssi_rej[2], rssi_rej[3]);
+ wpa_bss_tmp_disallow(wpa_s,
+ data->assoc_reject.bssid,
+ rssi_rej[3],
+ rssi_rej[2] +
+ wpa_s->current_bss->level);
+ }
+ }
+#endif /* CONFIG_MBO */
+
+ if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
+ sme_event_assoc_reject(wpa_s, data);
+ return;
+ }
+
+ /* Driver-based SME cases */
+
+#ifdef CONFIG_SAE
+ if (wpa_s->current_ssid &&
+ wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt) &&
+ !data->assoc_reject.timed_out) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "SAE: Drop PMKSA cache entry");
+ wpa_sm_aborted_cached(wpa_s->wpa);
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
+ }
+#endif /* CONFIG_SAE */
+
+#ifdef CONFIG_DPP
+ if (wpa_s->current_ssid &&
+ wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP &&
+ !data->assoc_reject.timed_out) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "DPP: Drop PMKSA cache entry");
+ wpa_sm_aborted_cached(wpa_s->wpa);
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
+ }
+#endif /* CONFIG_DPP */
+
+#ifdef CONFIG_FILS
+ /* Update ERP next sequence number */
+ if (wpa_s->auth_alg == WPA_AUTH_ALG_FILS) {
+ eapol_sm_update_erp_next_seq_num(
+ wpa_s->eapol,
+ data->assoc_reject.fils_erp_next_seq_num);
+ fils_connection_failure(wpa_s);
+ }
+#endif /* CONFIG_FILS */
+
+ wpas_connection_failed(wpa_s, bssid);
+ wpa_supplicant_mark_disassoc(wpa_s);
}
@@ -3429,6 +4181,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
{
struct wpa_supplicant *wpa_s = ctx;
int resched;
+#ifndef CONFIG_NO_STDOUT_DEBUG
+ int level = MSG_DEBUG;
+#endif /* CONFIG_NO_STDOUT_DEBUG */
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED &&
event != EVENT_INTERFACE_ENABLED &&
@@ -3442,9 +4197,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
}
#ifndef CONFIG_NO_STDOUT_DEBUG
-{
- int level = MSG_DEBUG;
-
if (event == EVENT_RX_MGMT && data->rx_mgmt.frame_len >= 24) {
const struct ieee80211_hdr *hdr;
u16 fc;
@@ -3457,7 +4209,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_dbg(wpa_s, level, "Event %s (%d) received",
event_to_string(event), event);
-}
#endif /* CONFIG_NO_STDOUT_DEBUG */
switch (event) {
@@ -3469,6 +4220,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
"FST: MB IEs updated from auth IE");
#endif /* CONFIG_FST */
sme_event_auth(wpa_s, data);
+ wpa_s->auth_status_code = data->auth.status_code;
+ wpas_notify_auth_status_code(wpa_s);
break;
case EVENT_ASSOC:
#ifdef CONFIG_TESTING_OPTIONS
@@ -3477,9 +4230,18 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
"EVENT_ASSOC - ignore_auth_resp active!");
break;
}
+ if (wpa_s->testing_resend_assoc) {
+ wpa_printf(MSG_INFO,
+ "EVENT_DEAUTH - testing_resend_assoc");
+ break;
+ }
#endif /* CONFIG_TESTING_OPTIONS */
wpa_supplicant_event_assoc(wpa_s, data);
- if (data && data->assoc_info.authorized)
+ wpa_s->assoc_status_code = WLAN_STATUS_SUCCESS;
+ if (data &&
+ (data->assoc_info.authorized ||
+ (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ wpa_fils_is_completed(wpa_s->wpa))))
wpa_supplicant_event_assoc_auth(wpa_s, data);
if (data) {
wpa_msg(wpa_s, MSG_INFO,
@@ -3498,6 +4260,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
"EVENT_DEAUTH - ignore_auth_resp active!");
break;
}
+ if (wpa_s->testing_resend_assoc) {
+ wpa_printf(MSG_INFO,
+ "EVENT_DEAUTH - testing_resend_assoc");
+ break;
+ }
#endif /* CONFIG_TESTING_OPTIONS */
wpas_event_deauth(wpa_s,
data ? &data->deauth_info : NULL);
@@ -3570,11 +4337,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
case EVENT_PMKID_CANDIDATE:
wpa_supplicant_event_pmkid_candidate(wpa_s, data);
break;
-#ifdef CONFIG_PEERKEY
- case EVENT_STKSTART:
- wpa_supplicant_event_stkstart(wpa_s, data);
- break;
-#endif /* CONFIG_PEERKEY */
#ifdef CONFIG_TDLS
case EVENT_TDLS:
wpa_supplicant_event_tdls(wpa_s, data);
@@ -3596,28 +4358,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
#endif /* CONFIG_IBSS_RSN */
case EVENT_ASSOC_REJECT:
- if (data->assoc_reject.bssid)
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
- "bssid=" MACSTR " status_code=%u%s",
- MAC2STR(data->assoc_reject.bssid),
- data->assoc_reject.status_code,
- data->assoc_reject.timed_out ? " timeout" : "");
- else
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
- "status_code=%u%s",
- data->assoc_reject.status_code,
- data->assoc_reject.timed_out ? " timeout" : "");
- wpa_s->assoc_status_code = data->assoc_reject.status_code;
- wpas_notify_assoc_status_code(wpa_s);
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
- sme_event_assoc_reject(wpa_s, data);
- else {
- const u8 *bssid = data->assoc_reject.bssid;
- if (bssid == NULL || is_zero_ether_addr(bssid))
- bssid = wpa_s->pending_bssid;
- wpas_connection_failed(wpa_s, bssid);
- wpa_supplicant_mark_disassoc(wpa_s);
- }
+ wpas_event_assoc_reject(wpa_s, data);
break;
case EVENT_AUTH_TIMED_OUT:
/* It is possible to get this event from earlier connection */
@@ -3719,6 +4460,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
ap_rx_from_unknown_sta(wpa_s, data->rx_from_unknown.addr,
data->rx_from_unknown.wds);
break;
+#endif /* CONFIG_AP */
case EVENT_CH_SWITCH:
if (!data || !wpa_s->current_ssid)
break;
@@ -3735,8 +4477,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_s->assoc_freq = data->ch_switch.freq;
wpa_s->current_ssid->frequency = data->ch_switch.freq;
+#ifdef CONFIG_AP
if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO ||
+ wpa_s->current_ssid->mode == WPAS_MODE_MESH ||
wpa_s->current_ssid->mode ==
WPAS_MODE_P2P_GROUP_FORMATION) {
wpas_ap_ch_switch(wpa_s, data->ch_switch.freq,
@@ -3746,14 +4490,28 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->ch_switch.cf1,
data->ch_switch.cf2);
}
+#endif /* CONFIG_AP */
+#ifdef CONFIG_IEEE80211W
+ sme_event_ch_switch(wpa_s);
+#endif /* CONFIG_IEEE80211W */
wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS);
+ wnm_clear_coloc_intf_reporting(wpa_s);
break;
+#ifdef CONFIG_AP
#ifdef NEED_AP_MLME
case EVENT_DFS_RADAR_DETECTED:
if (data)
- wpas_event_dfs_radar_detected(wpa_s, &data->dfs_event);
+ wpas_ap_event_dfs_radar_detected(wpa_s,
+ &data->dfs_event);
break;
+ case EVENT_DFS_NOP_FINISHED:
+ if (data)
+ wpas_ap_event_dfs_cac_nop_finished(wpa_s,
+ &data->dfs_event);
+ break;
+#endif /* NEED_AP_MLME */
+#endif /* CONFIG_AP */
case EVENT_DFS_CAC_STARTED:
if (data)
wpas_event_dfs_cac_started(wpa_s, &data->dfs_event);
@@ -3766,13 +4524,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
if (data)
wpas_event_dfs_cac_aborted(wpa_s, &data->dfs_event);
break;
- case EVENT_DFS_NOP_FINISHED:
- if (data)
- wpas_event_dfs_cac_nop_finished(wpa_s,
- &data->dfs_event);
- break;
-#endif /* NEED_AP_MLME */
-#endif /* CONFIG_AP */
case EVENT_RX_MGMT: {
u16 fc, stype;
const struct ieee80211_mgmt *mgmt;
@@ -3844,6 +4595,16 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
}
+#ifdef CONFIG_SAE
+ if (stype == WLAN_FC_STYPE_AUTH &&
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
+ sme_external_auth_mgmt_rx(
+ wpa_s, data->rx_mgmt.frame,
+ data->rx_mgmt.frame_len);
+ break;
+ }
+#endif /* CONFIG_SAE */
wpa_dbg(wpa_s, MSG_DEBUG, "AP: ignore received "
"management frame in non-AP mode");
break;
@@ -3908,6 +4669,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
#endif /* CONFIG_OFFCHANNEL */
wpas_p2p_cancel_remain_on_channel_cb(
wpa_s, data->remain_on_channel.freq);
+#ifdef CONFIG_DPP
+ wpas_dpp_cancel_remain_on_channel_cb(
+ wpa_s, data->remain_on_channel.freq);
+#endif /* CONFIG_DPP */
break;
case EVENT_EAPOL_RX:
wpa_supplicant_rx_eapol(wpa_s, data->eapol_rx.src,
@@ -3929,6 +4694,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->signal_change.current_noise,
data->signal_change.current_txrate);
break;
+ case EVENT_INTERFACE_MAC_CHANGED:
+ wpa_supplicant_update_mac_addr(wpa_s);
+ break;
case EVENT_INTERFACE_ENABLED:
wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled");
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
@@ -4095,7 +4863,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
case EVENT_WPS_BUTTON_PUSHED:
#ifdef CONFIG_WPS
- wpas_wps_start_pbc(wpa_s, NULL, 0);
+ wpas_wps_start_pbc(wpa_s, NULL, 0, 0);
#endif /* CONFIG_WPS */
break;
case EVENT_AVOID_FREQUENCIES:
@@ -4129,12 +4897,14 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
#endif /* CONFIG_AP */
break;
case EVENT_ACS_CHANNEL_SELECTED:
+#ifdef CONFIG_AP
#ifdef CONFIG_ACS
if (!wpa_s->ap_iface)
break;
hostapd_acs_channel_selected(wpa_s->ap_iface->bss[0],
&data->acs_selected_channels);
#endif /* CONFIG_ACS */
+#endif /* CONFIG_AP */
break;
case EVENT_P2P_LO_STOP:
#ifdef CONFIG_P2P
@@ -4144,6 +4914,36 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->p2p_lo_stop.reason_code);
#endif /* CONFIG_P2P */
break;
+ case EVENT_BEACON_LOSS:
+ if (!wpa_s->current_bss || !wpa_s->current_ssid)
+ break;
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_BEACON_LOSS);
+ bgscan_notify_beacon_loss(wpa_s);
+ break;
+ case EVENT_EXTERNAL_AUTH:
+#ifdef CONFIG_SAE
+ if (!wpa_s->current_ssid) {
+ wpa_printf(MSG_DEBUG, "SAE: current_ssid is NULL");
+ break;
+ }
+ sme_external_auth_trigger(wpa_s, data);
+#endif /* CONFIG_SAE */
+ break;
+ case EVENT_PORT_AUTHORIZED:
+ wpa_supplicant_event_port_authorized(wpa_s);
+ break;
+ case EVENT_STATION_OPMODE_CHANGED:
+#ifdef CONFIG_AP
+ if (!wpa_s->ap_iface || !data)
+ break;
+
+ hostapd_event_sta_opmode_changed(wpa_s->ap_iface->bss[0],
+ data->sta_opmode.addr,
+ data->sta_opmode.smps_mode,
+ data->sta_opmode.chan_width,
+ data->sta_opmode.rx_nss);
+#endif /* CONFIG_AP */
+ break;
default:
wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
break;
diff --git a/contrib/wpa/wpa_supplicant/examples/dbus-listen-preq.py b/contrib/wpa/wpa_supplicant/examples/dbus-listen-preq.py
index 5ac9859f7b72..337519f4e927 100755
--- a/contrib/wpa/wpa_supplicant/examples/dbus-listen-preq.py
+++ b/contrib/wpa/wpa_supplicant/examples/dbus-listen-preq.py
@@ -1,5 +1,6 @@
#!/usr/bin/python
+from __future__ import print_function
import dbus
import sys
import time
@@ -12,21 +13,24 @@ WPAS_DBUS_OPATH = "/fi/w1/wpa_supplicant1"
WPAS_DBUS_INTERFACES_INTERFACE = "fi.w1.wpa_supplicant1.Interface"
def usage():
- print "Usage: %s <ifname>" % sys.argv[0]
- print "Press Ctrl-C to stop"
+ print("Usage: %s <ifname>" % sys.argv[0])
+ print("Press Ctrl-C to stop")
def ProbeRequest(args):
if 'addr' in args:
- print '%.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['addr']),
+ print('%.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['addr']),
+ end=' ')
if 'dst' in args:
- print '-> %.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['dst']),
+ print('-> %.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['dst']),
+ end=' ')
if 'bssid' in args:
- print '(bssid %.2x:%.2x:%.2x:%.2x:%.2x:%.2x)' % tuple(args['dst']),
+ print('(bssid %.2x:%.2x:%.2x:%.2x:%.2x:%.2x)' % tuple(args['dst']),
+ end=' ')
if 'signal' in args:
- print 'signal:%d' % args['signal'],
+ print('signal:%d' % args['signal'], end=' ')
if 'ies' in args:
- print 'have IEs (%d bytes)' % len(args['ies']),
- print ''
+ print('have IEs (%d bytes)' % len(args['ies']), end=' ')
+ print('')
if __name__ == "__main__":
global bus
diff --git a/contrib/wpa/wpa_supplicant/examples/dpp-qrcode.py b/contrib/wpa/wpa_supplicant/examples/dpp-qrcode.py
new file mode 100644
index 000000000000..b468d15cf9cd
--- /dev/null
+++ b/contrib/wpa/wpa_supplicant/examples/dpp-qrcode.py
@@ -0,0 +1,130 @@
+#!/usr/bin/python
+#
+# Example Android logcat to wpa_supplicant wrapper for QR Code scans
+# Copyright (c) 2017, Qualcomm Atheros, Inc.
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import os
+import sys
+import argparse
+import logging
+import qrcode
+
+scriptsdir = os.path.dirname(os.path.realpath(sys.modules[__name__].__file__))
+sys.path.append(os.path.join(scriptsdir, '..', '..', 'wpaspy'))
+
+import wpaspy
+
+wpas_ctrl = '/var/run/wpa_supplicant'
+
+def wpas_connect():
+ ifaces = []
+ if os.path.isdir(wpas_ctrl):
+ try:
+ ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
+ except OSError as error:
+ print("Could not find wpa_supplicant: ", error)
+ return None
+
+ if len(ifaces) < 1:
+ print("No wpa_supplicant control interface found")
+ return None
+
+ for ctrl in ifaces:
+ try:
+ wpas = wpaspy.Ctrl(ctrl)
+ return wpas
+ except Exception as e:
+ pass
+ return None
+
+def dpp_logcat():
+ for line in iter(sys.stdin.readline, ''):
+ if "ResultHandler: Launching intent: Intent" not in line:
+ continue
+ if "act=android.intent.action.VIEW" not in line:
+ continue
+ uri = None
+ for val in line.split(' '):
+ if val.startswith('dat='):
+ uri = val.split('=', 1)[1]
+ break
+ if not uri:
+ continue
+ if not uri.startswith('DPP:'):
+ continue
+ print("Found DPP bootstrap info URI:")
+ print(uri)
+ wpas = wpas_connect()
+ if not wpas:
+ print("Could not connect to wpa_supplicant")
+ print('')
+ continue
+ res = wpas.request("DPP_QR_CODE " + uri);
+ try:
+ id = int(res)
+ except ValueError:
+ print("QR Code URI rejected")
+ continue
+ print("QR Code URI accepted - ID=%d" % id)
+ print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id))
+ del wpas
+
+def dpp_display(curve):
+ wpas = wpas_connect()
+ if not wpas:
+ print("Could not connect to wpa_supplicant")
+ return
+ res = wpas.request("STATUS")
+ addr = None
+ for line in res.splitlines():
+ if line.startswith("address="):
+ addr = line.split('=')[1]
+ break
+ cmd = "DPP_BOOTSTRAP_GEN type=qrcode"
+ cmd += " chan=81/1"
+ if addr:
+ cmd += " mac=" + addr.replace(':','')
+ if curve:
+ cmd += " curve=" + curve
+ res = wpas.request(cmd)
+ try:
+ id = int(res)
+ except ValueError:
+ print("Failed to generate bootstrap info URI")
+ return
+ print("Bootstrap information - ID=%d" % id)
+ print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id))
+ uri = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % id)
+ print(uri)
+ print("ID=%d" % id)
+ qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_M,
+ border=3)
+ qr.add_data(uri, optimize=5)
+ qr.print_ascii(tty=True)
+ print("ID=%d" % id)
+ del wpas
+
+def main():
+ parser = argparse.ArgumentParser(description='Android logcat to wpa_supplicant integration for DPP QR Code operations')
+ parser.add_argument('-d', const=logging.DEBUG, default=logging.INFO,
+ action='store_const', dest='loglevel',
+ help='verbose debug output')
+ parser.add_argument('--curve', '-c',
+ help='set a specific curve (P-256, P-384, P-521, BP-256R1, BP-384R1, BP-512R1) for key generation')
+ parser.add_argument('command', choices=['logcat',
+ 'display'],
+ nargs='?')
+ args = parser.parse_args()
+
+ logging.basicConfig(level=args.loglevel)
+
+ if args.command == "logcat":
+ dpp_logcat()
+ elif args.command == "display":
+ dpp_display(args.curve)
+
+if __name__ == '__main__':
+ main()
diff --git a/contrib/wpa/wpa_supplicant/examples/p2p-nfc.py b/contrib/wpa/wpa_supplicant/examples/p2p-nfc.py
index 91eba28908ed..889ac8bff155 100755
--- a/contrib/wpa/wpa_supplicant/examples/p2p-nfc.py
+++ b/contrib/wpa/wpa_supplicant/examples/p2p-nfc.py
@@ -37,7 +37,7 @@ summary_file = None
success_file = None
def summary(txt):
- print txt
+ print(txt)
if summary_file:
with open(summary_file, 'a') as f:
f.write(txt + "\n")
@@ -53,12 +53,12 @@ def wpas_connect():
if os.path.isdir(wpas_ctrl):
try:
ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
- except OSError, error:
- print "Could not find wpa_supplicant: ", error
+ except OSError as error:
+ print("Could not find wpa_supplicant: ", error)
return None
if len(ifaces) < 1:
- print "No wpa_supplicant control interface found"
+ print("No wpa_supplicant control interface found")
return None
for ctrl in ifaces:
@@ -66,10 +66,10 @@ def wpas_connect():
if ifname not in ctrl:
continue
try:
- print "Trying to use control interface " + ctrl
+ print("Trying to use control interface " + ctrl)
wpas = wpaspy.Ctrl(ctrl)
return wpas
- except Exception, e:
+ except Exception as e:
pass
return None
@@ -160,30 +160,30 @@ def p2p_handover_client(llc):
if (data == None):
summary("Could not get handover request carrier record from wpa_supplicant")
return
- print "Handover request carrier record from wpa_supplicant: " + data.encode("hex")
+ print("Handover request carrier record from wpa_supplicant: " + data.encode("hex"))
datamsg = nfc.ndef.Message(data)
message.add_carrier(datamsg[0], "active", datamsg[1:])
global include_wps_req
if include_wps_req:
- print "Handover request (pre-WPS):"
+ print("Handover request (pre-WPS):")
try:
- print message.pretty()
- except Exception, e:
- print e
+ print(message.pretty())
+ except Exception as e:
+ print(e)
data = wpas_get_handover_req_wps()
if data:
- print "Add WPS request in addition to P2P"
+ print("Add WPS request in addition to P2P")
datamsg = nfc.ndef.Message(data)
message.add_carrier(datamsg[0], "active", datamsg[1:])
- print "Handover request:"
+ print("Handover request:")
try:
- print message.pretty()
- except Exception, e:
- print e
- print str(message).encode("hex")
+ print(message.pretty())
+ except Exception as e:
+ print(e)
+ print(str(message).encode("hex"))
client = nfc.handover.HandoverClient(llc)
try:
@@ -194,7 +194,7 @@ def p2p_handover_client(llc):
summary("Handover connection refused")
client.close()
return
- except Exception, e:
+ except Exception as e:
summary("Other exception: " + str(e))
client.close()
return
@@ -217,41 +217,41 @@ def p2p_handover_client(llc):
client.close()
return
- print "Received message"
+ print("Received message")
try:
- print message.pretty()
- except Exception, e:
- print e
- print str(message).encode("hex")
+ print(message.pretty())
+ except Exception as e:
+ print(e)
+ print(str(message).encode("hex"))
message = nfc.ndef.HandoverSelectMessage(message)
summary("Handover select received")
try:
- print message.pretty()
- except Exception, e:
- print e
+ print(message.pretty())
+ except Exception as e:
+ print(e)
for carrier in message.carriers:
- print "Remote carrier type: " + carrier.type
+ print("Remote carrier type: " + carrier.type)
if carrier.type == "application/vnd.wfa.p2p":
- print "P2P carrier type match - send to wpa_supplicant"
+ print("P2P carrier type match - send to wpa_supplicant")
if "OK" in wpas_report_handover(data, carrier.record, "INIT"):
success_report("P2P handover reported successfully (initiator)")
else:
summary("P2P handover report rejected")
break
- print "Remove peer"
+ print("Remove peer")
client.close()
- print "Done with handover"
+ print("Done with handover")
global only_one
if only_one:
- print "only_one -> stop loop"
+ print("only_one -> stop loop")
global continue_loop
continue_loop = False
global no_wait
if no_wait:
- print "Trying to exit.."
+ print("Trying to exit..")
global terminate_now
terminate_now = True
@@ -283,33 +283,33 @@ class HandoverServer(nfc.handover.HandoverServer):
def process_request(self, request):
self.ho_server_processing = True
clear_raw_mode()
- print "HandoverServer - request received"
+ print("HandoverServer - request received")
try:
- print "Parsed handover request: " + request.pretty()
- except Exception, e:
- print e
+ print("Parsed handover request: " + request.pretty())
+ except Exception as e:
+ print(e)
sel = nfc.ndef.HandoverSelectMessage(version="1.2")
found = False
for carrier in request.carriers:
- print "Remote carrier type: " + carrier.type
+ print("Remote carrier type: " + carrier.type)
if carrier.type == "application/vnd.wfa.p2p":
- print "P2P carrier type match - add P2P carrier record"
+ print("P2P carrier type match - add P2P carrier record")
found = True
self.received_carrier = carrier.record
- print "Carrier record:"
+ print("Carrier record:")
try:
- print carrier.record.pretty()
- except Exception, e:
- print e
+ print(carrier.record.pretty())
+ except Exception as e:
+ print(e)
data = wpas_get_handover_sel()
if data is None:
- print "Could not get handover select carrier record from wpa_supplicant"
+ print("Could not get handover select carrier record from wpa_supplicant")
continue
- print "Handover select carrier record from wpa_supplicant:"
- print data.encode("hex")
+ print("Handover select carrier record from wpa_supplicant:")
+ print(data.encode("hex"))
self.sent_carrier = data
if "OK" in wpas_report_handover(self.received_carrier, self.sent_carrier, "RESP"):
success_report("P2P handover reported successfully (responder)")
@@ -324,22 +324,22 @@ class HandoverServer(nfc.handover.HandoverServer):
for carrier in request.carriers:
if found:
break
- print "Remote carrier type: " + carrier.type
+ print("Remote carrier type: " + carrier.type)
if carrier.type == "application/vnd.wfa.wsc":
- print "WSC carrier type match - add WSC carrier record"
+ print("WSC carrier type match - add WSC carrier record")
found = True
self.received_carrier = carrier.record
- print "Carrier record:"
+ print("Carrier record:")
try:
- print carrier.record.pretty()
- except Exception, e:
- print e
+ print(carrier.record.pretty())
+ except Exception as e:
+ print(e)
data = wpas_get_handover_sel_wps()
if data is None:
- print "Could not get handover select carrier record from wpa_supplicant"
+ print("Could not get handover select carrier record from wpa_supplicant")
continue
- print "Handover select carrier record from wpa_supplicant:"
- print data.encode("hex")
+ print("Handover select carrier record from wpa_supplicant:")
+ print(data.encode("hex"))
self.sent_carrier = data
if "OK" in wpas_report_handover_wsc(self.received_carrier, self.sent_carrier, "RESP"):
success_report("WSC handover reported successfully")
@@ -352,12 +352,12 @@ class HandoverServer(nfc.handover.HandoverServer):
found = True
break
- print "Handover select:"
+ print("Handover select:")
try:
- print sel.pretty()
- except Exception, e:
- print e
- print str(sel).encode("hex")
+ print(sel.pretty())
+ except Exception as e:
+ print(e)
+ print(str(sel).encode("hex"))
summary("Sending handover select")
self.success = True
@@ -396,7 +396,7 @@ def p2p_tag_read(tag):
success = False
if len(tag.ndef.message):
for record in tag.ndef.message:
- print "record type " + record.type
+ print("record type " + record.type)
if record.type == "application/vnd.wfa.wsc":
summary("WPS tag - send to wpa_supplicant")
success = wpas_tag_read(tag.ndef.message)
@@ -419,7 +419,7 @@ def rdwr_connected_p2p_write(tag):
global p2p_sel_data
tag.ndef.message = str(p2p_sel_data)
success_report("Tag write succeeded")
- print "Done - remove tag"
+ print("Done - remove tag")
global only_one
if only_one:
global continue_loop
@@ -428,7 +428,7 @@ def rdwr_connected_p2p_write(tag):
return p2p_sel_wait_remove
def wps_write_p2p_handover_sel(clf, wait_remove=True):
- print "Write P2P handover select"
+ print("Write P2P handover select")
data = wpas_get_handover_sel(tag=True)
if (data == None):
summary("Could not get P2P handover select from wpa_supplicant")
@@ -440,14 +440,14 @@ def wps_write_p2p_handover_sel(clf, wait_remove=True):
p2p_sel_data = nfc.ndef.HandoverSelectMessage(version="1.2")
message = nfc.ndef.Message(data);
p2p_sel_data.add_carrier(message[0], "active", message[1:])
- print "Handover select:"
+ print("Handover select:")
try:
- print p2p_sel_data.pretty()
- except Exception, e:
- print e
- print str(p2p_sel_data).encode("hex")
+ print(p2p_sel_data.pretty())
+ except Exception as e:
+ print(e)
+ print(str(p2p_sel_data).encode("hex"))
- print "Touch an NFC tag"
+ print("Touch an NFC tag")
clf.connect(rdwr={'on-connect': rdwr_connected_p2p_write})
@@ -456,11 +456,11 @@ def rdwr_connected(tag):
summary("Tag connected: " + str(tag))
if tag.ndef:
- print "NDEF tag: " + tag.type
+ print("NDEF tag: " + tag.type)
try:
- print tag.ndef.message.pretty()
- except Exception, e:
- print e
+ print(tag.ndef.message.pretty())
+ except Exception as e:
+ print(e)
success = p2p_tag_read(tag)
if only_one and success:
global continue_loop
@@ -475,15 +475,15 @@ def rdwr_connected(tag):
def llcp_worker(llc):
global init_on_touch
if init_on_touch:
- print "Starting handover client"
+ print("Starting handover client")
p2p_handover_client(llc)
return
global no_input
if no_input:
- print "Wait for handover to complete"
+ print("Wait for handover to complete")
else:
- print "Wait for handover to complete - press 'i' to initiate ('w' for WPS only, 'p' for P2P only)"
+ print("Wait for handover to complete - press 'i' to initiate ('w' for WPS only, 'p' for P2P only)")
global srv
global wait_connection
while not wait_connection and srv.sent_carrier is None:
@@ -506,21 +506,21 @@ def llcp_worker(llc):
else:
continue
clear_raw_mode()
- print "Starting handover client"
+ print("Starting handover client")
p2p_handover_client(llc)
return
clear_raw_mode()
- print "Exiting llcp_worker thread"
+ print("Exiting llcp_worker thread")
def llcp_startup(clf, llc):
- print "Start LLCP server"
+ print("Start LLCP server")
global srv
srv = HandoverServer(llc)
return llc
def llcp_connected(llc):
- print "P2P LLCP connected"
+ print("P2P LLCP connected")
global wait_connection
wait_connection = False
global init_on_touch
@@ -587,7 +587,7 @@ def main():
if args.ifname:
global ifname
ifname = args.ifname
- print "Selected ifname " + ifname
+ print("Selected ifname " + ifname)
if args.no_wps_req:
global include_wps_req
@@ -610,7 +610,7 @@ def main():
try:
if not clf.open("usb"):
- print "Could not open connection with an NFC device"
+ print("Could not open connection with an NFC device")
raise SystemExit
if args.command == "write-p2p-sel":
@@ -619,7 +619,7 @@ def main():
global continue_loop
while continue_loop:
- print "Waiting for a tag or peer to be touched"
+ print("Waiting for a tag or peer to be touched")
wait_connection = True
try:
if args.tag_read_only:
@@ -636,8 +636,8 @@ def main():
'on-connect': llcp_connected},
terminate=terminate_loop):
break
- except Exception, e:
- print "clf.connect failed"
+ except Exception as e:
+ print("clf.connect failed")
global srv
if only_one and srv and srv.success:
diff --git a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_connect.py b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_connect.py
index 59b0a9d36462..6e3d94e20ca3 100644
--- a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_connect.py
+++ b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_connect.py
@@ -13,40 +13,40 @@ from dbus.mainloop.glib import DBusGMainLoop
def usage():
- print "Usage:"
- print " %s -i <interface_name> -m <wps_method> \ " \
- % sys.argv[0]
- print " -a <addr> [-p <pin>] [-g <go_intent>] \ "
- print " [-w <wpas_dbus_interface>]"
- print "Options:"
- print " -i = interface name"
- print " -m = wps method"
- print " -a = peer address"
- print " -p = pin number (8 digits)"
- print " -g = group owner intent"
- print " -w = wpas dbus interface = fi.w1.wpa_supplicant1"
- print "Example:"
- print " %s -i wlan0 -a 0015008352c0 -m display -p 12345670" % sys.argv[0]
+ print("Usage:")
+ print(" %s -i <interface_name> -m <wps_method> \ " \
+ % sys.argv[0])
+ print(" -a <addr> [-p <pin>] [-g <go_intent>] \ ")
+ print(" [-w <wpas_dbus_interface>]")
+ print("Options:")
+ print(" -i = interface name")
+ print(" -m = wps method")
+ print(" -a = peer address")
+ print(" -p = pin number (8 digits)")
+ print(" -g = group owner intent")
+ print(" -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+ print("Example:")
+ print(" %s -i wlan0 -a 0015008352c0 -m display -p 12345670" % sys.argv[0])
# Required Signals
def GONegotiationSuccess(status):
- print "Go Negotiation Success"
+ print("Go Negotiation Success")
def GONegotiationFailure(status):
- print 'Go Negotiation Failed. Status:'
- print format(status)
+ print('Go Negotiation Failed. Status:')
+ print(format(status))
os._exit(0)
def GroupStarted(properties):
if properties.has_key("group_object"):
- print 'Group Formation Complete %s' \
- % properties["group_object"]
+ print('Group Formation Complete %s' \
+ % properties["group_object"])
os._exit(0)
def WpsFailure(status, etc):
- print "WPS Authentication Failure".format(status)
- print etc
+ print("WPS Authentication Failure".format(status))
+ print(etc)
os._exit(0)
class P2P_Connect():
@@ -118,7 +118,7 @@ class P2P_Connect():
{'Ifname': ifname, 'Driver': 'test'})
time.sleep(1)
- except dbus.DBusException, exc:
+ except dbus.DBusException as exc:
if not str(exc).startswith(
self.wpas_dbus_interface + \
".InterfaceExists:"):
@@ -157,12 +157,12 @@ class P2P_Connect():
if (self.pin != None):
self.p2p_connect_arguements.update({'pin':self.pin})
else:
- print "Error:\n Pin required for wps_method=display"
+ print("Error:\n Pin required for wps_method=display")
usage()
quit()
if (self.go_intent != None and int(self.go_intent) != 15):
- print "go_intent overwritten to 15"
+ print("go_intent overwritten to 15")
self.go_intent = '15'
@@ -171,14 +171,14 @@ class P2P_Connect():
if (self.pin != None):
self.p2p_connect_arguements.update({'pin':self.pin})
else:
- print "Error:\n Pin required for wps_method=keypad"
+ print("Error:\n Pin required for wps_method=keypad")
usage()
quit()
if (self.go_intent != None and int(self.go_intent) == 15):
error = "Error :\n Group Owner intent cannot be" + \
" 15 for wps_method=keypad"
- print error
+ print(error)
usage()
quit()
@@ -186,15 +186,15 @@ class P2P_Connect():
# for ./wpa_cli, p2p_connect [mac] [pin#], wps_method=keypad
elif (self.wps_method == 'pin'):
if (self.pin != None):
- print "pin ignored"
+ print("pin ignored")
# No pin is required for pbc so it is ignored
elif (self.wps_method == 'pbc'):
if (self.pin != None):
- print "pin ignored"
+ print("pin ignored")
else:
- print "Error:\n wps_method not supported or does not exist"
+ print("Error:\n wps_method not supported or does not exist")
usage()
quit()
@@ -209,12 +209,12 @@ class P2P_Connect():
result_pin = self.p2p_interface.Connect(
self.p2p_connect_arguements)
- except dbus.DBusException, exc:
+ except dbus.DBusException as exc:
raise exc
if (self.wps_method == 'pin' and \
not self.p2p_connect_arguements.has_key('pin') ):
- print "Connect return with pin value of %d " % int(result_pin)
+ print("Connect return with pin value of %d " % int(result_pin))
gobject.MainLoop().run()
if __name__ == "__main__":
@@ -268,19 +268,19 @@ if __name__ == "__main__":
# Required Arguements check
if (interface_name == None or wps_method == None or addr == None):
- print "Error:\n Required arguements not specified"
+ print("Error:\n Required arguements not specified")
usage()
quit()
# Group Owner Intent Check
if (go_intent != None and (int(go_intent) > 15 or int(go_intent) < 0) ):
- print "Error:\n Group Owner Intent must be between 0 and 15 inclusive"
+ print("Error:\n Group Owner Intent must be between 0 and 15 inclusive")
usage()
quit()
# Pin Check
if (pin != None and len(pin) != 8):
- print "Error:\n Pin is not 8 digits"
+ print("Error:\n Pin is not 8 digits")
usage()
quit()
@@ -289,7 +289,7 @@ if __name__ == "__main__":
addr,pin,wps_method,go_intent)
except:
- print "Error:\n Invalid Arguements"
+ print("Error:\n Invalid Arguements")
usage()
quit()
diff --git a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_disconnect.py b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_disconnect.py
index c3e39b3de285..85b5a8b39f5e 100644
--- a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_disconnect.py
+++ b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_disconnect.py
@@ -12,19 +12,19 @@ import getopt
from dbus.mainloop.glib import DBusGMainLoop
def usage():
- print "Usage:"
- print " %s -i <interface_name> \ " \
- % sys.argv[0]
- print " [-w <wpas_dbus_interface>]"
- print "Options:"
- print " -i = interface name"
- print " -w = wpas dbus interface = fi.w1.wpa_supplicant1"
- print "Example:"
- print " %s -i p2p-wlan0-0" % sys.argv[0]
+ print("Usage:")
+ print(" %s -i <interface_name> \ " \
+ % sys.argv[0])
+ print(" [-w <wpas_dbus_interface>]")
+ print("Options:")
+ print(" -i = interface name")
+ print(" -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+ print("Example:")
+ print(" %s -i p2p-wlan0-0" % sys.argv[0])
# Required Signals
def GroupFinished(status, etc):
- print "Disconnected"
+ print("Disconnected")
os._exit(0)
class P2P_Disconnect (threading.Thread):
@@ -81,10 +81,10 @@ class P2P_Disconnect (threading.Thread):
try:
self.path = self.wpas.GetInterface(
self.interface_name)
- except dbus.DBusException, exc:
+ except dbus.DBusException as exc:
error = 'Error:\n Interface ' + self.interface_name \
+ ' was not found'
- print error
+ print(error)
usage()
os._exit(0)
@@ -142,7 +142,7 @@ if __name__ == "__main__":
# Interface name is required and was not given
if (interface_name == None):
- print "Error:\n interface_name is required"
+ print("Error:\n interface_name is required")
usage()
quit()
@@ -152,7 +152,7 @@ if __name__ == "__main__":
wpas_dbus_interface,timeout)
except:
- print "Error:\n Invalid wpas_dbus_interface"
+ print("Error:\n Invalid wpas_dbus_interface")
usage()
quit()
@@ -165,5 +165,5 @@ if __name__ == "__main__":
except:
pass
- print "Disconnect timed out"
+ print("Disconnect timed out")
quit()
diff --git a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_find.py b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_find.py
index 973d46ab0f4b..e2df52896991 100644
--- a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_find.py
+++ b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_find.py
@@ -13,23 +13,23 @@ import getopt
from dbus.mainloop.glib import DBusGMainLoop
def usage():
- print "Usage:"
- print " %s -i <interface_name> [-t <timeout>] \ " \
- % sys.argv[0]
- print " [-w <wpas_dbus_interface>]"
- print "Options:"
- print " -i = interface name"
- print " -t = timeout = 0s (infinite)"
- print " -w = wpas dbus interface = fi.w1.wpa_supplicant1"
- print "Example:"
- print " %s -i wlan0 -t 10" % sys.argv[0]
+ print("Usage:")
+ print(" %s -i <interface_name> [-t <timeout>] \ " \
+ % sys.argv[0])
+ print(" [-w <wpas_dbus_interface>]")
+ print("Options:")
+ print(" -i = interface name")
+ print(" -t = timeout = 0s (infinite)")
+ print(" -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+ print("Example:")
+ print(" %s -i wlan0 -t 10" % sys.argv[0])
# Required Signals
def deviceFound(devicepath):
- print "Device found: %s" % (devicepath)
+ print("Device found: %s" % (devicepath))
def deviceLost(devicepath):
- print "Device lost: %s" % (devicepath)
+ print("Device lost: %s" % (devicepath))
class P2P_Find (threading.Thread):
# Needed Variables
@@ -85,10 +85,10 @@ class P2P_Find (threading.Thread):
try:
self.path = self.wpas.GetInterface(
self.interface_name)
- except dbus.DBusException, exc:
+ except dbus.DBusException as exc:
error = 'Error:\n Interface ' + self.interface_name \
+ ' was not found'
- print error
+ print(error)
usage()
os._exit(0)
@@ -150,7 +150,7 @@ if __name__ == "__main__":
if ( int(value) >= 0):
timeout = value
else:
- print "Error:\n Timeout cannot be negative"
+ print("Error:\n Timeout cannot be negative")
usage()
quit()
# Dbus interface
@@ -161,7 +161,7 @@ if __name__ == "__main__":
# Interface name is required and was not given
if (interface_name == None):
- print "Error:\n interface_name is required"
+ print("Error:\n interface_name is required")
usage()
quit()
@@ -170,7 +170,7 @@ if __name__ == "__main__":
p2p_find_test = P2P_Find(interface_name, wpas_dbus_interface, timeout)
except:
- print "Error:\n Invalid wpas_dbus_interface"
+ print("Error:\n Invalid wpas_dbus_interface")
usage()
quit()
diff --git a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_flush.py b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_flush.py
index ff8509d6053d..42fc7a3e915a 100644
--- a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_flush.py
+++ b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_flush.py
@@ -13,19 +13,19 @@ import getopt
from dbus.mainloop.glib import DBusGMainLoop
def usage():
- print "Usage:"
- print " %s -i <interface_name> \ " \
- % sys.argv[0]
- print " [-w <wpas_dbus_interface>]"
- print "Options:"
- print " -i = interface name"
- print " -w = wpas dbus interface = fi.w1.wpa_supplicant1"
- print "Example:"
- print " %s -i wlan0" % sys.argv[0]
+ print("Usage:")
+ print(" %s -i <interface_name> \ " \
+ % sys.argv[0])
+ print(" [-w <wpas_dbus_interface>]")
+ print("Options:")
+ print(" -i = interface name")
+ print(" -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+ print("Example:")
+ print(" %s -i wlan0" % sys.argv[0])
# Required Signals\
def deviceLost(devicepath):
- print "Device lost: %s" % (devicepath)
+ print("Device lost: %s" % (devicepath))
class P2P_Flush (threading.Thread):
# Needed Variables
@@ -81,10 +81,10 @@ class P2P_Flush (threading.Thread):
try:
self.path = self.wpas.GetInterface(
self.interface_name)
- except dbus.DBusException, exc:
+ except dbus.DBusException as exc:
error = 'Error:\n Interface ' + self.interface_name \
+ ' was not found'
- print error
+ print(error)
usage()
os._exit(0)
@@ -142,7 +142,7 @@ if __name__ == "__main__":
# Interface name is required and was not given
if (interface_name == None):
- print "Error:\n interface_name is required"
+ print("Error:\n interface_name is required")
usage()
quit()
@@ -151,7 +151,7 @@ if __name__ == "__main__":
p2p_flush_test = P2P_Flush(interface_name, wpas_dbus_interface,timeout)
except:
- print "Error:\n Invalid wpas_dbus_interface"
+ print("Error:\n Invalid wpas_dbus_interface")
usage()
quit()
@@ -164,5 +164,5 @@ if __name__ == "__main__":
except:
pass
- print "p2p_flush complete"
+ print("p2p_flush complete")
quit()
diff --git a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_group_add.py b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_group_add.py
index 5c8fdafdfd9a..6d408218a25e 100644
--- a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_group_add.py
+++ b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_group_add.py
@@ -11,30 +11,30 @@ import threading
from dbus.mainloop.glib import DBusGMainLoop
def usage():
- print "Usage:"
- print " %s -i <interface_name> [-p <persistent>] \ " \
- % sys.argv[0]
- print " [-f <frequency>] [-o <group_object_path>] \ "
- print " [-w <wpas_dbus_interface>]"
- print "Options:"
- print " -i = interface name"
- print " -p = persistant group = 0 (0=false, 1=true)"
- print " -f = frequency"
- print " -o = persistent group object path"
- print " -w = wpas dbus interface = fi.w1.wpa_supplicant1"
- print "Example:"
- print " %s -i wlan0" % sys.argv[0]
+ print("Usage:")
+ print(" %s -i <interface_name> [-p <persistent>] \ " \
+ % sys.argv[0])
+ print(" [-f <frequency>] [-o <group_object_path>] \ ")
+ print(" [-w <wpas_dbus_interface>]")
+ print("Options:")
+ print(" -i = interface name")
+ print(" -p = persistant group = 0 (0=false, 1=true)")
+ print(" -f = frequency")
+ print(" -o = persistent group object path")
+ print(" -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+ print("Example:")
+ print(" %s -i wlan0" % sys.argv[0])
# Required Signals
def GroupStarted(properties):
if properties.has_key("group_object"):
- print 'Group Formation Complete %s' \
- % properties["group_object"]
+ print('Group Formation Complete %s' \
+ % properties["group_object"])
os._exit(0)
def WpsFailure(status, etc):
- print "WPS Authentication Failure".format(status)
- print etc
+ print("WPS Authentication Failure".format(status))
+ print(etc)
os._exit(0)
class P2P_Group_Add (threading.Thread):
@@ -99,10 +99,10 @@ class P2P_Group_Add (threading.Thread):
try:
self.path = self.wpas.GetInterface(
self.interface_name)
- except dbus.DBusException, exc:
+ except dbus.DBusException as exc:
error = 'Error:\n Interface ' + self.interface_name \
+ ' was not found'
- print error
+ print(error)
usage()
os._exit(0)
@@ -127,7 +127,7 @@ class P2P_Group_Add (threading.Thread):
if (int(self.frequency) > 0):
self.P2PDictionary.update({'frequency':int(self.frequency)})
else:
- print "Error:\n Frequency must be greater than 0"
+ print("Error:\n Frequency must be greater than 0")
usage()
os._exit(0)
@@ -141,7 +141,7 @@ class P2P_Group_Add (threading.Thread):
self.p2p_interface.GroupAdd(self.P2PDictionary)
except:
- print "Error:\n Could not preform group add"
+ print("Error:\n Could not preform group add")
usage()
os._exit(0)
@@ -188,7 +188,7 @@ if __name__ == "__main__":
elif (value == '1'):
persistent = True
else:
- print "Error:\n Persistent can only be 1 or 0"
+ print("Error:\n Persistent can only be 1 or 0")
usage()
os._exit(0)
# Frequency
@@ -205,7 +205,7 @@ if __name__ == "__main__":
# Interface name is required and was not given
if (interface_name == None):
- print "Error:\n interface_name is required"
+ print("Error:\n interface_name is required")
usage()
quit()
@@ -213,10 +213,10 @@ if __name__ == "__main__":
p2p_group_add_test = P2P_Group_Add(interface_name,wpas_dbus_interface,
persistent,frequency,persistent_group_object)
except:
- print "Error:\n Invalid Arguements"
+ print("Error:\n Invalid Arguements")
p2p_group_add_test.constructArguements()
p2p_group_add_test.start()
time.sleep(5)
- print "Error:\n Group formation timed out"
+ print("Error:\n Group formation timed out")
os._exit(0)
diff --git a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_invite.py b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_invite.py
index 6deb397eca83..341dcd0a983d 100644
--- a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_invite.py
+++ b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_invite.py
@@ -11,29 +11,29 @@ import threading
from dbus.mainloop.glib import DBusGMainLoop
def usage():
- print "Usage:"
- print " %s -i <interface_name> -a <addr> \ " \
- % sys.argv[0]
- print " [-o <persistent_group_object>] [-w <wpas_dbus_interface>]"
- print "Options:"
- print " -i = interface name"
- print " -a = address of peer"
- print " -o = persistent group object path"
- print " -w = wpas dbus interface = fi.w1.wpa_supplicant1"
- print "Example:"
- print " %s -i p2p-wlan0-0 -a 00150083523c" % sys.argv[0]
+ print("Usage:")
+ print(" %s -i <interface_name> -a <addr> \ " \
+ % sys.argv[0])
+ print(" [-o <persistent_group_object>] [-w <wpas_dbus_interface>]")
+ print("Options:")
+ print(" -i = interface name")
+ print(" -a = address of peer")
+ print(" -o = persistent group object path")
+ print(" -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+ print("Example:")
+ print(" %s -i p2p-wlan0-0 -a 00150083523c" % sys.argv[0])
# Required Signals
def InvitationResult(invite_result):
- print "Inviation Result signal :"
+ print("Inviation Result signal :")
status = invite_result['status']
- print "status = ", status
+ print("status = ", status)
if invite_result.has_key('BSSID'):
bssid = invite_result['BSSID']
- print "BSSID = ", hex(bssid[0]) , ":" , \
+ print("BSSID = ", hex(bssid[0]) , ":" , \
hex(bssid[1]) , ":" , hex(bssid[2]) , ":", \
hex(bssid[3]) , ":" , hex(bssid[4]) , ":" , \
- hex(bssid[5])
+ hex(bssid[5]))
os._exit(0)
class P2P_Invite (threading.Thread):
@@ -96,10 +96,10 @@ class P2P_Invite (threading.Thread):
try:
self.path = self.wpas.GetInterface(
self.interface_name)
- except dbus.DBusException, exc:
+ except dbus.DBusException as exc:
error = 'Error:\n Interface ' + self.interface_name \
+ ' was not found'
- print error
+ print(error)
usage()
os._exit(0)
@@ -127,7 +127,7 @@ class P2P_Invite (threading.Thread):
self.p2p_interface.Invite(self.P2PDictionary)
except:
- print "Error:\n Invalid Arguements"
+ print("Error:\n Invalid Arguements")
usage()
os._exit(0)
@@ -176,12 +176,12 @@ if __name__ == "__main__":
# Interface name is required and was not given
if (interface_name == None):
- print "Error:\n interface_name is required"
+ print("Error:\n interface_name is required")
usage()
quit()
if (addr == None):
- print "Error:\n peer address is required"
+ print("Error:\n peer address is required")
usage()
quit()
@@ -190,12 +190,12 @@ if __name__ == "__main__":
P2P_Invite(interface_name,wpas_dbus_interface,
addr,persistent_group_object)
except:
- print "Error:\n Invalid Arguements"
+ print("Error:\n Invalid Arguements")
usage()
os._exit(1)
p2p_invite_test.constructArguements()
p2p_invite_test.start()
time.sleep(10)
- print "Error:\n p2p_invite timed out"
+ print("Error:\n p2p_invite timed out")
os._exit(0)
diff --git a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_listen.py b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_listen.py
index bb3c1e49d5f1..b0837d9df5d2 100644
--- a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_listen.py
+++ b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_listen.py
@@ -13,20 +13,20 @@ import getopt
from dbus.mainloop.glib import DBusGMainLoop
def usage():
- print "Usage:"
- print " %s -i <interface_name> [-t <timeout>] \ " \
- % sys.argv[0]
- print " [-w <wpas_dbus_interface>]"
- print "Options:"
- print " -i = interface name"
- print " -t = timeout = 0s (infinite)"
- print " -w = wpas dbus interface = fi.w1.wpa_supplicant1"
- print "Example:"
- print " %s -i wlan0 -t 5" % sys.argv[0]
+ print("Usage:")
+ print(" %s -i <interface_name> [-t <timeout>] \ " \
+ % sys.argv[0])
+ print(" [-w <wpas_dbus_interface>]")
+ print("Options:")
+ print(" -i = interface name")
+ print(" -t = timeout = 0s (infinite)")
+ print(" -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+ print("Example:")
+ print(" %s -i wlan0 -t 5" % sys.argv[0])
# Required Signals
def p2pStateChange(status):
- print status
+ print(status)
class P2P_Listen(threading.Thread):
# Needed Variables
@@ -82,10 +82,10 @@ class P2P_Listen(threading.Thread):
try:
self.path = self.wpas.GetInterface(
self.interface_name)
- except dbus.DBusException, exc:
+ except dbus.DBusException as exc:
error = 'Error:\n Interface ' + self.interface_name \
+ ' was not found'
- print error
+ print(error)
usage()
os._exit(0)
@@ -140,7 +140,7 @@ if __name__ == "__main__":
if ( int(value) >= 0):
timeout = value
else:
- print "Error:\n Timeout cannot be negative"
+ print("Error:\n Timeout cannot be negative")
usage()
quit()
# Dbus interface
@@ -151,7 +151,7 @@ if __name__ == "__main__":
# Interface name is required and was not given
if (interface_name == None):
- print "Error:\n interface_name is required"
+ print("Error:\n interface_name is required")
usage()
quit()
@@ -160,7 +160,7 @@ if __name__ == "__main__":
p2p_listen_test = P2P_Listen(interface_name, wpas_dbus_interface, timeout)
except:
- print "Error:\n Invalid wpas_dbus_interface"
+ print("Error:\n Invalid wpas_dbus_interface")
usage()
quit()
diff --git a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_stop_find.py b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_stop_find.py
index f6c03b027228..bdb4c0e3221d 100644
--- a/contrib/wpa/wpa_supplicant/examples/p2p/p2p_stop_find.py
+++ b/contrib/wpa/wpa_supplicant/examples/p2p/p2p_stop_find.py
@@ -11,22 +11,22 @@ import getopt
from dbus.mainloop.glib import DBusGMainLoop
def usage():
- print "Usage:"
- print " %s -i <interface_name> \ " \
- % sys.argv[0]
- print " [-w <wpas_dbus_interface>]"
- print "Options:"
- print " -i = interface name"
- print " -w = wpas dbus interface = fi.w1.wpa_supplicant1"
- print "Example:"
- print " %s -i wlan0" % sys.argv[0]
+ print("Usage:")
+ print(" %s -i <interface_name> \ " \
+ % sys.argv[0])
+ print(" [-w <wpas_dbus_interface>]")
+ print("Options:")
+ print(" -i = interface name")
+ print(" -w = wpas dbus interface = fi.w1.wpa_supplicant1")
+ print("Example:")
+ print(" %s -i wlan0" % sys.argv[0])
# Required Signals
def deviceLost(devicepath):
- print "Device lost: %s" % (devicepath)
+ print("Device lost: %s" % (devicepath))
def p2pStateChange(status):
- print status
+ print(status)
os._exit(0)
class P2P_Stop_Find (threading.Thread):
@@ -83,10 +83,10 @@ class P2P_Stop_Find (threading.Thread):
try:
self.path = self.wpas.GetInterface(
self.interface_name)
- except dbus.DBusException, exc:
+ except dbus.DBusException as exc:
error = 'Error:\n Interface ' + self.interface_name \
+ ' was not found'
- print error
+ print(error)
usage()
os._exit(0)
@@ -147,7 +147,7 @@ if __name__ == "__main__":
# Interface name is required and was not given
if (interface_name == None):
- print "Error:\n interface_name is required"
+ print("Error:\n interface_name is required")
usage()
quit()
@@ -157,7 +157,7 @@ if __name__ == "__main__":
wpas_dbus_interface,timeout)
except:
- print "Error:\n Invalid wpas_dbus_interface"
+ print("Error:\n Invalid wpas_dbus_interface")
usage()
quit()
@@ -170,5 +170,5 @@ if __name__ == "__main__":
except:
pass
- print "p2p find stopped"
+ print("p2p find stopped")
quit()
diff --git a/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new-getall.py b/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new-getall.py
index 03da187c8908..732f54d20f8b 100755
--- a/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new-getall.py
+++ b/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new-getall.py
@@ -11,8 +11,8 @@ def main():
"/fi/w1/wpa_supplicant1")
props = wpas_obj.GetAll("fi.w1.wpa_supplicant1",
dbus_interface=dbus.PROPERTIES_IFACE)
- print "GetAll(fi.w1.wpa_supplicant1, /fi/w1/wpa_supplicant1):"
- print props
+ print("GetAll(fi.w1.wpa_supplicant1, /fi/w1/wpa_supplicant1):")
+ print(props)
if len(sys.argv) != 2:
os._exit(1)
@@ -24,15 +24,15 @@ def main():
if_obj = bus.get_object("fi.w1.wpa_supplicant1", path)
props = if_obj.GetAll("fi.w1.wpa_supplicant1.Interface",
dbus_interface=dbus.PROPERTIES_IFACE)
- print
- print "GetAll(fi.w1.wpa_supplicant1.Interface, %s):" % (path)
- print props
+ print('')
+ print("GetAll(fi.w1.wpa_supplicant1.Interface, %s):" % (path))
+ print(props)
props = if_obj.GetAll("fi.w1.wpa_supplicant1.Interface.WPS",
dbus_interface=dbus.PROPERTIES_IFACE)
- print
- print "GetAll(fi.w1.wpa_supplicant1.Interface.WPS, %s):" % (path)
- print props
+ print('')
+ print("GetAll(fi.w1.wpa_supplicant1.Interface.WPS, %s):" % (path))
+ print(props)
res = if_obj.Get("fi.w1.wpa_supplicant1.Interface", 'BSSs',
dbus_interface=dbus.PROPERTIES_IFACE)
@@ -40,9 +40,9 @@ def main():
bss_obj = bus.get_object("fi.w1.wpa_supplicant1", res[0])
props = bss_obj.GetAll("fi.w1.wpa_supplicant1.BSS",
dbus_interface=dbus.PROPERTIES_IFACE)
- print
- print "GetAll(fi.w1.wpa_supplicant1.BSS, %s):" % (res[0])
- print props
+ print('')
+ print("GetAll(fi.w1.wpa_supplicant1.BSS, %s):" % (res[0]))
+ print(props)
res = if_obj.Get("fi.w1.wpa_supplicant1.Interface", 'Networks',
dbus_interface=dbus.PROPERTIES_IFACE)
@@ -50,10 +50,9 @@ def main():
net_obj = bus.get_object("fi.w1.wpa_supplicant1", res[0])
props = net_obj.GetAll("fi.w1.wpa_supplicant1.Network",
dbus_interface=dbus.PROPERTIES_IFACE)
- print
- print "GetAll(fi.w1.wpa_supplicant1.Network, %s):" % (res[0])
- print props
+ print('')
+ print("GetAll(fi.w1.wpa_supplicant1.Network, %s):" % (res[0]))
+ print(props)
if __name__ == "__main__":
main()
-
diff --git a/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new-signals.py b/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new-signals.py
index d90ef1878ca7..366a65546af6 100755
--- a/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new-signals.py
+++ b/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new-signals.py
@@ -32,17 +32,17 @@ def list_interfaces(wpas_obj):
if_obj = bus.get_object(WPAS_DBUS_SERVICE, path)
ifname = if_obj.Get(WPAS_DBUS_INTERFACES_INTERFACE, 'Ifname',
dbus_interface=dbus.PROPERTIES_IFACE)
- print ifname
+ print(ifname)
def interfaceAdded(interface, properties):
- print "InterfaceAdded(%s): Ifname=%s" % (interface, properties['Ifname'])
+ print("InterfaceAdded(%s): Ifname=%s" % (interface, properties['Ifname']))
def interfaceRemoved(interface):
- print "InterfaceRemoved(%s)" % (interface)
+ print("InterfaceRemoved(%s)" % (interface))
def propertiesChanged(properties):
for i in properties:
- print "PropertiesChanged: %s=%s" % (i, properties[i])
+ print("PropertiesChanged: %s=%s" % (i, properties[i]))
def showBss(bss):
net_obj = bus.get_object(WPAS_DBUS_SERVICE, bss)
@@ -80,48 +80,48 @@ def showBss(bss):
else:
maxrate = 0
- print " %s :: ssid='%s' wpa=%s wpa2=%s signal=%d rate=%d freq=%d" % (bssid, ssid, wpa, wpa2, signal, maxrate, freq)
+ print(" %s :: ssid='%s' wpa=%s wpa2=%s signal=%d rate=%d freq=%d" % (bssid, ssid, wpa, wpa2, signal, maxrate, freq))
def scanDone(success):
gobject.MainLoop().quit()
- print "Scan done: success=%s" % success
+ print("Scan done: success=%s" % success)
def scanDone2(success, path=None):
- print "Scan done: success=%s [path=%s]" % (success, path)
+ print("Scan done: success=%s [path=%s]" % (success, path))
def bssAdded(bss, properties):
- print "BSS added: %s" % (bss)
+ print("BSS added: %s" % (bss))
showBss(bss)
def bssRemoved(bss):
- print "BSS removed: %s" % (bss)
+ print("BSS removed: %s" % (bss))
def blobAdded(blob):
- print "BlobAdded(%s)" % (blob)
+ print("BlobAdded(%s)" % (blob))
def blobRemoved(blob):
- print "BlobRemoved(%s)" % (blob)
+ print("BlobRemoved(%s)" % (blob))
def networkAdded(network, properties):
- print "NetworkAdded(%s)" % (network)
+ print("NetworkAdded(%s)" % (network))
def networkRemoved(network):
- print "NetworkRemoved(%s)" % (network)
+ print("NetworkRemoved(%s)" % (network))
def networkSelected(network):
- print "NetworkSelected(%s)" % (network)
+ print("NetworkSelected(%s)" % (network))
def propertiesChangedInterface(properties):
for i in properties:
- print "PropertiesChanged(interface): %s=%s" % (i, properties[i])
+ print("PropertiesChanged(interface): %s=%s" % (i, properties[i]))
def propertiesChangedBss(properties):
for i in properties:
- print "PropertiesChanged(BSS): %s=%s" % (i, properties[i])
+ print("PropertiesChanged(BSS): %s=%s" % (i, properties[i]))
def propertiesChangedNetwork(properties):
for i in properties:
- print "PropertiesChanged(Network): %s=%s" % (i, properties[i])
+ print("PropertiesChanged(Network): %s=%s" % (i, properties[i]))
def main():
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
diff --git a/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new-wps.py b/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new-wps.py
index b8863858fe8c..7d87b1efd5dc 100755
--- a/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new-wps.py
+++ b/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new-wps.py
@@ -15,23 +15,23 @@ WPAS_DBUS_WPS_INTERFACE = "fi.w1.wpa_supplicant1.Interface.WPS"
def propertiesChanged(properties):
if properties.has_key("State"):
- print "PropertiesChanged: State: %s" % (properties["State"])
+ print("PropertiesChanged: State: %s" % (properties["State"]))
def scanDone(success):
- print "Scan done: success=%s" % success
+ print("Scan done: success=%s" % success)
def bssAdded(bss, properties):
- print "BSS added: %s" % (bss)
+ print("BSS added: %s" % (bss))
def bssRemoved(bss):
- print "BSS removed: %s" % (bss)
+ print("BSS removed: %s" % (bss))
def wpsEvent(name, args):
- print "WPS event: %s" % (name)
- print args
+ print("WPS event: %s" % (name))
+ print(args)
def credentials(cred):
- print "WPS credentials: %s" % (cred)
+ print("WPS credentials: %s" % (cred))
def main():
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
@@ -40,7 +40,7 @@ def main():
wpas_obj = bus.get_object(WPAS_DBUS_SERVICE, WPAS_DBUS_OPATH)
if len(sys.argv) != 2:
- print "Missing ifname argument"
+ print("Missing ifname argument")
os._exit(1)
wpas = dbus.Interface(wpas_obj, WPAS_DBUS_INTERFACE)
diff --git a/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new.py b/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new.py
index 25072ce9a2df..6bf74ae44122 100755
--- a/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new.py
+++ b/contrib/wpa/wpa_supplicant/examples/wpas-dbus-new.py
@@ -31,11 +31,11 @@ def list_interfaces(wpas_obj):
if_obj = bus.get_object(WPAS_DBUS_SERVICE, path)
ifname = if_obj.Get(WPAS_DBUS_INTERFACES_INTERFACE, 'Ifname',
dbus_interface=dbus.PROPERTIES_IFACE)
- print ifname
+ print(ifname)
def propertiesChanged(properties):
if properties.has_key("State"):
- print "PropertiesChanged: State: %s" % (properties["State"])
+ print("PropertiesChanged: State: %s" % (properties["State"]))
def showBss(bss):
net_obj = bus.get_object(WPAS_DBUS_SERVICE, bss)
@@ -73,25 +73,25 @@ def showBss(bss):
else:
maxrate = 0
- print " %s :: ssid='%s' wpa=%s wpa2=%s signal=%d rate=%d freq=%d" % (bssid, ssid, wpa, wpa2, signal, maxrate, freq)
+ print(" %s :: ssid='%s' wpa=%s wpa2=%s signal=%d rate=%d freq=%d" % (bssid, ssid, wpa, wpa2, signal, maxrate, freq))
def scanDone(success):
- print "Scan done: success=%s" % success
+ print("Scan done: success=%s" % success)
res = if_obj.Get(WPAS_DBUS_INTERFACES_INTERFACE, 'BSSs',
dbus_interface=dbus.PROPERTIES_IFACE)
- print "Scanned wireless networks:"
+ print("Scanned wireless networks:")
for opath in res:
- print opath
+ print(opath)
showBss(opath)
def bssAdded(bss, properties):
- print "BSS added: %s" % (bss)
+ print("BSS added: %s" % (bss))
showBss(bss)
def bssRemoved(bss):
- print "BSS removed: %s" % (bss)
+ print("BSS removed: %s" % (bss))
def main():
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
@@ -123,14 +123,14 @@ def main():
path = None
try:
path = wpas.GetInterface(ifname)
- except dbus.DBusException, exc:
+ except dbus.DBusException as exc:
if not str(exc).startswith("fi.w1.wpa_supplicant1.InterfaceUnknown:"):
raise exc
try:
path = wpas.CreateInterface({'Ifname': ifname, 'Driver': 'test'})
time.sleep(1)
- except dbus.DBusException, exc:
+ except dbus.DBusException as exc:
if not str(exc).startswith("fi.w1.wpa_supplicant1.InterfaceExists:"):
raise exc
diff --git a/contrib/wpa/wpa_supplicant/examples/wpas-test.py b/contrib/wpa/wpa_supplicant/examples/wpas-test.py
deleted file mode 100755
index fd7f73d428b8..000000000000
--- a/contrib/wpa/wpa_supplicant/examples/wpas-test.py
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/usr/bin/python
-
-import dbus
-import sys, os
-import time
-
-WPAS_DBUS_SERVICE = "fi.epitest.hostap.WPASupplicant"
-WPAS_DBUS_INTERFACE = "fi.epitest.hostap.WPASupplicant"
-WPAS_DBUS_OPATH = "/fi/epitest/hostap/WPASupplicant"
-
-WPAS_DBUS_INTERFACES_INTERFACE = "fi.epitest.hostap.WPASupplicant.Interface"
-WPAS_DBUS_INTERFACES_OPATH = "/fi/epitest/hostap/WPASupplicant/Interfaces"
-WPAS_DBUS_BSSID_INTERFACE = "fi.epitest.hostap.WPASupplicant.BSSID"
-
-def byte_array_to_string(s):
- import urllib
- r = ""
- for c in s:
- if c >= 32 and c < 127:
- r += "%c" % c
- else:
- r += urllib.quote(chr(c))
- return r
-
-def main():
- if len(sys.argv) != 2:
- print "Usage: wpas-test.py <interface>"
- os._exit(1)
-
- ifname = sys.argv[1]
-
- bus = dbus.SystemBus()
- wpas_obj = bus.get_object(WPAS_DBUS_SERVICE, WPAS_DBUS_OPATH)
- wpas = dbus.Interface(wpas_obj, WPAS_DBUS_INTERFACE)
-
- # See if wpa_supplicant already knows about this interface
- path = None
- try:
- path = wpas.getInterface(ifname)
- except dbus.dbus_bindings.DBusException, exc:
- if str(exc) != "wpa_supplicant knows nothing about this interface.":
- raise exc
- try:
- path = wpas.addInterface(ifname, {'driver': dbus.Variant('wext')})
- except dbus.dbus_bindings.DBusException, exc:
- if str(exc) != "wpa_supplicant already controls this interface.":
- raise exc
-
- if_obj = bus.get_object(WPAS_DBUS_SERVICE, path)
- iface = dbus.Interface(if_obj, WPAS_DBUS_INTERFACES_INTERFACE)
- iface.scan()
- # Should really wait for the "scanResults" signal instead of sleeping
- time.sleep(5)
- res = iface.scanResults()
-
- print "Scanned wireless networks:"
- for opath in res:
- net_obj = bus.get_object(WPAS_DBUS_SERVICE, opath)
- net = dbus.Interface(net_obj, WPAS_DBUS_BSSID_INTERFACE)
- props = net.properties()
-
- # Convert the byte-array for SSID and BSSID to printable strings
- bssid = ""
- for item in props["bssid"]:
- bssid = bssid + ":%02x" % item
- bssid = bssid[1:]
- ssid = byte_array_to_string(props["ssid"])
- wpa = "no"
- if props.has_key("wpaie"):
- wpa = "yes"
- wpa2 = "no"
- if props.has_key("rsnie"):
- wpa2 = "yes"
- freq = 0
- if props.has_key("frequency"):
- freq = props["frequency"]
- caps = props["capabilities"]
- qual = props["quality"]
- level = props["level"]
- noise = props["noise"]
- maxrate = props["maxrate"] / 1000000
-
- print " %s :: ssid='%s' wpa=%s wpa2=%s quality=%d%% rate=%d freq=%d" % (bssid, ssid, wpa, wpa2, qual, maxrate, freq)
-
- wpas.removeInterface(dbus.ObjectPath(path))
- # Should fail here with unknown interface error
- iface.scan()
-
-if __name__ == "__main__":
- main()
-
diff --git a/contrib/wpa/wpa_supplicant/examples/wps-ap-cli b/contrib/wpa/wpa_supplicant/examples/wps-ap-cli
index cc2cff2ebc24..15d913ef1fae 100755
--- a/contrib/wpa/wpa_supplicant/examples/wps-ap-cli
+++ b/contrib/wpa/wpa_supplicant/examples/wps-ap-cli
@@ -14,12 +14,12 @@ pbc()
enter_pin()
{
echo "Enter a PIN from a station to be enrolled to the network."
- echo -n "Enrollee PIN: "
+ printf "Enrollee PIN: "
read pin
cpin=`$CLI wps_check_pin "$pin" | tail -1`
if [ "$cpin" = "FAIL-CHECKSUM" ]; then
echo "Checksum digit is not valid"
- echo -n "Do you want to use this PIN (y/n)? "
+ printf "Do you want to use this PIN (y/n)? "
read resp
case "$resp" in
y*)
@@ -52,7 +52,7 @@ main_menu()
echo "3: Show current configuration"
echo "0: Exit wps-ap-cli"
- echo -n "Command: "
+ printf "Command: "
read cmd
case "$cmd" in
diff --git a/contrib/wpa/wpa_supplicant/examples/wps-nfc.py b/contrib/wpa/wpa_supplicant/examples/wps-nfc.py
index 7459eb9ae574..bb458fb37a84 100755
--- a/contrib/wpa/wpa_supplicant/examples/wps-nfc.py
+++ b/contrib/wpa/wpa_supplicant/examples/wps-nfc.py
@@ -30,7 +30,7 @@ summary_file = None
success_file = None
def summary(txt):
- print txt
+ print(txt)
if summary_file:
with open(summary_file, 'a') as f:
f.write(txt + "\n")
@@ -46,19 +46,19 @@ def wpas_connect():
if os.path.isdir(wpas_ctrl):
try:
ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
- except OSError, error:
- print "Could not find wpa_supplicant: ", error
+ except OSError as error:
+ print("Could not find wpa_supplicant: ", error)
return None
if len(ifaces) < 1:
- print "No wpa_supplicant control interface found"
+ print("No wpa_supplicant control interface found")
return None
for ctrl in ifaces:
try:
wpas = wpaspy.Ctrl(ctrl)
return wpas
- except Exception, e:
+ except Exception as e:
pass
return None
@@ -163,22 +163,22 @@ class HandoverServer(nfc.handover.HandoverServer):
self.ho_server_processing = True
summary("HandoverServer - request received")
try:
- print "Parsed handover request: " + request.pretty()
- except Exception, e:
- print e
+ print("Parsed handover request: " + request.pretty())
+ except Exception as e:
+ print(e)
sel = nfc.ndef.HandoverSelectMessage(version="1.2")
for carrier in request.carriers:
- print "Remote carrier type: " + carrier.type
+ print("Remote carrier type: " + carrier.type)
if carrier.type == "application/vnd.wfa.wsc":
summary("WPS carrier type match - add WPS carrier record")
data = wpas_get_handover_sel(self.uuid)
if data is None:
summary("Could not get handover select carrier record from wpa_supplicant")
continue
- print "Handover select carrier record from wpa_supplicant:"
- print data.encode("hex")
+ print("Handover select carrier record from wpa_supplicant:")
+ print(data.encode("hex"))
self.sent_carrier = data
if "OK" in wpas_report_handover(carrier.record, self.sent_carrier, "RESP"):
success_report("Handover reported successfully (responder)")
@@ -188,12 +188,12 @@ class HandoverServer(nfc.handover.HandoverServer):
message = nfc.ndef.Message(data);
sel.add_carrier(message[0], "active", message[1:])
- print "Handover select:"
+ print("Handover select:")
try:
- print sel.pretty()
- except Exception, e:
- print e
- print str(sel).encode("hex")
+ print(sel.pretty())
+ except Exception as e:
+ print(e)
+ print(str(sel).encode("hex"))
summary("Sending handover select")
self.success = True
@@ -207,19 +207,19 @@ def wps_handover_init(llc):
if (data == None):
summary("Could not get handover request carrier record from wpa_supplicant")
return
- print "Handover request carrier record from wpa_supplicant: " + data.encode("hex")
+ print("Handover request carrier record from wpa_supplicant: " + data.encode("hex"))
message = nfc.ndef.HandoverRequestMessage(version="1.2")
message.nonce = random.randint(0, 0xffff)
datamsg = nfc.ndef.Message(data)
message.add_carrier(datamsg[0], "active", datamsg[1:])
- print "Handover request:"
+ print("Handover request:")
try:
- print message.pretty()
- except Exception, e:
- print e
- print str(message).encode("hex")
+ print(message.pretty())
+ except Exception as e:
+ print(e)
+ print(str(message).encode("hex"))
client = nfc.handover.HandoverClient(llc)
try:
@@ -230,7 +230,7 @@ def wps_handover_init(llc):
summary("Handover connection refused")
client.close()
return
- except Exception, e:
+ except Exception as e:
summary("Other exception: " + str(e))
client.close()
return
@@ -253,23 +253,23 @@ def wps_handover_init(llc):
client.close()
return
- print "Received message"
+ print("Received message")
try:
- print message.pretty()
- except Exception, e:
- print e
- print str(message).encode("hex")
+ print(message.pretty())
+ except Exception as e:
+ print(e)
+ print(str(message).encode("hex"))
message = nfc.ndef.HandoverSelectMessage(message)
summary("Handover select received")
try:
- print message.pretty()
- except Exception, e:
- print e
+ print(message.pretty())
+ except Exception as e:
+ print(e)
for carrier in message.carriers:
- print "Remote carrier type: " + carrier.type
+ print("Remote carrier type: " + carrier.type)
if carrier.type == "application/vnd.wfa.wsc":
- print "WPS carrier type match - send to wpa_supplicant"
+ print("WPS carrier type match - send to wpa_supplicant")
if "OK" in wpas_report_handover(data, carrier.record, "INIT"):
success_report("Handover reported successfully (initiator)")
else:
@@ -278,9 +278,9 @@ def wps_handover_init(llc):
#wifi = nfc.ndef.WifiConfigRecord(carrier.record)
#print wifi.pretty()
- print "Remove peer"
+ print("Remove peer")
client.close()
- print "Done with handover"
+ print("Done with handover")
global only_one
if only_one:
global continue_loop
@@ -288,7 +288,7 @@ def wps_handover_init(llc):
global no_wait
if no_wait:
- print "Trying to exit.."
+ print("Trying to exit..")
global terminate_now
terminate_now = True
@@ -296,7 +296,7 @@ def wps_tag_read(tag, wait_remove=True):
success = False
if len(tag.ndef.message):
for record in tag.ndef.message:
- print "record type " + record.type
+ print("record type " + record.type)
if record.type == "application/vnd.wfa.wsc":
summary("WPS tag - send to wpa_supplicant")
success = wpas_tag_read(tag.ndef.message)
@@ -308,7 +308,7 @@ def wps_tag_read(tag, wait_remove=True):
success_report("Tag read succeeded")
if wait_remove:
- print "Remove tag"
+ print("Remove tag")
while tag.is_present:
time.sleep(0.1)
@@ -320,7 +320,7 @@ def rdwr_connected_write(tag):
global write_data
tag.ndef.message = str(write_data)
success_report("Tag write succeeded")
- print "Done - remove tag"
+ print("Done - remove tag")
global only_one
if only_one:
global continue_loop
@@ -330,41 +330,41 @@ def rdwr_connected_write(tag):
time.sleep(0.1)
def wps_write_config_tag(clf, id=None, wait_remove=True):
- print "Write WPS config token"
+ print("Write WPS config token")
global write_data, write_wait_remove
write_wait_remove = wait_remove
write_data = wpas_get_config_token(id)
if write_data == None:
- print "Could not get WPS config token from wpa_supplicant"
+ print("Could not get WPS config token from wpa_supplicant")
sys.exit(1)
return
- print "Touch an NFC tag"
+ print("Touch an NFC tag")
clf.connect(rdwr={'on-connect': rdwr_connected_write})
def wps_write_er_config_tag(clf, uuid, wait_remove=True):
- print "Write WPS ER config token"
+ print("Write WPS ER config token")
global write_data, write_wait_remove
write_wait_remove = wait_remove
write_data = wpas_get_er_config_token(uuid)
if write_data == None:
- print "Could not get WPS config token from wpa_supplicant"
+ print("Could not get WPS config token from wpa_supplicant")
return
- print "Touch an NFC tag"
+ print("Touch an NFC tag")
clf.connect(rdwr={'on-connect': rdwr_connected_write})
def wps_write_password_tag(clf, wait_remove=True):
- print "Write WPS password token"
+ print("Write WPS password token")
global write_data, write_wait_remove
write_wait_remove = wait_remove
write_data = wpas_get_password_token()
if write_data == None:
- print "Could not get WPS password token from wpa_supplicant"
+ print("Could not get WPS password token from wpa_supplicant")
return
- print "Touch an NFC tag"
+ print("Touch an NFC tag")
clf.connect(rdwr={'on-connect': rdwr_connected_write})
@@ -373,11 +373,11 @@ def rdwr_connected(tag):
summary("Tag connected: " + str(tag))
if tag.ndef:
- print "NDEF tag: " + tag.type
+ print("NDEF tag: " + tag.type)
try:
- print tag.ndef.message.pretty()
- except Exception, e:
- print e
+ print(tag.ndef.message.pretty())
+ except Exception as e:
+ print(e)
success = wps_tag_read(tag, not only_one)
if only_one and success:
global continue_loop
@@ -393,7 +393,7 @@ def llcp_worker(llc):
global arg_uuid
if arg_uuid is None:
wps_handover_init(llc)
- print "Exiting llcp_worker thread"
+ print("Exiting llcp_worker thread")
return
global srv
@@ -405,19 +405,19 @@ def llcp_worker(llc):
def llcp_startup(clf, llc):
global arg_uuid
if arg_uuid:
- print "Start LLCP server"
+ print("Start LLCP server")
global srv
srv = HandoverServer(llc)
if arg_uuid is "ap":
- print "Trying to handle WPS handover"
+ print("Trying to handle WPS handover")
srv.uuid = None
else:
- print "Trying to handle WPS handover with AP " + arg_uuid
+ print("Trying to handle WPS handover with AP " + arg_uuid)
srv.uuid = arg_uuid
return llc
def llcp_connected(llc):
- print "P2P LLCP connected"
+ print("P2P LLCP connected")
global wait_connection
wait_connection = False
global arg_uuid
@@ -426,7 +426,7 @@ def llcp_connected(llc):
srv.start()
else:
threading.Thread(target=llcp_worker, args=(llc,)).start()
- print "llcp_connected returning"
+ print("llcp_connected returning")
return True
@@ -482,7 +482,7 @@ def main():
try:
if not clf.open("usb"):
- print "Could not open connection with an NFC device"
+ print("Could not open connection with an NFC device")
raise SystemExit
if args.command == "write-config":
@@ -499,7 +499,7 @@ def main():
global continue_loop
while continue_loop:
- print "Waiting for a tag or peer to be touched"
+ print("Waiting for a tag or peer to be touched")
wait_connection = True
try:
if not clf.connect(rdwr={'on-connect': rdwr_connected},
@@ -507,8 +507,8 @@ def main():
'on-connect': llcp_connected},
terminate=terminate_loop):
break
- except Exception, e:
- print "clf.connect failed"
+ except Exception as e:
+ print("clf.connect failed")
global srv
if only_one and srv and srv.success:
diff --git a/contrib/wpa/wpa_supplicant/gas_query.c b/contrib/wpa/wpa_supplicant/gas_query.c
index 691de0345d13..8e977a3eccb3 100644
--- a/contrib/wpa/wpa_supplicant/gas_query.c
+++ b/contrib/wpa/wpa_supplicant/gas_query.c
@@ -42,6 +42,7 @@ struct gas_query_pending {
unsigned int wait_comeback:1;
unsigned int offchannel_tx_started:1;
unsigned int retry:1;
+ unsigned int wildcard_bssid:1;
int freq;
u16 status_code;
struct wpabuf *req;
@@ -53,6 +54,7 @@ struct gas_query_pending {
const struct wpabuf *adv_proto,
const struct wpabuf *resp, u16 status_code);
void *ctx;
+ u8 sa[ETH_ALEN];
};
/**
@@ -63,6 +65,9 @@ struct gas_query {
struct dl_list pending; /* struct gas_query_pending */
struct gas_query_pending *current;
struct wpa_radio_work *work;
+ struct os_reltime last_mac_addr_rand;
+ int last_rand_sa_type;
+ u8 rand_addr[ETH_ALEN];
};
@@ -117,6 +122,8 @@ static const char * gas_result_txt(enum gas_query_result result)
return "PEER_ERROR";
case GAS_QUERY_INTERNAL_ERROR:
return "INTERNAL_ERROR";
+ case GAS_QUERY_STOPPED:
+ return "STOPPED";
case GAS_QUERY_DELETED_AT_DEINIT:
return "DELETED_AT_DEINIT";
}
@@ -239,10 +246,17 @@ static void gas_query_tx_status(struct wpa_supplicant *wpa_s,
}
os_get_reltime(&query->last_oper);
- if (result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
+ if (result == OFFCHANNEL_SEND_ACTION_SUCCESS ||
+ result == OFFCHANNEL_SEND_ACTION_NO_ACK) {
eloop_cancel_timeout(gas_query_timeout, gas, query);
- eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0,
- gas_query_timeout, gas, query);
+ if (result == OFFCHANNEL_SEND_ACTION_NO_ACK) {
+ wpa_printf(MSG_DEBUG, "GAS: No ACK to GAS request");
+ eloop_register_timeout(0, 250000,
+ gas_query_timeout, gas, query);
+ } else {
+ eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0,
+ gas_query_timeout, gas, query);
+ }
if (query->wait_comeback && !query->retry) {
eloop_cancel_timeout(gas_query_rx_comeback_timeout,
gas, query);
@@ -258,7 +272,7 @@ static void gas_query_tx_status(struct wpa_supplicant *wpa_s,
}
-static int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
+int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
{
if (wpa_s->current_ssid == NULL ||
wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
@@ -278,8 +292,9 @@ static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
};
wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u "
- "freq=%d prot=%d", MAC2STR(query->addr),
- (unsigned int) wpabuf_len(req), query->freq, prot);
+ "freq=%d prot=%d using src addr " MACSTR,
+ MAC2STR(query->addr), (unsigned int) wpabuf_len(req),
+ query->freq, prot, MAC2STR(query->sa));
if (prot) {
u8 *categ = wpabuf_mhead_u8(req);
*categ = WLAN_ACTION_PROTECTED_DUAL;
@@ -288,17 +303,20 @@ static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
if (gas->wpa_s->max_remain_on_chan &&
wait_time > gas->wpa_s->max_remain_on_chan)
wait_time = gas->wpa_s->max_remain_on_chan;
- if (!gas->wpa_s->conf->gas_address3 ||
- (gas->wpa_s->current_ssid &&
- gas->wpa_s->wpa_state >= WPA_ASSOCIATED &&
- os_memcmp(query->addr, gas->wpa_s->bssid, ETH_ALEN) == 0))
+ if (!query->wildcard_bssid &&
+ (!gas->wpa_s->conf->gas_address3 ||
+ (gas->wpa_s->current_ssid &&
+ gas->wpa_s->wpa_state >= WPA_ASSOCIATED &&
+ os_memcmp(query->addr, gas->wpa_s->bssid, ETH_ALEN) == 0)))
bssid = query->addr;
else
bssid = wildcard_bssid;
+
res = offchannel_send_action(gas->wpa_s, query->freq, query->addr,
- gas->wpa_s->own_addr, bssid,
- wpabuf_head(req), wpabuf_len(req),
- wait_time, gas_query_tx_status, 0);
+ query->sa, bssid, wpabuf_head(req),
+ wpabuf_len(req), wait_time,
+ gas_query_tx_status, 0);
+
if (res == 0)
query->offchannel_tx_started = 1;
return res;
@@ -407,6 +425,7 @@ static void gas_query_rx_initial(struct gas_query *gas,
}
if (comeback_delay) {
+ eloop_cancel_timeout(gas_query_timeout, gas, query);
query->wait_comeback = 1;
gas_query_tx_comeback_req_delay(gas, query, comeback_delay);
return;
@@ -724,6 +743,58 @@ static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst)
}
+static int gas_query_set_sa(struct gas_query *gas,
+ struct gas_query_pending *query)
+{
+ struct wpa_supplicant *wpa_s = gas->wpa_s;
+ struct os_reltime now;
+
+ if (!wpa_s->conf->gas_rand_mac_addr ||
+ !(wpa_s->current_bss ?
+ (wpa_s->drv_flags &
+ WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA_CONNECTED) :
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA))) {
+ /* Use own MAC address as the transmitter address */
+ os_memcpy(query->sa, wpa_s->own_addr, ETH_ALEN);
+ return 0;
+ }
+
+ os_get_reltime(&now);
+
+ if (wpa_s->conf->gas_rand_mac_addr == gas->last_rand_sa_type &&
+ gas->last_mac_addr_rand.sec != 0 &&
+ !os_reltime_expired(&now, &gas->last_mac_addr_rand,
+ wpa_s->conf->gas_rand_addr_lifetime)) {
+ wpa_printf(MSG_DEBUG,
+ "GAS: Use the previously selected random transmitter address "
+ MACSTR, MAC2STR(gas->rand_addr));
+ os_memcpy(query->sa, gas->rand_addr, ETH_ALEN);
+ return 0;
+ }
+
+ if (wpa_s->conf->gas_rand_mac_addr == 1 &&
+ random_mac_addr(gas->rand_addr) < 0) {
+ wpa_printf(MSG_ERROR, "GAS: Failed to get random address");
+ return -1;
+ }
+
+ if (wpa_s->conf->gas_rand_mac_addr == 2 &&
+ random_mac_addr_keep_oui(gas->rand_addr) < 0) {
+ wpa_printf(MSG_ERROR,
+ "GAS: Failed to get random address with same OUI");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "GAS: Use a new random transmitter address "
+ MACSTR, MAC2STR(gas->rand_addr));
+ os_memcpy(query->sa, gas->rand_addr, ETH_ALEN);
+ os_get_reltime(&gas->last_mac_addr_rand);
+ gas->last_rand_sa_type = wpa_s->conf->gas_rand_mac_addr;
+
+ return 0;
+}
+
+
/**
* gas_query_req - Request a GAS query
* @gas: GAS query data from gas_query_init()
@@ -736,7 +807,7 @@ static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst)
* Returns: dialog token (>= 0) on success or -1 on failure
*/
int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
- struct wpabuf *req,
+ int wildcard_bssid, struct wpabuf *req,
void (*cb)(void *ctx, const u8 *dst, u8 dialog_token,
enum gas_query_result result,
const struct wpabuf *adv_proto,
@@ -758,8 +829,13 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
return -1;
query->gas = gas;
+ if (gas_query_set_sa(gas, query)) {
+ os_free(query);
+ return -1;
+ }
os_memcpy(query->addr, dst, ETH_ALEN);
query->dialog_token = dialog_token;
+ query->wildcard_bssid = !!wildcard_bssid;
query->freq = freq;
query->cb = cb;
query->ctx = ctx;
@@ -781,3 +857,27 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
return dialog_token;
}
+
+
+int gas_query_stop(struct gas_query *gas, u8 dialog_token)
+{
+ struct gas_query_pending *query;
+
+ dl_list_for_each(query, &gas->pending, struct gas_query_pending, list) {
+ if (query->dialog_token == dialog_token) {
+ if (!gas->work) {
+ /* The pending radio work has not yet been
+ * started, but the pending entry has a
+ * reference to the soon to be freed query.
+ * Need to remove that radio work now to avoid
+ * leaving behind a reference to freed memory.
+ */
+ radio_remove_pending_work(gas->wpa_s, query);
+ }
+ gas_query_done(gas, query, GAS_QUERY_STOPPED);
+ return 0;
+ }
+ }
+
+ return -1;
+}
diff --git a/contrib/wpa/wpa_supplicant/gas_query.h b/contrib/wpa/wpa_supplicant/gas_query.h
index ef82097e2424..d2b455442f0a 100644
--- a/contrib/wpa/wpa_supplicant/gas_query.h
+++ b/contrib/wpa/wpa_supplicant/gas_query.h
@@ -19,6 +19,7 @@ void gas_query_deinit(struct gas_query *gas);
int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
const u8 *bssid, u8 categ, const u8 *data, size_t len,
int freq);
+int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr);
/**
* enum gas_query_result - GAS query result
@@ -29,16 +30,18 @@ enum gas_query_result {
GAS_QUERY_TIMEOUT,
GAS_QUERY_PEER_ERROR,
GAS_QUERY_INTERNAL_ERROR,
+ GAS_QUERY_STOPPED,
GAS_QUERY_DELETED_AT_DEINIT
};
int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
- struct wpabuf *req,
+ int wildcard_bssid, struct wpabuf *req,
void (*cb)(void *ctx, const u8 *dst, u8 dialog_token,
enum gas_query_result result,
const struct wpabuf *adv_proto,
const struct wpabuf *resp, u16 status_code),
void *ctx);
+int gas_query_stop(struct gas_query *gas, u8 dialog_token);
#else /* CONFIG_GAS */
diff --git a/contrib/wpa/wpa_supplicant/hs20_supplicant.c b/contrib/wpa/wpa_supplicant/hs20_supplicant.c
index e88f147bbd1b..cb236df18d86 100644
--- a/contrib/wpa/wpa_supplicant/hs20_supplicant.c
+++ b/contrib/wpa/wpa_supplicant/hs20_supplicant.c
@@ -49,9 +49,12 @@ struct osu_provider {
u8 bssid[ETH_ALEN];
u8 osu_ssid[SSID_MAX_LEN];
u8 osu_ssid_len;
+ u8 osu_ssid2[SSID_MAX_LEN];
+ u8 osu_ssid2_len;
char server_uri[256];
u32 osu_methods; /* bit 0 = OMA-DM, bit 1 = SOAP-XML SPP */
char osu_nai[256];
+ char osu_nai2[256];
struct osu_lang_string friendly_name[OSU_MAX_ITEMS];
size_t friendly_name_count;
struct osu_lang_string serv_desc[OSU_MAX_ITEMS];
@@ -92,8 +95,7 @@ void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s)
return;
}
- /* Check if Proxy ARP is enabled (2nd byte in the IE) */
- if (ext_capa[3] & BIT(4))
+ if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_PROXY_ARP))
filter |= WPA_DATA_FRAME_FILTER_FLAG_ARP |
WPA_DATA_FRAME_FILTER_FLAG_NA;
@@ -101,15 +103,22 @@ void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s)
}
-void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id)
+void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id, int ap_release)
{
+ int release;
u8 conf;
+ release = (HS20_VERSION >> 4) + 1;
+ if (ap_release > 0 && release > ap_release)
+ release = ap_release;
+ if (release < 2)
+ pps_mo_id = -1;
+
wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
wpabuf_put_u8(buf, pps_mo_id >= 0 ? 7 : 5);
wpabuf_put_be24(buf, OUI_WFA);
wpabuf_put_u8(buf, HS20_INDICATION_OUI_TYPE);
- conf = HS20_VERSION;
+ conf = (release - 1) << 4;
if (pps_mo_id >= 0)
conf |= HS20_PPS_MO_ID_PRESENT;
wpabuf_put_u8(buf, conf);
@@ -118,6 +127,37 @@ void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id)
}
+void wpas_hs20_add_roam_cons_sel(struct wpabuf *buf,
+ const struct wpa_ssid *ssid)
+{
+ if (!ssid->roaming_consortium_selection ||
+ !ssid->roaming_consortium_selection_len)
+ return;
+
+ wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
+ wpabuf_put_u8(buf, 4 + ssid->roaming_consortium_selection_len);
+ wpabuf_put_be24(buf, OUI_WFA);
+ wpabuf_put_u8(buf, HS20_ROAMING_CONS_SEL_OUI_TYPE);
+ wpabuf_put_data(buf, ssid->roaming_consortium_selection,
+ ssid->roaming_consortium_selection_len);
+}
+
+
+int get_hs20_version(struct wpa_bss *bss)
+{
+ const u8 *ie;
+
+ if (!bss)
+ return 0;
+
+ ie = wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE);
+ if (!ie || ie[1] < 5)
+ return 0;
+
+ return ((ie[6] >> 4) & 0x0f) + 1;
+}
+
+
int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
struct wpa_bss *bss)
{
@@ -248,7 +288,7 @@ int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
if (buf == NULL)
return -1;
- res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s);
+ res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s);
if (res < 0) {
wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
wpabuf_free(buf);
@@ -391,7 +431,7 @@ static void hs20_set_osu_access_permission(const char *osu_dir,
return;
}
- if (chown(fname, statbuf.st_uid, statbuf.st_gid) < 0) {
+ if (lchown(fname, statbuf.st_uid, statbuf.st_gid) < 0) {
wpa_printf(MSG_WARNING, "Cannot change the ownership for %s",
fname);
}
@@ -429,10 +469,9 @@ static int hs20_process_icon_binary_file(struct wpa_supplicant *wpa_s,
dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
if (icon->dialog_token == dialog_token && !icon->image &&
os_memcmp(icon->bssid, sa, ETH_ALEN) == 0) {
- icon->image = os_malloc(slen);
+ icon->image = os_memdup(pos, slen);
if (!icon->image)
return -1;
- os_memcpy(icon->image, pos, slen);
icon->image_len = slen;
hs20_remove_duplicate_icons(wpa_s, icon);
wpa_msg(wpa_s, MSG_INFO,
@@ -646,6 +685,25 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
wpa_s, NULL);
}
break;
+ case HS20_STYPE_OPERATOR_ICON_METADATA:
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
+ " Operator Icon Metadata", MAC2STR(sa));
+ wpa_hexdump(MSG_DEBUG, "Operator Icon Metadata", pos, slen);
+ if (anqp) {
+ wpabuf_free(anqp->hs20_operator_icon_metadata);
+ anqp->hs20_operator_icon_metadata =
+ wpabuf_alloc_copy(pos, slen);
+ }
+ break;
+ case HS20_STYPE_OSU_PROVIDERS_NAI_LIST:
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
+ " OSU Providers NAI List", MAC2STR(sa));
+ if (anqp) {
+ wpabuf_free(anqp->hs20_osu_providers_nai_list);
+ anqp->hs20_osu_providers_nai_list =
+ wpabuf_alloc_copy(pos, slen);
+ }
+ break;
default:
wpa_printf(MSG_DEBUG, "HS20: Unsupported subtype %u", subtype);
break;
@@ -725,8 +783,15 @@ static void hs20_osu_fetch_done(struct wpa_supplicant *wpa_s)
wpa_ssid_txt(osu->osu_ssid,
osu->osu_ssid_len));
}
+ if (osu->osu_ssid2_len) {
+ fprintf(f, "osu_ssid2=%s\n",
+ wpa_ssid_txt(osu->osu_ssid2,
+ osu->osu_ssid2_len));
+ }
if (osu->osu_nai[0])
fprintf(f, "osu_nai=%s\n", osu->osu_nai);
+ if (osu->osu_nai2[0])
+ fprintf(f, "osu_nai2=%s\n", osu->osu_nai2);
for (j = 0; j < osu->friendly_name_count; j++) {
fprintf(f, "friendly_name=%s:%s\n",
osu->friendly_name[j].lang,
@@ -790,6 +855,7 @@ void hs20_next_osu_icon(struct wpa_supplicant *wpa_s)
static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
const u8 *osu_ssid, u8 osu_ssid_len,
+ const u8 *osu_ssid2, u8 osu_ssid2_len,
const u8 *pos, size_t len)
{
struct osu_provider *prov;
@@ -811,6 +877,9 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
os_memcpy(prov->bssid, bss->bssid, ETH_ALEN);
os_memcpy(prov->osu_ssid, osu_ssid, osu_ssid_len);
prov->osu_ssid_len = osu_ssid_len;
+ if (osu_ssid2)
+ os_memcpy(prov->osu_ssid2, osu_ssid2, osu_ssid2_len);
+ prov->osu_ssid2_len = osu_ssid2_len;
/* OSU Friendly Name Length */
if (end - pos < 2) {
@@ -992,18 +1061,30 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
struct wpabuf *prov_anqp;
const u8 *pos, *end;
u16 len;
- const u8 *osu_ssid;
- u8 osu_ssid_len;
+ const u8 *osu_ssid, *osu_ssid2;
+ u8 osu_ssid_len, osu_ssid2_len;
u8 num_providers;
hs20_free_osu_prov(wpa_s);
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
+ struct wpa_ie_data data;
+ const u8 *ie;
+
if (bss->anqp == NULL)
continue;
prov_anqp = bss->anqp->hs20_osu_providers_list;
if (prov_anqp == NULL)
continue;
+ ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+ if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &data) == 0 &&
+ (data.key_mgmt & WPA_KEY_MGMT_OSEN)) {
+ osu_ssid2 = bss->ssid;
+ osu_ssid2_len = bss->ssid_len;
+ } else {
+ osu_ssid2 = NULL;
+ osu_ssid2_len = 0;
+ }
wpa_printf(MSG_DEBUG, "HS 2.0: Parsing OSU Providers list from "
MACSTR, MAC2STR(bss->bssid));
wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers list",
@@ -1045,7 +1126,8 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
if (len > (unsigned int) (end - pos))
break;
hs20_osu_add_prov(wpa_s, bss, osu_ssid,
- osu_ssid_len, pos, len);
+ osu_ssid_len, osu_ssid2,
+ osu_ssid2_len, pos, len);
pos += len;
}
@@ -1054,6 +1136,35 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
"extra data after OSU Providers",
(int) (end - pos));
}
+
+ prov_anqp = bss->anqp->hs20_osu_providers_nai_list;
+ if (!prov_anqp)
+ continue;
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Parsing OSU Providers NAI List from "
+ MACSTR, MAC2STR(bss->bssid));
+ wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers NAI List",
+ prov_anqp);
+ pos = wpabuf_head(prov_anqp);
+ end = pos + wpabuf_len(prov_anqp);
+ num_providers = 0;
+ while (end - pos > 0) {
+ len = *pos++;
+ if (end - pos < len) {
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Not enough room for OSU_NAI");
+ break;
+ }
+ if (num_providers >= wpa_s->osu_prov_count) {
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Ignore unexpected OSU Provider NAI List entries");
+ break;
+ }
+ os_memcpy(wpa_s->osu_prov[num_providers].osu_nai2,
+ pos, len);
+ pos += len;
+ num_providers++;
+ }
}
wpa_s->fetch_osu_icon_in_progress = 1;
@@ -1207,6 +1318,18 @@ void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code,
}
+void hs20_rx_t_c_acceptance(struct wpa_supplicant *wpa_s, const char *url)
+{
+ if (!wpa_sm_pmf_enabled(wpa_s->wpa)) {
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Ignore Terms and Conditions Acceptance since PMF was not enabled");
+ return;
+ }
+
+ wpa_msg(wpa_s, MSG_INFO, HS20_T_C_ACCEPTANCE "%s", url);
+}
+
+
void hs20_init(struct wpa_supplicant *wpa_s)
{
dl_list_init(&wpa_s->icon_head);
diff --git a/contrib/wpa/wpa_supplicant/hs20_supplicant.h b/contrib/wpa/wpa_supplicant/hs20_supplicant.h
index 0dd559fdbf01..e43414bc65c5 100644
--- a/contrib/wpa/wpa_supplicant/hs20_supplicant.h
+++ b/contrib/wpa/wpa_supplicant/hs20_supplicant.h
@@ -9,7 +9,10 @@
#define HS20_SUPPLICANT_H
void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s);
-void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id);
+void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id,
+ int ap_release);
+void wpas_hs20_add_roam_cons_sel(struct wpabuf *buf,
+ const struct wpa_ssid *ssid);
int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
const u8 *payload, size_t payload_len, int inmem);
@@ -18,6 +21,7 @@ void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len,
void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, const u8 *sa,
const u8 *data, size_t slen, u8 dialog_token);
+int get_hs20_version(struct wpa_bss *bss);
int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
struct wpa_bss *bss);
int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
@@ -27,6 +31,7 @@ void hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s,
const char *url, u8 osu_method);
void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code,
u16 reauth_delay, const char *url);
+void hs20_rx_t_c_acceptance(struct wpa_supplicant *wpa_s, const char *url);
void hs20_free_osu_prov(struct wpa_supplicant *wpa_s);
void hs20_next_osu_icon(struct wpa_supplicant *wpa_s);
diff --git a/contrib/wpa/wpa_supplicant/ibss_rsn.c b/contrib/wpa/wpa_supplicant/ibss_rsn.c
index 53d7d57bde35..e96ea65a7887 100644
--- a/contrib/wpa/wpa_supplicant/ibss_rsn.c
+++ b/contrib/wpa/wpa_supplicant/ibss_rsn.c
@@ -259,9 +259,15 @@ static void auth_logger(void *ctx, const u8 *addr, logger_level level,
static const u8 * auth_get_psk(void *ctx, const u8 *addr,
- const u8 *p2p_dev_addr, const u8 *prev_psk)
+ const u8 *p2p_dev_addr, const u8 *prev_psk,
+ size_t *psk_len, int *vlan_id)
{
struct ibss_rsn *ibss_rsn = ctx;
+
+ if (psk_len)
+ *psk_len = PMK_LEN;
+ if (vlan_id)
+ *vlan_id = 0;
wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)",
__func__, MAC2STR(addr), prev_psk);
if (prev_psk)
@@ -408,7 +414,15 @@ static int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn,
const u8 *own_addr, struct wpa_ssid *ssid)
{
struct wpa_auth_config conf;
- struct wpa_auth_callbacks cb;
+ static const struct wpa_auth_callbacks cb = {
+ .logger = auth_logger,
+ .set_eapol = auth_set_eapol,
+ .send_eapol = auth_send_eapol,
+ .get_psk = auth_get_psk,
+ .set_key = auth_set_key,
+ .for_each_sta = auth_for_each_sta,
+ .disconnect = ibss_rsn_disconnect,
+ };
wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine");
@@ -420,18 +434,10 @@ static int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn,
conf.wpa_group = WPA_CIPHER_CCMP;
conf.eapol_version = 2;
conf.wpa_group_rekey = ssid->group_rekey ? ssid->group_rekey : 600;
+ conf.wpa_group_update_count = 4;
+ conf.wpa_pairwise_update_count = 4;
- os_memset(&cb, 0, sizeof(cb));
- cb.ctx = ibss_rsn;
- cb.logger = auth_logger;
- cb.set_eapol = auth_set_eapol;
- cb.send_eapol = auth_send_eapol;
- cb.get_psk = auth_get_psk;
- cb.set_key = auth_set_key;
- cb.for_each_sta = auth_for_each_sta;
- cb.disconnect = ibss_rsn_disconnect;
-
- ibss_rsn->auth_group = wpa_init(own_addr, &conf, &cb);
+ ibss_rsn->auth_group = wpa_init(own_addr, &conf, &cb, ibss_rsn);
if (ibss_rsn->auth_group == NULL) {
wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed");
return -1;
@@ -453,12 +459,12 @@ static int ibss_rsn_auth_init(struct ibss_rsn *ibss_rsn,
}
/* TODO: get peer RSN IE with Probe Request */
- if (wpa_validate_wpa_ie(ibss_rsn->auth_group, peer->auth,
+ if (wpa_validate_wpa_ie(ibss_rsn->auth_group, peer->auth, 0,
(u8 *) "\x30\x14\x01\x00"
"\x00\x0f\xac\x04"
"\x01\x00\x00\x0f\xac\x04"
"\x01\x00\x00\x0f\xac\x02"
- "\x00\x00", 22, NULL, 0) !=
+ "\x00\x00", 22, NULL, 0, NULL, 0) !=
WPA_IE_OK) {
wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed");
return -1;
@@ -760,10 +766,9 @@ static int ibss_rsn_process_rx_eapol(struct ibss_rsn *ibss_rsn,
if (supp < 0)
return -1;
- tmp = os_malloc(len);
+ tmp = os_memdup(buf, len);
if (tmp == NULL)
return -1;
- os_memcpy(tmp, buf, len);
if (supp) {
peer->authentication_status |= IBSS_RSN_AUTH_EAPOL_BY_PEER;
wpa_printf(MSG_DEBUG, "RSN: IBSS RX EAPOL for Supplicant from "
@@ -838,6 +843,18 @@ static void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn,
MAC2STR(addr));
if (peer &&
+ peer->authentication_status & (IBSS_RSN_SET_PTK_SUPP |
+ IBSS_RSN_SET_PTK_AUTH)) {
+ /* Clear the TK for this pair to allow recovery from the case
+ * where the peer STA has restarted and lost its key while we
+ * still have a pairwise key configured. */
+ wpa_printf(MSG_DEBUG, "RSN: Clear pairwise key for peer "
+ MACSTR, MAC2STR(addr));
+ wpa_drv_set_key(ibss_rsn->wpa_s, WPA_ALG_NONE, addr, 0, 0,
+ NULL, 0, NULL, 0);
+ }
+
+ if (peer &&
peer->authentication_status & IBSS_RSN_AUTH_EAPOL_BY_PEER) {
if (peer->own_auth_tx.sec) {
struct os_reltime now, diff;
diff --git a/contrib/wpa/wpa_supplicant/interworking.c b/contrib/wpa/wpa_supplicant/interworking.c
index 1fb40c74e5cf..f94cd1614c60 100644
--- a/contrib/wpa/wpa_supplicant/interworking.c
+++ b/contrib/wpa/wpa_supplicant/interworking.c
@@ -106,10 +106,12 @@ static struct wpabuf * anqp_build_req(u16 info_ids[], size_t num_ids,
if (buf == NULL)
return NULL;
- len_pos = gas_anqp_add_element(buf, ANQP_QUERY_LIST);
- for (i = 0; i < num_ids; i++)
- wpabuf_put_le16(buf, info_ids[i]);
- gas_anqp_set_element_len(buf, len_pos);
+ if (num_ids > 0) {
+ len_pos = gas_anqp_add_element(buf, ANQP_QUERY_LIST);
+ for (i = 0; i < num_ids; i++)
+ wpabuf_put_le16(buf, info_ids[i]);
+ gas_anqp_set_element_len(buf, len_pos);
+ }
if (extra)
wpabuf_put_buf(buf, extra);
@@ -146,6 +148,8 @@ static int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s)
return 1;
if (cred->required_roaming_consortium_len)
return 1;
+ if (cred->num_roaming_consortiums)
+ return 1;
}
return 0;
}
@@ -299,8 +303,10 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s,
wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY);
if (all)
wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS);
- if (all)
+ if (all) {
wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_LIST);
+ wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_NAI_LIST);
+ }
gas_anqp_set_element_len(extra, len_pos);
}
#endif /* CONFIG_HS20 */
@@ -310,7 +316,7 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s,
if (buf == NULL)
return -1;
- res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, buf,
+ res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, 0, buf,
interworking_anqp_resp_cb, wpa_s);
if (res < 0) {
wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request");
@@ -952,6 +958,7 @@ static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s,
"WPA-EAP WPA-EAP-SHA256" : "WPA-EAP";
if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0 ||
wpa_config_set(ssid, "proto", "RSN", 0) < 0 ||
+ wpa_config_set(ssid, "ieee80211w", "1", 0) < 0 ||
wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0)
return -1;
return 0;
@@ -1143,6 +1150,23 @@ static int roaming_consortium_match(const u8 *ie, const struct wpabuf *anqp,
}
+static int cred_roaming_consortiums_match(const u8 *ie,
+ const struct wpabuf *anqp,
+ const struct wpa_cred *cred)
+{
+ unsigned int i;
+
+ for (i = 0; i < cred->num_roaming_consortiums; i++) {
+ if (roaming_consortium_match(ie, anqp,
+ cred->roaming_consortiums[i],
+ cred->roaming_consortiums_len[i]))
+ return 1;
+ }
+
+ return 0;
+}
+
+
static int cred_no_required_oi_match(struct wpa_cred *cred, struct wpa_bss *bss)
{
const u8 *ie;
@@ -1347,27 +1371,28 @@ static struct wpa_cred * interworking_credentials_available_roaming_consortium(
{
struct wpa_cred *cred, *selected = NULL;
const u8 *ie;
+ const struct wpabuf *anqp;
int is_excluded = 0;
ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
+ anqp = bss->anqp ? bss->anqp->roaming_consortium : NULL;
- if (ie == NULL &&
- (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL))
+ if (!ie && !anqp)
return NULL;
if (wpa_s->conf->cred == NULL)
return NULL;
for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
- if (cred->roaming_consortium_len == 0)
+ if (cred->roaming_consortium_len == 0 &&
+ cred->num_roaming_consortiums == 0)
continue;
- if (!roaming_consortium_match(ie,
- bss->anqp ?
- bss->anqp->roaming_consortium :
- NULL,
- cred->roaming_consortium,
- cred->roaming_consortium_len))
+ if ((cred->roaming_consortium_len == 0 ||
+ !roaming_consortium_match(ie, anqp,
+ cred->roaming_consortium,
+ cred->roaming_consortium_len)) &&
+ !cred_roaming_consortiums_match(ie, anqp, cred))
continue;
if (cred_no_required_oi_match(cred, bss))
@@ -1533,6 +1558,9 @@ static int interworking_connect_roaming_consortium(
struct wpa_bss *bss, int only_add)
{
struct wpa_ssid *ssid;
+ const u8 *ie;
+ const struct wpabuf *anqp;
+ unsigned int i;
wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR
" based on roaming consortium match", MAC2STR(bss->bssid));
@@ -1562,6 +1590,26 @@ static int interworking_connect_roaming_consortium(
if (interworking_set_hs20_params(wpa_s, ssid) < 0)
goto fail;
+ ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
+ anqp = bss->anqp ? bss->anqp->roaming_consortium : NULL;
+ for (i = 0; (ie || anqp) && i < cred->num_roaming_consortiums; i++) {
+ if (!roaming_consortium_match(
+ ie, anqp, cred->roaming_consortiums[i],
+ cred->roaming_consortiums_len[i]))
+ continue;
+
+ ssid->roaming_consortium_selection =
+ os_malloc(cred->roaming_consortiums_len[i]);
+ if (!ssid->roaming_consortium_selection)
+ goto fail;
+ os_memcpy(ssid->roaming_consortium_selection,
+ cred->roaming_consortiums[i],
+ cred->roaming_consortiums_len[i]);
+ ssid->roaming_consortium_selection_len =
+ cred->roaming_consortiums_len[i];
+ break;
+ }
+
if (cred->eap_method == NULL) {
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: No EAP method set for credential using roaming consortium");
@@ -1769,9 +1817,10 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
switch (eap->method) {
case EAP_TYPE_TTLS:
if (eap->inner_method) {
- os_snprintf(buf, sizeof(buf), "\"autheap=%s\"",
- eap_get_name(EAP_VENDOR_IETF,
- eap->inner_method));
+ name = eap_get_name(EAP_VENDOR_IETF, eap->inner_method);
+ if (!name)
+ goto fail;
+ os_snprintf(buf, sizeof(buf), "\"autheap=%s\"", name);
if (wpa_config_set(ssid, "phase2", buf, 0) < 0)
goto fail;
break;
@@ -1894,7 +1943,7 @@ static struct wpa_cred * interworking_credentials_available_3gpp(
size_t len;
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: IMSI not available - try to read again through eap_proxy");
- wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol,
+ wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
wpa_s->imsi,
&len);
if (wpa_s->mnc_len > 0) {
@@ -2530,7 +2579,8 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s)
wpa_msg(wpa_s, MSG_INFO, INTERWORKING_SELECTED MACSTR,
MAC2STR(selected->bssid));
interworking_connect(wpa_s, selected, 0);
- }
+ } else if (wpa_s->wpa_state == WPA_SCANNING)
+ wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
}
@@ -2576,7 +2626,6 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
{
struct wpa_bss *bss;
int found = 0;
- const u8 *ie;
wpa_printf(MSG_DEBUG, "Interworking: next_anqp_fetch - "
"fetch_anqp_in_progress=%d fetch_osu_icon_in_progress=%d",
@@ -2599,8 +2648,7 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
if (!(bss->caps & IEEE80211_CAP_ESS))
continue;
- ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB);
- if (ie == NULL || ie[1] < 4 || !(ie[5] & 0x80))
+ if (!wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_INTERWORKING))
continue; /* AP does not support Interworking */
if (disallowed_bssid(wpa_s, bss->bssid) ||
disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len))
@@ -2693,7 +2741,7 @@ void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s)
int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
u16 info_ids[], size_t num_ids, u32 subtypes,
- int get_cell_pref)
+ u32 mbo_subtypes)
{
struct wpabuf *buf;
struct wpabuf *extra_buf = NULL;
@@ -2727,13 +2775,14 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
- if (get_cell_pref) {
+ if (mbo_subtypes) {
struct wpabuf *mbo;
- mbo = mbo_build_anqp_buf(wpa_s, bss);
+ mbo = mbo_build_anqp_buf(wpa_s, bss, mbo_subtypes);
if (mbo) {
if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) {
wpabuf_free(extra_buf);
+ wpabuf_free(mbo);
return -1;
}
wpabuf_put_buf(extra_buf, mbo);
@@ -2747,7 +2796,7 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
if (buf == NULL)
return -1;
- res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s);
+ res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s);
if (res < 0) {
wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request");
wpabuf_free(buf);
@@ -2796,6 +2845,31 @@ static void anqp_add_extra(struct wpa_supplicant *wpa_s,
}
+static void interworking_parse_venue_url(struct wpa_supplicant *wpa_s,
+ const u8 *data, size_t len)
+{
+ const u8 *pos = data, *end = data + len;
+ char url[255];
+
+ while (end - pos >= 2) {
+ u8 slen, num;
+
+ slen = *pos++;
+ if (slen < 1 || slen > end - pos) {
+ wpa_printf(MSG_DEBUG,
+ "ANQP: Truncated Venue URL Duple field");
+ return;
+ }
+
+ num = *pos++;
+ os_memcpy(url, pos, slen - 1);
+ url[slen - 1] = '\0';
+ wpa_msg(wpa_s, MSG_INFO, RX_VENUE_URL "%u %s", num, url);
+ pos += slen - 1;
+ }
+}
+
+
static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, const u8 *sa,
u16 info_id,
@@ -2804,9 +2878,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
{
const u8 *pos = data;
struct wpa_bss_anqp *anqp = NULL;
-#ifdef CONFIG_HS20
u8 type;
-#endif /* CONFIG_HS20 */
if (bss)
anqp = bss->anqp;
@@ -2892,12 +2964,35 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
anqp->domain_name = wpabuf_alloc_copy(pos, slen);
}
break;
+#ifdef CONFIG_FILS
+ case ANQP_FILS_REALM_INFO:
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
+ " FILS Realm Information", MAC2STR(sa));
+ wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: FILS Realm Information",
+ pos, slen);
+ if (anqp) {
+ wpabuf_free(anqp->fils_realm_info);
+ anqp->fils_realm_info = wpabuf_alloc_copy(pos, slen);
+ }
+ break;
+#endif /* CONFIG_FILS */
+ case ANQP_VENUE_URL:
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR " Venue URL",
+ MAC2STR(sa));
+ anqp_add_extra(wpa_s, anqp, info_id, pos, slen);
+
+ if (!pmf_in_use(wpa_s, sa)) {
+ wpa_printf(MSG_DEBUG,
+ "ANQP: Ignore Venue URL since PMF was not enabled");
+ break;
+ }
+ interworking_parse_venue_url(wpa_s, pos, slen);
+ break;
case ANQP_VENDOR_SPECIFIC:
if (slen < 3)
return;
switch (WPA_GET_BE24(pos)) {
-#ifdef CONFIG_HS20
case OUI_WFA:
pos += 3;
slen -= 3;
@@ -2908,19 +3003,26 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
slen--;
switch (type) {
+#ifdef CONFIG_HS20
case HS20_ANQP_OUI_TYPE:
hs20_parse_rx_hs20_anqp_resp(wpa_s, bss, sa,
pos, slen,
dialog_token);
break;
+#endif /* CONFIG_HS20 */
+#ifdef CONFIG_MBO
+ case MBO_ANQP_OUI_TYPE:
+ mbo_parse_rx_anqp_resp(wpa_s, bss, sa,
+ pos, slen);
+ break;
+#endif /* CONFIG_MBO */
default:
wpa_msg(wpa_s, MSG_DEBUG,
- "HS20: Unsupported ANQP vendor type %u",
+ "ANQP: Unsupported ANQP vendor type %u",
type);
break;
}
break;
-#endif /* CONFIG_HS20 */
default:
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Unsupported vendor-specific ANQP OUI %06x",
@@ -3133,7 +3235,7 @@ int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst,
} else
wpabuf_put_le16(buf, 0);
- res = gas_query_req(wpa_s->gas, dst, freq, buf, gas_resp_cb, wpa_s);
+ res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, gas_resp_cb, wpa_s);
if (res < 0) {
wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
wpabuf_free(buf);
diff --git a/contrib/wpa/wpa_supplicant/interworking.h b/contrib/wpa/wpa_supplicant/interworking.h
index 3d22292618b2..37ee2e904e48 100644
--- a/contrib/wpa/wpa_supplicant/interworking.h
+++ b/contrib/wpa/wpa_supplicant/interworking.h
@@ -13,7 +13,7 @@ enum gas_query_result;
int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
u16 info_ids[], size_t num_ids, u32 subtypes,
- int get_cell_pref);
+ u32 mbo_subtypes);
void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
enum gas_query_result result,
const struct wpabuf *adv_proto,
diff --git a/contrib/wpa/wpa_supplicant/main.c b/contrib/wpa/wpa_supplicant/main.c
index e08c2fd266f1..51a8a0298a9b 100644
--- a/contrib/wpa/wpa_supplicant/main.c
+++ b/contrib/wpa/wpa_supplicant/main.c
@@ -28,9 +28,9 @@ static void usage(void)
"s"
#endif /* CONFIG_DEBUG_SYSLOG */
"t"
-#ifdef CONFIG_DBUS
+#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
"u"
-#endif /* CONFIG_DBUS */
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
"vW] [-P<pid file>] "
"[-g<global ctrl>] \\\n"
" [-G<group>] \\\n"
@@ -98,9 +98,9 @@ static void usage(void)
" -T = record to Linux tracing in addition to logging\n"
" (records all messages regardless of debug verbosity)\n"
#endif /* CONFIG_DEBUG_LINUX_TRACING */
-#ifdef CONFIG_DBUS
+#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
" -u = enable DBus control interface\n"
-#endif /* CONFIG_DBUS */
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
" -v = show version\n"
" -W = wait for a control interface monitor before starting\n");
@@ -295,11 +295,11 @@ int main(int argc, char *argv[])
case 't':
params.wpa_debug_timestamp++;
break;
-#ifdef CONFIG_DBUS
+#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
case 'u':
params.dbus_ctrl_interface = 1;
break;
-#endif /* CONFIG_DBUS */
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
case 'v':
printf("%s\n", wpa_supplicant_version);
exitcode = 0;
diff --git a/contrib/wpa/wpa_supplicant/mbo.c b/contrib/wpa/wpa_supplicant/mbo.c
index 7e049be3df41..43b1fa7beb38 100644
--- a/contrib/wpa/wpa_supplicant/mbo.c
+++ b/contrib/wpa/wpa_supplicant/mbo.c
@@ -38,6 +38,32 @@ static int wpas_mbo_validate_non_pref_chan(u8 oper_class, u8 chan, u8 reason)
}
+const u8 * mbo_attr_from_mbo_ie(const u8 *mbo_ie, enum mbo_attr_id attr)
+{
+ const u8 *mbo;
+ u8 ie_len = mbo_ie[1];
+
+ if (ie_len < MBO_IE_HEADER - 2)
+ return NULL;
+ mbo = mbo_ie + MBO_IE_HEADER;
+
+ return get_ie(mbo, 2 + ie_len - MBO_IE_HEADER, attr);
+}
+
+
+const u8 * mbo_get_attr_from_ies(const u8 *ies, size_t ies_len,
+ enum mbo_attr_id attr)
+{
+ const u8 *mbo_ie;
+
+ mbo_ie = get_vendor_ie(ies, ies_len, MBO_IE_VENDOR_TYPE);
+ if (!mbo_ie)
+ return NULL;
+
+ return mbo_attr_from_mbo_ie(mbo_ie, attr);
+}
+
+
const u8 * wpas_mbo_get_bss_attr(struct wpa_bss *bss, enum mbo_attr_id attr)
{
const u8 *mbo, *end;
@@ -72,6 +98,13 @@ static void wpas_mbo_non_pref_chan_attr_body(struct wpa_supplicant *wpa_s,
}
+static void wpas_mbo_non_pref_chan_attr_hdr(struct wpabuf *mbo, size_t size)
+{
+ wpabuf_put_u8(mbo, MBO_ATTR_ID_NON_PREF_CHAN_REPORT);
+ wpabuf_put_u8(mbo, size); /* Length */
+}
+
+
static void wpas_mbo_non_pref_chan_attr(struct wpa_supplicant *wpa_s,
struct wpabuf *mbo, u8 start, u8 end)
{
@@ -80,9 +113,7 @@ static void wpas_mbo_non_pref_chan_attr(struct wpa_supplicant *wpa_s,
if (size + 2 > wpabuf_tailroom(mbo))
return;
- wpabuf_put_u8(mbo, MBO_ATTR_ID_NON_PREF_CHAN_REPORT);
- wpabuf_put_u8(mbo, size); /* Length */
-
+ wpas_mbo_non_pref_chan_attr_hdr(mbo, size);
wpas_mbo_non_pref_chan_attr_body(wpa_s, mbo, start, end);
}
@@ -119,6 +150,8 @@ static void wpas_mbo_non_pref_chan_attrs(struct wpa_supplicant *wpa_s,
if (!wpa_s->non_pref_chan || !wpa_s->non_pref_chan_num) {
if (subelement)
wpas_mbo_non_pref_chan_subelem_hdr(mbo, 4);
+ else
+ wpas_mbo_non_pref_chan_attr_hdr(mbo, 0);
return;
}
start_pref = &wpa_s->non_pref_chan[0];
@@ -149,12 +182,14 @@ static void wpas_mbo_non_pref_chan_attrs(struct wpa_supplicant *wpa_s,
}
-int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len)
+int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len,
+ int add_oce_capa)
{
struct wpabuf *mbo;
int res;
- if (len < MBO_IE_HEADER + 3 + 7)
+ if (len < MBO_IE_HEADER + 3 + 7 +
+ ((wpa_s->enable_oce & OCE_STA) ? 3 : 0))
return 0;
/* Leave room for the MBO IE header */
@@ -173,9 +208,16 @@ int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len)
wpabuf_put_u8(mbo, 1);
wpabuf_put_u8(mbo, wpa_s->conf->mbo_cell_capa);
+ /* Add OCE capability indication attribute if OCE is enabled */
+ if ((wpa_s->enable_oce & OCE_STA) && add_oce_capa) {
+ wpabuf_put_u8(mbo, OCE_ATTR_ID_CAPA_IND);
+ wpabuf_put_u8(mbo, 1);
+ wpabuf_put_u8(mbo, OCE_RELEASE);
+ }
+
res = mbo_add_ie(buf, len, wpabuf_head_u8(mbo), wpabuf_len(mbo));
if (!res)
- wpa_printf(MSG_ERROR, "Failed to add MBO IE");
+ wpa_printf(MSG_ERROR, "Failed to add MBO/OCE IE");
wpabuf_free(mbo);
return res;
@@ -233,6 +275,7 @@ static void wpas_mbo_non_pref_chan_changed(struct wpa_supplicant *wpa_s)
wpas_mbo_non_pref_chan_attrs(wpa_s, buf, 1);
wpas_mbo_send_wnm_notification(wpa_s, wpabuf_head_u8(buf),
wpabuf_len(buf));
+ wpas_update_mbo_connect_params(wpa_s);
wpabuf_free(buf);
}
@@ -258,10 +301,10 @@ static int wpa_non_pref_chan_cmp(const void *_a, const void *_b)
const struct wpa_mbo_non_pref_channel *a = _a, *b = _b;
if (a->oper_class != b->oper_class)
- return a->oper_class - b->oper_class;
+ return (int) a->oper_class - (int) b->oper_class;
if (a->reason != b->reason)
- return a->reason - b->reason;
- return a->preference - b->preference;
+ return (int) a->reason - (int) b->reason;
+ return (int) a->preference - (int) b->preference;
}
@@ -277,11 +320,10 @@ int wpas_mbo_update_non_pref_chan(struct wpa_supplicant *wpa_s,
non_pref_chan ? non_pref_chan : "N/A");
/*
- * The shortest channel configuration is 10 characters - commas, 3
- * colons, and 4 values that one of them (oper_class) is 2 digits or
- * more.
+ * The shortest channel configuration is 7 characters - 3 colons and
+ * 4 values.
*/
- if (!non_pref_chan || os_strlen(non_pref_chan) < 10)
+ if (!non_pref_chan || os_strlen(non_pref_chan) < 7)
goto update;
cmd = os_strdup(non_pref_chan);
@@ -369,315 +411,30 @@ fail:
void wpas_mbo_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ie)
{
+ u8 *len;
+
wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
- wpabuf_put_u8(ie, 7);
+ len = wpabuf_put(ie, 1);
+
wpabuf_put_be24(ie, OUI_WFA);
wpabuf_put_u8(ie, MBO_OUI_TYPE);
wpabuf_put_u8(ie, MBO_ATTR_ID_CELL_DATA_CAPA);
wpabuf_put_u8(ie, 1);
wpabuf_put_u8(ie, wpa_s->conf->mbo_cell_capa);
-}
-
-
-enum chan_allowed {
- NOT_ALLOWED, ALLOWED
-};
-
-static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode, u8 chan,
- unsigned int *flags)
-{
- int i;
-
- for (i = 0; i < mode->num_channels; i++) {
- if (mode->channels[i].chan == chan)
- break;
+ if (wpa_s->enable_oce & OCE_STA) {
+ wpabuf_put_u8(ie, OCE_ATTR_ID_CAPA_IND);
+ wpabuf_put_u8(ie, 1);
+ wpabuf_put_u8(ie, OCE_RELEASE);
}
-
- if (i == mode->num_channels ||
- (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED))
- return NOT_ALLOWED;
-
- if (flags)
- *flags = mode->channels[i].flag;
-
- return ALLOWED;
-}
-
-
-static int get_center_80mhz(struct hostapd_hw_modes *mode, u8 channel)
-{
- u8 center_channels[] = {42, 58, 106, 122, 138, 155};
- size_t i;
-
- if (mode->mode != HOSTAPD_MODE_IEEE80211A)
- return 0;
-
- for (i = 0; i < ARRAY_SIZE(center_channels); i++) {
- /*
- * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48),
- * so the center channel is 6 channels away from the start/end.
- */
- if (channel >= center_channels[i] - 6 &&
- channel <= center_channels[i] + 6)
- return center_channels[i];
- }
-
- return 0;
-}
-
-
-static enum chan_allowed verify_80mhz(struct hostapd_hw_modes *mode, u8 channel)
-{
- u8 center_chan;
- unsigned int i;
-
- center_chan = get_center_80mhz(mode, channel);
- if (!center_chan)
- return NOT_ALLOWED;
-
- /* check all the channels are available */
- for (i = 0; i < 4; i++) {
- unsigned int flags;
- u8 adj_chan = center_chan - 6 + i * 4;
-
- if (allow_channel(mode, adj_chan, &flags) == NOT_ALLOWED)
- return NOT_ALLOWED;
-
- if ((i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70)) ||
- (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50)) ||
- (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_30)) ||
- (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10)))
- return NOT_ALLOWED;
- }
-
- return ALLOWED;
-}
-
-
-static int get_center_160mhz(struct hostapd_hw_modes *mode, u8 channel)
-{
- u8 center_channels[] = { 50, 114 };
- unsigned int i;
-
- if (mode->mode != HOSTAPD_MODE_IEEE80211A)
- return 0;
-
- for (i = 0; i < ARRAY_SIZE(center_channels); i++) {
- /*
- * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64),
- * so the center channel is 14 channels away from the start/end.
- */
- if (channel >= center_channels[i] - 14 &&
- channel <= center_channels[i] + 14)
- return center_channels[i];
- }
-
- return 0;
-}
-
-
-static enum chan_allowed verify_160mhz(struct hostapd_hw_modes *mode,
- u8 channel)
-{
- u8 center_chan;
- unsigned int i;
-
- center_chan = get_center_160mhz(mode, channel);
- if (!center_chan)
- return NOT_ALLOWED;
-
- /* Check all the channels are available */
- for (i = 0; i < 8; i++) {
- unsigned int flags;
- u8 adj_chan = center_chan - 14 + i * 4;
-
- if (allow_channel(mode, adj_chan, &flags) == NOT_ALLOWED)
- return NOT_ALLOWED;
-
- if ((i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150)) ||
- (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130)) ||
- (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_110)) ||
- (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_90)) ||
- (i == 4 && !(flags & HOSTAPD_CHAN_VHT_90_70)) ||
- (i == 5 && !(flags & HOSTAPD_CHAN_VHT_110_50)) ||
- (i == 6 && !(flags & HOSTAPD_CHAN_VHT_130_30)) ||
- (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10)))
- return NOT_ALLOWED;
- }
-
- return ALLOWED;
-}
-
-
-static enum chan_allowed verify_channel(struct hostapd_hw_modes *mode,
- u8 channel, u8 bw)
-{
- unsigned int flag = 0;
- enum chan_allowed res, res2;
-
- res2 = res = allow_channel(mode, channel, &flag);
- if (bw == BW40MINUS) {
- if (!(flag & HOSTAPD_CHAN_HT40MINUS))
- return NOT_ALLOWED;
- res2 = allow_channel(mode, channel - 4, NULL);
- } else if (bw == BW40PLUS) {
- if (!(flag & HOSTAPD_CHAN_HT40PLUS))
- return NOT_ALLOWED;
- res2 = allow_channel(mode, channel + 4, NULL);
- } else if (bw == BW80) {
- /*
- * channel is a center channel and as such, not necessarily a
- * valid 20 MHz channels. Override earlier allow_channel()
- * result and use only the 80 MHz specific version.
- */
- res2 = res = verify_80mhz(mode, channel);
- } else if (bw == BW160) {
- /*
- * channel is a center channel and as such, not necessarily a
- * valid 20 MHz channels. Override earlier allow_channel()
- * result and use only the 160 MHz specific version.
- */
- res2 = res = verify_160mhz(mode, channel);
- } else if (bw == BW80P80) {
- /*
- * channel is a center channel and as such, not necessarily a
- * valid 20 MHz channels. Override earlier allow_channel()
- * result and use only the 80 MHz specific version.
- */
- res2 = res = verify_80mhz(mode, channel);
- }
-
- if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
- return NOT_ALLOWED;
-
- return ALLOWED;
-}
-
-
-static int wpas_op_class_supported(struct wpa_supplicant *wpa_s,
- const struct oper_class_map *op_class)
-{
- int chan;
- size_t i;
- struct hostapd_hw_modes *mode;
- int found;
-
- mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode);
- if (!mode)
- return 0;
-
- if (op_class->op_class == 128) {
- u8 channels[] = { 42, 58, 106, 122, 138, 155 };
-
- for (i = 0; i < ARRAY_SIZE(channels); i++) {
- if (verify_channel(mode, channels[i], op_class->bw) ==
- ALLOWED)
- return 1;
- }
-
- return 0;
- }
-
- if (op_class->op_class == 129) {
- /* Check if either 160 MHz channels is allowed */
- return verify_channel(mode, 50, op_class->bw) == ALLOWED ||
- verify_channel(mode, 114, op_class->bw) == ALLOWED;
- }
-
- if (op_class->op_class == 130) {
- /* Need at least two non-contiguous 80 MHz segments */
- found = 0;
-
- if (verify_channel(mode, 42, op_class->bw) == ALLOWED ||
- verify_channel(mode, 58, op_class->bw) == ALLOWED)
- found++;
- if (verify_channel(mode, 106, op_class->bw) == ALLOWED ||
- verify_channel(mode, 122, op_class->bw) == ALLOWED ||
- verify_channel(mode, 138, op_class->bw) == ALLOWED)
- found++;
- if (verify_channel(mode, 106, op_class->bw) == ALLOWED &&
- verify_channel(mode, 138, op_class->bw) == ALLOWED)
- found++;
- if (verify_channel(mode, 155, op_class->bw) == ALLOWED)
- found++;
-
- if (found >= 2)
- return 1;
-
- return 0;
- }
-
- found = 0;
- for (chan = op_class->min_chan; chan <= op_class->max_chan;
- chan += op_class->inc) {
- if (verify_channel(mode, chan, op_class->bw) == ALLOWED) {
- found = 1;
- break;
- }
- }
-
- return found;
-}
-
-
-int wpas_mbo_supp_op_class_ie(struct wpa_supplicant *wpa_s, int freq, u8 *pos,
- size_t len)
-{
- struct wpabuf *buf;
- u8 op, current, chan;
- u8 *ie_len;
- int res;
-
- /*
- * Assume 20 MHz channel for now.
- * TODO: Use the secondary channel and VHT channel width that will be
- * used after association.
- */
- if (ieee80211_freq_to_channel_ext(freq, 0, VHT_CHANWIDTH_USE_HT,
- &current, &chan) == NUM_HOSTAPD_MODES)
- return 0;
-
- /*
- * Need 3 bytes for EID, length, and current operating class, plus
- * 1 byte for every other supported operating class.
- */
- buf = wpabuf_alloc(global_op_class_size + 3);
- if (!buf)
- return 0;
-
- wpabuf_put_u8(buf, WLAN_EID_SUPPORTED_OPERATING_CLASSES);
- /* Will set the length later, putting a placeholder */
- ie_len = wpabuf_put(buf, 1);
- wpabuf_put_u8(buf, current);
-
- for (op = 0; global_op_class[op].op_class; op++) {
- if (wpas_op_class_supported(wpa_s, &global_op_class[op]))
- wpabuf_put_u8(buf, global_op_class[op].op_class);
- }
-
- *ie_len = wpabuf_len(buf) - 2;
- if (*ie_len < 2 || wpabuf_len(buf) > len) {
- wpa_printf(MSG_ERROR,
- "Failed to add supported operating classes IE");
- res = 0;
- } else {
- os_memcpy(pos, wpabuf_head(buf), wpabuf_len(buf));
- res = wpabuf_len(buf);
- wpa_hexdump_buf(MSG_DEBUG,
- "MBO: Added supported operating classes IE",
- buf);
- }
-
- wpabuf_free(buf);
- return res;
+ *len = (u8 *) wpabuf_put(ie, 0) - len - 1;
}
void wpas_mbo_ie_trans_req(struct wpa_supplicant *wpa_s, const u8 *mbo_ie,
size_t len)
{
- const u8 *pos, *cell_pref = NULL, *reason = NULL;
+ const u8 *pos, *cell_pref = NULL;
u8 id, elen;
u16 disallowed_sec = 0;
@@ -712,7 +469,8 @@ void wpas_mbo_ie_trans_req(struct wpa_supplicant *wpa_s, const u8 *mbo_ie,
if (elen != 1)
goto fail;
- reason = pos;
+ wpa_s->wnm_mbo_trans_reason_present = 1;
+ wpa_s->wnm_mbo_transition_reason = *pos;
break;
case MBO_ATTR_ID_ASSOC_RETRY_DELAY:
if (elen != 2)
@@ -726,6 +484,9 @@ void wpas_mbo_ie_trans_req(struct wpa_supplicant *wpa_s, const u8 *mbo_ie,
} else if (wpa_s->wnm_mode &
WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
disallowed_sec = WPA_GET_LE16(pos);
+ wpa_printf(MSG_DEBUG,
+ "MBO: Association retry delay: %u",
+ disallowed_sec);
} else {
wpa_printf(MSG_DEBUG,
"MBO: Association retry delay attribute not in disassoc imminent mode");
@@ -755,13 +516,13 @@ void wpas_mbo_ie_trans_req(struct wpa_supplicant *wpa_s, const u8 *mbo_ie,
wpa_msg(wpa_s, MSG_INFO, MBO_CELL_PREFERENCE "preference=%u",
*cell_pref);
- if (reason)
+ if (wpa_s->wnm_mbo_trans_reason_present)
wpa_msg(wpa_s, MSG_INFO, MBO_TRANSITION_REASON "reason=%u",
- *reason);
+ wpa_s->wnm_mbo_transition_reason);
if (disallowed_sec && wpa_s->current_bss)
wpa_bss_tmp_disallow(wpa_s, wpa_s->current_bss->bssid,
- disallowed_sec);
+ disallowed_sec, 0);
return;
fail:
@@ -805,14 +566,16 @@ void wpas_mbo_update_cell_capa(struct wpa_supplicant *wpa_s, u8 mbo_cell_capa)
wpas_mbo_send_wnm_notification(wpa_s, cell_capa, 7);
wpa_supplicant_set_default_scan_ies(wpa_s);
+ wpas_update_mbo_connect_params(wpa_s);
}
struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s,
- struct wpa_bss *bss)
+ struct wpa_bss *bss, u32 mbo_subtypes)
{
struct wpabuf *anqp_buf;
u8 *len_pos;
+ u8 i;
if (!wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE)) {
wpa_printf(MSG_INFO, "MBO: " MACSTR
@@ -821,7 +584,8 @@ struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s,
return NULL;
}
- anqp_buf = wpabuf_alloc(10);
+ /* Allocate size for the maximum case - all MBO subtypes are set */
+ anqp_buf = wpabuf_alloc(9 + MAX_MBO_ANQP_SUBTYPE);
if (!anqp_buf)
return NULL;
@@ -829,8 +593,43 @@ struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s,
wpabuf_put_be24(anqp_buf, OUI_WFA);
wpabuf_put_u8(anqp_buf, MBO_ANQP_OUI_TYPE);
- wpabuf_put_u8(anqp_buf, MBO_ANQP_SUBTYPE_CELL_CONN_PREF);
+ wpabuf_put_u8(anqp_buf, MBO_ANQP_SUBTYPE_QUERY_LIST);
+
+ /* The first valid MBO subtype is 1 */
+ for (i = 1; i <= MAX_MBO_ANQP_SUBTYPE; i++) {
+ if (mbo_subtypes & BIT(i))
+ wpabuf_put_u8(anqp_buf, i);
+ }
+
gas_anqp_set_element_len(anqp_buf, len_pos);
return anqp_buf;
}
+
+
+void mbo_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss, const u8 *sa,
+ const u8 *data, size_t slen)
+{
+ const u8 *pos = data;
+ u8 subtype;
+
+ if (slen < 1)
+ return;
+
+ subtype = *pos++;
+ slen--;
+
+ switch (subtype) {
+ case MBO_ANQP_SUBTYPE_CELL_CONN_PREF:
+ if (slen < 1)
+ break;
+ wpa_msg(wpa_s, MSG_INFO, RX_MBO_ANQP MACSTR
+ " cell_conn_pref=%u", MAC2STR(sa), *pos);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "MBO: Unsupported ANQP subtype %u",
+ subtype);
+ break;
+ }
+}
diff --git a/contrib/wpa/wpa_supplicant/mesh.c b/contrib/wpa/wpa_supplicant/mesh.c
index d67d3b2aa390..92600211ac2d 100644
--- a/contrib/wpa/wpa_supplicant/mesh.c
+++ b/contrib/wpa/wpa_supplicant/mesh.c
@@ -34,6 +34,8 @@ static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s)
wpa_s->current_ssid = NULL;
os_free(wpa_s->mesh_rsn);
wpa_s->mesh_rsn = NULL;
+ os_free(wpa_s->mesh_params);
+ wpa_s->mesh_params = NULL;
/* TODO: leave mesh (stop beacon). This will happen on link down
* anyway, so it's not urgent */
}
@@ -84,6 +86,7 @@ static struct mesh_conf * mesh_config_create(struct wpa_supplicant *wpa_s,
MESH_CONF_SEC_AMPE;
else
conf->security |= MESH_CONF_SEC_NONE;
+#ifdef CONFIG_IEEE80211W
conf->ieee80211w = ssid->ieee80211w;
if (conf->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
if (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)
@@ -91,6 +94,10 @@ static struct mesh_conf * mesh_config_create(struct wpa_supplicant *wpa_s,
else
conf->ieee80211w = NO_MGMT_FRAME_PROTECTION;
}
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+ conf->ocv = ssid->ocv;
+#endif /* CONFIG_OCV */
cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher, 0);
if (cipher < 0 || cipher == WPA_CIPHER_TKIP) {
@@ -145,17 +152,104 @@ static void wpas_mesh_copy_groups(struct hostapd_data *bss,
}
+static int wpas_mesh_init_rsn(struct wpa_supplicant *wpa_s)
+{
+ struct hostapd_iface *ifmsh = wpa_s->ifmsh;
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ struct hostapd_data *bss = ifmsh->bss[0];
+ static int default_groups[] = { 19, 20, 21, 25, 26, -1 };
+ const char *password;
+ size_t len;
+
+ password = ssid->sae_password;
+ if (!password)
+ password = ssid->passphrase;
+ if (!password) {
+ wpa_printf(MSG_ERROR,
+ "mesh: Passphrase for SAE not configured");
+ return -1;
+ }
+
+ bss->conf->wpa = ssid->proto;
+ bss->conf->wpa_key_mgmt = ssid->key_mgmt;
+
+ if (wpa_s->conf->sae_groups && wpa_s->conf->sae_groups[0] > 0) {
+ wpas_mesh_copy_groups(bss, wpa_s);
+ } else {
+ bss->conf->sae_groups = os_memdup(default_groups,
+ sizeof(default_groups));
+ if (!bss->conf->sae_groups)
+ return -1;
+ }
+
+ len = os_strlen(password);
+ bss->conf->ssid.wpa_passphrase = dup_binstr(password, len);
+
+ wpa_s->mesh_rsn = mesh_rsn_auth_init(wpa_s, ifmsh->mconf);
+ return !wpa_s->mesh_rsn ? -1 : 0;
+}
+
+
+static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)
+{
+ struct hostapd_iface *ifmsh = wpa_s->ifmsh;
+ struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params;
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ int ret;
+
+ if (!params || !ssid || !ifmsh) {
+ wpa_printf(MSG_ERROR, "mesh: %s called without active mesh",
+ __func__);
+ return -1;
+ }
+
+ if (ifmsh->mconf->security != MESH_CONF_SEC_NONE &&
+ wpas_mesh_init_rsn(wpa_s)) {
+ wpa_printf(MSG_ERROR,
+ "mesh: RSN initialization failed - deinit mesh");
+ wpa_supplicant_mesh_deinit(wpa_s);
+ return -1;
+ }
+
+ if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
+ wpa_s->pairwise_cipher = wpa_s->mesh_rsn->pairwise_cipher;
+ wpa_s->group_cipher = wpa_s->mesh_rsn->group_cipher;
+ wpa_s->mgmt_group_cipher = wpa_s->mesh_rsn->mgmt_group_cipher;
+ }
+
+ params->ies = ifmsh->mconf->rsn_ie;
+ params->ie_len = ifmsh->mconf->rsn_ie_len;
+ params->basic_rates = ifmsh->basic_rates;
+ params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
+ params->conf.ht_opmode = ifmsh->bss[0]->iface->ht_op_mode;
+
+ wpa_msg(wpa_s, MSG_INFO, "joining mesh %s",
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+ ret = wpa_drv_join_mesh(wpa_s, params);
+ if (ret)
+ wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d", ret);
+
+ /* hostapd sets the interface down until we associate */
+ wpa_drv_set_operstate(wpa_s, 1);
+
+ if (!ret)
+ wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+
+ return ret;
+}
+
+
static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid)
+ struct wpa_ssid *ssid,
+ struct hostapd_freq_params *freq)
{
struct hostapd_iface *ifmsh;
struct hostapd_data *bss;
struct hostapd_config *conf;
struct mesh_conf *mconf;
int basic_rates_erp[] = { 10, 20, 55, 60, 110, 120, 240, -1 };
- static int default_groups[] = { 19, 20, 21, 25, 26, -1 };
- size_t len;
int rate_len;
+ int frequency;
if (!wpa_s->conf->user_mpm) {
/* not much for us to do here */
@@ -164,7 +258,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
return 0;
}
- wpa_s->ifmsh = ifmsh = os_zalloc(sizeof(*wpa_s->ifmsh));
+ wpa_s->ifmsh = ifmsh = hostapd_alloc_iface();
if (!ifmsh)
return -ENOMEM;
@@ -175,17 +269,23 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
if (!ifmsh->bss)
goto out_free;
- ifmsh->bss[0] = bss = os_zalloc(sizeof(struct hostapd_data));
+ ifmsh->bss[0] = bss = hostapd_alloc_bss_data(NULL, NULL, NULL);
if (!bss)
goto out_free;
- dl_list_init(&bss->nr_db);
+ ifmsh->bss[0]->msg_ctx = wpa_s;
os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
bss->driver = wpa_s->driver;
bss->drv_priv = wpa_s->drv_priv;
bss->iface = ifmsh;
bss->mesh_sta_free_cb = mesh_mpm_free_sta;
- wpa_s->assoc_freq = ssid->frequency;
+ frequency = ssid->frequency;
+ if (frequency != freq->freq &&
+ frequency == freq->freq + freq->sec_channel_offset * 20) {
+ wpa_printf(MSG_DEBUG, "mesh: pri/sec channels switched");
+ frequency = freq->freq;
+ }
+ wpa_s->assoc_freq = frequency;
wpa_s->current_ssid = ssid;
/* setup an AP config for auth processing */
@@ -197,6 +297,16 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
bss->conf->start_disabled = 1;
bss->conf->mesh = MESH_ENABLED;
bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
+
+ if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes,
+ wpa_s->hw.num_modes) && wpa_s->conf->country[0]) {
+ conf->ieee80211h = 1;
+ conf->ieee80211d = 1;
+ conf->country[0] = wpa_s->conf->country[0];
+ conf->country[1] = wpa_s->conf->country[1];
+ conf->country[2] = ' ';
+ }
+
bss->iconf = conf;
ifmsh->conf = conf;
@@ -211,27 +321,28 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
ifmsh->mconf = mconf;
/* need conf->hw_mode for supported rates. */
- conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency, &conf->channel);
+ conf->hw_mode = ieee80211_freq_to_chan(frequency, &conf->channel);
if (conf->hw_mode == NUM_HOSTAPD_MODES) {
wpa_printf(MSG_ERROR, "Unsupported mesh mode frequency: %d MHz",
- ssid->frequency);
+ frequency);
goto out_free;
}
if (ssid->ht40)
conf->secondary_channel = ssid->ht40;
if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && ssid->vht) {
- conf->vht_oper_chwidth = ssid->max_oper_chwidth;
+ if (ssid->max_oper_chwidth != DEFAULT_MAX_OPER_CHWIDTH)
+ conf->vht_oper_chwidth = ssid->max_oper_chwidth;
switch (conf->vht_oper_chwidth) {
case VHT_CHANWIDTH_80MHZ:
case VHT_CHANWIDTH_80P80MHZ:
ieee80211_freq_to_chan(
- ssid->frequency,
+ frequency,
&conf->vht_oper_centr_freq_seg0_idx);
conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2;
break;
case VHT_CHANWIDTH_160MHZ:
ieee80211_freq_to_chan(
- ssid->frequency,
+ frequency,
&conf->vht_oper_centr_freq_seg0_idx);
conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2;
conf->vht_oper_centr_freq_seg0_idx += 40 / 5;
@@ -250,11 +361,10 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
* advertised in beacons match the one in peering frames, sigh.
*/
if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
- conf->basic_rates = os_malloc(sizeof(basic_rates_erp));
+ conf->basic_rates = os_memdup(basic_rates_erp,
+ sizeof(basic_rates_erp));
if (!conf->basic_rates)
goto out_free;
- os_memcpy(conf->basic_rates, basic_rates_erp,
- sizeof(basic_rates_erp));
}
} else {
rate_len = 0;
@@ -271,46 +381,15 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
conf->basic_rates[rate_len] = -1;
}
- if (hostapd_setup_interface(ifmsh)) {
- wpa_printf(MSG_ERROR,
- "Failed to initialize hostapd interface for mesh");
- return -1;
- }
-
if (wpa_drv_init_mesh(wpa_s)) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
return -1;
}
- if (mconf->security != MESH_CONF_SEC_NONE) {
- if (ssid->passphrase == NULL) {
- wpa_printf(MSG_ERROR,
- "mesh: Passphrase for SAE not configured");
- goto out_free;
- }
-
- bss->conf->wpa = ssid->proto;
- bss->conf->wpa_key_mgmt = ssid->key_mgmt;
-
- if (wpa_s->conf->sae_groups &&
- wpa_s->conf->sae_groups[0] > 0) {
- wpas_mesh_copy_groups(bss, wpa_s);
- } else {
- bss->conf->sae_groups =
- os_malloc(sizeof(default_groups));
- if (!bss->conf->sae_groups)
- goto out_free;
- os_memcpy(bss->conf->sae_groups, default_groups,
- sizeof(default_groups));
- }
-
- len = os_strlen(ssid->passphrase);
- bss->conf->ssid.wpa_passphrase =
- dup_binstr(ssid->passphrase, len);
-
- wpa_s->mesh_rsn = mesh_rsn_auth_init(wpa_s, mconf);
- if (!wpa_s->mesh_rsn)
- goto out_free;
+ if (hostapd_setup_interface(ifmsh)) {
+ wpa_printf(MSG_ERROR,
+ "Failed to initialize hostapd interface for mesh");
+ return -1;
}
wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
@@ -355,11 +434,13 @@ void wpa_supplicant_mesh_add_scan_ie(struct wpa_supplicant *wpa_s,
int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
- struct wpa_driver_mesh_join_params params;
+ struct wpa_driver_mesh_join_params *params = os_zalloc(sizeof(*params));
int ret = 0;
- if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency) {
+ if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency ||
+ !params) {
ret = -ENOENT;
+ os_free(params);
goto out;
}
@@ -369,22 +450,23 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
wpa_s->group_cipher = WPA_CIPHER_NONE;
wpa_s->mgmt_group_cipher = 0;
- os_memset(&params, 0, sizeof(params));
- params.meshid = ssid->ssid;
- params.meshid_len = ssid->ssid_len;
- ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
- wpa_s->mesh_ht_enabled = !!params.freq.ht_enabled;
- wpa_s->mesh_vht_enabled = !!params.freq.vht_enabled;
- if (params.freq.ht_enabled && params.freq.sec_channel_offset)
- ssid->ht40 = params.freq.sec_channel_offset;
+ params->meshid = ssid->ssid;
+ params->meshid_len = ssid->ssid_len;
+ ibss_mesh_setup_freq(wpa_s, ssid, &params->freq);
+ wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled;
+ wpa_s->mesh_vht_enabled = !!params->freq.vht_enabled;
+ if (params->freq.ht_enabled && params->freq.sec_channel_offset)
+ ssid->ht40 = params->freq.sec_channel_offset;
+
if (wpa_s->mesh_vht_enabled) {
ssid->vht = 1;
- switch (params.freq.bandwidth) {
+ ssid->vht_center_freq1 = params->freq.center_freq1;
+ switch (params->freq.bandwidth) {
case 80:
- if (params.freq.center_freq2) {
+ if (params->freq.center_freq2) {
ssid->max_oper_chwidth = VHT_CHANWIDTH_80P80MHZ;
ssid->vht_center_freq2 =
- params.freq.center_freq2;
+ params->freq.center_freq2;
} else {
ssid->max_oper_chwidth = VHT_CHANWIDTH_80MHZ;
}
@@ -398,63 +480,44 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
}
}
if (ssid->beacon_int > 0)
- params.beacon_int = ssid->beacon_int;
+ params->beacon_int = ssid->beacon_int;
else if (wpa_s->conf->beacon_int > 0)
- params.beacon_int = wpa_s->conf->beacon_int;
+ params->beacon_int = wpa_s->conf->beacon_int;
if (ssid->dtim_period > 0)
- params.dtim_period = ssid->dtim_period;
+ params->dtim_period = ssid->dtim_period;
else if (wpa_s->conf->dtim_period > 0)
- params.dtim_period = wpa_s->conf->dtim_period;
- params.conf.max_peer_links = wpa_s->conf->max_peer_links;
+ params->dtim_period = wpa_s->conf->dtim_period;
+ params->conf.max_peer_links = wpa_s->conf->max_peer_links;
+ if (ssid->mesh_rssi_threshold < DEFAULT_MESH_RSSI_THRESHOLD) {
+ params->conf.rssi_threshold = ssid->mesh_rssi_threshold;
+ params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD;
+ }
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
- params.flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
- params.flags |= WPA_DRIVER_MESH_FLAG_AMPE;
+ params->flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
+ params->flags |= WPA_DRIVER_MESH_FLAG_AMPE;
wpa_s->conf->user_mpm = 1;
}
if (wpa_s->conf->user_mpm) {
- params.flags |= WPA_DRIVER_MESH_FLAG_USER_MPM;
- params.conf.auto_plinks = 0;
+ params->flags |= WPA_DRIVER_MESH_FLAG_USER_MPM;
+ params->conf.auto_plinks = 0;
} else {
- params.flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM;
- params.conf.auto_plinks = 1;
+ params->flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM;
+ params->conf.auto_plinks = 1;
}
- params.conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
+ params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
- if (wpa_supplicant_mesh_init(wpa_s, ssid)) {
+ os_free(wpa_s->mesh_params);
+ wpa_s->mesh_params = params;
+ if (wpa_supplicant_mesh_init(wpa_s, ssid, &params->freq)) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh");
wpa_drv_leave_mesh(wpa_s);
ret = -1;
goto out;
}
- if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
- wpa_s->pairwise_cipher = wpa_s->mesh_rsn->pairwise_cipher;
- wpa_s->group_cipher = wpa_s->mesh_rsn->group_cipher;
- wpa_s->mgmt_group_cipher = wpa_s->mesh_rsn->mgmt_group_cipher;
- }
-
- if (wpa_s->ifmsh) {
- params.ies = wpa_s->ifmsh->mconf->rsn_ie;
- params.ie_len = wpa_s->ifmsh->mconf->rsn_ie_len;
- params.basic_rates = wpa_s->ifmsh->basic_rates;
- params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
- params.conf.ht_opmode = wpa_s->ifmsh->bss[0]->iface->ht_op_mode;
- }
-
- wpa_msg(wpa_s, MSG_INFO, "joining mesh %s",
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
- ret = wpa_drv_join_mesh(wpa_s, &params);
- if (ret)
- wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d", ret);
-
- /* hostapd sets the interface down until we associate */
- wpa_drv_set_operstate(wpa_s, 1);
-
- if (!ret)
- wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
-
+ ret = wpas_mesh_complete(wpa_s);
out:
return ret;
}
diff --git a/contrib/wpa/wpa_supplicant/mesh_mpm.c b/contrib/wpa/wpa_supplicant/mesh_mpm.c
index d14c7e3b2045..9d6ab8da1ebe 100644
--- a/contrib/wpa/wpa_supplicant/mesh_mpm.c
+++ b/contrib/wpa/wpa_supplicant/mesh_mpm.c
@@ -11,6 +11,8 @@
#include "utils/common.h"
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
+#include "common/hw_features_common.h"
+#include "common/ocv.h"
#include "ap/hostapd.h"
#include "ap/sta_info.h"
#include "ap/ieee802_11.h"
@@ -19,6 +21,7 @@
#include "driver_i.h"
#include "mesh_mpm.h"
#include "mesh_rsn.h"
+#include "notify.h"
struct mesh_peer_mgmt_ie {
const u8 *proto_id; /* Mesh Peering Protocol Identifier (2 octets) */
@@ -186,7 +189,7 @@ static void mesh_mpm_init_link(struct wpa_supplicant *wpa_s,
do {
if (os_get_random((u8 *) &llid, sizeof(llid)) < 0)
- continue;
+ llid = 0; /* continue */
} while (!llid || llid_in_use(wpa_s, llid));
sta->my_lid = llid;
@@ -220,13 +223,14 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
if (!sta)
return;
- buf_len = 2 + /* capability info */
+ buf_len = 2 + /* Category and Action */
+ 2 + /* capability info */
2 + /* AID */
2 + 8 + /* supported rates */
2 + (32 - 8) +
2 + 32 + /* mesh ID */
2 + 7 + /* mesh config */
- 2 + 23 + /* peering management */
+ 2 + 24 + /* peering management */
2 + 96 + /* AMPE */
2 + 16; /* MIC */
#ifdef CONFIG_IEEE80211N
@@ -243,6 +247,11 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_IEEE80211AC */
if (type != PLINK_CLOSE)
buf_len += conf->rsn_ie_len; /* RSN IE */
+#ifdef CONFIG_OCV
+ /* OCI is included even when the other STA doesn't support OCV */
+ if (type != PLINK_CLOSE && conf->ocv)
+ buf_len += OCV_OCI_EXTENDED_LEN;
+#endif /* CONFIG_OCV */
buf = wpabuf_alloc(buf_len);
if (!buf)
@@ -354,6 +363,22 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_IEEE80211AC */
+#ifdef CONFIG_OCV
+ if (type != PLINK_CLOSE && conf->ocv) {
+ struct wpa_channel_info ci;
+
+ if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Mesh MPM: Failed to get channel info for OCI element");
+ goto fail;
+ }
+
+ pos = wpabuf_put(buf, OCV_OCI_EXTENDED_LEN);
+ if (ocv_insert_extended_oci(&ci, pos) < 0)
+ goto fail;
+ }
+#endif /* CONFIG_OCV */
+
if (ampe && mesh_rsn_protect_frame(wpa_s->mesh_rsn, sta, cat, buf)) {
wpa_msg(wpa_s, MSG_INFO,
"Mesh MPM: failed to add AMPE and MIC IE");
@@ -435,7 +460,7 @@ static void plink_timer(void *eloop_ctx, void *user_data)
break;
}
reason = WLAN_REASON_MESH_MAX_RETRIES;
- /* fall through on else */
+ /* fall through */
case PLINK_CNF_RCVD:
/* confirm timer */
@@ -646,6 +671,9 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s,
struct mesh_conf *conf = wpa_s->ifmsh->mconf;
struct hostapd_data *data = wpa_s->ifmsh->bss[0];
struct sta_info *sta;
+#ifdef CONFIG_IEEE80211N
+ struct ieee80211_ht_operation *oper;
+#endif /* CONFIG_IEEE80211N */
int ret;
if (elems->mesh_config_len >= 7 &&
@@ -677,11 +705,23 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_IEEE80211N
copy_sta_ht_capab(data, sta, elems->ht_capabilities);
+
+ oper = (struct ieee80211_ht_operation *) elems->ht_operation;
+ if (oper &&
+ !(oper->ht_param & HT_INFO_HT_PARAM_STA_CHNL_WIDTH) &&
+ sta->ht_capabilities) {
+ wpa_msg(wpa_s, MSG_DEBUG, MACSTR
+ " does not support 40 MHz bandwidth",
+ MAC2STR(sta->addr));
+ set_disable_ht40(sta->ht_capabilities, 1);
+ }
+
update_ht_state(data, sta);
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
copy_sta_vht_capab(data, sta, elems->vht_capabilities);
+ copy_sta_vht_oper(data, sta, elems->vht_operation);
set_sta_vht_opmode(data, sta, elems->vht_opmode_notif);
#endif /* CONFIG_IEEE80211AC */
@@ -842,6 +882,9 @@ static void mesh_mpm_plink_estab(struct wpa_supplicant *wpa_s,
/* Send ctrl event */
wpa_msg(wpa_s, MSG_INFO, MESH_PEER_CONNECTED MACSTR,
MAC2STR(sta->addr));
+
+ /* Send D-Bus event */
+ wpas_notify_mesh_peer_connected(wpa_s, sta->addr);
}
@@ -994,6 +1037,10 @@ static void mesh_mpm_fsm(struct wpa_supplicant *wpa_s, struct sta_info *sta,
wpa_msg(wpa_s, MSG_INFO, MESH_PEER_DISCONNECTED MACSTR,
MAC2STR(sta->addr));
+ /* Send D-Bus event */
+ wpas_notify_mesh_peer_disconnected(wpa_s, sta->addr,
+ reason);
+
hapd->num_plinks--;
mesh_mpm_send_plink_action(wpa_s, sta,
@@ -1135,7 +1182,7 @@ void mesh_mpm_action_rx(struct wpa_supplicant *wpa_s,
*/
if (!sta && action_field == PLINK_OPEN &&
(!(mconf->security & MESH_CONF_SEC_AMPE) ||
- wpa_auth_pmksa_get(hapd->wpa_auth, mgmt->sa)))
+ wpa_auth_pmksa_get(hapd->wpa_auth, mgmt->sa, NULL)))
sta = mesh_mpm_add_peer(wpa_s, mgmt->sa, &elems);
if (!sta) {
@@ -1172,6 +1219,56 @@ void mesh_mpm_action_rx(struct wpa_supplicant *wpa_s,
}
return;
}
+
+#ifdef CONFIG_OCV
+ if (action_field == PLINK_OPEN && elems.rsn_ie) {
+ struct wpa_state_machine *sm = sta->wpa_sm;
+ struct wpa_ie_data data;
+
+ res = wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2,
+ elems.rsn_ie_len + 2,
+ &data);
+ if (res) {
+ wpa_printf(MSG_DEBUG,
+ "Failed to parse RSN IE (res=%d)",
+ res);
+ wpa_hexdump(MSG_DEBUG, "RSN IE", elems.rsn_ie,
+ elems.rsn_ie_len);
+ return;
+ }
+
+ wpa_auth_set_ocv(sm, mconf->ocv &&
+ (data.capabilities &
+ WPA_CAPABILITY_OCVC));
+ }
+
+ if (action_field != PLINK_CLOSE &&
+ wpa_auth_uses_ocv(sta->wpa_sm)) {
+ struct wpa_channel_info ci;
+ int tx_chanwidth;
+ int tx_seg1_idx;
+
+ if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "MPM: Failed to get channel info to validate received OCI in MPM Confirm");
+ return;
+ }
+
+ if (get_tx_parameters(
+ sta, channel_width_to_int(ci.chanwidth),
+ ci.seg1_idx, &tx_chanwidth,
+ &tx_seg1_idx) < 0)
+ return;
+
+ if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
+ tx_chanwidth, tx_seg1_idx) !=
+ 0) {
+ wpa_printf(MSG_WARNING, "MPM: %s",
+ ocv_errorstr);
+ return;
+ }
+ }
+#endif /* CONFIG_OCV */
}
if (sta->plink_state == PLINK_BLOCKED) {
diff --git a/contrib/wpa/wpa_supplicant/mesh_rsn.c b/contrib/wpa/wpa_supplicant/mesh_rsn.c
index 27ab8cb36458..4b8d6c469173 100644
--- a/contrib/wpa/wpa_supplicant/mesh_rsn.c
+++ b/contrib/wpa/wpa_supplicant/mesh_rsn.c
@@ -75,12 +75,17 @@ static void auth_logger(void *ctx, const u8 *addr, logger_level level,
static const u8 *auth_get_psk(void *ctx, const u8 *addr,
- const u8 *p2p_dev_addr, const u8 *prev_psk)
+ const u8 *p2p_dev_addr, const u8 *prev_psk,
+ size_t *psk_len, int *vlan_id)
{
struct mesh_rsn *mesh_rsn = ctx;
struct hostapd_data *hapd = mesh_rsn->wpa_s->ifmsh->bss[0];
struct sta_info *sta = ap_get_sta(hapd, addr);
+ if (psk_len)
+ *psk_len = PMK_LEN;
+ if (vlan_id)
+ *vlan_id = 0;
wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)",
__func__, MAC2STR(addr), prev_psk);
@@ -137,10 +142,15 @@ static int auth_start_ampe(void *ctx, const u8 *addr)
static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
- enum mfp_options ieee80211w)
+ enum mfp_options ieee80211w, int ocv)
{
struct wpa_auth_config conf;
- struct wpa_auth_callbacks cb;
+ static const struct wpa_auth_callbacks cb = {
+ .logger = auth_logger,
+ .get_psk = auth_get_psk,
+ .set_key = auth_set_key,
+ .start_ampe = auth_start_ampe,
+ };
u8 seq[6] = {};
wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine");
@@ -153,20 +163,18 @@ static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
conf.wpa_group = rsn->group_cipher;
conf.eapol_version = 0;
conf.wpa_group_rekey = -1;
+ conf.wpa_group_update_count = 4;
+ conf.wpa_pairwise_update_count = 4;
#ifdef CONFIG_IEEE80211W
conf.ieee80211w = ieee80211w;
if (ieee80211w != NO_MGMT_FRAME_PROTECTION)
conf.group_mgmt_cipher = rsn->mgmt_group_cipher;
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+ conf.ocv = ocv;
+#endif /* CONFIG_OCV */
- os_memset(&cb, 0, sizeof(cb));
- cb.ctx = rsn;
- cb.logger = auth_logger;
- cb.get_psk = auth_get_psk;
- cb.set_key = auth_set_key;
- cb.start_ampe = auth_start_ampe;
-
- rsn->auth = wpa_init(addr, &conf, &cb);
+ rsn->auth = wpa_init(addr, &conf, &cb, rsn);
if (rsn->auth == NULL) {
wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed");
return -1;
@@ -224,6 +232,9 @@ struct mesh_rsn *mesh_rsn_auth_init(struct wpa_supplicant *wpa_s,
struct hostapd_data *bss = wpa_s->ifmsh->bss[0];
const u8 *ie;
size_t ie_len;
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+ struct external_pmksa_cache *entry;
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
mesh_rsn = os_zalloc(sizeof(*mesh_rsn));
if (mesh_rsn == NULL)
@@ -234,7 +245,7 @@ struct mesh_rsn *mesh_rsn_auth_init(struct wpa_supplicant *wpa_s,
mesh_rsn->mgmt_group_cipher = conf->mgmt_group_cipher;
if (__mesh_rsn_auth_init(mesh_rsn, wpa_s->own_addr,
- conf->ieee80211w) < 0) {
+ conf->ieee80211w, conf->ocv) < 0) {
mesh_rsn_deinit(mesh_rsn);
os_free(mesh_rsn);
return NULL;
@@ -242,6 +253,22 @@ struct mesh_rsn *mesh_rsn_auth_init(struct wpa_supplicant *wpa_s,
bss->wpa_auth = mesh_rsn->auth;
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+ while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
+ struct external_pmksa_cache,
+ list)) != NULL) {
+ int ret;
+
+ ret = wpa_auth_pmksa_add_entry(bss->wpa_auth,
+ entry->pmksa_cache);
+ dl_list_del(&entry->list);
+ os_free(entry);
+
+ if (ret < 0)
+ return NULL;
+ }
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
ie = wpa_auth_get_wpa_ie(mesh_rsn->auth, &ie_len);
conf->rsn_ie = (u8 *) ie;
conf->rsn_ie_len = ie_len;
@@ -295,7 +322,12 @@ static int mesh_rsn_build_sae_commit(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
struct sta_info *sta)
{
- if (ssid->passphrase == NULL) {
+ const char *password;
+
+ password = ssid->sae_password;
+ if (!password)
+ password = ssid->passphrase;
+ if (!password) {
wpa_msg(wpa_s, MSG_DEBUG, "SAE: No password available");
return -1;
}
@@ -305,9 +337,15 @@ static int mesh_rsn_build_sae_commit(struct wpa_supplicant *wpa_s,
return -1;
}
+ if (sta->sae->tmp && !sta->sae->tmp->pw_id && ssid->sae_password_id) {
+ sta->sae->tmp->pw_id = os_strdup(ssid->sae_password_id);
+ if (!sta->sae->tmp->pw_id)
+ return -1;
+ }
return sae_prepare_commit(wpa_s->own_addr, sta->addr,
- (u8 *) ssid->passphrase,
- os_strlen(ssid->passphrase), sta->sae);
+ (u8 *) password, os_strlen(password),
+ ssid->sae_password_id,
+ sta->sae);
}
@@ -333,7 +371,7 @@ int mesh_rsn_auth_sae_sta(struct wpa_supplicant *wpa_s,
return -1;
}
- pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr);
+ pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr, NULL);
if (pmksa) {
if (!sta->wpa_sm)
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
@@ -579,7 +617,7 @@ skip_keys:
/* encrypt after MIC */
mic_payload = wpabuf_put(buf, 2 + len + AES_BLOCK_SIZE);
- if (aes_siv_encrypt(sta->aek, ampe_ie, 2 + len, 3,
+ if (aes_siv_encrypt(sta->aek, sizeof(sta->aek), ampe_ie, 2 + len, 3,
aad, aad_len, mic_payload)) {
wpa_printf(MSG_ERROR, "protect frame: failed to encrypt");
ret = -ENOMEM;
@@ -605,13 +643,13 @@ int mesh_rsn_process_ampe(struct wpa_supplicant *wpa_s, struct sta_info *sta,
size_t crypt_len;
const u8 *aad[] = { sta->addr, wpa_s->own_addr, cat };
const size_t aad_len[] = { ETH_ALEN, ETH_ALEN,
- (elems->mic - 2) - cat };
+ elems->mic ? (elems->mic - 2) - cat : 0 };
size_t key_len;
if (!sta->sae) {
struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
- if (!wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr)) {
+ if (!wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr, NULL)) {
wpa_printf(MSG_INFO,
"Mesh RSN: SAE is not prepared yet");
return -1;
@@ -619,7 +657,9 @@ int mesh_rsn_process_ampe(struct wpa_supplicant *wpa_s, struct sta_info *sta,
mesh_rsn_auth_sae_sta(wpa_s, sta);
}
- if (chosen_pmk && os_memcmp(chosen_pmk, sta->sae->pmkid, PMKID_LEN)) {
+ if (chosen_pmk &&
+ (!sta->sae ||
+ os_memcmp(chosen_pmk, sta->sae->pmkid, PMKID_LEN) != 0)) {
wpa_msg(wpa_s, MSG_DEBUG,
"Mesh RSN: Invalid PMKID (Chosen PMK did not match calculated PMKID)");
return -1;
@@ -650,7 +690,7 @@ int mesh_rsn_process_ampe(struct wpa_supplicant *wpa_s, struct sta_info *sta,
os_memcpy(crypt, elems->mic, crypt_len);
- if (aes_siv_decrypt(sta->aek, crypt, crypt_len, 3,
+ if (aes_siv_decrypt(sta->aek, sizeof(sta->aek), crypt, crypt_len, 3,
aad, aad_len, ampe_buf)) {
wpa_printf(MSG_ERROR, "Mesh RSN: frame verification failed!");
ret = -2;
diff --git a/contrib/wpa/wpa_supplicant/notify.c b/contrib/wpa/wpa_supplicant/notify.c
index 67e36ae34cb8..bedb74b34440 100644
--- a/contrib/wpa/wpa_supplicant/notify.c
+++ b/contrib/wpa/wpa_supplicant/notify.c
@@ -15,7 +15,6 @@
#include "wps_supplicant.h"
#include "binder/binder.h"
#include "dbus/dbus_common.h"
-#include "dbus/dbus_old.h"
#include "dbus/dbus_new.h"
#include "rsn_supp/wpa.h"
#include "fst/fst.h"
@@ -27,13 +26,13 @@
int wpas_notify_supplicant_initialized(struct wpa_global *global)
{
-#ifdef CONFIG_DBUS
+#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
if (global->params.dbus_ctrl_interface) {
global->dbus = wpas_dbus_init(global);
if (global->dbus == NULL)
return -1;
}
-#endif /* CONFIG_DBUS */
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
#ifdef CONFIG_BINDER
global->binder = wpas_binder_init(global);
@@ -47,10 +46,10 @@ int wpas_notify_supplicant_initialized(struct wpa_global *global)
void wpas_notify_supplicant_deinitialized(struct wpa_global *global)
{
-#ifdef CONFIG_DBUS
+#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
if (global->dbus)
wpas_dbus_deinit(global->dbus);
-#endif /* CONFIG_DBUS */
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
#ifdef CONFIG_BINDER
if (global->binder)
@@ -64,9 +63,6 @@ int wpas_notify_iface_added(struct wpa_supplicant *wpa_s)
if (wpa_s->p2p_mgmt)
return 0;
- if (wpas_dbus_register_iface(wpa_s))
- return -1;
-
if (wpas_dbus_register_interface(wpa_s))
return -1;
@@ -79,9 +75,6 @@ void wpas_notify_iface_removed(struct wpa_supplicant *wpa_s)
if (wpa_s->p2p_mgmt)
return;
- /* unregister interface in old DBus ctrl iface */
- wpas_dbus_unregister_iface(wpa_s);
-
/* unregister interface in new DBus ctrl iface */
wpas_dbus_unregister_interface(wpa_s);
}
@@ -94,10 +87,6 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s,
if (wpa_s->p2p_mgmt)
return;
- /* notify the old DBus API */
- wpa_supplicant_dbus_notify_state_change(wpa_s, new_state,
- old_state);
-
/* notify the new DBus API */
wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATE);
@@ -140,6 +129,15 @@ void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s)
}
+void wpas_notify_auth_status_code(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_AUTH_STATUS_CODE);
+}
+
+
void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s)
{
if (wpa_s->p2p_mgmt)
@@ -149,6 +147,42 @@ void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s)
}
+void wpas_notify_roam_time(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_ROAM_TIME);
+}
+
+
+void wpas_notify_roam_complete(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_ROAM_COMPLETE);
+}
+
+
+void wpas_notify_session_length(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_SESSION_LENGTH);
+}
+
+
+void wpas_notify_bss_tm_status(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSS_TM_STATUS);
+}
+
+
void wpas_notify_network_changed(struct wpa_supplicant *wpa_s)
{
if (wpa_s->p2p_mgmt)
@@ -222,9 +256,6 @@ void wpas_notify_scanning(struct wpa_supplicant *wpa_s)
if (wpa_s->p2p_mgmt)
return;
- /* notify the old DBus API */
- wpa_supplicant_dbus_notify_scanning(wpa_s);
-
/* notify the new DBus API */
wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_SCANNING);
}
@@ -244,9 +275,6 @@ void wpas_notify_scan_results(struct wpa_supplicant *wpa_s)
if (wpa_s->p2p_mgmt)
return;
- /* notify the old DBus API */
- wpa_supplicant_dbus_notify_scan_results(wpa_s);
-
wpas_wps_notify_scan_results(wpa_s);
}
@@ -258,8 +286,6 @@ void wpas_notify_wps_credential(struct wpa_supplicant *wpa_s,
return;
#ifdef CONFIG_WPS
- /* notify the old DBus API */
- wpa_supplicant_dbus_notify_wps_cred(wpa_s, cred);
/* notify the new DBus API */
wpas_dbus_signal_wps_cred(wpa_s, cred);
#endif /* CONFIG_WPS */
@@ -669,12 +695,12 @@ void wpas_notify_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int persistent,
- int client)
+ int client, const u8 *ip)
{
/* Notify a group has been started */
wpas_dbus_register_p2p_group(wpa_s, ssid);
- wpas_dbus_signal_p2p_group_started(wpa_s, client, persistent);
+ wpas_dbus_signal_p2p_group_started(wpa_s, client, persistent, ip);
}
@@ -720,6 +746,9 @@ static void wpas_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
wpas_dbus_signal_p2p_peer_joined(wpa_s, p2p_dev_addr);
#endif /* CONFIG_P2P */
+ /* Register the station */
+ wpas_dbus_register_sta(wpa_s, sta);
+
/* Notify listeners a new station has been authorized */
wpas_dbus_signal_sta_authorized(wpa_s, sta);
}
@@ -740,6 +769,9 @@ static void wpas_notify_ap_sta_deauthorized(struct wpa_supplicant *wpa_s,
/* Notify listeners a station has been deauthorized */
wpas_dbus_signal_sta_deauthorized(wpa_s, sta);
+
+ /* Unregister the station */
+ wpas_dbus_unregister_sta(wpa_s, sta);
}
@@ -787,9 +819,6 @@ void wpas_notify_certification(struct wpa_supplicant *wpa_s, int depth,
"depth=%d %s", depth, altsubject[i]);
}
- /* notify the old DBus API */
- wpa_supplicant_dbus_notify_certification(wpa_s, depth, subject,
- cert_hash, cert);
/* notify the new DBus API */
wpas_dbus_signal_certification(wpa_s, depth, subject, altsubject,
num_altsubject, cert_hash, cert);
@@ -816,6 +845,12 @@ void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status,
}
+void wpas_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code)
+{
+ wpa_msg(wpa_s, MSG_ERROR, WPA_EVENT_EAP_ERROR_CODE "%d", error_code);
+}
+
+
void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
@@ -850,3 +885,49 @@ void wpas_notify_network_type_changed(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_P2P */
}
+
+
+#ifdef CONFIG_MESH
+
+void wpas_notify_mesh_group_started(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_mesh_group_started(wpa_s, ssid);
+}
+
+
+void wpas_notify_mesh_group_removed(struct wpa_supplicant *wpa_s,
+ const u8 *meshid, u8 meshid_len,
+ int reason_code)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_mesh_group_removed(wpa_s, meshid, meshid_len,
+ reason_code);
+}
+
+
+void wpas_notify_mesh_peer_connected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_mesh_peer_connected(wpa_s, peer_addr);
+}
+
+
+void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr, int reason_code)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_mesh_peer_disconnected(wpa_s, peer_addr, reason_code);
+}
+
+#endif /* CONFIG_MESH */
diff --git a/contrib/wpa/wpa_supplicant/notify.h b/contrib/wpa/wpa_supplicant/notify.h
index 8cce0f30c2a9..65f513ea9770 100644
--- a/contrib/wpa/wpa_supplicant/notify.h
+++ b/contrib/wpa/wpa_supplicant/notify.h
@@ -23,7 +23,12 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s,
enum wpa_states new_state,
enum wpa_states old_state);
void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s);
+void wpas_notify_auth_status_code(struct wpa_supplicant *wpa_s);
void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s);
+void wpas_notify_roam_time(struct wpa_supplicant *wpa_s);
+void wpas_notify_roam_complete(struct wpa_supplicant *wpa_s);
+void wpas_notify_session_length(struct wpa_supplicant *wpa_s);
+void wpas_notify_bss_tm_status(struct wpa_supplicant *wpa_s);
void wpas_notify_network_changed(struct wpa_supplicant *wpa_s);
void wpas_notify_ap_scan_changed(struct wpa_supplicant *wpa_s);
void wpas_notify_bssid_changed(struct wpa_supplicant *wpa_s);
@@ -114,7 +119,7 @@ void wpas_notify_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
unsigned int generated_pin);
void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int persistent,
- int client);
+ int client, const u8 *ip);
void wpas_notify_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
const char *reason);
void wpas_notify_persistent_group_added(struct wpa_supplicant *wpa_s,
@@ -134,6 +139,7 @@ void wpas_notify_preq(struct wpa_supplicant *wpa_s,
const u8 *ie, size_t ie_len, u32 ssi_signal);
void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status,
const char *parameter);
+void wpas_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code);
void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
void wpas_notify_network_type_changed(struct wpa_supplicant *wpa_s,
@@ -141,5 +147,14 @@ void wpas_notify_network_type_changed(struct wpa_supplicant *wpa_s,
void wpas_notify_p2p_invitation_received(struct wpa_supplicant *wpa_s,
const u8 *sa, const u8 *go_dev_addr,
const u8 *bssid, int id, int op_freq);
+void wpas_notify_mesh_group_started(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
+void wpas_notify_mesh_group_removed(struct wpa_supplicant *wpa_s,
+ const u8 *meshid, u8 meshid_len,
+ int reason_code);
+void wpas_notify_mesh_peer_connected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr);
+void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr, int reason_code);
#endif /* NOTIFY_H */
diff --git a/contrib/wpa/wpa_supplicant/offchannel.c b/contrib/wpa/wpa_supplicant/offchannel.c
index 26d41a4ad5c6..b74be7dad4ac 100644
--- a/contrib/wpa/wpa_supplicant/offchannel.c
+++ b/contrib/wpa/wpa_supplicant/offchannel.c
@@ -310,6 +310,8 @@ int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
iface = wpas_get_tx_interface(wpa_s, src);
wpa_s->action_tx_wait_time = wait_time;
+ if (wait_time)
+ wpa_s->action_tx_wait_time_used = 1;
ret = wpa_drv_send_action(
iface, wpa_s->pending_action_freq,
@@ -398,13 +400,14 @@ void offchannel_send_action_done(struct wpa_supplicant *wpa_s)
wpabuf_free(wpa_s->pending_action_tx);
wpa_s->pending_action_tx = NULL;
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX &&
- wpa_s->action_tx_wait_time)
+ (wpa_s->action_tx_wait_time || wpa_s->action_tx_wait_time_used))
wpa_drv_send_action_cancel_wait(wpa_s);
else if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
wpa_drv_cancel_remain_on_channel(wpa_s);
wpa_s->off_channel_freq = 0;
wpa_s->roc_waiting_drv_freq = 0;
}
+ wpa_s->action_tx_wait_time_used = 0;
}
diff --git a/contrib/wpa/wpa_supplicant/op_classes.c b/contrib/wpa/wpa_supplicant/op_classes.c
new file mode 100644
index 000000000000..947917bb05f4
--- /dev/null
+++ b/contrib/wpa/wpa_supplicant/op_classes.c
@@ -0,0 +1,387 @@
+/*
+ * Operating classes
+ * Copyright(c) 2015 Intel Deutschland GmbH
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "common/ieee802_11_common.h"
+#include "wpa_supplicant_i.h"
+
+
+static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode, u8 chan,
+ unsigned int *flags)
+{
+ int i;
+
+ for (i = 0; i < mode->num_channels; i++) {
+ if (mode->channels[i].chan == chan)
+ break;
+ }
+
+ if (i == mode->num_channels ||
+ (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED))
+ return NOT_ALLOWED;
+
+ if (flags)
+ *flags = mode->channels[i].flag;
+
+ if (mode->channels[i].flag & HOSTAPD_CHAN_NO_IR)
+ return NO_IR;
+
+ return ALLOWED;
+}
+
+
+static int get_center_80mhz(struct hostapd_hw_modes *mode, u8 channel)
+{
+ u8 center_channels[] = { 42, 58, 106, 122, 138, 155 };
+ size_t i;
+
+ if (mode->mode != HOSTAPD_MODE_IEEE80211A)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(center_channels); i++) {
+ /*
+ * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48),
+ * so the center channel is 6 channels away from the start/end.
+ */
+ if (channel >= center_channels[i] - 6 &&
+ channel <= center_channels[i] + 6)
+ return center_channels[i];
+ }
+
+ return 0;
+}
+
+
+static enum chan_allowed verify_80mhz(struct hostapd_hw_modes *mode, u8 channel)
+{
+ u8 center_chan;
+ unsigned int i;
+ unsigned int no_ir = 0;
+
+ center_chan = get_center_80mhz(mode, channel);
+ if (!center_chan)
+ return NOT_ALLOWED;
+
+ /* check all the channels are available */
+ for (i = 0; i < 4; i++) {
+ unsigned int flags;
+ u8 adj_chan = center_chan - 6 + i * 4;
+
+ if (allow_channel(mode, adj_chan, &flags) == NOT_ALLOWED)
+ return NOT_ALLOWED;
+
+ if ((i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70)) ||
+ (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50)) ||
+ (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_30)) ||
+ (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10)))
+ return NOT_ALLOWED;
+
+ if (flags & HOSTAPD_CHAN_NO_IR)
+ no_ir = 1;
+ }
+
+ if (no_ir)
+ return NO_IR;
+
+ return ALLOWED;
+}
+
+
+static int get_center_160mhz(struct hostapd_hw_modes *mode, u8 channel)
+{
+ u8 center_channels[] = { 50, 114 };
+ unsigned int i;
+
+ if (mode->mode != HOSTAPD_MODE_IEEE80211A)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(center_channels); i++) {
+ /*
+ * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64),
+ * so the center channel is 14 channels away from the start/end.
+ */
+ if (channel >= center_channels[i] - 14 &&
+ channel <= center_channels[i] + 14)
+ return center_channels[i];
+ }
+
+ return 0;
+}
+
+
+static enum chan_allowed verify_160mhz(struct hostapd_hw_modes *mode,
+ u8 channel)
+{
+ u8 center_chan;
+ unsigned int i;
+ unsigned int no_ir = 0;
+
+ center_chan = get_center_160mhz(mode, channel);
+ if (!center_chan)
+ return NOT_ALLOWED;
+
+ /* Check all the channels are available */
+ for (i = 0; i < 8; i++) {
+ unsigned int flags;
+ u8 adj_chan = center_chan - 14 + i * 4;
+
+ if (allow_channel(mode, adj_chan, &flags) == NOT_ALLOWED)
+ return NOT_ALLOWED;
+
+ if ((i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150)) ||
+ (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130)) ||
+ (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_110)) ||
+ (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_90)) ||
+ (i == 4 && !(flags & HOSTAPD_CHAN_VHT_90_70)) ||
+ (i == 5 && !(flags & HOSTAPD_CHAN_VHT_110_50)) ||
+ (i == 6 && !(flags & HOSTAPD_CHAN_VHT_130_30)) ||
+ (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10)))
+ return NOT_ALLOWED;
+
+ if (flags & HOSTAPD_CHAN_NO_IR)
+ no_ir = 1;
+ }
+
+ if (no_ir)
+ return NO_IR;
+
+ return ALLOWED;
+}
+
+
+enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 channel,
+ u8 bw)
+{
+ unsigned int flag = 0;
+ enum chan_allowed res, res2;
+
+ res2 = res = allow_channel(mode, channel, &flag);
+ if (bw == BW40MINUS) {
+ if (!(flag & HOSTAPD_CHAN_HT40MINUS))
+ return NOT_ALLOWED;
+ res2 = allow_channel(mode, channel - 4, NULL);
+ } else if (bw == BW40PLUS) {
+ if (!(flag & HOSTAPD_CHAN_HT40PLUS))
+ return NOT_ALLOWED;
+ res2 = allow_channel(mode, channel + 4, NULL);
+ } else if (bw == BW80) {
+ /*
+ * channel is a center channel and as such, not necessarily a
+ * valid 20 MHz channels. Override earlier allow_channel()
+ * result and use only the 80 MHz specific version.
+ */
+ res2 = res = verify_80mhz(mode, channel);
+ } else if (bw == BW160) {
+ /*
+ * channel is a center channel and as such, not necessarily a
+ * valid 20 MHz channels. Override earlier allow_channel()
+ * result and use only the 160 MHz specific version.
+ */
+ res2 = res = verify_160mhz(mode, channel);
+ } else if (bw == BW80P80) {
+ /*
+ * channel is a center channel and as such, not necessarily a
+ * valid 20 MHz channels. Override earlier allow_channel()
+ * result and use only the 80 MHz specific version.
+ */
+ res2 = res = verify_80mhz(mode, channel);
+ }
+
+ if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
+ return NOT_ALLOWED;
+
+ if (res == NO_IR || res2 == NO_IR)
+ return NO_IR;
+
+ return ALLOWED;
+}
+
+
+static int wpas_op_class_supported(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ const struct oper_class_map *op_class)
+{
+ int chan;
+ size_t i;
+ struct hostapd_hw_modes *mode;
+ int found;
+ int z;
+ int freq2 = 0;
+ int freq5 = 0;
+
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode);
+ if (!mode)
+ return 0;
+
+ /* If we are configured to disable certain things, take that into
+ * account here. */
+ if (ssid->freq_list && ssid->freq_list[0]) {
+ for (z = 0; ; z++) {
+ int f = ssid->freq_list[z];
+
+ if (f == 0)
+ break; /* end of list */
+ if (f > 4000 && f < 6000)
+ freq5 = 1;
+ else if (f > 2400 && f < 2500)
+ freq2 = 1;
+ }
+ } else {
+ /* No frequencies specified, can use anything hardware supports.
+ */
+ freq2 = freq5 = 1;
+ }
+
+ if (op_class->op_class >= 115 && op_class->op_class <= 130 && !freq5)
+ return 0;
+ if (op_class->op_class >= 81 && op_class->op_class <= 84 && !freq2)
+ return 0;
+
+#ifdef CONFIG_HT_OVERRIDES
+ if (ssid->disable_ht) {
+ switch (op_class->op_class) {
+ case 83:
+ case 84:
+ case 104:
+ case 105:
+ case 116:
+ case 117:
+ case 119:
+ case 120:
+ case 122:
+ case 123:
+ case 126:
+ case 127:
+ case 128:
+ case 129:
+ case 130:
+ /* Disable >= 40 MHz channels if HT is disabled */
+ return 0;
+ }
+ }
+#endif /* CONFIG_HT_OVERRIDES */
+
+#ifdef CONFIG_VHT_OVERRIDES
+ if (ssid->disable_vht) {
+ if (op_class->op_class >= 128 && op_class->op_class <= 130) {
+ /* Disable >= 80 MHz channels if VHT is disabled */
+ return 0;
+ }
+ }
+#endif /* CONFIG_VHT_OVERRIDES */
+
+ if (op_class->op_class == 128) {
+ u8 channels[] = { 42, 58, 106, 122, 138, 155 };
+
+ for (i = 0; i < ARRAY_SIZE(channels); i++) {
+ if (verify_channel(mode, channels[i], op_class->bw) !=
+ NOT_ALLOWED)
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if (op_class->op_class == 129) {
+ /* Check if either 160 MHz channels is allowed */
+ return verify_channel(mode, 50, op_class->bw) != NOT_ALLOWED ||
+ verify_channel(mode, 114, op_class->bw) != NOT_ALLOWED;
+ }
+
+ if (op_class->op_class == 130) {
+ /* Need at least two non-contiguous 80 MHz segments */
+ found = 0;
+
+ if (verify_channel(mode, 42, op_class->bw) != NOT_ALLOWED ||
+ verify_channel(mode, 58, op_class->bw) != NOT_ALLOWED)
+ found++;
+ if (verify_channel(mode, 106, op_class->bw) != NOT_ALLOWED ||
+ verify_channel(mode, 122, op_class->bw) != NOT_ALLOWED ||
+ verify_channel(mode, 138, op_class->bw) != NOT_ALLOWED)
+ found++;
+ if (verify_channel(mode, 106, op_class->bw) != NOT_ALLOWED &&
+ verify_channel(mode, 138, op_class->bw) != NOT_ALLOWED)
+ found++;
+ if (verify_channel(mode, 155, op_class->bw) != NOT_ALLOWED)
+ found++;
+
+ if (found >= 2)
+ return 1;
+
+ return 0;
+ }
+
+ found = 0;
+ for (chan = op_class->min_chan; chan <= op_class->max_chan;
+ chan += op_class->inc) {
+ if (verify_channel(mode, chan, op_class->bw) != NOT_ALLOWED) {
+ found = 1;
+ break;
+ }
+ }
+
+ return found;
+}
+
+
+size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ int freq, u8 *pos, size_t len)
+{
+ struct wpabuf *buf;
+ u8 op, current, chan;
+ u8 *ie_len;
+ size_t res;
+
+ /*
+ * Assume 20 MHz channel for now.
+ * TODO: Use the secondary channel and VHT channel width that will be
+ * used after association.
+ */
+ if (ieee80211_freq_to_channel_ext(freq, 0, VHT_CHANWIDTH_USE_HT,
+ &current, &chan) == NUM_HOSTAPD_MODES)
+ return 0;
+
+ /*
+ * Need 3 bytes for EID, length, and current operating class, plus
+ * 1 byte for every other supported operating class.
+ */
+ buf = wpabuf_alloc(global_op_class_size + 3);
+ if (!buf)
+ return 0;
+
+ wpabuf_put_u8(buf, WLAN_EID_SUPPORTED_OPERATING_CLASSES);
+ /* Will set the length later, putting a placeholder */
+ ie_len = wpabuf_put(buf, 1);
+ wpabuf_put_u8(buf, current);
+
+ for (op = 0; global_op_class[op].op_class; op++) {
+ if (wpas_op_class_supported(wpa_s, ssid, &global_op_class[op]))
+ wpabuf_put_u8(buf, global_op_class[op].op_class);
+ }
+
+ *ie_len = wpabuf_len(buf) - 2;
+ if (*ie_len < 2 || wpabuf_len(buf) > len) {
+ wpa_printf(MSG_ERROR,
+ "Failed to add supported operating classes IE");
+ res = 0;
+ } else {
+ os_memcpy(pos, wpabuf_head(buf), wpabuf_len(buf));
+ res = wpabuf_len(buf);
+ wpa_hexdump_buf(MSG_DEBUG,
+ "Added supported operating classes IE", buf);
+ }
+
+ wpabuf_free(buf);
+ return res;
+}
diff --git a/contrib/wpa/wpa_supplicant/p2p_supplicant.c b/contrib/wpa/wpa_supplicant/p2p_supplicant.c
index b1fdc2837ff0..e7c1f5d5aca4 100644
--- a/contrib/wpa/wpa_supplicant/p2p_supplicant.c
+++ b/contrib/wpa/wpa_supplicant/p2p_supplicant.c
@@ -307,7 +307,14 @@ static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
return;
}
+ if (wpa_s->clear_driver_scan_cache) {
+ wpa_printf(MSG_DEBUG,
+ "Request driver to clear scan cache due to local BSS flush");
+ params->only_new_results = 1;
+ }
ret = wpa_drv_scan(wpa_s, params);
+ if (ret == 0)
+ wpa_s->curr_scan_cookie = params->scan_cookie;
wpa_scan_free_params(params);
work->ctx = NULL;
if (ret) {
@@ -320,6 +327,7 @@ static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
os_get_reltime(&wpa_s->scan_trigger_time);
wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
wpa_s->own_scan_requested = 1;
+ wpa_s->clear_driver_scan_cache = 0;
wpa_s->p2p_scan_work = work;
}
@@ -740,6 +748,7 @@ static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role,
conncap = P2PS_SETUP_GROUP_OWNER;
goto grp_owner;
}
+ /* fall through */
default:
return P2PS_SETUP_NONE;
@@ -807,7 +816,7 @@ grp_owner:
wpa_s->own_addr);
} else if (!s && !go_wpa_s) {
if (wpas_p2p_add_group_interface(wpa_s,
- WPA_IF_P2P_GO) < 0) {
+ WPA_IF_P2P_GROUP) < 0) {
wpa_printf(MSG_ERROR,
"P2P: Failed to allocate a new interface for the group");
return P2PS_SETUP_NONE;
@@ -971,6 +980,7 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
os_free(wpa_s->p2p_group_common_freqs);
wpa_s->p2p_group_common_freqs = NULL;
wpa_s->p2p_group_common_freqs_num = 0;
+ wpa_s->p2p_go_do_acs = 0;
wpa_s->waiting_presence_resp = 0;
@@ -1312,6 +1322,10 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
if (wpa_s->p2p_go_group_formation_completed) {
wpa_s->global->p2p_group_formation = NULL;
wpa_s->p2p_in_provisioning = 0;
+ } else if (wpa_s->p2p_in_provisioning && !success) {
+ wpa_msg(wpa_s, MSG_DEBUG,
+ "P2P: Stop provisioning state due to failure");
+ wpa_s->p2p_in_provisioning = 0;
}
wpa_s->p2p_in_invitation = 0;
wpa_s->group_formation_reported = 1;
@@ -1383,7 +1397,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
}
if (!client) {
- wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 0);
+ wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 0, NULL);
os_get_reltime(&wpa_s->global->p2p_go_wait_client);
}
}
@@ -1571,20 +1585,27 @@ static int wpas_send_action_work(struct wpa_supplicant *wpa_s,
static int wpas_send_action(void *ctx, unsigned int freq, const u8 *dst,
const u8 *src, const u8 *bssid, const u8 *buf,
- size_t len, unsigned int wait_time)
+ size_t len, unsigned int wait_time, int *scheduled)
{
struct wpa_supplicant *wpa_s = ctx;
int listen_freq = -1, send_freq = -1;
+ if (scheduled)
+ *scheduled = 0;
if (wpa_s->p2p_listen_work)
listen_freq = wpa_s->p2p_listen_work->freq;
if (wpa_s->p2p_send_action_work)
send_freq = wpa_s->p2p_send_action_work->freq;
if (listen_freq != (int) freq && send_freq != (int) freq) {
- wpa_printf(MSG_DEBUG, "P2P: Schedule new radio work for Action frame TX (listen_freq=%d send_freq=%d)",
- listen_freq, send_freq);
- return wpas_send_action_work(wpa_s, freq, dst, src, bssid, buf,
- len, wait_time);
+ int res;
+
+ wpa_printf(MSG_DEBUG, "P2P: Schedule new radio work for Action frame TX (listen_freq=%d send_freq=%d freq=%u)",
+ listen_freq, send_freq, freq);
+ res = wpas_send_action_work(wpa_s, freq, dst, src, bssid, buf,
+ len, wait_time);
+ if (res == 0 && scheduled)
+ *scheduled = 1;
+ return res;
}
wpa_printf(MSG_DEBUG, "P2P: Use ongoing radio work for Action frame TX");
@@ -1636,7 +1657,7 @@ static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s,
wpa_supplicant_ap_deinit(wpa_s);
wpas_copy_go_neg_results(wpa_s, res);
if (res->wps_method == WPS_PBC) {
- wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1);
+ wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1, 0);
#ifdef CONFIG_WPS_NFC
} else if (res->wps_method == WPS_NFC) {
wpas_wps_start_nfc(wpa_s, res->peer_device_addr,
@@ -1701,14 +1722,23 @@ static void wpas_p2p_add_psk_list(struct wpa_supplicant *wpa_s,
static void p2p_go_dump_common_freqs(struct wpa_supplicant *wpa_s)
{
+ char buf[20 + P2P_MAX_CHANNELS * 6];
+ char *pos, *end;
unsigned int i;
+ int res;
- wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Common group frequencies (len=%u):",
- wpa_s->p2p_group_common_freqs_num);
+ pos = buf;
+ end = pos + sizeof(buf);
+ for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
+ res = os_snprintf(pos, end - pos, " %d",
+ wpa_s->p2p_group_common_freqs[i]);
+ if (os_snprintf_error(end - pos, res))
+ break;
+ pos += res;
+ }
+ *pos = '\0';
- for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++)
- wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d",
- i, wpa_s->p2p_group_common_freqs[i]);
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Common group frequencies:%s", buf);
}
@@ -1801,7 +1831,8 @@ static void p2p_go_configured(void *ctx, void *data)
}
wpas_notify_p2p_group_started(wpa_s, ssid,
- params->persistent_group, 0);
+ params->persistent_group, 0,
+ NULL);
wpas_p2p_cross_connect_setup(wpa_s);
wpas_p2p_set_group_idle_timeout(wpa_s);
@@ -1889,6 +1920,7 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
ssid->vht = params->vht;
ssid->max_oper_chwidth = params->max_oper_chwidth;
ssid->vht_center_freq2 = params->vht_center_freq2;
+ ssid->he = params->he;
ssid->ssid = os_zalloc(params->ssid_len + 1);
if (ssid->ssid) {
os_memcpy(ssid->ssid, params->ssid, params->ssid_len);
@@ -1989,6 +2021,11 @@ do { \
d->wps_nfc_dh_pubkey = wpabuf_dup(s->wps_nfc_dh_pubkey);
}
d->p2p_cli_probe = s->p2p_cli_probe;
+ d->go_interworking = s->go_interworking;
+ d->go_access_network_type = s->go_access_network_type;
+ d->go_internet = s->go_internet;
+ d->go_venue_group = s->go_venue_group;
+ d->go_venue_type = s->go_venue_type;
}
@@ -2047,6 +2084,13 @@ static int wpas_p2p_add_group_interface(struct wpa_supplicant *wpa_s,
return -1;
}
+ if (wpa_s->conf->p2p_interface_random_mac_addr) {
+ random_mac_addr(wpa_s->pending_interface_addr);
+ wpa_printf(MSG_DEBUG, "P2P: Generate random MAC address " MACSTR
+ " for the group",
+ MAC2STR(wpa_s->pending_interface_addr));
+ }
+
if (force_ifname[0]) {
wpa_printf(MSG_DEBUG, "P2P: Driver forced interface name %s",
force_ifname);
@@ -2125,6 +2169,29 @@ wpas_p2p_init_group_interface(struct wpa_supplicant *wpa_s, int go)
wpas_p2p_clone_config(group_wpa_s, wpa_s);
+ if (wpa_s->conf->p2p_interface_random_mac_addr) {
+ if (wpa_drv_set_mac_addr(group_wpa_s,
+ wpa_s->pending_interface_addr) < 0) {
+ wpa_msg(group_wpa_s, MSG_INFO,
+ "Failed to set random MAC address");
+ wpa_supplicant_remove_iface(wpa_s->global, group_wpa_s,
+ 0);
+ return NULL;
+ }
+
+ if (wpa_supplicant_update_mac_addr(group_wpa_s) < 0) {
+ wpa_msg(group_wpa_s, MSG_INFO,
+ "Could not update MAC address information");
+ wpa_supplicant_remove_iface(wpa_s->global, group_wpa_s,
+ 0);
+ return NULL;
+ }
+
+ wpa_printf(MSG_DEBUG, "P2P: Using random MAC address " MACSTR
+ " for the group",
+ MAC2STR(wpa_s->pending_interface_addr));
+ }
+
return group_wpa_s;
}
@@ -3020,7 +3087,7 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
MAC2STR(sa), s->id);
}
wpas_p2p_group_add_persistent(
- wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, NULL,
+ wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, 0, NULL,
go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0,
1);
} else if (bssid) {
@@ -3246,6 +3313,7 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
wpa_s->p2p_go_vht_center_freq2,
wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht,
wpa_s->p2p_go_max_oper_chwidth,
+ wpa_s->p2p_go_he,
channels,
ssid->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
@@ -3331,10 +3399,6 @@ static int wpas_p2p_default_channels(struct wpa_supplicant *wpa_s,
}
-enum chan_allowed {
- NOT_ALLOWED, NO_IR, ALLOWED
-};
-
static int has_channel(struct wpa_global *global,
struct hostapd_hw_modes *mode, u8 chan, int *flags)
{
@@ -3894,6 +3958,10 @@ static int wpas_remove_stale_groups(void *ctx, const u8 *peer, const u8 *go,
/* Remove stale persistent group */
if (s->mode != WPAS_MODE_P2P_GO || s->num_p2p_clients <= 1) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Remove stale persistent group id=%d",
+ s->id);
+ wpas_notify_persistent_group_removed(wpa_s, s);
wpa_config_remove_network(wpa_s->conf, s->id);
save_config = 1;
continue;
@@ -4017,6 +4085,11 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
if (persistent_go && !persistent_go->num_p2p_clients) {
/* remove empty persistent GO */
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Remove empty persistent group id=%d",
+ persistent_go->id);
+ wpas_notify_persistent_group_removed(wpa_s,
+ persistent_go);
wpa_config_remove_network(wpa_s->conf,
persistent_go->id);
}
@@ -4057,6 +4130,10 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
/* Remove stale persistent group */
if (stale->mode != WPAS_MODE_P2P_GO ||
stale->num_p2p_clients <= 1) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Remove stale persistent group id=%d",
+ stale->id);
+ wpas_notify_persistent_group_removed(wpa_s, stale);
wpa_config_remove_network(wpa_s->conf, stale->id);
} else {
size_t i;
@@ -4089,6 +4166,11 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
if (persistent_go && s != persistent_go &&
!persistent_go->num_p2p_clients) {
/* remove empty persistent GO */
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Remove empty persistent group id=%d",
+ persistent_go->id);
+ wpas_notify_persistent_group_removed(wpa_s,
+ persistent_go);
wpa_config_remove_network(wpa_s->conf,
persistent_go->id);
/* Save config */
@@ -4106,6 +4188,9 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
return;
}
+ wpa_s->global->pending_p2ps_group = 0;
+ wpa_s->global->pending_p2ps_group_freq = 0;
+
if (conncap == P2PS_SETUP_GROUP_OWNER) {
/*
* We need to copy the interface name. Simply saving a
@@ -4116,8 +4201,10 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
go_ifname[0] = '\0';
if (!go_wpa_s) {
- wpa_s->global->pending_p2ps_group = 1;
- wpa_s->global->pending_p2ps_group_freq = freq;
+ if (!response_done) {
+ wpa_s->global->pending_p2ps_group = 1;
+ wpa_s->global->pending_p2ps_group_freq = freq;
+ }
if (!wpas_p2p_create_iface(wpa_s))
os_memcpy(go_ifname, wpa_s->ifname,
@@ -4141,13 +4228,14 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
if (response_done && persistent_go) {
wpas_p2p_group_add_persistent(
wpa_s, persistent_go,
- 0, 0, freq, 0, 0, 0, 0, NULL,
+ 0, 0, freq, 0, 0, 0, 0, 0, NULL,
persistent_go->mode ==
WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
0, 0);
} else if (response_done) {
- wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0);
+ wpas_p2p_group_add(wpa_s, 1, freq,
+ 0, 0, 0, 0, 0);
}
if (passwd_id == DEV_PW_P2PS_DEFAULT) {
@@ -4196,6 +4284,10 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
if (persistent_go && !persistent_go->num_p2p_clients) {
/* remove empty persistent GO */
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Remove empty persistent group id=%d",
+ persistent_go->id);
+ wpas_notify_persistent_group_removed(wpa_s, persistent_go);
wpa_config_remove_network(wpa_s->conf, persistent_go->id);
}
@@ -4259,11 +4351,11 @@ static int wpas_prov_disc_resp_cb(void *ctx)
if (persistent_go) {
wpas_p2p_group_add_persistent(
- wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, NULL,
+ wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, 0, NULL,
persistent_go->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0);
} else {
- wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0);
+ wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0);
}
return 1;
@@ -4281,6 +4373,54 @@ static int wpas_p2p_get_pref_freq_list(void *ctx, int go,
}
+int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s)
+{
+ u8 addr[ETH_ALEN] = {0};
+
+ if (wpa_s->conf->p2p_device_random_mac_addr == 0)
+ return 0;
+
+ if (!wpa_s->conf->ssid) {
+ if (random_mac_addr(addr) < 0) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Failed to generate random MAC address");
+ return -EINVAL;
+ }
+
+ /* Store generated MAC address. */
+ os_memcpy(wpa_s->conf->p2p_device_persistent_mac_addr, addr,
+ ETH_ALEN);
+ } else {
+ /* If there are existing saved groups, restore last MAC address.
+ * if there is no last used MAC address, the last one is
+ * factory MAC. */
+ if (is_zero_ether_addr(
+ wpa_s->conf->p2p_device_persistent_mac_addr))
+ return 0;
+ os_memcpy(addr, wpa_s->conf->p2p_device_persistent_mac_addr,
+ ETH_ALEN);
+ wpa_msg(wpa_s, MSG_DEBUG, "Restore last used MAC address.");
+ }
+
+ if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Failed to set random MAC address");
+ return -EINVAL;
+ }
+
+ if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Could not update MAC address information");
+ return -EINVAL;
+ }
+
+ wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
+ MAC2STR(addr));
+
+ return 0;
+}
+
+
/**
* wpas_p2p_init - Initialize P2P module for %wpa_supplicant
* @global: Pointer to global data from wpa_supplicant_init()
@@ -4301,6 +4441,12 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
if (global->p2p)
return 0;
+ if (wpas_p2p_mac_setup(wpa_s) < 0) {
+ wpa_msg(wpa_s, MSG_ERROR,
+ "Failed to initialize P2P random MAC address.");
+ return -1;
+ }
+
os_memset(&p2p, 0, sizeof(p2p));
p2p.cb_ctx = wpa_s;
p2p.debug_print = wpas_p2p_debug_print;
@@ -4365,7 +4511,10 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
* channel.
*/
if (p2p_config_get_random_social(&p2p, &p2p.reg_class,
- &p2p.channel) != 0) {
+ &p2p.channel,
+ &global->p2p_go_avoid_freq,
+ &global->p2p_disallow_freq) !=
+ 0) {
wpa_printf(MSG_INFO,
"P2P: No social channels supported by the driver - do not enable P2P");
return 0;
@@ -4390,10 +4539,14 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
* other preference is indicated.
*/
if (p2p_config_get_random_social(&p2p, &p2p.op_reg_class,
- &p2p.op_channel) != 0) {
- wpa_printf(MSG_ERROR,
+ &p2p.op_channel, NULL,
+ NULL) != 0) {
+ wpa_printf(MSG_INFO,
"P2P: Failed to select random social channel as operation channel");
- return -1;
+ p2p.op_reg_class = 0;
+ p2p.op_channel = 0;
+ /* This will be overridden during group setup in
+ * p2p_prepare_channel(), so allow setup to continue. */
}
p2p.cfg_op_channel = 0;
wpa_printf(MSG_DEBUG, "P2P: Random operating channel: "
@@ -4786,6 +4939,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
wpa_s->p2p_go_ht40,
wpa_s->p2p_go_vht,
wpa_s->p2p_go_max_oper_chwidth,
+ wpa_s->p2p_go_he,
NULL, 0);
return;
}
@@ -5003,6 +5157,12 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
params.extra_ies = wpabuf_head(ies);
params.extra_ies_len = wpabuf_len(ies);
+ if (wpa_s->clear_driver_scan_cache) {
+ wpa_printf(MSG_DEBUG,
+ "Request driver to clear scan cache due to local BSS flush");
+ params.only_new_results = 1;
+ }
+
/*
* Run a scan to update BSS table and start Provision Discovery once
* the new scan results become available.
@@ -5012,6 +5172,7 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
os_get_reltime(&wpa_s->scan_trigger_time);
wpa_s->scan_res_handler = wpas_p2p_scan_res_join;
wpa_s->own_scan_requested = 1;
+ wpa_s->clear_driver_scan_cache = 0;
}
wpabuf_free(ies);
@@ -5076,17 +5237,18 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq,
os_memcpy(group->p2p_pin, wpa_s->p2p_pin,
sizeof(group->p2p_pin));
group->p2p_wps_method = wpa_s->p2p_wps_method;
- } else {
- /*
- * Need to mark the current interface for p2p_group_formation
- * when a separate group interface is not used. This is needed
- * to allow p2p_cancel stop a pending p2p_connect-join.
- * wpas_p2p_init_group_interface() addresses this for the case
- * where a separate group interface is used.
- */
- wpa_s->global->p2p_group_formation = wpa_s;
}
+ /*
+ * Need to mark the current interface for p2p_group_formation
+ * when a separate group interface is not used. This is needed
+ * to allow p2p_cancel stop a pending p2p_connect-join.
+ * wpas_p2p_init_group_interface() addresses this for the case
+ * where a separate group interface is used.
+ */
+ if (group == wpa_s->parent)
+ wpa_s->global->p2p_group_formation = group;
+
group->p2p_in_provisioning = 1;
group->p2p_fallback_to_go_neg = wpa_s->p2p_fallback_to_go_neg;
@@ -5183,7 +5345,8 @@ static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
ret = p2p_supported_freq_cli(wpa_s->global->p2p, freq);
if (!ret) {
if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
- ieee80211_is_dfs(freq)) {
+ ieee80211_is_dfs(freq, wpa_s->hw.modes,
+ wpa_s->hw.num_modes)) {
/*
* If freq is a DFS channel and DFS is offloaded
* to the driver, allow P2P GO to use it.
@@ -5236,9 +5399,11 @@ static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
if (!res && max_pref_freq > 0) {
*num_pref_freq = max_pref_freq;
i = 0;
- while (wpas_p2p_disallowed_freq(wpa_s->global,
- pref_freq_list[i]) &&
- i < *num_pref_freq) {
+ while (i < *num_pref_freq &&
+ (!p2p_supported_freq(wpa_s->global->p2p,
+ pref_freq_list[i]) ||
+ wpas_p2p_disallowed_freq(wpa_s->global,
+ pref_freq_list[i]))) {
wpa_printf(MSG_DEBUG,
"P2P: preferred_freq_list[%d]=%d is disallowed",
i, pref_freq_list[i]);
@@ -5323,7 +5488,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
int persistent_group, int auto_join, int join, int auth,
int go_intent, int freq, unsigned int vht_center_freq2,
int persistent_id, int pd, int ht40, int vht,
- unsigned int vht_chwidth, const u8 *group_ssid,
+ unsigned int vht_chwidth, int he, const u8 *group_ssid,
size_t group_ssid_len)
{
int force_freq = 0, pref_freq = 0;
@@ -5368,6 +5533,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
wpa_s->p2p_go_vht = !!vht;
wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
wpa_s->p2p_go_max_oper_chwidth = vht_chwidth;
+ wpa_s->p2p_go_he = !!he;
if (pin)
os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
@@ -5601,9 +5767,11 @@ static int wpas_p2p_select_go_freq(struct wpa_supplicant *wpa_s, int freq)
&size, pref_freq_list);
if (!res && size > 0) {
i = 0;
- while (wpas_p2p_disallowed_freq(wpa_s->global,
- pref_freq_list[i]) &&
- i < size) {
+ while (i < size &&
+ (!p2p_supported_freq(wpa_s->global->p2p,
+ pref_freq_list[i]) ||
+ wpas_p2p_disallowed_freq(wpa_s->global,
+ pref_freq_list[i]))) {
wpa_printf(MSG_DEBUG,
"P2P: preferred_freq_list[%d]=%d is disallowed",
i, pref_freq_list[i]);
@@ -5667,7 +5835,8 @@ static int wpas_p2p_select_go_freq(struct wpa_supplicant *wpa_s, int freq)
if (freq > 0 && !p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
- ieee80211_is_dfs(freq)) {
+ ieee80211_is_dfs(freq, wpa_s->hw.modes,
+ wpa_s->hw.num_modes)) {
/*
* If freq is a DFS channel and DFS is offloaded to the
* driver, allow P2P GO to use it.
@@ -5705,30 +5874,6 @@ static void wpas_p2p_select_go_freq_no_pref(struct wpa_supplicant *wpa_s,
{
unsigned int i, r;
- /* first try some random selection of the social channels */
- if (os_get_random((u8 *) &r, sizeof(r)) < 0)
- return;
-
- for (i = 0; i < 3; i++) {
- params->freq = 2412 + ((r + i) % 3) * 25;
- if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
- goto out;
- }
-
- /* try all other channels in operating class 81 */
- for (i = 0; i < 11; i++) {
- params->freq = 2412 + i * 5;
-
- /* skip social channels; covered in the previous loop */
- if (params->freq == 2412 ||
- params->freq == 2437 ||
- params->freq == 2462)
- continue;
-
- if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
- goto out;
- }
-
/* try all channels in operating class 115 */
for (i = 0; i < 4; i++) {
params->freq = 5180 + i * 20;
@@ -5763,6 +5908,30 @@ static void wpas_p2p_select_go_freq_no_pref(struct wpa_supplicant *wpa_s,
goto out;
}
+ /* try some random selection of the social channels */
+ if (os_get_random((u8 *) &r, sizeof(r)) < 0)
+ return;
+
+ for (i = 0; i < 3; i++) {
+ params->freq = 2412 + ((r + i) % 3) * 25;
+ if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
+ goto out;
+ }
+
+ /* try all other channels in operating class 81 */
+ for (i = 0; i < 11; i++) {
+ params->freq = 2412 + i * 5;
+
+ /* skip social channels; covered in the previous loop */
+ if (params->freq == 2412 ||
+ params->freq == 2437 ||
+ params->freq == 2462)
+ continue;
+
+ if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
+ goto out;
+ }
+
params->freq = 0;
wpa_printf(MSG_DEBUG, "P2P: No 2.4, 5, or 60 GHz channel allowed");
return;
@@ -5772,10 +5941,23 @@ out:
}
+static int wpas_same_band(int freq1, int freq2)
+{
+ enum hostapd_hw_mode mode1, mode2;
+ u8 chan1, chan2;
+
+ mode1 = ieee80211_freq_to_chan(freq1, &chan1);
+ mode2 = ieee80211_freq_to_chan(freq2, &chan2);
+ if (mode1 == NUM_HOSTAPD_MODES)
+ return 0;
+ return mode1 == mode2;
+}
+
+
static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *params,
int freq, int vht_center_freq2, int ht40,
- int vht, int max_oper_chwidth,
+ int vht, int max_oper_chwidth, int he,
const struct p2p_channels *channels)
{
struct wpa_used_freq_data *freqs;
@@ -5788,6 +5970,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
params->role_go = 1;
params->ht40 = ht40;
params->vht = vht;
+ params->he = he;
params->max_oper_chwidth = max_oper_chwidth;
params->vht_center_freq2 = vht_center_freq2;
@@ -5822,12 +6005,31 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
/* try using the forced freq */
if (freq) {
- if (!wpas_p2p_supported_freq_go(wpa_s, channels, freq)) {
+ if (wpas_p2p_disallowed_freq(wpa_s->global, freq) ||
+ !freq_included(wpa_s, channels, freq)) {
wpa_printf(MSG_DEBUG,
- "P2P: Forced GO freq %d MHz not accepted",
+ "P2P: Forced GO freq %d MHz disallowed",
freq);
goto fail;
}
+ if (!p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
+ ieee80211_is_dfs(freq, wpa_s->hw.modes,
+ wpa_s->hw.num_modes)) {
+ /*
+ * If freq is a DFS channel and DFS is offloaded
+ * to the driver, allow P2P GO to use it.
+ */
+ wpa_printf(MSG_DEBUG,
+ "P2P: %s: The forced channel for GO (%u MHz) requires DFS and DFS is offloaded",
+ __func__, freq);
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "P2P: The forced channel for GO (%u MHz) is not supported for P2P uses",
+ freq);
+ goto fail;
+ }
+ }
for (i = 0; i < num; i++) {
if (freqs[i].freq == freq) {
@@ -5953,6 +6155,80 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
goto success;
}
+ /* Try using a channel that allows VHT to be used with 80 MHz */
+ if (wpa_s->hw.modes && wpa_s->p2p_group_common_freqs) {
+ for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
+ enum hostapd_hw_mode mode;
+ struct hostapd_hw_modes *hwmode;
+ u8 chan;
+
+ cand = wpa_s->p2p_group_common_freqs[i];
+ mode = ieee80211_freq_to_chan(cand, &chan);
+ hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+ mode);
+ if (!hwmode ||
+ wpas_p2p_verify_channel(wpa_s, hwmode, chan,
+ BW80) != ALLOWED)
+ continue;
+ if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
+ params->freq = cand;
+ wpa_printf(MSG_DEBUG,
+ "P2P: Use freq %d MHz common with the peer and allowing VHT80",
+ params->freq);
+ goto success;
+ }
+ }
+ }
+
+ /* Try using a channel that allows HT to be used with 40 MHz on the same
+ * band so that CSA can be used */
+ if (wpa_s->current_ssid && wpa_s->hw.modes &&
+ wpa_s->p2p_group_common_freqs) {
+ for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
+ enum hostapd_hw_mode mode;
+ struct hostapd_hw_modes *hwmode;
+ u8 chan;
+
+ cand = wpa_s->p2p_group_common_freqs[i];
+ mode = ieee80211_freq_to_chan(cand, &chan);
+ hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+ mode);
+ if (!wpas_same_band(wpa_s->current_ssid->frequency,
+ cand) ||
+ !hwmode ||
+ (wpas_p2p_verify_channel(wpa_s, hwmode, chan,
+ BW40MINUS) != ALLOWED &&
+ wpas_p2p_verify_channel(wpa_s, hwmode, chan,
+ BW40PLUS) != ALLOWED))
+ continue;
+ if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
+ params->freq = cand;
+ wpa_printf(MSG_DEBUG,
+ "P2P: Use freq %d MHz common with the peer, allowing HT40, and maintaining same band",
+ params->freq);
+ goto success;
+ }
+ }
+ }
+
+ /* Try using one of the group common freqs on the same band so that CSA
+ * can be used */
+ if (wpa_s->current_ssid && wpa_s->p2p_group_common_freqs) {
+ for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
+ cand = wpa_s->p2p_group_common_freqs[i];
+ if (!wpas_same_band(wpa_s->current_ssid->frequency,
+ cand))
+ continue;
+ if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
+ params->freq = cand;
+ wpa_printf(MSG_DEBUG,
+ "P2P: Use freq %d MHz common with the peer and maintaining same band",
+ params->freq);
+ goto success;
+ }
+ }
+ }
+
/* Try using one of the group common freqs */
if (wpa_s->p2p_group_common_freqs) {
for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
@@ -6022,6 +6298,12 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
return NULL;
}
+ if (go && wpa_s->p2p_go_do_acs) {
+ group_wpa_s->p2p_go_do_acs = wpa_s->p2p_go_do_acs;
+ group_wpa_s->p2p_go_acs_band = wpa_s->p2p_go_acs_band;
+ wpa_s->p2p_go_do_acs = 0;
+ }
+
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use separate group interface %s",
group_wpa_s->ifname);
group_wpa_s->p2p_first_connection_timeout = 0;
@@ -6045,7 +6327,7 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
*/
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
int freq, int vht_center_freq2, int ht40, int vht,
- int max_oper_chwidth)
+ int max_oper_chwidth, int he)
{
struct p2p_go_neg_results params;
@@ -6059,31 +6341,16 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND");
wpas_p2p_stop_find_oper(wpa_s);
- freq = wpas_p2p_select_go_freq(wpa_s, freq);
- if (freq < 0)
- return -1;
+ if (!wpa_s->p2p_go_do_acs) {
+ freq = wpas_p2p_select_go_freq(wpa_s, freq);
+ if (freq < 0)
+ return -1;
+ }
if (wpas_p2p_init_go_params(wpa_s, &params, freq, vht_center_freq2,
- ht40, vht, max_oper_chwidth, NULL))
+ ht40, vht, max_oper_chwidth, he, NULL))
return -1;
- if (params.freq &&
- !p2p_supported_freq_go(wpa_s->global->p2p, params.freq)) {
- if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
- ieee80211_is_dfs(params.freq)) {
- /*
- * If freq is a DFS channel and DFS is offloaded to the
- * driver, allow P2P GO to use it.
- */
- wpa_printf(MSG_DEBUG,
- "P2P: %s: The forced channel for GO (%u MHz) is DFS, and DFS is offloaded to driver",
- __func__, params.freq);
- } else {
- wpa_printf(MSG_DEBUG,
- "P2P: The selected channel for GO (%u MHz) is not supported for P2P uses",
- params.freq);
- return -1;
- }
- }
+
p2p_go_params(wpa_s->global->p2p, &params);
params.persistent_group = persistent_group;
@@ -6160,7 +6427,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int addr_allocated,
int force_freq, int neg_freq,
int vht_center_freq2, int ht40,
- int vht, int max_oper_chwidth,
+ int vht, int max_oper_chwidth, int he,
const struct p2p_channels *channels,
int connection_timeout, int force_scan)
{
@@ -6236,7 +6503,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
}
if (wpas_p2p_init_go_params(wpa_s, &params, freq, vht_center_freq2,
- ht40, vht, max_oper_chwidth, channels))
+ ht40, vht, max_oper_chwidth, he, channels))
return -1;
params.role_go = 1;
@@ -6559,8 +6826,14 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout,
wpa_s->p2p_long_listen = 0;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL ||
- wpa_s->p2p_in_provisioning)
+ wpa_s->p2p_in_provisioning) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Reject p2p_find operation%s%s",
+ (wpa_s->global->p2p_disabled || !wpa_s->global->p2p) ?
+ " (P2P disabled)" : "",
+ wpa_s->p2p_in_provisioning ?
+ " (p2p_in_provisioning)" : "");
return -1;
+ }
wpa_supplicant_cancel_sched_scan(wpa_s);
@@ -6782,7 +7055,7 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr)
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
int vht_center_freq2, int ht40, int vht, int max_chwidth,
- int pref_freq)
+ int pref_freq, int he)
{
enum p2p_invite_role role;
u8 *bssid = NULL;
@@ -6800,6 +7073,7 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
wpa_s->p2p_persistent_go_freq = freq;
wpa_s->p2p_go_ht40 = !!ht40;
wpa_s->p2p_go_vht = !!vht;
+ wpa_s->p2p_go_he = !!he;
wpa_s->p2p_go_max_oper_chwidth = max_chwidth;
wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
if (ssid->mode == WPAS_MODE_P2P_GO) {
@@ -6946,7 +7220,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
u8 go_dev_addr[ETH_ALEN];
int persistent;
int freq;
- u8 ip[3 * 4];
+ u8 ip[3 * 4], *ip_ptr = NULL;
char ip_addr[100];
if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) {
@@ -6993,6 +7267,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
ip[8], ip[9], ip[10], ip[11]);
if (os_snprintf_error(sizeof(ip_addr), res))
ip_addr[0] = '\0';
+ ip_ptr = ip;
}
wpas_p2p_group_started(wpa_s, 0, ssid, freq,
@@ -7005,7 +7280,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
wpas_p2p_store_persistent_group(wpa_s->p2pdev,
ssid, go_dev_addr);
- wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 1);
+ wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 1, ip_ptr);
}
@@ -7822,7 +8097,8 @@ static int wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
wpa_s->p2p_pd_before_go_neg,
wpa_s->p2p_go_ht40,
wpa_s->p2p_go_vht,
- wpa_s->p2p_go_max_oper_chwidth, NULL, 0);
+ wpa_s->p2p_go_max_oper_chwidth,
+ wpa_s->p2p_go_he, NULL, 0);
return ret;
}
@@ -8358,6 +8634,7 @@ static int wpas_p2p_nfc_join_group(struct wpa_supplicant *wpa_s,
WPS_NFC, 0, 0, 1, 0, wpa_s->conf->p2p_go_intent,
params->go_freq, wpa_s->p2p_go_vht_center_freq2,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
+ wpa_s->p2p_go_he,
params->go_ssid_len ? params->go_ssid : NULL,
params->go_ssid_len);
}
@@ -8437,7 +8714,7 @@ static int wpas_p2p_nfc_init_go_neg(struct wpa_supplicant *wpa_s,
WPS_NFC, 0, 0, 0, 0, wpa_s->conf->p2p_go_intent,
forced_freq, wpa_s->p2p_go_vht_center_freq2,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
- NULL, 0);
+ wpa_s->p2p_go_he, NULL, 0);
}
@@ -8453,7 +8730,7 @@ static int wpas_p2p_nfc_resp_go_neg(struct wpa_supplicant *wpa_s,
WPS_NFC, 0, 0, 0, 1, wpa_s->conf->p2p_go_intent,
forced_freq, wpa_s->p2p_go_vht_center_freq2,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
- NULL, 0);
+ wpa_s->p2p_go_he, NULL, 0);
if (res)
return res;
@@ -8838,7 +9115,7 @@ static int wpas_p2p_move_go_csa(struct wpa_supplicant *wpa_s)
* TODO: This function may not always work correctly. For example,
* when we have a running GO and a BSS on a DFS channel.
*/
- if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, NULL)) {
+ if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, 0, NULL)) {
wpa_dbg(wpa_s, MSG_DEBUG,
"P2P CSA: Failed to select new frequency for GO");
return -1;
@@ -8950,7 +9227,7 @@ static void wpas_p2p_move_go_no_csa(struct wpa_supplicant *wpa_s)
wpa_supplicant_ap_deinit(wpa_s);
/* Reselect the GO frequency */
- if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, NULL)) {
+ if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, 0, NULL)) {
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Failed to reselect freq");
wpas_p2p_group_delete(wpa_s,
P2P_GROUP_REMOVAL_GO_LEAVE_CHANNEL);
@@ -9041,16 +9318,20 @@ static void wpas_p2p_consider_moving_one_go(struct wpa_supplicant *wpa_s,
unsigned int i, invalid_freq = 0, policy_move = 0, flags = 0;
unsigned int timeout;
int freq;
+ int dfs_offload;
wpas_p2p_go_update_common_freqs(wpa_s);
freq = wpa_s->current_ssid->frequency;
+ dfs_offload = (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
+ ieee80211_is_dfs(freq, wpa_s->hw.modes, wpa_s->hw.num_modes);
for (i = 0, invalid_freq = 0; i < num; i++) {
if (freqs[i].freq == freq) {
flags = freqs[i].flags;
/* The channel is invalid, must change it */
- if (!p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
+ if (!p2p_supported_freq_go(wpa_s->global->p2p, freq) &&
+ !dfs_offload) {
wpa_dbg(wpa_s, MSG_DEBUG,
"P2P: Freq=%d MHz no longer valid for GO",
freq);
@@ -9060,7 +9341,7 @@ static void wpas_p2p_consider_moving_one_go(struct wpa_supplicant *wpa_s,
/* Freq is not used by any other station interface */
continue;
} else if (!p2p_supported_freq(wpa_s->global->p2p,
- freqs[i].freq)) {
+ freqs[i].freq) && !dfs_offload) {
/* Freq is not valid for P2P use cases */
continue;
} else if (wpa_s->conf->p2p_go_freq_change_policy ==
diff --git a/contrib/wpa/wpa_supplicant/p2p_supplicant.h b/contrib/wpa/wpa_supplicant/p2p_supplicant.h
index 63910d1c268e..24ec2cafc249 100644
--- a/contrib/wpa/wpa_supplicant/p2p_supplicant.h
+++ b/contrib/wpa/wpa_supplicant/p2p_supplicant.h
@@ -37,18 +37,18 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
int persistent_group, int auto_join, int join, int auth,
int go_intent, int freq, unsigned int vht_center_freq2,
int persistent_id, int pd, int ht40, int vht,
- unsigned int vht_chwidth, const u8 *group_ssid,
+ unsigned int vht_chwidth, int he, const u8 *group_ssid,
size_t group_ssid_len);
int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
int freq, struct wpa_ssid *ssid);
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
int freq, int vht_center_freq2, int ht40, int vht,
- int max_oper_chwidth);
+ int max_oper_chwidth, int he);
int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int addr_allocated,
int force_freq, int neg_freq,
int vht_center_freq2, int ht40,
- int vht, int max_oper_chwidth,
+ int vht, int max_oper_chwidth, int he,
const struct p2p_channels *channels,
int connection_timeout, int force_scan);
struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
@@ -117,7 +117,7 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr);
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
int vht_center_freq2, int ht40, int vht,
- int max_oper_chwidth, int pref_freq);
+ int max_oper_chwidth, int pref_freq, int he);
int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
const u8 *peer_addr, const u8 *go_dev_addr);
int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
@@ -211,6 +211,7 @@ int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq,
unsigned int period, unsigned int interval,
unsigned int count);
int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s);
+int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s);
#else /* CONFIG_P2P */
diff --git a/contrib/wpa/wpa_supplicant/preauth_test.c b/contrib/wpa/wpa_supplicant/preauth_test.c
index f4bba98e2a82..f2fff550aa81 100644
--- a/contrib/wpa/wpa_supplicant/preauth_test.c
+++ b/contrib/wpa/wpa_supplicant/preauth_test.c
@@ -143,16 +143,19 @@ static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr,
}
-static int wpa_supplicant_add_pmkid(void *wpa_s,
- const u8 *bssid, const u8 *pmkid)
+static int wpa_supplicant_add_pmkid(void *wpa_s, void *network_ctx,
+ const u8 *bssid, const u8 *pmkid,
+ const u8 *fils_cache_id,
+ const u8 *pmk, size_t pmk_len)
{
printf("%s - not implemented\n", __func__);
return -1;
}
-static int wpa_supplicant_remove_pmkid(void *wpa_s,
- const u8 *bssid, const u8 *pmkid)
+static int wpa_supplicant_remove_pmkid(void *wpa_s, void *network_ctx,
+ const u8 *bssid, const u8 *pmkid,
+ const u8 *fils_cache_id)
{
printf("%s - not implemented\n", __func__);
return -1;
@@ -344,8 +347,8 @@ int main(int argc, char *argv[])
if (preauth_test.auth_timed_out)
ret = -2;
else {
- ret = pmksa_cache_set_current(wpa_s.wpa, NULL, bssid, NULL, 0)
- ? 0 : -3;
+ ret = pmksa_cache_set_current(wpa_s.wpa, NULL, bssid, NULL, 0,
+ NULL, 0) ? 0 : -3;
}
test_eapol_clean(&wpa_s);
diff --git a/contrib/wpa/wpa_supplicant/rrm.c b/contrib/wpa/wpa_supplicant/rrm.c
new file mode 100644
index 000000000000..cb3c6c995dd9
--- /dev/null
+++ b/contrib/wpa/wpa_supplicant/rrm.c
@@ -0,0 +1,1575 @@
+/*
+ * wpa_supplicant - Radio Measurements
+ * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "common/ieee802_11_common.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
+#include "bss.h"
+#include "scan.h"
+#include "p2p_supplicant.h"
+
+
+static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
+{
+ struct rrm_data *rrm = data;
+
+ if (!rrm->notify_neighbor_rep) {
+ wpa_printf(MSG_ERROR,
+ "RRM: Unexpected neighbor report timeout");
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
+ rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
+
+ rrm->notify_neighbor_rep = NULL;
+ rrm->neighbor_rep_cb_ctx = NULL;
+}
+
+
+/*
+ * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
+ * @wpa_s: Pointer to wpa_supplicant
+ */
+void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
+{
+ wpa_s->rrm.rrm_used = 0;
+
+ eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
+ NULL);
+ if (wpa_s->rrm.notify_neighbor_rep)
+ wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
+ wpa_s->rrm.next_neighbor_rep_token = 1;
+ wpas_clear_beacon_rep_data(wpa_s);
+}
+
+
+/*
+ * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
+ * @wpa_s: Pointer to wpa_supplicant
+ * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
+ * @report_len: Length of neighbor report buffer
+ */
+void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
+ const u8 *report, size_t report_len)
+{
+ struct wpabuf *neighbor_rep;
+
+ wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
+ if (report_len < 1)
+ return;
+
+ if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Discarding neighbor report with token %d (expected %d)",
+ report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
+ return;
+ }
+
+ eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
+ NULL);
+
+ if (!wpa_s->rrm.notify_neighbor_rep) {
+ wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
+ return;
+ }
+
+ /* skipping the first byte, which is only an id (dialog token) */
+ neighbor_rep = wpabuf_alloc(report_len - 1);
+ if (!neighbor_rep) {
+ wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
+ return;
+ }
+ wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
+ wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
+ report[0]);
+ wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
+ neighbor_rep);
+ wpa_s->rrm.notify_neighbor_rep = NULL;
+ wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
+}
+
+
+#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
+/* Workaround different, undefined for Windows, error codes used here */
+#define ENOTCONN -1
+#define EOPNOTSUPP -1
+#define ECANCELED -1
+#endif
+
+/* Measurement Request element + Location Subject + Maximum Age subelement */
+#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
+/* Measurement Request element + Location Civic Request */
+#define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
+
+
+/**
+ * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
+ * @wpa_s: Pointer to wpa_supplicant
+ * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
+ * is sent in the request.
+ * @lci: if set, neighbor request will include LCI request
+ * @civic: if set, neighbor request will include civic location request
+ * @cb: Callback function to be called once the requested report arrives, or
+ * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
+ * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
+ * the requester's responsibility to free it.
+ * In the latter case NULL will be sent in 'neighbor_rep'.
+ * @cb_ctx: Context value to send the callback function
+ * Returns: 0 in case of success, negative error code otherwise
+ *
+ * In case there is a previous request which has not been answered yet, the
+ * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
+ * Request must contain a callback function.
+ */
+int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
+ const struct wpa_ssid_value *ssid,
+ int lci, int civic,
+ void (*cb)(void *ctx,
+ struct wpabuf *neighbor_rep),
+ void *cb_ctx)
+{
+ struct wpabuf *buf;
+ const u8 *rrm_ie;
+
+ if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
+ return -ENOTCONN;
+ }
+
+ if (!wpa_s->rrm.rrm_used) {
+ wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
+ return -EOPNOTSUPP;
+ }
+
+ rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
+ WLAN_EID_RRM_ENABLED_CAPABILITIES);
+ if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
+ !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: No network support for Neighbor Report.");
+ return -EOPNOTSUPP;
+ }
+
+ /* Refuse if there's a live request */
+ if (wpa_s->rrm.notify_neighbor_rep) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Currently handling previous Neighbor Report.");
+ return -EBUSY;
+ }
+
+ /* 3 = action category + action code + dialog token */
+ buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) +
+ (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
+ (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
+ if (buf == NULL) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Failed to allocate Neighbor Report Request");
+ return -ENOMEM;
+ }
+
+ wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
+ (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
+ wpa_s->rrm.next_neighbor_rep_token);
+
+ wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
+ wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
+ wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
+ if (ssid) {
+ wpabuf_put_u8(buf, WLAN_EID_SSID);
+ wpabuf_put_u8(buf, ssid->ssid_len);
+ wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
+ }
+
+ if (lci) {
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
+ wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
+ wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
+
+ /*
+ * Measurement token; nonzero number that is unique among the
+ * Measurement Request elements in a particular frame.
+ */
+ wpabuf_put_u8(buf, 1); /* Measurement Token */
+
+ /*
+ * Parallel, Enable, Request, and Report bits are 0, Duration is
+ * reserved.
+ */
+ wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
+ wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
+
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
+ /* Location Subject */
+ wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
+
+ /* Optional Subelements */
+ /*
+ * IEEE P802.11-REVmc/D5.0 Figure 9-170
+ * The Maximum Age subelement is required, otherwise the AP can
+ * send only data that was determined after receiving the
+ * request. Setting it here to unlimited age.
+ */
+ wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
+ wpabuf_put_u8(buf, 2);
+ wpabuf_put_le16(buf, 0xffff);
+ }
+
+ if (civic) {
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
+ wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
+ wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
+
+ /*
+ * Measurement token; nonzero number that is unique among the
+ * Measurement Request elements in a particular frame.
+ */
+ wpabuf_put_u8(buf, 2); /* Measurement Token */
+
+ /*
+ * Parallel, Enable, Request, and Report bits are 0, Duration is
+ * reserved.
+ */
+ wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
+ /* Measurement Type */
+ wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
+
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
+ * Location Civic request */
+ /* Location Subject */
+ wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
+ wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
+ /* Location Service Interval Units: Seconds */
+ wpabuf_put_u8(buf, 0);
+ /* Location Service Interval: 0 - Only one report is requested
+ */
+ wpabuf_put_le16(buf, 0);
+ /* No optional subelements */
+ }
+
+ wpa_s->rrm.next_neighbor_rep_token++;
+
+ if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Failed to send Neighbor Report Request");
+ wpabuf_free(buf);
+ return -ECANCELED;
+ }
+
+ wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
+ wpa_s->rrm.notify_neighbor_rep = cb;
+ eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
+ wpas_rrm_neighbor_rep_timeout_handler,
+ &wpa_s->rrm, NULL);
+
+ wpabuf_free(buf);
+ return 0;
+}
+
+
+static int wpas_rrm_report_elem(struct wpabuf **buf, u8 token, u8 mode, u8 type,
+ const u8 *data, size_t data_len)
+{
+ if (wpabuf_resize(buf, 5 + data_len))
+ return -1;
+
+ wpabuf_put_u8(*buf, WLAN_EID_MEASURE_REPORT);
+ wpabuf_put_u8(*buf, 3 + data_len);
+ wpabuf_put_u8(*buf, token);
+ wpabuf_put_u8(*buf, mode);
+ wpabuf_put_u8(*buf, type);
+
+ if (data_len)
+ wpabuf_put_data(*buf, data, data_len);
+
+ return 0;
+}
+
+
+static int
+wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s,
+ const struct rrm_measurement_request_element *req,
+ struct wpabuf **buf)
+{
+ u8 subject;
+ u16 max_age = 0;
+ struct os_reltime t, diff;
+ unsigned long diff_l;
+ const u8 *subelem;
+ const u8 *request = req->variable;
+ size_t len = req->len - 3;
+
+ if (len < 1)
+ return -1;
+
+ if (!wpa_s->lci)
+ goto reject;
+
+ subject = *request++;
+ len--;
+
+ wpa_printf(MSG_DEBUG, "Measurement request location subject=%u",
+ subject);
+
+ if (subject != LOCATION_SUBJECT_REMOTE) {
+ wpa_printf(MSG_INFO,
+ "Not building LCI report - bad location subject");
+ return 0;
+ }
+
+ /* Subelements are formatted exactly like elements */
+ wpa_hexdump(MSG_DEBUG, "LCI request subelements", request, len);
+ subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE);
+ if (subelem && subelem[1] == 2)
+ max_age = WPA_GET_LE16(subelem + 2);
+
+ if (os_get_reltime(&t))
+ goto reject;
+
+ os_reltime_sub(&t, &wpa_s->lci_time, &diff);
+ /* LCI age is calculated in 10th of a second units. */
+ diff_l = diff.sec * 10 + diff.usec / 100000;
+
+ if (max_age != 0xffff && max_age < diff_l)
+ goto reject;
+
+ if (wpas_rrm_report_elem(buf, req->token,
+ MEASUREMENT_REPORT_MODE_ACCEPT, req->type,
+ wpabuf_head_u8(wpa_s->lci),
+ wpabuf_len(wpa_s->lci)) < 0) {
+ wpa_printf(MSG_DEBUG, "Failed to add LCI report element");
+ return -1;
+ }
+
+ return 0;
+
+reject:
+ if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr) &&
+ wpas_rrm_report_elem(buf, req->token,
+ MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE,
+ req->type, NULL, 0) < 0) {
+ wpa_printf(MSG_DEBUG, "RRM: Failed to add report element");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void wpas_rrm_send_msr_report_mpdu(struct wpa_supplicant *wpa_s,
+ const u8 *data, size_t len)
+{
+ struct wpabuf *report = wpabuf_alloc(len + 3);
+
+ if (!report)
+ return;
+
+ wpabuf_put_u8(report, WLAN_ACTION_RADIO_MEASUREMENT);
+ wpabuf_put_u8(report, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
+ wpabuf_put_u8(report, wpa_s->rrm.token);
+
+ wpabuf_put_data(report, data, len);
+
+ if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head(report), wpabuf_len(report), 0)) {
+ wpa_printf(MSG_ERROR,
+ "RRM: Radio measurement report failed: Sending Action frame failed");
+ }
+
+ wpabuf_free(report);
+}
+
+
+static int wpas_rrm_beacon_rep_update_last_frame(u8 *pos, size_t len)
+{
+ struct rrm_measurement_report_element *msr_rep;
+ u8 *end = pos + len;
+ u8 *msr_rep_end;
+ struct rrm_measurement_beacon_report *rep = NULL;
+ u8 *subelem;
+
+ /* Find the last beacon report element */
+ while (end - pos >= (int) sizeof(*msr_rep)) {
+ msr_rep = (struct rrm_measurement_report_element *) pos;
+ msr_rep_end = pos + msr_rep->len + 2;
+
+ if (msr_rep->eid != WLAN_EID_MEASURE_REPORT ||
+ msr_rep_end > end) {
+ /* Should not happen. This indicates a bug. */
+ wpa_printf(MSG_ERROR,
+ "RRM: non-measurement report element in measurement report frame");
+ return -1;
+ }
+
+ if (msr_rep->type == MEASURE_TYPE_BEACON)
+ rep = (struct rrm_measurement_beacon_report *)
+ msr_rep->variable;
+
+ pos += pos[1] + 2;
+ }
+
+ if (!rep)
+ return 0;
+
+ subelem = rep->variable;
+ while (subelem + 2 < msr_rep_end &&
+ subelem[0] != WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION)
+ subelem += 2 + subelem[1];
+
+ if (subelem + 2 < msr_rep_end &&
+ subelem[0] == WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION &&
+ subelem[1] == 1 &&
+ subelem + BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN <= end)
+ subelem[2] = 1;
+
+ return 0;
+}
+
+
+static void wpas_rrm_send_msr_report(struct wpa_supplicant *wpa_s,
+ struct wpabuf *buf)
+{
+ int len = wpabuf_len(buf);
+ u8 *pos = wpabuf_mhead_u8(buf), *next = pos;
+
+#define MPDU_REPORT_LEN (int) (IEEE80211_MAX_MMPDU_SIZE - IEEE80211_HDRLEN - 3)
+
+ while (len) {
+ int send_len = (len > MPDU_REPORT_LEN) ? next - pos : len;
+
+ if (send_len == len)
+ wpas_rrm_beacon_rep_update_last_frame(pos, len);
+
+ if (send_len == len ||
+ (send_len + next[1] + 2) > MPDU_REPORT_LEN) {
+ wpas_rrm_send_msr_report_mpdu(wpa_s, pos, send_len);
+ len -= send_len;
+ pos = next;
+ }
+
+ if (len)
+ next += next[1] + 2;
+ }
+#undef MPDU_REPORT_LEN
+}
+
+
+static int wpas_add_channel(u8 op_class, u8 chan, u8 num_primary_channels,
+ int *freqs)
+{
+ size_t i;
+
+ for (i = 0; i < num_primary_channels; i++) {
+ u8 primary_chan = chan - (2 * num_primary_channels - 2) + i * 4;
+
+ freqs[i] = ieee80211_chan_to_freq(NULL, op_class, primary_chan);
+ /* ieee80211_chan_to_freq() is not really meant for this
+ * conversion of 20 MHz primary channel numbers for wider VHT
+ * channels, so handle those as special cases here for now. */
+ if (freqs[i] < 0 &&
+ (op_class == 128 || op_class == 129 || op_class == 130))
+ freqs[i] = 5000 + 5 * primary_chan;
+ if (freqs[i] < 0) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon Report: Invalid channel %u",
+ chan);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int * wpas_add_channels(const struct oper_class_map *op,
+ struct hostapd_hw_modes *mode, int active,
+ const u8 *channels, const u8 size)
+{
+ int *freqs, *next_freq;
+ u8 num_primary_channels, i;
+ u8 num_chans;
+
+ num_chans = channels ? size :
+ (op->max_chan - op->min_chan) / op->inc + 1;
+
+ if (op->bw == BW80 || op->bw == BW80P80)
+ num_primary_channels = 4;
+ else if (op->bw == BW160)
+ num_primary_channels = 8;
+ else
+ num_primary_channels = 1;
+
+ /* one extra place for the zero-terminator */
+ freqs = os_calloc(num_chans * num_primary_channels + 1, sizeof(*freqs));
+ if (!freqs) {
+ wpa_printf(MSG_ERROR,
+ "Beacon Report: Failed to allocate freqs array");
+ return NULL;
+ }
+
+ next_freq = freqs;
+ for (i = 0; i < num_chans; i++) {
+ u8 chan = channels ? channels[i] : op->min_chan + i * op->inc;
+ enum chan_allowed res = verify_channel(mode, chan, op->bw);
+
+ if (res == NOT_ALLOWED || (res == NO_IR && active))
+ continue;
+
+ if (wpas_add_channel(op->op_class, chan, num_primary_channels,
+ next_freq) < 0) {
+ os_free(freqs);
+ return NULL;
+ }
+
+ next_freq += num_primary_channels;
+ }
+
+ if (!freqs[0]) {
+ os_free(freqs);
+ return NULL;
+ }
+
+ return freqs;
+}
+
+
+static int * wpas_op_class_freqs(const struct oper_class_map *op,
+ struct hostapd_hw_modes *mode, int active)
+{
+ u8 channels_80mhz[] = { 42, 58, 106, 122, 138, 155 };
+ u8 channels_160mhz[] = { 50, 114 };
+
+ /*
+ * When adding all channels in the operating class, 80 + 80 MHz
+ * operating classes are like 80 MHz channels because we add all valid
+ * channels anyway.
+ */
+ if (op->bw == BW80 || op->bw == BW80P80)
+ return wpas_add_channels(op, mode, active, channels_80mhz,
+ ARRAY_SIZE(channels_80mhz));
+
+ if (op->bw == BW160)
+ return wpas_add_channels(op, mode, active, channels_160mhz,
+ ARRAY_SIZE(channels_160mhz));
+
+ return wpas_add_channels(op, mode, active, NULL, 0);
+}
+
+
+static int * wpas_channel_report_freqs(struct wpa_supplicant *wpa_s, int active,
+ const char *country, const u8 *subelems,
+ size_t len)
+{
+ int *freqs = NULL, *new_freqs;
+ const u8 *end = subelems + len;
+
+ while (end - subelems > 2) {
+ const struct oper_class_map *op;
+ const u8 *ap_chan_elem, *pos;
+ u8 left;
+ struct hostapd_hw_modes *mode;
+
+ ap_chan_elem = get_ie(subelems, end - subelems,
+ WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL);
+ if (!ap_chan_elem)
+ break;
+ pos = ap_chan_elem + 2;
+ left = ap_chan_elem[1];
+ if (left < 1)
+ break;
+ subelems = ap_chan_elem + 2 + left;
+
+ op = get_oper_class(country, *pos);
+ if (!op) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon request: unknown operating class in AP Channel Report subelement %u",
+ *pos);
+ goto out;
+ }
+ pos++;
+ left--;
+
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op->mode);
+ if (!mode)
+ continue;
+
+ /*
+ * For 80 + 80 MHz operating classes, this AP Channel Report
+ * element should be followed by another element specifying
+ * the second 80 MHz channel. For now just add this 80 MHz
+ * channel, the second 80 MHz channel will be added when the
+ * next element is parsed.
+ * TODO: Verify that this AP Channel Report element is followed
+ * by a corresponding AP Channel Report element as specified in
+ * IEEE Std 802.11-2016, 11.11.9.1.
+ */
+ new_freqs = wpas_add_channels(op, mode, active, pos, left);
+ if (new_freqs)
+ int_array_concat(&freqs, new_freqs);
+
+ os_free(new_freqs);
+ }
+
+ return freqs;
+out:
+ os_free(freqs);
+ return NULL;
+}
+
+
+static int * wpas_beacon_request_freqs(struct wpa_supplicant *wpa_s,
+ u8 op_class, u8 chan, int active,
+ const u8 *subelems, size_t len)
+{
+ int *freqs = NULL, *ext_freqs = NULL;
+ struct hostapd_hw_modes *mode;
+ const char *country = NULL;
+ const struct oper_class_map *op;
+ const u8 *elem;
+
+ if (!wpa_s->current_bss)
+ return NULL;
+ elem = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY);
+ if (elem && elem[1] >= 2)
+ country = (const char *) (elem + 2);
+
+ op = get_oper_class(country, op_class);
+ if (!op) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon request: invalid operating class %d",
+ op_class);
+ return NULL;
+ }
+
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op->mode);
+ if (!mode)
+ return NULL;
+
+ switch (chan) {
+ case 0:
+ freqs = wpas_op_class_freqs(op, mode, active);
+ if (!freqs)
+ return NULL;
+ break;
+ case 255:
+ /* freqs will be added from AP channel subelements */
+ break;
+ default:
+ freqs = wpas_add_channels(op, mode, active, &chan, 1);
+ if (!freqs)
+ return NULL;
+ break;
+ }
+
+ ext_freqs = wpas_channel_report_freqs(wpa_s, active, country, subelems,
+ len);
+ if (ext_freqs) {
+ int_array_concat(&freqs, ext_freqs);
+ os_free(ext_freqs);
+ int_array_sort_unique(freqs);
+ }
+
+ return freqs;
+}
+
+
+static int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len,
+ u8 *op_class, u8 *chan, u8 *phy_type)
+{
+ const u8 *ie;
+ int sec_chan = 0, vht = 0;
+ struct ieee80211_ht_operation *ht_oper = NULL;
+ struct ieee80211_vht_operation *vht_oper = NULL;
+ u8 seg0, seg1;
+
+ ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
+ if (ie && ie[1] >= sizeof(struct ieee80211_ht_operation)) {
+ u8 sec_chan_offset;
+
+ ht_oper = (struct ieee80211_ht_operation *) (ie + 2);
+ sec_chan_offset = ht_oper->ht_param &
+ HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
+ if (sec_chan_offset == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
+ sec_chan = 1;
+ else if (sec_chan_offset ==
+ HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
+ sec_chan = -1;
+ }
+
+ ie = get_ie(ies, ies_len, WLAN_EID_VHT_OPERATION);
+ if (ie && ie[1] >= sizeof(struct ieee80211_vht_operation)) {
+ vht_oper = (struct ieee80211_vht_operation *) (ie + 2);
+
+ switch (vht_oper->vht_op_info_chwidth) {
+ case 1:
+ seg0 = vht_oper->vht_op_info_chan_center_freq_seg0_idx;
+ seg1 = vht_oper->vht_op_info_chan_center_freq_seg1_idx;
+ if (seg1 && abs(seg1 - seg0) == 8)
+ vht = VHT_CHANWIDTH_160MHZ;
+ else if (seg1)
+ vht = VHT_CHANWIDTH_80P80MHZ;
+ else
+ vht = VHT_CHANWIDTH_80MHZ;
+ break;
+ case 2:
+ vht = VHT_CHANWIDTH_160MHZ;
+ break;
+ case 3:
+ vht = VHT_CHANWIDTH_80P80MHZ;
+ break;
+ default:
+ vht = VHT_CHANWIDTH_USE_HT;
+ break;
+ }
+ }
+
+ if (ieee80211_freq_to_channel_ext(freq, sec_chan, vht, op_class,
+ chan) == NUM_HOSTAPD_MODES) {
+ wpa_printf(MSG_DEBUG,
+ "Cannot determine operating class and channel");
+ return -1;
+ }
+
+ *phy_type = ieee80211_get_phy_type(freq, ht_oper != NULL,
+ vht_oper != NULL);
+ if (*phy_type == PHY_TYPE_UNSPECIFIED) {
+ wpa_printf(MSG_DEBUG, "Cannot determine phy type");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int wpas_beacon_rep_add_frame_body(struct bitfield *eids,
+ enum beacon_report_detail detail,
+ struct wpa_bss *bss, u8 *buf,
+ size_t buf_len, u8 **ies_buf,
+ size_t *ie_len, int add_fixed)
+{
+ u8 *ies = *ies_buf;
+ size_t ies_len = *ie_len;
+ u8 *pos = buf;
+ int rem_len;
+
+ rem_len = 255 - sizeof(struct rrm_measurement_beacon_report) -
+ sizeof(struct rrm_measurement_report_element) - 2 -
+ REPORTED_FRAME_BODY_SUBELEM_LEN;
+
+ if (detail > BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon Request: Invalid reporting detail: %d",
+ detail);
+ return -1;
+ }
+
+ if (detail == BEACON_REPORT_DETAIL_NONE)
+ return 0;
+
+ /*
+ * Minimal frame body subelement size: EID(1) + length(1) + TSF(8) +
+ * beacon interval(2) + capabilities(2) = 14 bytes
+ */
+ if (add_fixed && buf_len < 14)
+ return -1;
+
+ *pos++ = WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY;
+ /* The length will be filled later */
+ pos++;
+
+ if (add_fixed) {
+ WPA_PUT_LE64(pos, bss->tsf);
+ pos += sizeof(bss->tsf);
+ WPA_PUT_LE16(pos, bss->beacon_int);
+ pos += 2;
+ WPA_PUT_LE16(pos, bss->caps);
+ pos += 2;
+ }
+
+ rem_len -= pos - buf;
+
+ /*
+ * According to IEEE Std 802.11-2016, 9.4.2.22.7, if the reported frame
+ * body subelement causes the element to exceed the maximum element
+ * size, the subelement is truncated so that the last IE is a complete
+ * IE. So even when required to report all IEs, add elements one after
+ * the other and stop once there is no more room in the measurement
+ * element.
+ */
+ while (ies_len > 2 && 2U + ies[1] <= ies_len && rem_len > 0) {
+ if (detail == BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS ||
+ (eids && bitfield_is_set(eids, ies[0]))) {
+ u8 elen = ies[1];
+
+ if (2 + elen > buf + buf_len - pos ||
+ 2 + elen > rem_len)
+ break;
+
+ *pos++ = ies[0];
+ *pos++ = elen;
+ os_memcpy(pos, ies + 2, elen);
+ pos += elen;
+ rem_len -= 2 + elen;
+ }
+
+ ies_len -= 2 + ies[1];
+ ies += 2 + ies[1];
+ }
+
+ *ie_len = ies_len;
+ *ies_buf = ies;
+
+ /* Now the length is known */
+ buf[1] = pos - buf - 2;
+ return pos - buf;
+}
+
+
+static int wpas_add_beacon_rep_elem(struct beacon_rep_data *data,
+ struct wpa_bss *bss,
+ struct wpabuf **wpa_buf,
+ struct rrm_measurement_beacon_report *rep,
+ u8 **ie, size_t *ie_len, u8 idx)
+{
+ int ret;
+ u8 *buf, *pos;
+ u32 subelems_len = REPORTED_FRAME_BODY_SUBELEM_LEN +
+ (data->last_indication ?
+ BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN : 0);
+
+ /* Maximum element length: Beacon Report element + Reported Frame Body
+ * subelement + all IEs of the reported Beacon frame + Reported Frame
+ * Body Fragment ID subelement */
+ buf = os_malloc(sizeof(*rep) + 14 + *ie_len + subelems_len);
+ if (!buf)
+ return -1;
+
+ os_memcpy(buf, rep, sizeof(*rep));
+
+ ret = wpas_beacon_rep_add_frame_body(data->eids, data->report_detail,
+ bss, buf + sizeof(*rep),
+ 14 + *ie_len, ie, ie_len,
+ idx == 0);
+ if (ret < 0)
+ goto out;
+
+ pos = buf + ret + sizeof(*rep);
+ pos[0] = WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY_FRAGMENT_ID;
+ pos[1] = 2;
+
+ /*
+ * Only one Beacon Report Measurement is supported at a time, so
+ * the Beacon Report ID can always be set to 1.
+ */
+ pos[2] = 1;
+
+ /* Fragment ID Number (bits 0..6) and More Frame Body Fragments (bit 7)
+ */
+ pos[3] = idx;
+ if (data->report_detail != BEACON_REPORT_DETAIL_NONE && *ie_len)
+ pos[3] |= REPORTED_FRAME_BODY_MORE_FRAGMENTS;
+ else
+ pos[3] &= ~REPORTED_FRAME_BODY_MORE_FRAGMENTS;
+
+ pos += REPORTED_FRAME_BODY_SUBELEM_LEN;
+
+ if (data->last_indication) {
+ pos[0] = WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION;
+ pos[1] = 1;
+
+ /* This field will be updated later if this is the last frame */
+ pos[2] = 0;
+ }
+
+ ret = wpas_rrm_report_elem(wpa_buf, data->token,
+ MEASUREMENT_REPORT_MODE_ACCEPT,
+ MEASURE_TYPE_BEACON, buf,
+ ret + sizeof(*rep) + subelems_len);
+out:
+ os_free(buf);
+ return ret;
+}
+
+
+static int wpas_add_beacon_rep(struct wpa_supplicant *wpa_s,
+ struct wpabuf **wpa_buf, struct wpa_bss *bss,
+ u64 start, u64 parent_tsf)
+{
+ struct beacon_rep_data *data = &wpa_s->beacon_rep_data;
+ u8 *ies = (u8 *) (bss + 1);
+ u8 *pos = ies;
+ size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
+ struct rrm_measurement_beacon_report rep;
+ u8 idx = 0;
+
+ if (os_memcmp(data->bssid, broadcast_ether_addr, ETH_ALEN) != 0 &&
+ os_memcmp(data->bssid, bss->bssid, ETH_ALEN) != 0)
+ return 0;
+
+ if (data->ssid_len &&
+ (data->ssid_len != bss->ssid_len ||
+ os_memcmp(data->ssid, bss->ssid, bss->ssid_len) != 0))
+ return 0;
+
+ if (wpas_get_op_chan_phy(bss->freq, ies, ies_len, &rep.op_class,
+ &rep.channel, &rep.report_info) < 0)
+ return 0;
+
+ rep.start_time = host_to_le64(start);
+ rep.duration = host_to_le16(data->scan_params.duration);
+ rep.rcpi = rssi_to_rcpi(bss->level);
+ rep.rsni = 255; /* 255 indicates that RSNI is not available */
+ os_memcpy(rep.bssid, bss->bssid, ETH_ALEN);
+ rep.antenna_id = 0; /* unknown */
+ rep.parent_tsf = host_to_le32(parent_tsf);
+
+ do {
+ int ret;
+
+ ret = wpas_add_beacon_rep_elem(data, bss, wpa_buf, &rep,
+ &pos, &ies_len, idx++);
+ if (ret)
+ return ret;
+ } while (data->report_detail != BEACON_REPORT_DETAIL_NONE &&
+ ies_len >= 2);
+
+ return 0;
+}
+
+
+static int wpas_beacon_rep_no_results(struct wpa_supplicant *wpa_s,
+ struct wpabuf **buf)
+{
+ return wpas_rrm_report_elem(buf, wpa_s->beacon_rep_data.token,
+ MEASUREMENT_REPORT_MODE_ACCEPT,
+ MEASURE_TYPE_BEACON, NULL, 0);
+}
+
+
+static void wpas_beacon_rep_table(struct wpa_supplicant *wpa_s,
+ struct wpabuf **buf)
+{
+ size_t i;
+
+ for (i = 0; i < wpa_s->last_scan_res_used; i++) {
+ if (wpas_add_beacon_rep(wpa_s, buf, wpa_s->last_scan_res[i],
+ 0, 0) < 0)
+ break;
+ }
+
+ if (!(*buf))
+ wpas_beacon_rep_no_results(wpa_s, buf);
+
+ wpa_hexdump_buf(MSG_DEBUG, "RRM: Radio Measurement report", *buf);
+}
+
+
+void wpas_rrm_refuse_request(struct wpa_supplicant *wpa_s)
+{
+ if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr)) {
+ struct wpabuf *buf = NULL;
+
+ if (wpas_rrm_report_elem(&buf, wpa_s->beacon_rep_data.token,
+ MEASUREMENT_REPORT_MODE_REJECT_REFUSED,
+ MEASURE_TYPE_BEACON, NULL, 0)) {
+ wpa_printf(MSG_ERROR, "RRM: Memory allocation failed");
+ wpabuf_free(buf);
+ return;
+ }
+
+ wpas_rrm_send_msr_report(wpa_s, buf);
+ wpabuf_free(buf);
+ }
+
+ wpas_clear_beacon_rep_data(wpa_s);
+}
+
+
+static void wpas_rrm_scan_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct wpa_driver_scan_params *params =
+ &wpa_s->beacon_rep_data.scan_params;
+ u16 prev_duration = params->duration;
+
+ if (!wpa_s->current_bss)
+ return;
+
+ if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL) &&
+ params->duration) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Cannot set scan duration due to missing driver support");
+ params->duration = 0;
+ }
+ os_get_reltime(&wpa_s->beacon_rep_scan);
+ if (wpa_s->scanning || wpas_p2p_in_progress(wpa_s) ||
+ wpa_supplicant_trigger_scan(wpa_s, params))
+ wpas_rrm_refuse_request(wpa_s);
+ params->duration = prev_duration;
+}
+
+
+static int wpas_rm_handle_beacon_req_subelem(struct wpa_supplicant *wpa_s,
+ struct beacon_rep_data *data,
+ u8 sid, u8 slen, const u8 *subelem)
+{
+ u8 report_info, i;
+
+ switch (sid) {
+ case WLAN_BEACON_REQUEST_SUBELEM_SSID:
+ if (!slen) {
+ wpa_printf(MSG_DEBUG,
+ "SSID subelement with zero length - wildcard SSID");
+ break;
+ }
+
+ if (slen > SSID_MAX_LEN) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid SSID subelement length: %u", slen);
+ return -1;
+ }
+
+ data->ssid_len = slen;
+ os_memcpy(data->ssid, subelem, data->ssid_len);
+ break;
+ case WLAN_BEACON_REQUEST_SUBELEM_INFO:
+ if (slen != 2) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid reporting information subelement length: %u",
+ slen);
+ return -1;
+ }
+
+ report_info = subelem[0];
+ if (report_info != 0) {
+ wpa_printf(MSG_DEBUG,
+ "reporting information=%u is not supported",
+ report_info);
+ return 0;
+ }
+ break;
+ case WLAN_BEACON_REQUEST_SUBELEM_DETAIL:
+ if (slen != 1) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid reporting detail subelement length: %u",
+ slen);
+ return -1;
+ }
+
+ data->report_detail = subelem[0];
+ if (data->report_detail >
+ BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS) {
+ wpa_printf(MSG_DEBUG, "Invalid reporting detail: %u",
+ subelem[0]);
+ return -1;
+ }
+
+ break;
+ case WLAN_BEACON_REQUEST_SUBELEM_REQUEST:
+ if (data->report_detail !=
+ BEACON_REPORT_DETAIL_REQUESTED_ONLY) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon request: request subelement is present but report detail is %u",
+ data->report_detail);
+ return -1;
+ }
+
+ if (!slen) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid request subelement length: %u",
+ slen);
+ return -1;
+ }
+
+ if (data->eids) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon Request: Request subelement appears more than once");
+ return -1;
+ }
+
+ data->eids = bitfield_alloc(255);
+ if (!data->eids) {
+ wpa_printf(MSG_DEBUG, "Failed to allocate EIDs bitmap");
+ return -1;
+ }
+
+ for (i = 0; i < slen; i++)
+ bitfield_set(data->eids, subelem[i]);
+ break;
+ case WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL:
+ /* Skip - it will be processed when freqs are added */
+ break;
+ case WLAN_BEACON_REQUEST_SUBELEM_LAST_INDICATION:
+ if (slen != 1) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon request: Invalid last indication request subelement length: %u",
+ slen);
+ return -1;
+ }
+
+ data->last_indication = subelem[0];
+ break;
+ default:
+ wpa_printf(MSG_DEBUG,
+ "Beacon request: Unknown subelement id %u", sid);
+ break;
+ }
+
+ return 1;
+}
+
+
+/**
+ * Returns 0 if the next element can be processed, 1 if some operation was
+ * triggered, and -1 if processing failed (i.e., the element is in invalid
+ * format or an internal error occurred).
+ */
+static int
+wpas_rm_handle_beacon_req(struct wpa_supplicant *wpa_s,
+ u8 elem_token, int duration_mandatory,
+ const struct rrm_measurement_beacon_request *req,
+ size_t len, struct wpabuf **buf)
+{
+ struct beacon_rep_data *data = &wpa_s->beacon_rep_data;
+ struct wpa_driver_scan_params *params = &data->scan_params;
+ const u8 *subelems;
+ size_t elems_len;
+ u16 rand_interval;
+ u32 interval_usec;
+ u32 _rand;
+ int ret = 0, res;
+ u8 reject_mode;
+
+ if (len < sizeof(*req))
+ return -1;
+
+ if (req->mode != BEACON_REPORT_MODE_PASSIVE &&
+ req->mode != BEACON_REPORT_MODE_ACTIVE &&
+ req->mode != BEACON_REPORT_MODE_TABLE)
+ return 0;
+
+ subelems = req->variable;
+ elems_len = len - sizeof(*req);
+ rand_interval = le_to_host16(req->rand_interval);
+
+ os_free(params->freqs);
+ os_memset(params, 0, sizeof(*params));
+
+ data->token = elem_token;
+
+ /* default reporting detail is all fixed length fields and all
+ * elements */
+ data->report_detail = BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS;
+ os_memcpy(data->bssid, req->bssid, ETH_ALEN);
+
+ while (elems_len >= 2) {
+ if (subelems[1] > elems_len - 2) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon Request: Truncated subelement");
+ ret = -1;
+ goto out;
+ }
+
+ res = wpas_rm_handle_beacon_req_subelem(
+ wpa_s, data, subelems[0], subelems[1], &subelems[2]);
+ if (res < 0) {
+ ret = res;
+ goto out;
+ } else if (!res) {
+ reject_mode = MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE;
+ goto out_reject;
+ }
+
+ elems_len -= 2 + subelems[1];
+ subelems += 2 + subelems[1];
+ }
+
+ if (req->mode == BEACON_REPORT_MODE_TABLE) {
+ wpas_beacon_rep_table(wpa_s, buf);
+ goto out;
+ }
+
+ params->freqs = wpas_beacon_request_freqs(
+ wpa_s, req->oper_class, req->channel,
+ req->mode == BEACON_REPORT_MODE_ACTIVE,
+ req->variable, len - sizeof(*req));
+ if (!params->freqs) {
+ wpa_printf(MSG_DEBUG, "Beacon request: No valid channels");
+ reject_mode = MEASUREMENT_REPORT_MODE_REJECT_REFUSED;
+ goto out_reject;
+ }
+
+ params->duration = le_to_host16(req->duration);
+ params->duration_mandatory = duration_mandatory;
+ if (!params->duration) {
+ wpa_printf(MSG_DEBUG, "Beacon request: Duration is 0");
+ ret = -1;
+ goto out;
+ }
+
+ params->only_new_results = 1;
+
+ if (req->mode == BEACON_REPORT_MODE_ACTIVE) {
+ params->ssids[params->num_ssids].ssid = data->ssid;
+ params->ssids[params->num_ssids++].ssid_len = data->ssid_len;
+ }
+
+ if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
+ _rand = os_random();
+ interval_usec = (_rand % (rand_interval + 1)) * 1024;
+ eloop_register_timeout(0, interval_usec, wpas_rrm_scan_timeout, wpa_s,
+ NULL);
+ return 1;
+out_reject:
+ if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr) &&
+ wpas_rrm_report_elem(buf, elem_token, reject_mode,
+ MEASURE_TYPE_BEACON, NULL, 0) < 0) {
+ wpa_printf(MSG_DEBUG, "RRM: Failed to add report element");
+ ret = -1;
+ }
+out:
+ wpas_clear_beacon_rep_data(wpa_s);
+ return ret;
+}
+
+
+static int
+wpas_rrm_handle_msr_req_element(
+ struct wpa_supplicant *wpa_s,
+ const struct rrm_measurement_request_element *req,
+ struct wpabuf **buf)
+{
+ int duration_mandatory;
+
+ wpa_printf(MSG_DEBUG, "Measurement request type %d token %d",
+ req->type, req->token);
+
+ if (req->mode & MEASUREMENT_REQUEST_MODE_ENABLE) {
+ /* Enable bit is not supported for now */
+ wpa_printf(MSG_DEBUG, "RRM: Enable bit not supported, ignore");
+ return 0;
+ }
+
+ if ((req->mode & MEASUREMENT_REQUEST_MODE_PARALLEL) &&
+ req->type > MEASURE_TYPE_RPI_HIST) {
+ /* Parallel measurements are not supported for now */
+ wpa_printf(MSG_DEBUG,
+ "RRM: Parallel measurements are not supported, reject");
+ goto reject;
+ }
+
+ duration_mandatory =
+ !!(req->mode & MEASUREMENT_REQUEST_MODE_DURATION_MANDATORY);
+
+ switch (req->type) {
+ case MEASURE_TYPE_LCI:
+ return wpas_rrm_build_lci_report(wpa_s, req, buf);
+ case MEASURE_TYPE_BEACON:
+ if (duration_mandatory &&
+ !(wpa_s->drv_rrm_flags &
+ WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL)) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Driver does not support dwell time configuration - reject beacon report with mandatory duration");
+ goto reject;
+ }
+ return wpas_rm_handle_beacon_req(wpa_s, req->token,
+ duration_mandatory,
+ (const void *) req->variable,
+ req->len - 3, buf);
+ default:
+ wpa_printf(MSG_INFO,
+ "RRM: Unsupported radio measurement type %u",
+ req->type);
+ break;
+ }
+
+reject:
+ if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr) &&
+ wpas_rrm_report_elem(buf, req->token,
+ MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE,
+ req->type, NULL, 0) < 0) {
+ wpa_printf(MSG_DEBUG, "RRM: Failed to add report element");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static struct wpabuf *
+wpas_rrm_process_msr_req_elems(struct wpa_supplicant *wpa_s, const u8 *pos,
+ size_t len)
+{
+ struct wpabuf *buf = NULL;
+
+ while (len) {
+ const struct rrm_measurement_request_element *req;
+ int res;
+
+ if (len < 2) {
+ wpa_printf(MSG_DEBUG, "RRM: Truncated element");
+ goto out;
+ }
+
+ req = (const struct rrm_measurement_request_element *) pos;
+ if (req->eid != WLAN_EID_MEASURE_REQUEST) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Expected Measurement Request element, but EID is %u",
+ req->eid);
+ goto out;
+ }
+
+ if (req->len < 3) {
+ wpa_printf(MSG_DEBUG, "RRM: Element length too short");
+ goto out;
+ }
+
+ if (req->len > len - 2) {
+ wpa_printf(MSG_DEBUG, "RRM: Element length too long");
+ goto out;
+ }
+
+ res = wpas_rrm_handle_msr_req_element(wpa_s, req, &buf);
+ if (res < 0)
+ goto out;
+
+ pos += req->len + 2;
+ len -= req->len + 2;
+ }
+
+ return buf;
+
+out:
+ wpabuf_free(buf);
+ return NULL;
+}
+
+
+void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
+ const u8 *src, const u8 *dst,
+ const u8 *frame, size_t len)
+{
+ struct wpabuf *report;
+
+ if (wpa_s->wpa_state != WPA_COMPLETED) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring radio measurement request: Not associated");
+ return;
+ }
+
+ if (!wpa_s->rrm.rrm_used) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring radio measurement request: Not RRM network");
+ return;
+ }
+
+ if (len < 3) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring too short radio measurement request");
+ return;
+ }
+
+ wpa_s->rrm.token = *frame;
+ os_memcpy(wpa_s->rrm.dst_addr, dst, ETH_ALEN);
+
+ /* Number of repetitions is not supported */
+
+ report = wpas_rrm_process_msr_req_elems(wpa_s, frame + 3, len - 3);
+ if (!report)
+ return;
+
+ wpas_rrm_send_msr_report(wpa_s, report);
+ wpabuf_free(report);
+}
+
+
+void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
+ const u8 *src,
+ const u8 *frame, size_t len,
+ int rssi)
+{
+ struct wpabuf *buf;
+ const struct rrm_link_measurement_request *req;
+ struct rrm_link_measurement_report report;
+
+ if (wpa_s->wpa_state != WPA_COMPLETED) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring link measurement request. Not associated");
+ return;
+ }
+
+ if (!wpa_s->rrm.rrm_used) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring link measurement request. Not RRM network");
+ return;
+ }
+
+ if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
+ wpa_printf(MSG_INFO,
+ "RRM: Measurement report failed. TX power insertion not supported");
+ return;
+ }
+
+ req = (const struct rrm_link_measurement_request *) frame;
+ if (len < sizeof(*req)) {
+ wpa_printf(MSG_INFO,
+ "RRM: Link measurement report failed. Request too short");
+ return;
+ }
+
+ os_memset(&report, 0, sizeof(report));
+ report.dialog_token = req->dialog_token;
+ report.tpc.eid = WLAN_EID_TPC_REPORT;
+ report.tpc.len = 2;
+ /* Note: The driver is expected to update report.tpc.tx_power and
+ * report.tpc.link_margin subfields when sending out this frame.
+ * Similarly, the driver would need to update report.rx_ant_id and
+ * report.tx_ant_id subfields. */
+ report.rsni = 255; /* 255 indicates that RSNI is not available */
+ report.rcpi = rssi_to_rcpi(rssi);
+
+ /* action_category + action_code */
+ buf = wpabuf_alloc(2 + sizeof(report));
+ if (buf == NULL) {
+ wpa_printf(MSG_ERROR,
+ "RRM: Link measurement report failed. Buffer allocation failed");
+ return;
+ }
+
+ wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
+ wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
+ wpabuf_put_data(buf, &report, sizeof(report));
+ wpa_hexdump_buf(MSG_DEBUG, "RRM: Link measurement report", buf);
+
+ if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head(buf), wpabuf_len(buf), 0)) {
+ wpa_printf(MSG_ERROR,
+ "RRM: Link measurement report failed. Send action failed");
+ }
+ wpabuf_free(buf);
+}
+
+
+int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *scan_res,
+ struct scan_info *info)
+{
+ size_t i = 0;
+ struct wpabuf *buf = NULL;
+
+ if (!wpa_s->beacon_rep_data.token)
+ return 0;
+
+ if (!wpa_s->current_bss)
+ goto out;
+
+ /* If the measurement was aborted, don't report partial results */
+ if (info->aborted)
+ goto out;
+
+ wpa_printf(MSG_DEBUG, "RRM: TSF BSSID: " MACSTR " current BSS: " MACSTR,
+ MAC2STR(info->scan_start_tsf_bssid),
+ MAC2STR(wpa_s->current_bss->bssid));
+ if ((wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) &&
+ os_memcmp(info->scan_start_tsf_bssid, wpa_s->current_bss->bssid,
+ ETH_ALEN) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Ignore scan results due to mismatching TSF BSSID");
+ goto out;
+ }
+
+ for (i = 0; i < scan_res->num; i++) {
+ struct wpa_bss *bss =
+ wpa_bss_get_bssid(wpa_s, scan_res->res[i]->bssid);
+
+ if (!bss)
+ continue;
+
+ if ((wpa_s->drv_rrm_flags &
+ WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) &&
+ os_memcmp(scan_res->res[i]->tsf_bssid,
+ wpa_s->current_bss->bssid, ETH_ALEN) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Ignore scan result for " MACSTR
+ " due to mismatching TSF BSSID" MACSTR,
+ MAC2STR(scan_res->res[i]->bssid),
+ MAC2STR(scan_res->res[i]->tsf_bssid));
+ continue;
+ }
+
+ /*
+ * Don't report results that were not received during the
+ * current measurement.
+ */
+ if (!(wpa_s->drv_rrm_flags &
+ WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT)) {
+ struct os_reltime update_time, diff;
+
+ /* For now, allow 8 ms older results due to some
+ * unknown issue with cfg80211 BSS table updates during
+ * a scan with the current BSS.
+ * TODO: Fix this more properly to avoid having to have
+ * this type of hacks in place. */
+ calculate_update_time(&scan_res->fetch_time,
+ scan_res->res[i]->age,
+ &update_time);
+ os_reltime_sub(&wpa_s->beacon_rep_scan,
+ &update_time, &diff);
+ if (os_reltime_before(&update_time,
+ &wpa_s->beacon_rep_scan) &&
+ (diff.sec || diff.usec >= 8000)) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Ignore scan result for " MACSTR
+ " due to old update (age(ms) %u, calculated age %u.%06u seconds)",
+ MAC2STR(scan_res->res[i]->bssid),
+ scan_res->res[i]->age,
+ (unsigned int) diff.sec,
+ (unsigned int) diff.usec);
+ continue;
+ }
+ } else if (info->scan_start_tsf >
+ scan_res->res[i]->parent_tsf) {
+ continue;
+ }
+
+ if (wpas_add_beacon_rep(wpa_s, &buf, bss, info->scan_start_tsf,
+ scan_res->res[i]->parent_tsf) < 0)
+ break;
+ }
+
+ if (!buf && wpas_beacon_rep_no_results(wpa_s, &buf))
+ goto out;
+
+ wpa_hexdump_buf(MSG_DEBUG, "RRM: Radio Measurement report", buf);
+
+ wpas_rrm_send_msr_report(wpa_s, buf);
+ wpabuf_free(buf);
+
+out:
+ wpas_clear_beacon_rep_data(wpa_s);
+ return 1;
+}
+
+
+void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s)
+{
+ struct beacon_rep_data *data = &wpa_s->beacon_rep_data;
+
+ eloop_cancel_timeout(wpas_rrm_scan_timeout, wpa_s, NULL);
+ bitfield_free(data->eids);
+ os_free(data->scan_params.freqs);
+ os_memset(data, 0, sizeof(*data));
+}
diff --git a/contrib/wpa/wpa_supplicant/scan.c b/contrib/wpa/wpa_supplicant/scan.c
index fb8ebdf2ecc1..7abb028dd344 100644
--- a/contrib/wpa/wpa_supplicant/scan.c
+++ b/contrib/wpa/wpa_supplicant/scan.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant - Scanning
- * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -117,9 +117,19 @@ int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s)
static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
+ int min_temp_disabled = 0;
+
while (ssid) {
- if (!wpas_network_disabled(wpa_s, ssid))
- break;
+ if (!wpas_network_disabled(wpa_s, ssid)) {
+ int temp_disabled = wpas_temp_disabled(wpa_s, ssid);
+
+ if (temp_disabled <= 0)
+ break;
+
+ if (!min_temp_disabled ||
+ temp_disabled < min_temp_disabled)
+ min_temp_disabled = temp_disabled;
+ }
ssid = ssid->next;
}
@@ -128,7 +138,7 @@ static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG, "wpa_supplicant_assoc_try: Reached "
"end of scan list - go back to beginning");
wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
+ wpa_supplicant_req_scan(wpa_s, min_temp_disabled, 0);
return;
}
if (ssid->next) {
@@ -176,10 +186,22 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
params->only_new_results = 1;
}
ret = wpa_drv_scan(wpa_s, params);
+ /*
+ * Store the obtained vendor scan cookie (if any) in wpa_s context.
+ * The current design is to allow only one scan request on each
+ * interface, hence having this scan cookie stored in wpa_s context is
+ * fine for now.
+ *
+ * Revisit this logic if concurrent scan operations per interface
+ * is supported.
+ */
+ if (ret == 0)
+ wpa_s->curr_scan_cookie = params->scan_cookie;
wpa_scan_free_params(params);
work->ctx = NULL;
if (ret) {
- int retry = wpa_s->last_scan_req != MANUAL_SCAN_REQ;
+ int retry = wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
+ !wpa_s->beacon_rep_data.token;
if (wpa_s->disconnected)
retry = 0;
@@ -197,7 +219,14 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
/* Restore scan_req since we will try to scan again */
wpa_s->scan_req = wpa_s->last_scan_req;
wpa_supplicant_req_scan(wpa_s, 1, 0);
+ } else if (wpa_s->scan_res_handler) {
+ /* Clear the scan_res_handler */
+ wpa_s->scan_res_handler = NULL;
}
+
+ if (wpa_s->beacon_rep_data.token)
+ wpas_rrm_refuse_request(wpa_s);
+
return;
}
@@ -426,6 +455,33 @@ static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_MBO
+static void wpas_fils_req_param_add_max_channel(struct wpa_supplicant *wpa_s,
+ struct wpabuf **ie)
+{
+ if (wpabuf_resize(ie, 5)) {
+ wpa_printf(MSG_DEBUG,
+ "Failed to allocate space for FILS Request Parameters element");
+ return;
+ }
+
+ /* FILS Request Parameters element */
+ wpabuf_put_u8(*ie, WLAN_EID_EXTENSION);
+ wpabuf_put_u8(*ie, 3); /* FILS Request attribute length */
+ wpabuf_put_u8(*ie, WLAN_EID_EXT_FILS_REQ_PARAMS);
+ /* Parameter control bitmap */
+ wpabuf_put_u8(*ie, 0);
+ /* Max Channel Time field - contains the value of MaxChannelTime
+ * parameter of the MLME-SCAN.request primitive represented in units of
+ * TUs, as an unsigned integer. A Max Channel Time field value of 255
+ * is used to indicate any duration of more than 254 TUs, or an
+ * unspecified or unknown duration. (IEEE Std 802.11ai-2016, 9.4.2.178)
+ */
+ wpabuf_put_u8(*ie, 255);
+}
+#endif /* CONFIG_MBO */
+
+
void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
{
struct wpabuf *default_ies = NULL;
@@ -447,8 +503,10 @@ void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
wpabuf_put_data(default_ies, ext_capab, ext_capab_len);
#ifdef CONFIG_MBO
- /* Send cellular capabilities for potential MBO STAs */
- if (wpabuf_resize(&default_ies, 9) == 0)
+ if (wpa_s->enable_oce & OCE_STA)
+ wpas_fils_req_param_add_max_channel(wpa_s, &default_ies);
+ /* Send MBO and OCE capabilities */
+ if (wpabuf_resize(&default_ies, 12) == 0)
wpas_mbo_scan_ie(wpa_s, default_ies);
#endif /* CONFIG_MBO */
@@ -488,6 +546,11 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
wpas_add_interworking_elements(wpa_s, extra_ie);
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_MBO
+ if (wpa_s->enable_oce & OCE_STA)
+ wpas_fils_req_param_add_max_channel(wpa_s, &extra_ie);
+#endif /* CONFIG_MBO */
+
#ifdef CONFIG_WPS
wps = wpas_wps_in_use(wpa_s, &req_type);
@@ -518,8 +581,8 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
#endif /* CONFIG_WPS */
#ifdef CONFIG_HS20
- if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
- wpas_hs20_add_indication(extra_ie, -1);
+ if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 9) == 0)
+ wpas_hs20_add_indication(extra_ie, -1, 0);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_FST
@@ -529,8 +592,8 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
#endif /* CONFIG_FST */
#ifdef CONFIG_MBO
- /* Send cellular capabilities for potential MBO STAs */
- if (wpabuf_resize(&extra_ie, 9) == 0)
+ /* Send MBO and OCE capabilities */
+ if (wpabuf_resize(&extra_ie, 12) == 0)
wpas_mbo_scan_ie(wpa_s, extra_ie);
#endif /* CONFIG_MBO */
@@ -614,6 +677,87 @@ static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s,
}
+static void wpa_add_scan_ssid(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params,
+ size_t max_ssids, const u8 *ssid, size_t ssid_len)
+{
+ unsigned int j;
+
+ for (j = 0; j < params->num_ssids; j++) {
+ if (params->ssids[j].ssid_len == ssid_len &&
+ params->ssids[j].ssid &&
+ os_memcmp(params->ssids[j].ssid, ssid, ssid_len) == 0)
+ return; /* already in the list */
+ }
+
+ if (params->num_ssids + 1 > max_ssids) {
+ wpa_printf(MSG_DEBUG, "Over max scan SSIDs for manual request");
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s",
+ wpa_ssid_txt(ssid, ssid_len));
+
+ params->ssids[params->num_ssids].ssid = ssid;
+ params->ssids[params->num_ssids].ssid_len = ssid_len;
+ params->num_ssids++;
+}
+
+
+static void wpa_add_owe_scan_ssid(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params,
+ struct wpa_ssid *ssid, size_t max_ssids)
+{
+#ifdef CONFIG_OWE
+ struct wpa_bss *bss;
+
+ if (!(ssid->key_mgmt & WPA_KEY_MGMT_OWE))
+ return;
+
+ wpa_printf(MSG_DEBUG, "OWE: Look for transition mode AP. ssid=%s",
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+
+ dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
+ const u8 *owe, *pos, *end;
+ const u8 *owe_ssid;
+ size_t owe_ssid_len;
+
+ if (bss->ssid_len != ssid->ssid_len ||
+ os_memcmp(bss->ssid, ssid->ssid, ssid->ssid_len) != 0)
+ continue;
+
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+ if (!owe || owe[1] < 4)
+ continue;
+
+ pos = owe + 6;
+ end = owe + 2 + owe[1];
+
+ /* Must include BSSID and ssid_len */
+ if (end - pos < ETH_ALEN + 1)
+ return;
+
+ /* Skip BSSID */
+ pos += ETH_ALEN;
+ owe_ssid_len = *pos++;
+ owe_ssid = pos;
+
+ if ((size_t) (end - pos) < owe_ssid_len ||
+ owe_ssid_len > SSID_MAX_LEN)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "OWE: scan_ssids: transition mode OWE ssid=%s",
+ wpa_ssid_txt(owe_ssid, owe_ssid_len));
+
+ wpa_add_scan_ssid(wpa_s, params, max_ssids,
+ owe_ssid, owe_ssid_len);
+ return;
+ }
+#endif /* CONFIG_OWE */
+}
+
+
static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s,
struct wpa_driver_scan_params *params,
size_t max_ssids)
@@ -628,33 +772,17 @@ static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s,
max_ssids = max_ssids > 1 ? max_ssids - 1 : max_ssids;
for (i = 0; i < wpa_s->scan_id_count; i++) {
- unsigned int j;
-
ssid = wpa_config_get_network(wpa_s->conf, wpa_s->scan_id[i]);
- if (!ssid || !ssid->scan_ssid)
+ if (!ssid)
continue;
-
- for (j = 0; j < params->num_ssids; j++) {
- if (params->ssids[j].ssid_len == ssid->ssid_len &&
- params->ssids[j].ssid &&
- os_memcmp(params->ssids[j].ssid, ssid->ssid,
- ssid->ssid_len) == 0)
- break;
- }
- if (j < params->num_ssids)
- continue; /* already in the list */
-
- if (params->num_ssids + 1 > max_ssids) {
- wpa_printf(MSG_DEBUG,
- "Over max scan SSIDs for manual request");
- break;
- }
-
- wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s",
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
- params->ssids[params->num_ssids].ssid = ssid->ssid;
- params->ssids[params->num_ssids].ssid_len = ssid->ssid_len;
- params->num_ssids++;
+ if (ssid->scan_ssid)
+ wpa_add_scan_ssid(wpa_s, params, max_ssids,
+ ssid->ssid, ssid->ssid_len);
+ /*
+ * Also add the SSID of the OWE BSS, to allow discovery of
+ * transition mode APs more quickly.
+ */
+ wpa_add_owe_scan_ssid(wpa_s, params, ssid, max_ssids);
}
wpa_s->scan_id_count = 0;
@@ -703,10 +831,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
size_t max_ssids;
int connect_without_scan = 0;
- if (wpa_s->pno || wpa_s->pno_sched_pending) {
- wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - PNO is in progress");
- return;
- }
+ wpa_s->ignore_post_flush_scan_res = 0;
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled");
@@ -768,6 +893,21 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
return;
}
+ /*
+ * Don't cancel the scan based on ongoing PNO; defer it. Some scans are
+ * used for changing modes inside wpa_supplicant (roaming,
+ * auto-reconnect, etc). Discarding the scan might hurt these processes.
+ * The normal use case for PNO is to suspend the host immediately after
+ * starting PNO, so the periodic 100 ms attempts to run the scan do not
+ * normally happen in practice multiple times, i.e., this is simply
+ * restarting scanning once the host is woken up and PNO stopped.
+ */
+ if (wpa_s->pno || wpa_s->pno_sched_pending) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Defer scan - PNO is in progress");
+ wpa_supplicant_req_scan(wpa_s, 0, 100000);
+ return;
+ }
+
if (wpa_s->conf->ap_scan == 2)
max_ssids = 1;
else {
@@ -909,6 +1049,17 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
if (params.num_ssids + 1 >= max_ssids)
break;
}
+
+ if (!wpas_network_disabled(wpa_s, ssid)) {
+ /*
+ * Also add the SSID of the OWE BSS, to allow
+ * discovery of transition mode APs more
+ * quickly.
+ */
+ wpa_add_owe_scan_ssid(wpa_s, &params, ssid,
+ max_ssids);
+ }
+
ssid = ssid->next;
if (ssid == start)
break;
@@ -995,6 +1146,13 @@ ssid_list_set:
wpa_s->manual_scan_freqs = NULL;
}
+ if (params.freqs == NULL && wpa_s->select_network_scan_freqs) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Limit select_network scan to specified channels");
+ params.freqs = wpa_s->select_network_scan_freqs;
+ wpa_s->select_network_scan_freqs = NULL;
+ }
+
if (params.freqs == NULL && wpa_s->next_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
"generated frequency list");
@@ -1029,6 +1187,11 @@ ssid_list_set:
}
}
+#ifdef CONFIG_MBO
+ if (wpa_s->enable_oce & OCE_STA)
+ params.oce_scan = 1;
+#endif /* CONFIG_MBO */
+
params.filter_ssids = wpa_supplicant_build_filter_ssids(
wpa_s->conf, &params.num_filter_ssids);
if (extra_ie) {
@@ -1047,7 +1210,8 @@ ssid_list_set:
}
#endif /* CONFIG_P2P */
- if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) {
+ if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) &&
+ wpa_s->wpa_state <= WPA_SCANNING) {
params.mac_addr_rand = 1;
if (wpa_s->mac_addr_scan) {
params.mac_addr = wpa_s->mac_addr_scan;
@@ -1225,6 +1389,26 @@ int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s,
}
+static void
+wpa_scan_set_relative_rssi_params(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params)
+{
+ if (wpa_s->wpa_state != WPA_COMPLETED ||
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SCHED_SCAN_RELATIVE_RSSI) ||
+ wpa_s->srp.relative_rssi_set == 0)
+ return;
+
+ params->relative_rssi_set = 1;
+ params->relative_rssi = wpa_s->srp.relative_rssi;
+
+ if (wpa_s->srp.relative_adjust_rssi == 0)
+ return;
+
+ params->relative_adjust_band = wpa_s->srp.relative_adjust_band;
+ params->relative_adjust_rssi = wpa_s->srp.relative_adjust_rssi;
+}
+
+
/**
* wpa_supplicant_req_sched_scan - Start a periodic scheduled scan
* @wpa_s: Pointer to wpa_supplicant data
@@ -1417,6 +1601,11 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
int_array_concat(&params.freqs, wpa_s->conf->freq_list);
}
+#ifdef CONFIG_MBO
+ if (wpa_s->enable_oce & OCE_STA)
+ params.oce_scan = 1;
+#endif /* CONFIG_MBO */
+
scan_params = &params;
scan:
@@ -1458,18 +1647,24 @@ scan:
params.sched_scan_plans_num = 1;
}
+ params.sched_scan_start_delay = wpa_s->conf->sched_scan_start_delay;
+
if (ssid || !wpa_s->first_sched_scan) {
wpa_dbg(wpa_s, MSG_DEBUG,
- "Starting sched scan: interval %u timeout %d",
+ "Starting sched scan after %u seconds: interval %u timeout %d",
+ params.sched_scan_start_delay,
params.sched_scan_plans[0].interval,
wpa_s->sched_scan_timeout);
} else {
- wpa_dbg(wpa_s, MSG_DEBUG, "Starting sched scan (no timeout)");
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Starting sched scan after %u seconds (no timeout)",
+ params.sched_scan_start_delay);
}
wpa_setband_scan_freqs(wpa_s, scan_params);
- if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCHED_SCAN) {
+ if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCHED_SCAN) &&
+ wpa_s->wpa_state <= WPA_SCANNING) {
params.mac_addr_rand = 1;
if (wpa_s->mac_addr_sched_scan) {
params.mac_addr = wpa_s->mac_addr_sched_scan;
@@ -1478,6 +1673,8 @@ scan:
}
}
+ wpa_scan_set_relative_rssi_params(wpa_s, scan_params);
+
ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params);
wpabuf_free(extra_ie);
os_free(params.filter_ssids);
@@ -1618,7 +1815,13 @@ static int wpa_scan_get_max_rate(const struct wpa_scan_res *res)
*/
const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
{
- return get_ie((const u8 *) (res + 1), res->ie_len, ie);
+ size_t ie_len = res->ie_len;
+
+ /* Use the Beacon frame IEs if res->ie_len is not available */
+ if (!ie_len)
+ ie_len = res->beacon_ie_len;
+
+ return get_ie((const u8 *) (res + 1), ie_len, ie);
}
@@ -1735,10 +1938,12 @@ struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
* This doc https://supportforums.cisco.com/docs/DOC-12954 says, "the general
* rule of thumb is that any SNR above 20 is good." This one
* http://www.cisco.com/en/US/tech/tk722/tk809/technologies_q_and_a_item09186a00805e9a96.shtml#qa23
- * recommends 25 as a minimum SNR for 54 Mbps data rate. 30 is chosen here as a
- * conservative value.
+ * recommends 25 as a minimum SNR for 54 Mbps data rate. The estimates used in
+ * scan_est_throughput() allow even smaller SNR values for the maximum rates
+ * (21 for 54 Mbps, 22 for VHT80 MCS9, 24 for HT40 and HT20 MCS7). Use 25 as a
+ * somewhat conservative value here.
*/
-#define GREAT_SNR 30
+#define GREAT_SNR 25
#define IS_5GHZ(n) (n > 4000)
@@ -1786,10 +1991,13 @@ static int wpa_scan_result_compar(const void *a, const void *b)
}
/* if SNR is close, decide by max rate or frequency band */
+ if (snr_a && snr_b && abs(snr_b - snr_a) < 7) {
+ if (wa->est_throughput != wb->est_throughput)
+ return (int) wb->est_throughput -
+ (int) wa->est_throughput;
+ }
if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) ||
(wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) {
- if (wa->est_throughput != wb->est_throughput)
- return wb->est_throughput - wa->est_throughput;
if (IS_5GHZ(wa->freq) ^ IS_5GHZ(wb->freq))
return IS_5GHZ(wa->freq) ? -1 : 1;
}
@@ -2177,10 +2385,22 @@ wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_WPS */
- qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),
- compar);
+ if (scan_res->res) {
+ qsort(scan_res->res, scan_res->num,
+ sizeof(struct wpa_scan_res *), compar);
+ }
dump_scan_res(scan_res);
+ if (wpa_s->ignore_post_flush_scan_res) {
+ /* FLUSH command aborted an ongoing scan and these are the
+ * results from the aborted scan. Do not process the results to
+ * maintain flushed state. */
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Do not update BSS table based on pending post-FLUSH scan results");
+ wpa_s->ignore_post_flush_scan_res = 0;
+ return scan_res;
+ }
+
wpa_bss_update_start(wpa_s);
for (i = 0; i < scan_res->num; i++)
wpa_bss_update_scan_res(wpa_s, scan_res->res[i],
@@ -2262,11 +2482,10 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
for (i = 0; i < src->num_ssids; i++) {
if (src->ssids[i].ssid) {
- n = os_malloc(src->ssids[i].ssid_len);
+ n = os_memdup(src->ssids[i].ssid,
+ src->ssids[i].ssid_len);
if (n == NULL)
goto failed;
- os_memcpy(n, src->ssids[i].ssid,
- src->ssids[i].ssid_len);
params->ssids[i].ssid = n;
params->ssids[i].ssid_len = src->ssids[i].ssid_len;
}
@@ -2274,30 +2493,26 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
params->num_ssids = src->num_ssids;
if (src->extra_ies) {
- n = os_malloc(src->extra_ies_len);
+ n = os_memdup(src->extra_ies, src->extra_ies_len);
if (n == NULL)
goto failed;
- os_memcpy(n, src->extra_ies, src->extra_ies_len);
params->extra_ies = n;
params->extra_ies_len = src->extra_ies_len;
}
if (src->freqs) {
int len = int_array_len(src->freqs);
- params->freqs = os_malloc((len + 1) * sizeof(int));
+ params->freqs = os_memdup(src->freqs, (len + 1) * sizeof(int));
if (params->freqs == NULL)
goto failed;
- os_memcpy(params->freqs, src->freqs, (len + 1) * sizeof(int));
}
if (src->filter_ssids) {
- params->filter_ssids = os_malloc(sizeof(*params->filter_ssids) *
+ params->filter_ssids = os_memdup(src->filter_ssids,
+ sizeof(*params->filter_ssids) *
src->num_filter_ssids);
if (params->filter_ssids == NULL)
goto failed;
- os_memcpy(params->filter_ssids, src->filter_ssids,
- sizeof(*params->filter_ssids) *
- src->num_filter_ssids);
params->num_filter_ssids = src->num_filter_ssids;
}
@@ -2305,17 +2520,18 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
params->p2p_probe = src->p2p_probe;
params->only_new_results = src->only_new_results;
params->low_priority = src->low_priority;
+ params->duration = src->duration;
+ params->duration_mandatory = src->duration_mandatory;
+ params->oce_scan = src->oce_scan;
if (src->sched_scan_plans_num > 0) {
params->sched_scan_plans =
- os_malloc(sizeof(*src->sched_scan_plans) *
+ os_memdup(src->sched_scan_plans,
+ sizeof(*src->sched_scan_plans) *
src->sched_scan_plans_num);
if (!params->sched_scan_plans)
goto failed;
- os_memcpy(params->sched_scan_plans, src->sched_scan_plans,
- sizeof(*src->sched_scan_plans) *
- src->sched_scan_plans_num);
params->sched_scan_plans_num = src->sched_scan_plans_num;
}
@@ -2340,13 +2556,16 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
if (src->bssid) {
u8 *bssid;
- bssid = os_malloc(ETH_ALEN);
+ bssid = os_memdup(src->bssid, ETH_ALEN);
if (!bssid)
goto failed;
- os_memcpy(bssid, src->bssid, ETH_ALEN);
params->bssid = bssid;
}
+ params->relative_rssi_set = src->relative_rssi_set;
+ params->relative_rssi = src->relative_rssi;
+ params->relative_adjust_band = src->relative_adjust_band;
+ params->relative_adjust_rssi = src->relative_adjust_rssi;
return params;
failed:
@@ -2404,7 +2623,7 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s)
return 0;
if ((wpa_s->wpa_state > WPA_SCANNING) &&
- (wpa_s->wpa_state <= WPA_COMPLETED)) {
+ (wpa_s->wpa_state < WPA_COMPLETED)) {
wpa_printf(MSG_ERROR, "PNO: In assoc process");
return -EAGAIN;
}
@@ -2511,12 +2730,15 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s)
params.sched_scan_plans_num = 1;
}
+ params.sched_scan_start_delay = wpa_s->conf->sched_scan_start_delay;
+
if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels");
params.freqs = wpa_s->manual_sched_scan_freqs;
}
- if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_PNO) {
+ if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_PNO) &&
+ wpa_s->wpa_state <= WPA_SCANNING) {
params.mac_addr_rand = 1;
if (wpa_s->mac_addr_pno) {
params.mac_addr = wpa_s->mac_addr_pno;
@@ -2524,6 +2746,8 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s)
}
}
+ wpa_scan_set_relative_rssi_params(wpa_s, &params);
+
ret = wpa_supplicant_start_sched_scan(wpa_s, &params);
os_free(params.filter_ssids);
if (ret == 0)
@@ -2583,6 +2807,13 @@ int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s,
{
u8 *tmp = NULL;
+ if ((wpa_s->mac_addr_rand_supported & type) != type ) {
+ wpa_printf(MSG_INFO,
+ "scan: MAC randomization type %u != supported=%u",
+ type, wpa_s->mac_addr_rand_supported);
+ return -1;
+ }
+
wpas_mac_addr_rand_scan_clear(wpa_s, type);
if (addr) {
@@ -2614,18 +2845,20 @@ int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s,
int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s)
{
- int scan_work = !!wpa_s->scan_work;
-
-#ifdef CONFIG_P2P
- scan_work |= !!wpa_s->p2p_scan_work;
-#endif /* CONFIG_P2P */
+ struct wpa_radio_work *work;
+ struct wpa_radio *radio = wpa_s->radio;
- if (scan_work && wpa_s->own_scan_running) {
+ dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
+ if (work->wpa_s != wpa_s || !work->started ||
+ (os_strcmp(work->type, "scan") != 0 &&
+ os_strcmp(work->type, "p2p-scan") != 0))
+ continue;
wpa_dbg(wpa_s, MSG_DEBUG, "Abort an ongoing scan");
- return wpa_drv_abort_scan(wpa_s);
+ return wpa_drv_abort_scan(wpa_s, wpa_s->curr_scan_cookie);
}
- return 0;
+ wpa_dbg(wpa_s, MSG_DEBUG, "No ongoing scan/p2p-scan found to abort");
+ return -1;
}
diff --git a/contrib/wpa/wpa_supplicant/sme.c b/contrib/wpa/wpa_supplicant/sme.c
index 61fd3b24549c..17a984d1a17d 100644
--- a/contrib/wpa/wpa_supplicant/sme.c
+++ b/contrib/wpa/wpa_supplicant/sme.c
@@ -12,9 +12,11 @@
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
+#include "common/ocv.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "common/wpa_common.h"
#include "common/sae.h"
+#include "common/dpp.h"
#include "rsn_supp/wpa.h"
#include "rsn_supp/pmksa_cache.h"
#include "config.h"
@@ -56,7 +58,7 @@ static int index_within_array(const int *array, int idx)
static int sme_set_sae_group(struct wpa_supplicant *wpa_s)
{
int *groups = wpa_s->conf->sae_groups;
- int default_groups[] = { 19, 20, 21, 25, 26, 0 };
+ int default_groups[] = { 19, 20, 21, 0 };
if (!groups || groups[0] <= 0)
groups = default_groups;
@@ -72,7 +74,7 @@ static int sme_set_sae_group(struct wpa_supplicant *wpa_s)
if (sae_set_group(&wpa_s->sme.sae, group) == 0) {
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d",
wpa_s->sme.sae.group);
- return 0;
+ return 0;
}
wpa_s->sme.sae_group_index++;
}
@@ -83,43 +85,77 @@ static int sme_set_sae_group(struct wpa_supplicant *wpa_s)
static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
- const u8 *bssid)
+ const u8 *bssid, int external,
+ int reuse)
{
struct wpabuf *buf;
size_t len;
+ const char *password;
+
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->sae_commit_override) {
+ wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
+ buf = wpabuf_alloc(4 + wpabuf_len(wpa_s->sae_commit_override));
+ if (!buf)
+ return NULL;
+ if (!external) {
+ wpabuf_put_le16(buf, 1); /* Transaction seq# */
+ wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+ }
+ wpabuf_put_buf(buf, wpa_s->sae_commit_override);
+ return buf;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
- if (ssid->passphrase == NULL) {
+ password = ssid->sae_password;
+ if (!password)
+ password = ssid->passphrase;
+ if (!password) {
wpa_printf(MSG_DEBUG, "SAE: No password available");
return NULL;
}
+ if (reuse && wpa_s->sme.sae.tmp &&
+ os_memcmp(bssid, wpa_s->sme.sae.tmp->bssid, ETH_ALEN) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "SAE: Reuse previously generated PWE on a retry with the same AP");
+ goto reuse_data;
+ }
if (sme_set_sae_group(wpa_s) < 0) {
wpa_printf(MSG_DEBUG, "SAE: Failed to select group");
return NULL;
}
if (sae_prepare_commit(wpa_s->own_addr, bssid,
- (u8 *) ssid->passphrase,
- os_strlen(ssid->passphrase),
+ (u8 *) password, os_strlen(password),
+ ssid->sae_password_id,
&wpa_s->sme.sae) < 0) {
wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
return NULL;
}
+ if (wpa_s->sme.sae.tmp)
+ os_memcpy(wpa_s->sme.sae.tmp->bssid, bssid, ETH_ALEN);
+reuse_data:
len = wpa_s->sme.sae_token ? wpabuf_len(wpa_s->sme.sae_token) : 0;
+ if (ssid->sae_password_id)
+ len += 4 + os_strlen(ssid->sae_password_id);
buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + len);
if (buf == NULL)
return NULL;
-
- wpabuf_put_le16(buf, 1); /* Transaction seq# */
- wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
- sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token);
+ if (!external) {
+ wpabuf_put_le16(buf, 1); /* Transaction seq# */
+ wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+ }
+ sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token,
+ ssid->sae_password_id);
return buf;
}
-static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s)
+static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s,
+ int external)
{
struct wpabuf *buf;
@@ -127,8 +163,10 @@ static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s)
if (buf == NULL)
return NULL;
- wpabuf_put_le16(buf, 2); /* Transaction seq# */
- wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+ if (!external) {
+ wpabuf_put_le16(buf, 2); /* Transaction seq# */
+ wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+ }
sae_write_confirm(&wpa_s->sme.sae, buf);
return buf;
@@ -187,6 +225,10 @@ static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)
*pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
+ *pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
+ WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
+ WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
+
if (wpa_s->lci)
pos[1] |= WLAN_RRM_CAPS_LCI_MEASUREMENT;
@@ -204,16 +246,18 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_IEEE80211R
const u8 *ie;
#endif /* CONFIG_IEEE80211R */
-#ifdef CONFIG_IEEE80211R
+#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
const u8 *md = NULL;
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
int i, bssid_changed;
struct wpabuf *resp = NULL;
u8 ext_capab[18];
int ext_capab_len;
int skip_auth;
+ u8 *wpa_ie;
+ size_t wpa_ie_len;
#ifdef CONFIG_MBO
- const u8 *mbo;
+ const u8 *mbo_ie;
#endif /* CONFIG_MBO */
if (bss == NULL) {
@@ -272,6 +316,12 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
if (!rsn) {
wpa_dbg(wpa_s, MSG_DEBUG,
"SAE enabled, but target BSS does not advertise RSN");
+#ifdef CONFIG_DPP
+ } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
+ (ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
+ (ied.key_mgmt & WPA_KEY_MGMT_DPP)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Prefer DPP over SAE when both are enabled");
+#endif /* CONFIG_DPP */
} else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
wpa_key_mgmt_sae(ied.key_mgmt)) {
wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg");
@@ -300,13 +350,20 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
wpa_key_mgmt_wpa(ssid->key_mgmt)) {
int try_opportunistic;
+ const u8 *cache_id = NULL;
+
try_opportunistic = (ssid->proactive_key_caching < 0 ?
wpa_s->conf->okc :
ssid->proactive_key_caching) &&
(ssid->proto & WPA_PROTO_RSN);
+#ifdef CONFIG_FILS
+ if (wpa_key_mgmt_fils(ssid->key_mgmt))
+ cache_id = wpa_bss_get_fils_cache_id(bss);
+#endif /* CONFIG_FILS */
if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
wpa_s->current_ssid,
- try_opportunistic) == 0)
+ try_opportunistic, cache_id,
+ 0) == 0)
eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
@@ -317,6 +374,20 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
wpas_connect_work_done(wpa_s);
return;
}
+#ifdef CONFIG_HS20
+ } else if (wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
+ (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
+ /* No PMKSA caching, but otherwise similar to RSN/WPA */
+ wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
+ if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
+ wpa_s->sme.assoc_req_ie,
+ &wpa_s->sme.assoc_req_ie_len)) {
+ wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
+ "key management and encryption suites");
+ wpas_connect_work_done(wpa_s);
+ return;
+ }
+#endif /* CONFIG_HS20 */
} else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
/*
@@ -356,17 +427,45 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
wpa_s->sme.assoc_req_ie_len = 0;
}
+ /* In case the WPA vendor IE is used, it should be placed after all the
+ * non-vendor IEs, as the lower layer expects the IEs to be ordered as
+ * defined in the standard. Store the WPA IE so it can later be
+ * inserted at the correct location.
+ */
+ wpa_ie = NULL;
+ wpa_ie_len = 0;
+ if (wpa_s->wpa_proto == WPA_PROTO_WPA) {
+ wpa_ie = os_memdup(wpa_s->sme.assoc_req_ie,
+ wpa_s->sme.assoc_req_ie_len);
+ if (wpa_ie) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Storing WPA IE");
+
+ wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
+ wpa_s->sme.assoc_req_ie_len = 0;
+ } else {
+ wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed copy WPA IE");
+ wpas_connect_work_done(wpa_s);
+ return;
+ }
+ }
+
#ifdef CONFIG_IEEE80211R
ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
md = ie + 2;
wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
+ if (md && (!wpa_key_mgmt_ft(ssid->key_mgmt) ||
+ !wpa_key_mgmt_ft(wpa_s->key_mgmt)))
+ md = NULL;
if (md) {
/* Prepare for the next transition */
wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
}
- if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) {
+ if (md) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x",
+ md[0], md[1]);
+
if (wpa_s->sme.assoc_req_ie_len + 5 <
sizeof(wpa_s->sme.assoc_req_ie)) {
struct rsn_mdie *mdie;
@@ -381,7 +480,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
wpa_s->sme.assoc_req_ie_len += 5;
}
- if (wpa_s->sme.ft_used &&
+ if (wpa_s->sme.prev_bssid_set && wpa_s->sme.ft_used &&
os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
wpa_sm_has_ptk(wpa_s->wpa)) {
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
@@ -440,20 +539,10 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
sme_auth_handle_rrm(wpa_s, bss);
-#ifdef CONFIG_MBO
- mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
- if (mbo) {
- int len;
-
- len = wpas_mbo_supp_op_class_ie(
- wpa_s, bss->freq,
- wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
- sizeof(wpa_s->sme.assoc_req_ie) -
- wpa_s->sme.assoc_req_ie_len);
- if (len > 0)
- wpa_s->sme.assoc_req_ie_len += len;
- }
-#endif /* CONFIG_MBO */
+ wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
+ wpa_s, ssid, bss->freq,
+ wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
+ sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
if (params.p2p)
wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
@@ -477,12 +566,14 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
if (is_hs20_network(wpa_s, ssid, bss)) {
struct wpabuf *hs20;
- hs20 = wpabuf_alloc(20);
+ hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
if (hs20) {
int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
size_t len;
- wpas_hs20_add_indication(hs20, pps_mo_id);
+ wpas_hs20_add_indication(hs20, pps_mo_id,
+ get_hs20_version(bss));
+ wpas_hs20_add_roam_cons_sel(hs20, ssid);
len = sizeof(wpa_s->sme.assoc_req_ie) -
wpa_s->sme.assoc_req_ie_len;
if (wpabuf_len(hs20) <= len) {
@@ -496,6 +587,26 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_HS20 */
+ if (wpa_ie) {
+ size_t len;
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Reinsert WPA IE");
+
+ len = sizeof(wpa_s->sme.assoc_req_ie) -
+ wpa_s->sme.assoc_req_ie_len;
+
+ if (len > wpa_ie_len) {
+ os_memcpy(wpa_s->sme.assoc_req_ie +
+ wpa_s->sme.assoc_req_ie_len,
+ wpa_ie, wpa_ie_len);
+ wpa_s->sme.assoc_req_ie_len += wpa_ie_len;
+ } else {
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Failed to add WPA IE");
+ }
+
+ os_free(wpa_ie);
+ }
+
if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
size_t len;
@@ -511,13 +622,16 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
}
#ifdef CONFIG_MBO
- if (mbo) {
+ mbo_ie = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
+ if (mbo_ie) {
int len;
len = wpas_mbo_ie(wpa_s, wpa_s->sme.assoc_req_ie +
wpa_s->sme.assoc_req_ie_len,
sizeof(wpa_s->sme.assoc_req_ie) -
- wpa_s->sme.assoc_req_ie_len);
+ wpa_s->sme.assoc_req_ie_len,
+ !!mbo_attr_from_mbo_ie(mbo_ie,
+ OCE_ATTR_ID_CAPA_IND));
if (len >= 0)
wpa_s->sme.assoc_req_ie_len += len;
}
@@ -525,10 +639,14 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_SAE
if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
- pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0) == 0)
- {
+ pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0,
+ NULL,
+ wpa_s->key_mgmt == WPA_KEY_MGMT_FT_SAE ?
+ WPA_KEY_MGMT_FT_SAE :
+ WPA_KEY_MGMT_SAE) == 0) {
wpa_dbg(wpa_s, MSG_DEBUG,
"PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
+ wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
params.auth_alg = WPA_AUTH_ALG_OPEN;
wpa_s->sme.sae_pmksa_caching = 1;
}
@@ -536,19 +654,106 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) {
if (start)
resp = sme_auth_build_sae_commit(wpa_s, ssid,
- bss->bssid);
+ bss->bssid, 0,
+ start == 2);
else
- resp = sme_auth_build_sae_confirm(wpa_s);
+ resp = sme_auth_build_sae_confirm(wpa_s, 0);
if (resp == NULL) {
wpas_connection_failed(wpa_s, bss->bssid);
return;
}
- params.sae_data = wpabuf_head(resp);
- params.sae_data_len = wpabuf_len(resp);
+ params.auth_data = wpabuf_head(resp);
+ params.auth_data_len = wpabuf_len(resp);
wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED;
}
#endif /* CONFIG_SAE */
+ old_ssid = wpa_s->current_ssid;
+ wpa_s->current_ssid = ssid;
+ wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
+ wpa_supplicant_initiate_eapol(wpa_s);
+
+#ifdef CONFIG_FILS
+ /* TODO: FILS operations can in some cases be done between different
+ * network_ctx (i.e., same credentials can be used with multiple
+ * networks). */
+ if (params.auth_alg == WPA_AUTH_ALG_OPEN &&
+ wpa_key_mgmt_fils(ssid->key_mgmt)) {
+ const u8 *indic;
+ u16 fils_info;
+ const u8 *realm, *username, *rrk;
+ size_t realm_len, username_len, rrk_len;
+ u16 next_seq_num;
+
+ /*
+ * Check FILS Indication element (FILS Information field) bits
+ * indicating supported authentication algorithms against local
+ * configuration (ssid->fils_dh_group). Try to use FILS
+ * authentication only if the AP supports the combination in the
+ * network profile. */
+ indic = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
+ if (!indic || indic[1] < 2) {
+ wpa_printf(MSG_DEBUG, "SME: " MACSTR
+ " does not include FILS Indication element - cannot use FILS authentication with it",
+ MAC2STR(bss->bssid));
+ goto no_fils;
+ }
+
+ fils_info = WPA_GET_LE16(indic + 2);
+ if (ssid->fils_dh_group == 0 && !(fils_info & BIT(9))) {
+ wpa_printf(MSG_DEBUG, "SME: " MACSTR
+ " does not support FILS SK without PFS - cannot use FILS authentication with it",
+ MAC2STR(bss->bssid));
+ goto no_fils;
+ }
+ if (ssid->fils_dh_group != 0 && !(fils_info & BIT(10))) {
+ wpa_printf(MSG_DEBUG, "SME: " MACSTR
+ " does not support FILS SK with PFS - cannot use FILS authentication with it",
+ MAC2STR(bss->bssid));
+ goto no_fils;
+ }
+
+ if (wpa_s->last_con_fail_realm &&
+ eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
+ &username, &username_len,
+ &realm, &realm_len, &next_seq_num,
+ &rrk, &rrk_len) == 0 &&
+ realm && realm_len == wpa_s->last_con_fail_realm_len &&
+ os_memcmp(realm, wpa_s->last_con_fail_realm,
+ realm_len) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "SME: FILS authentication for this realm failed last time - try to regenerate ERP key hierarchy");
+ goto no_fils;
+ }
+
+ if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
+ ssid, 0,
+ wpa_bss_get_fils_cache_id(bss),
+ 0) == 0)
+ wpa_printf(MSG_DEBUG,
+ "SME: Try to use FILS with PMKSA caching");
+ resp = fils_build_auth(wpa_s->wpa, ssid->fils_dh_group, md);
+ if (resp) {
+ int auth_alg;
+
+ if (ssid->fils_dh_group)
+ wpa_printf(MSG_DEBUG,
+ "SME: Try to use FILS SK authentication with PFS (DH Group %u)",
+ ssid->fils_dh_group);
+ else
+ wpa_printf(MSG_DEBUG,
+ "SME: Try to use FILS SK authentication without PFS");
+ auth_alg = ssid->fils_dh_group ?
+ WPA_AUTH_ALG_FILS_SK_PFS : WPA_AUTH_ALG_FILS;
+ params.auth_alg = auth_alg;
+ params.auth_data = wpabuf_head(resp);
+ params.auth_data_len = wpabuf_len(resp);
+ wpa_s->sme.auth_alg = auth_alg;
+ }
+ }
+no_fils:
+#endif /* CONFIG_FILS */
+
wpa_supplicant_cancel_sched_scan(wpa_s);
wpa_supplicant_cancel_scan(wpa_s);
@@ -556,12 +761,9 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
" (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
+ eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
wpa_clear_keys(wpa_s, bss->bssid);
wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
- old_ssid = wpa_s->current_ssid;
- wpa_s->current_ssid = ssid;
- wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
- wpa_supplicant_initiate_eapol(wpa_s);
if (old_ssid != wpa_s->current_ssid)
wpas_notify_network_changed(wpa_s);
@@ -650,6 +852,10 @@ static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit)
return;
}
+ /* Starting new connection, so clear the possibly used WPA IE from the
+ * previous association. */
+ wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
+
sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1);
}
@@ -700,8 +906,150 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_SAE
+static int sme_external_auth_build_buf(struct wpabuf *buf,
+ struct wpabuf *params,
+ const u8 *sa, const u8 *da,
+ u16 auth_transaction, u16 seq_num)
+{
+ struct ieee80211_mgmt *resp;
+
+ resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
+ u.auth.variable));
+
+ resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
+ (WLAN_FC_STYPE_AUTH << 4));
+ os_memcpy(resp->da, da, ETH_ALEN);
+ os_memcpy(resp->sa, sa, ETH_ALEN);
+ os_memcpy(resp->bssid, da, ETH_ALEN);
+ resp->u.auth.auth_alg = host_to_le16(WLAN_AUTH_SAE);
+ resp->seq_ctrl = host_to_le16(seq_num << 4);
+ resp->u.auth.auth_transaction = host_to_le16(auth_transaction);
+ resp->u.auth.status_code = host_to_le16(WLAN_STATUS_SUCCESS);
+ if (params)
+ wpabuf_put_buf(buf, params);
+
+ return 0;
+}
+
+
+static void sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
+ const u8 *bssid,
+ struct wpa_ssid *ssid)
+{
+ struct wpabuf *resp, *buf;
+
+ resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid, 1, 0);
+ if (!resp)
+ return;
+
+ wpa_s->sme.sae.state = SAE_COMMITTED;
+ buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + wpabuf_len(resp));
+ if (!buf) {
+ wpabuf_free(resp);
+ return;
+ }
+
+ wpa_s->sme.seq_num++;
+ sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
+ bssid, 1, wpa_s->sme.seq_num);
+ wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0);
+ wpabuf_free(resp);
+ wpabuf_free(buf);
+}
+
+
+static void sme_send_external_auth_status(struct wpa_supplicant *wpa_s,
+ u16 status)
+{
+ struct external_auth params;
+
+ os_memset(&params, 0, sizeof(params));
+ params.status = status;
+ params.ssid = wpa_s->sme.ext_auth.ssid;
+ params.ssid_len = wpa_s->sme.ext_auth.ssid_len;
+ params.bssid = wpa_s->sme.ext_auth.bssid;
+ wpa_drv_send_external_auth_status(wpa_s, &params);
+}
+
+
+static void sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ struct wpa_ssid *ssid;
+ size_t ssid_str_len = data->external_auth.ssid_len;
+ const u8 *ssid_str = data->external_auth.ssid;
+
+ /* Get the SSID conf from the ssid string obtained */
+ for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+ if (!wpas_network_disabled(wpa_s, ssid) &&
+ ssid_str_len == ssid->ssid_len &&
+ os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0 &&
+ (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)))
+ break;
+ }
+ if (ssid)
+ sme_external_auth_send_sae_commit(wpa_s,
+ data->external_auth.bssid,
+ ssid);
+ else
+ sme_send_external_auth_status(wpa_s,
+ WLAN_STATUS_UNSPECIFIED_FAILURE);
+}
+
+
+static void sme_external_auth_send_sae_confirm(struct wpa_supplicant *wpa_s,
+ const u8 *da)
+{
+ struct wpabuf *resp, *buf;
+
+ resp = sme_auth_build_sae_confirm(wpa_s, 1);
+ if (!resp) {
+ wpa_printf(MSG_DEBUG, "SAE: Confirm message buf alloc failure");
+ return;
+ }
+
+ wpa_s->sme.sae.state = SAE_CONFIRMED;
+ buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN + wpabuf_len(resp));
+ if (!buf) {
+ wpa_printf(MSG_DEBUG, "SAE: Auth Confirm buf alloc failure");
+ wpabuf_free(resp);
+ return;
+ }
+ wpa_s->sme.seq_num++;
+ sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
+ da, 2, wpa_s->sme.seq_num);
+ wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0);
+ wpabuf_free(resp);
+ wpabuf_free(buf);
+}
+
+
+void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ if (RSN_SELECTOR_GET(&data->external_auth.key_mgmt_suite) !=
+ RSN_AUTH_KEY_MGMT_SAE)
+ return;
+
+ if (data->external_auth.action == EXT_AUTH_START) {
+ os_memcpy(&wpa_s->sme.ext_auth, data,
+ sizeof(struct external_auth));
+ wpa_s->sme.seq_num = 0;
+ wpa_s->sme.sae.state = SAE_NOTHING;
+ wpa_s->sme.sae.send_confirm = 0;
+ wpa_s->sme.sae_group_index = 0;
+ sme_handle_external_auth_start(wpa_s, data);
+ } else if (data->external_auth.action == EXT_AUTH_ABORT) {
+ /* Report failure to driver for the wrong trigger */
+ sme_send_external_auth_status(wpa_s,
+ WLAN_STATUS_UNSPECIFIED_FAILURE);
+ }
+}
+
+
static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
- u16 status_code, const u8 *data, size_t len)
+ u16 status_code, const u8 *data, size_t len,
+ int external, const u8 *sa)
{
int *groups;
@@ -711,8 +1059,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
if (auth_transaction == 1 &&
status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
wpa_s->sme.sae.state == SAE_COMMITTED &&
- wpa_s->current_bss && wpa_s->current_ssid) {
- int default_groups[] = { 19, 20, 21, 25, 26, 0 };
+ (external || wpa_s->current_bss) && wpa_s->current_ssid) {
+ int default_groups[] = { 19, 20, 21, 0 };
u16 group;
groups = wpa_s->conf->sae_groups;
@@ -738,25 +1086,45 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
wpabuf_free(wpa_s->sme.sae_token);
wpa_s->sme.sae_token = wpabuf_alloc_copy(data + sizeof(le16),
len - sizeof(le16));
- sme_send_authentication(wpa_s, wpa_s->current_bss,
- wpa_s->current_ssid, 1);
+ if (!external)
+ sme_send_authentication(wpa_s, wpa_s->current_bss,
+ wpa_s->current_ssid, 2);
+ else
+ sme_external_auth_send_sae_commit(
+ wpa_s, wpa_s->sme.ext_auth.bssid,
+ wpa_s->current_ssid);
return 0;
}
if (auth_transaction == 1 &&
status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
wpa_s->sme.sae.state == SAE_COMMITTED &&
- wpa_s->current_bss && wpa_s->current_ssid) {
+ (external || wpa_s->current_bss) && wpa_s->current_ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported");
wpa_s->sme.sae_group_index++;
if (sme_set_sae_group(wpa_s) < 0)
return -1; /* no other groups enabled */
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Try next enabled SAE group");
- sme_send_authentication(wpa_s, wpa_s->current_bss,
- wpa_s->current_ssid, 1);
+ if (!external)
+ sme_send_authentication(wpa_s, wpa_s->current_bss,
+ wpa_s->current_ssid, 1);
+ else
+ sme_external_auth_send_sae_commit(
+ wpa_s, wpa_s->sme.ext_auth.bssid,
+ wpa_s->current_ssid);
return 0;
}
+ if (auth_transaction == 1 &&
+ status_code == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) {
+ const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
+
+ wpa_msg(wpa_s, MSG_INFO,
+ WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER MACSTR,
+ MAC2STR(bssid));
+ return -1;
+ }
+
if (status_code != WLAN_STATUS_SUCCESS)
return -1;
@@ -766,7 +1134,7 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
groups = wpa_s->conf->sae_groups;
wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
- if (wpa_s->current_bss == NULL ||
+ if ((!external && wpa_s->current_bss == NULL) ||
wpa_s->current_ssid == NULL)
return -1;
if (wpa_s->sme.sae.state != SAE_COMMITTED)
@@ -791,8 +1159,11 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
wpabuf_free(wpa_s->sme.sae_token);
wpa_s->sme.sae_token = NULL;
- sme_send_authentication(wpa_s, wpa_s->current_bss,
- wpa_s->current_ssid, 0);
+ if (!external)
+ sme_send_authentication(wpa_s, wpa_s->current_bss,
+ wpa_s->current_ssid, 0);
+ else
+ sme_external_auth_send_sae_confirm(wpa_s, sa);
return 0;
} else if (auth_transaction == 2) {
wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
@@ -802,11 +1173,60 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
return -1;
wpa_s->sme.sae.state = SAE_ACCEPTED;
sae_clear_temp_data(&wpa_s->sme.sae);
+
+ if (external) {
+ /* Report success to driver */
+ sme_send_external_auth_status(wpa_s,
+ WLAN_STATUS_SUCCESS);
+ }
+
return 1;
}
return -1;
}
+
+
+void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
+ const u8 *auth_frame, size_t len)
+{
+ const struct ieee80211_mgmt *header;
+ size_t auth_length;
+
+ header = (const struct ieee80211_mgmt *) auth_frame;
+ auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth);
+
+ if (len < auth_length) {
+ /* Notify failure to the driver */
+ sme_send_external_auth_status(wpa_s,
+ WLAN_STATUS_UNSPECIFIED_FAILURE);
+ return;
+ }
+
+ if (le_to_host16(header->u.auth.auth_alg) == WLAN_AUTH_SAE) {
+ int res;
+
+ res = sme_sae_auth(
+ wpa_s, le_to_host16(header->u.auth.auth_transaction),
+ le_to_host16(header->u.auth.status_code),
+ header->u.auth.variable,
+ len - auth_length, 1, header->sa);
+ if (res < 0) {
+ /* Notify failure to the driver */
+ sme_send_external_auth_status(
+ wpa_s, WLAN_STATUS_UNSPECIFIED_FAILURE);
+ return;
+ }
+ if (res != 1)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "SME: SAE completed - setting PMK for 4-way handshake");
+ wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN,
+ wpa_s->sme.sae.pmkid, wpa_s->pending_bssid);
+ }
+}
+
#endif /* CONFIG_SAE */
@@ -847,7 +1267,7 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
int res;
res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
data->auth.status_code, data->auth.ies,
- data->auth.ies_len);
+ data->auth.ies_len, 0, NULL);
if (res < 0) {
wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
@@ -875,12 +1295,19 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
}
}
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
- " auth_type=%u auth_transaction=%u status_code=%u ie=%s",
+ " auth_type=%u auth_transaction=%u status_code=%u%s%s",
MAC2STR(data->auth.peer), data->auth.auth_type,
data->auth.auth_transaction, data->auth.status_code,
- ie_txt);
+ ie_txt ? " ie=" : "",
+ ie_txt ? ie_txt : "");
os_free(ie_txt);
+#ifdef CONFIG_FILS
+ if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
+ wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS_SK_PFS)
+ fils_connection_failure(wpa_s);
+#endif /* CONFIG_FILS */
+
if (data->auth.status_code !=
WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
wpa_s->sme.auth_alg == data->auth.auth_type ||
@@ -916,9 +1343,17 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
#ifdef CONFIG_IEEE80211R
if (data->auth.auth_type == WLAN_AUTH_FT) {
+ const u8 *ric_ies = NULL;
+ size_t ric_ies_len = 0;
+
+ if (wpa_s->ric_ies) {
+ ric_ies = wpabuf_head(wpa_s->ric_ies);
+ ric_ies_len = wpabuf_len(wpa_s->ric_ies);
+ }
if (wpa_ft_process_response(wpa_s->wpa, data->auth.ies,
data->auth.ies_len, 0,
- data->auth.peer, NULL, 0) < 0) {
+ data->auth.peer,
+ ric_ies, ric_ies_len) < 0) {
wpa_dbg(wpa_s, MSG_DEBUG,
"SME: FT Authentication response processing failed");
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
@@ -933,16 +1368,73 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
}
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_FILS
+ if (data->auth.auth_type == WLAN_AUTH_FILS_SK ||
+ data->auth.auth_type == WLAN_AUTH_FILS_SK_PFS) {
+ u16 expect_auth_type;
+
+ expect_auth_type = wpa_s->sme.auth_alg ==
+ WPA_AUTH_ALG_FILS_SK_PFS ? WLAN_AUTH_FILS_SK_PFS :
+ WLAN_AUTH_FILS_SK;
+ if (data->auth.auth_type != expect_auth_type) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "SME: FILS Authentication response used different auth alg (%u; expected %u)",
+ data->auth.auth_type, expect_auth_type);
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
+ MACSTR
+ " reason=%d locally_generated=1",
+ MAC2STR(wpa_s->pending_bssid),
+ WLAN_REASON_DEAUTH_LEAVING);
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ wpa_supplicant_mark_disassoc(wpa_s);
+ return;
+ }
+
+ if (fils_process_auth(wpa_s->wpa, wpa_s->pending_bssid,
+ data->auth.ies, data->auth.ies_len) < 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "SME: FILS Authentication response processing failed");
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
+ MACSTR
+ " reason=%d locally_generated=1",
+ MAC2STR(wpa_s->pending_bssid),
+ WLAN_REASON_DEAUTH_LEAVING);
+ wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ wpa_supplicant_mark_disassoc(wpa_s);
+ return;
+ }
+ }
+#endif /* CONFIG_FILS */
+
sme_associate(wpa_s, ssid->mode, data->auth.peer,
data->auth.auth_type);
}
+#ifdef CONFIG_IEEE80211R
+static void remove_ie(u8 *buf, size_t *len, u8 eid)
+{
+ u8 *pos, *next, *end;
+
+ pos = (u8 *) get_ie(buf, *len, eid);
+ if (pos) {
+ next = pos + 2 + pos[1];
+ end = buf + *len;
+ *len -= 2 + pos[1];
+ os_memmove(pos, next, end - next);
+ }
+}
+#endif /* CONFIG_IEEE80211R */
+
+
void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
const u8 *bssid, u16 auth_type)
{
struct wpa_driver_associate_params params;
struct ieee802_11_elems elems;
+#ifdef CONFIG_FILS
+ u8 nonces[2 * FILS_NONCE_LEN];
+#endif /* CONFIG_FILS */
#ifdef CONFIG_HT_OVERRIDES
struct ieee80211_ht_capabilities htcaps;
struct ieee80211_ht_capabilities htcaps_mask;
@@ -953,6 +1445,184 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
#endif /* CONFIG_VHT_OVERRIDES */
os_memset(&params, 0, sizeof(params));
+
+#ifdef CONFIG_FILS
+ if (auth_type == WLAN_AUTH_FILS_SK ||
+ auth_type == WLAN_AUTH_FILS_SK_PFS) {
+ struct wpabuf *buf;
+ const u8 *snonce, *anonce;
+ const unsigned int max_hlp = 20;
+ struct wpabuf *hlp[max_hlp];
+ unsigned int i, num_hlp = 0;
+ struct fils_hlp_req *req;
+
+ dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
+ list) {
+ hlp[num_hlp] = wpabuf_alloc(2 * ETH_ALEN + 6 +
+ wpabuf_len(req->pkt));
+ if (!hlp[num_hlp])
+ break;
+ wpabuf_put_data(hlp[num_hlp], req->dst, ETH_ALEN);
+ wpabuf_put_data(hlp[num_hlp], wpa_s->own_addr,
+ ETH_ALEN);
+ wpabuf_put_data(hlp[num_hlp],
+ "\xaa\xaa\x03\x00\x00\x00", 6);
+ wpabuf_put_buf(hlp[num_hlp], req->pkt);
+ num_hlp++;
+ if (num_hlp >= max_hlp)
+ break;
+ }
+
+ buf = fils_build_assoc_req(wpa_s->wpa, &params.fils_kek,
+ &params.fils_kek_len, &snonce,
+ &anonce,
+ (const struct wpabuf **) hlp,
+ num_hlp);
+ for (i = 0; i < num_hlp; i++)
+ wpabuf_free(hlp[i]);
+ if (!buf)
+ return;
+ wpa_hexdump(MSG_DEBUG, "FILS: assoc_req before FILS elements",
+ wpa_s->sme.assoc_req_ie,
+ wpa_s->sme.assoc_req_ie_len);
+#ifdef CONFIG_IEEE80211R
+ if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) {
+ /* Remove RSNE and MDE to allow them to be overridden
+ * with FILS+FT specific values from
+ * fils_build_assoc_req(). */
+ remove_ie(wpa_s->sme.assoc_req_ie,
+ &wpa_s->sme.assoc_req_ie_len,
+ WLAN_EID_RSN);
+ wpa_hexdump(MSG_DEBUG,
+ "FILS: assoc_req after RSNE removal",
+ wpa_s->sme.assoc_req_ie,
+ wpa_s->sme.assoc_req_ie_len);
+ remove_ie(wpa_s->sme.assoc_req_ie,
+ &wpa_s->sme.assoc_req_ie_len,
+ WLAN_EID_MOBILITY_DOMAIN);
+ wpa_hexdump(MSG_DEBUG,
+ "FILS: assoc_req after MDE removal",
+ wpa_s->sme.assoc_req_ie,
+ wpa_s->sme.assoc_req_ie_len);
+ }
+#endif /* CONFIG_IEEE80211R */
+ /* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */
+ if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(buf) >
+ sizeof(wpa_s->sme.assoc_req_ie)) {
+ wpa_printf(MSG_ERROR,
+ "FILS: Not enough buffer room for own AssocReq elements");
+ wpabuf_free(buf);
+ return;
+ }
+ os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
+ wpabuf_head(buf), wpabuf_len(buf));
+ wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
+ wpabuf_free(buf);
+ wpa_hexdump(MSG_DEBUG, "FILS: assoc_req after FILS elements",
+ wpa_s->sme.assoc_req_ie,
+ wpa_s->sme.assoc_req_ie_len);
+
+ os_memcpy(nonces, snonce, FILS_NONCE_LEN);
+ os_memcpy(nonces + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN);
+ params.fils_nonces = nonces;
+ params.fils_nonces_len = sizeof(nonces);
+ }
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_OWE
+#ifdef CONFIG_TESTING_OPTIONS
+ if (get_ie_ext(wpa_s->sme.assoc_req_ie, wpa_s->sme.assoc_req_ie_len,
+ WLAN_EID_EXT_OWE_DH_PARAM)) {
+ wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
+ } else
+#endif /* CONFIG_TESTING_OPTIONS */
+ if (auth_type == WLAN_AUTH_OPEN &&
+ wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
+ struct wpabuf *owe_ie;
+ u16 group;
+
+ if (wpa_s->current_ssid && wpa_s->current_ssid->owe_group) {
+ group = wpa_s->current_ssid->owe_group;
+ } else if (wpa_s->assoc_status_code ==
+ WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
+ if (wpa_s->last_owe_group == 19)
+ group = 20;
+ else if (wpa_s->last_owe_group == 20)
+ group = 21;
+ else
+ group = OWE_DH_GROUP;
+ } else {
+ group = OWE_DH_GROUP;
+ }
+
+ wpa_s->last_owe_group = group;
+ wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
+ owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
+ if (!owe_ie) {
+ wpa_printf(MSG_ERROR,
+ "OWE: Failed to build IE for Association Request frame");
+ return;
+ }
+ if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(owe_ie) >
+ sizeof(wpa_s->sme.assoc_req_ie)) {
+ wpa_printf(MSG_ERROR,
+ "OWE: Not enough buffer room for own Association Request frame elements");
+ wpabuf_free(owe_ie);
+ return;
+ }
+ os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
+ wpabuf_head(owe_ie), wpabuf_len(owe_ie));
+ wpa_s->sme.assoc_req_ie_len += wpabuf_len(owe_ie);
+ wpabuf_free(owe_ie);
+ }
+#endif /* CONFIG_OWE */
+
+#ifdef CONFIG_DPP2
+ if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->current_ssid &&
+ wpa_s->current_ssid->dpp_netaccesskey) {
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+
+ dpp_pfs_free(wpa_s->dpp_pfs);
+ wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
+ ssid->dpp_netaccesskey_len);
+ if (!wpa_s->dpp_pfs) {
+ wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
+ /* Try to continue without PFS */
+ goto pfs_fail;
+ }
+ if (wpa_s->sme.assoc_req_ie_len +
+ wpabuf_len(wpa_s->dpp_pfs->ie) >
+ sizeof(wpa_s->sme.assoc_req_ie)) {
+ wpa_printf(MSG_ERROR,
+ "DPP: Not enough buffer room for own Association Request frame elements");
+ dpp_pfs_free(wpa_s->dpp_pfs);
+ wpa_s->dpp_pfs = NULL;
+ goto pfs_fail;
+ }
+ os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
+ wpabuf_head(wpa_s->dpp_pfs->ie),
+ wpabuf_len(wpa_s->dpp_pfs->ie));
+ wpa_s->sme.assoc_req_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
+ }
+pfs_fail:
+#endif /* CONFIG_DPP2 */
+
+ if (wpa_s->current_ssid && wpa_s->current_ssid->multi_ap_backhaul_sta) {
+ size_t multi_ap_ie_len;
+
+ multi_ap_ie_len = add_multi_ap_ie(
+ wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
+ sizeof(wpa_s->sme.assoc_req_ie) -
+ wpa_s->sme.assoc_req_ie_len,
+ MULTI_AP_BACKHAUL_STA);
+ if (multi_ap_ie_len == 0) {
+ wpa_printf(MSG_ERROR,
+ "Multi-AP: Failed to build Multi-AP IE");
+ return;
+ }
+ wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
+ }
+
params.bssid = bssid;
params.ssid = wpa_s->sme.ssid;
params.ssid_len = wpa_s->sme.ssid_len;
@@ -962,8 +1632,11 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
wpa_s->sme.assoc_req_ie : NULL;
params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
+ wpa_hexdump(MSG_DEBUG, "SME: Association Request IEs",
+ params.wpa_ie, params.wpa_ie_len);
params.pairwise_suite = wpa_s->pairwise_cipher;
params.group_suite = wpa_s->group_cipher;
+ params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
params.key_mgmt_suite = wpa_s->key_mgmt;
params.wpa_proto = wpa_s->wpa_proto;
#ifdef CONFIG_HT_OVERRIDES
@@ -981,9 +1654,85 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
#endif /* CONFIG_VHT_OVERRIDES */
#ifdef CONFIG_IEEE80211R
- if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
+ if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies &&
+ get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len,
+ WLAN_EID_RIC_DATA)) {
+ /* There seems to be a pretty inconvenient bug in the Linux
+ * kernel IE splitting functionality when RIC is used. For now,
+ * skip correct behavior in IE construction here (i.e., drop the
+ * additional non-FT-specific IEs) to avoid kernel issues. This
+ * is fine since RIC is used only for testing purposes in the
+ * current implementation. */
+ wpa_printf(MSG_INFO,
+ "SME: Linux kernel workaround - do not try to include additional IEs with RIC");
params.wpa_ie = wpa_s->sme.ft_ies;
params.wpa_ie_len = wpa_s->sme.ft_ies_len;
+ } else if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
+ const u8 *rm_en, *pos, *end;
+ size_t rm_en_len = 0;
+ u8 *rm_en_dup = NULL, *wpos;
+
+ /* Remove RSNE, MDE, FTE to allow them to be overridden with
+ * FT specific values */
+ remove_ie(wpa_s->sme.assoc_req_ie,
+ &wpa_s->sme.assoc_req_ie_len,
+ WLAN_EID_RSN);
+ remove_ie(wpa_s->sme.assoc_req_ie,
+ &wpa_s->sme.assoc_req_ie_len,
+ WLAN_EID_MOBILITY_DOMAIN);
+ remove_ie(wpa_s->sme.assoc_req_ie,
+ &wpa_s->sme.assoc_req_ie_len,
+ WLAN_EID_FAST_BSS_TRANSITION);
+ rm_en = get_ie(wpa_s->sme.assoc_req_ie,
+ wpa_s->sme.assoc_req_ie_len,
+ WLAN_EID_RRM_ENABLED_CAPABILITIES);
+ if (rm_en) {
+ /* Need to remove RM Enabled Capabilities element as
+ * well temporarily, so that it can be placed between
+ * RSNE and MDE. */
+ rm_en_len = 2 + rm_en[1];
+ rm_en_dup = os_memdup(rm_en, rm_en_len);
+ remove_ie(wpa_s->sme.assoc_req_ie,
+ &wpa_s->sme.assoc_req_ie_len,
+ WLAN_EID_RRM_ENABLED_CAPABILITIES);
+ }
+ wpa_hexdump(MSG_DEBUG,
+ "SME: Association Request IEs after FT IE removal",
+ wpa_s->sme.assoc_req_ie,
+ wpa_s->sme.assoc_req_ie_len);
+ if (wpa_s->sme.assoc_req_ie_len + wpa_s->sme.ft_ies_len +
+ rm_en_len > sizeof(wpa_s->sme.assoc_req_ie)) {
+ wpa_printf(MSG_ERROR,
+ "SME: Not enough buffer room for FT IEs in Association Request frame");
+ os_free(rm_en_dup);
+ return;
+ }
+
+ os_memmove(wpa_s->sme.assoc_req_ie + wpa_s->sme.ft_ies_len +
+ rm_en_len,
+ wpa_s->sme.assoc_req_ie,
+ wpa_s->sme.assoc_req_ie_len);
+ pos = wpa_s->sme.ft_ies;
+ end = pos + wpa_s->sme.ft_ies_len;
+ wpos = wpa_s->sme.assoc_req_ie;
+ if (*pos == WLAN_EID_RSN) {
+ os_memcpy(wpos, pos, 2 + pos[1]);
+ wpos += 2 + pos[1];
+ pos += 2 + pos[1];
+ }
+ if (rm_en_dup) {
+ os_memcpy(wpos, rm_en_dup, rm_en_len);
+ wpos += rm_en_len;
+ os_free(rm_en_dup);
+ }
+ os_memcpy(wpos, pos, end - pos);
+ wpa_s->sme.assoc_req_ie_len += wpa_s->sme.ft_ies_len +
+ rm_en_len;
+ params.wpa_ie = wpa_s->sme.assoc_req_ie;
+ params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
+ wpa_hexdump(MSG_DEBUG,
+ "SME: Association Request IEs after FT override",
+ params.wpa_ie, params.wpa_ie_len);
}
#endif /* CONFIG_IEEE80211R */
params.mode = mode;
@@ -1038,6 +1787,14 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
NULL);
+
+#ifdef CONFIG_TESTING_OPTIONS
+ wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
+ wpa_s->last_assoc_req_wpa_ie = NULL;
+ if (params.wpa_ie)
+ wpa_s->last_assoc_req_wpa_ie =
+ wpabuf_alloc_copy(params.wpa_ie, params.wpa_ie_len);
+#endif /* CONFIG_TESTING_OPTIONS */
}
@@ -1056,10 +1813,9 @@ int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len);
os_free(wpa_s->sme.ft_ies);
- wpa_s->sme.ft_ies = os_malloc(ies_len);
+ wpa_s->sme.ft_ies = os_memdup(ies, ies_len);
if (wpa_s->sme.ft_ies == NULL)
return -1;
- os_memcpy(wpa_s->sme.ft_ies, ies, ies_len);
wpa_s->sme.ft_ies_len = ies_len;
return 0;
}
@@ -1226,20 +1982,17 @@ void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
sae_clear_data(&wpa_s->sme.sae);
#endif /* CONFIG_SAE */
#ifdef CONFIG_IEEE80211R
- if (wpa_s->sme.ft_ies)
+ if (wpa_s->sme.ft_ies || wpa_s->sme.ft_used)
sme_update_ft_ies(wpa_s, NULL, NULL, 0);
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_IEEE80211W
+ sme_stop_sa_query(wpa_s);
+#endif /* CONFIG_IEEE80211W */
}
void sme_deinit(struct wpa_supplicant *wpa_s)
{
- os_free(wpa_s->sme.ft_ies);
- wpa_s->sme.ft_ies = NULL;
- wpa_s->sme.ft_ies_len = 0;
-#ifdef CONFIG_IEEE80211W
- sme_stop_sa_query(wpa_s);
-#endif /* CONFIG_IEEE80211W */
sme_clear_on_disassoc(wpa_s);
eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
@@ -1533,6 +2286,7 @@ void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
static const unsigned int sa_query_max_timeout = 1000;
static const unsigned int sa_query_retry_timeout = 201;
+static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */
static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
{
@@ -1556,7 +2310,9 @@ static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
const u8 *trans_id)
{
- u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN];
+ u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
+ u8 req_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
+
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
MACSTR, MAC2STR(wpa_s->bssid));
wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID",
@@ -1564,9 +2320,27 @@ static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
req[0] = WLAN_ACTION_SA_QUERY;
req[1] = WLAN_SA_QUERY_REQUEST;
os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
+
+#ifdef CONFIG_OCV
+ if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
+ struct wpa_channel_info ci;
+
+ if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info for OCI element in SA Query Request frame");
+ return;
+ }
+
+ if (ocv_insert_extended_oci(&ci, req + req_len) < 0)
+ return;
+
+ req_len += OCV_OCI_EXTENDED_LEN;
+ }
+#endif /* CONFIG_OCV */
+
if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
wpa_s->own_addr, wpa_s->bssid,
- req, sizeof(req), 0) < 0)
+ req, req_len, 0) < 0)
wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
"Request");
}
@@ -1623,6 +2397,8 @@ static void sme_start_sa_query(struct wpa_supplicant *wpa_s)
static void sme_stop_sa_query(struct wpa_supplicant *wpa_s)
{
+ if (wpa_s->sme.sa_query_trans_id)
+ wpa_dbg(wpa_s, MSG_DEBUG, "SME: Stop SA Query");
eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL);
os_free(wpa_s->sme.sa_query_trans_id);
wpa_s->sme.sa_query_trans_id = NULL;
@@ -1661,15 +2437,74 @@ void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
}
-void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
- const u8 *data, size_t len)
+void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
+{
+ unsigned int usec;
+ u32 _rand;
+
+ if (wpa_s->wpa_state != WPA_COMPLETED ||
+ !wpa_sm_ocv_enabled(wpa_s->wpa))
+ return;
+
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "SME: Channel switch completed - trigger new SA Query to verify new operating channel");
+ sme_stop_sa_query(wpa_s);
+
+ if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
+ _rand = os_random();
+ usec = _rand % (sa_query_ch_switch_max_delay + 1);
+ eloop_register_timeout(0, usec, sme_sa_query_timer, wpa_s, NULL);
+}
+
+
+static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s,
+ const u8 *sa, const u8 *data,
+ size_t len)
+{
+ u8 resp[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
+ u8 resp_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Response to "
+ MACSTR, MAC2STR(wpa_s->bssid));
+
+ resp[0] = WLAN_ACTION_SA_QUERY;
+ resp[1] = WLAN_SA_QUERY_RESPONSE;
+ os_memcpy(resp + 2, data + 1, WLAN_SA_QUERY_TR_ID_LEN);
+
+#ifdef CONFIG_OCV
+ if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
+ struct wpa_channel_info ci;
+
+ if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info for OCI element in SA Query Response frame");
+ return;
+ }
+
+ if (ocv_insert_extended_oci(&ci, resp + resp_len) < 0)
+ return;
+
+ resp_len += OCV_OCI_EXTENDED_LEN;
+ }
+#endif /* CONFIG_OCV */
+
+ if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+ wpa_s->own_addr, wpa_s->bssid,
+ resp, resp_len, 0) < 0)
+ wpa_msg(wpa_s, MSG_INFO,
+ "SME: Failed to send SA Query Response");
+}
+
+
+static void sme_process_sa_query_response(struct wpa_supplicant *wpa_s,
+ const u8 *sa, const u8 *data,
+ size_t len)
{
int i;
- if (wpa_s->sme.sa_query_trans_id == NULL ||
- len < 1 + WLAN_SA_QUERY_TR_ID_LEN ||
- data[0] != WLAN_SA_QUERY_RESPONSE)
+ if (!wpa_s->sme.sa_query_trans_id)
return;
+
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
@@ -1694,4 +2529,48 @@ void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
sme_stop_sa_query(wpa_s);
}
+
+void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
+ const u8 *data, size_t len)
+{
+ if (len < 1 + WLAN_SA_QUERY_TR_ID_LEN)
+ return;
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query frame from "
+ MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
+
+#ifdef CONFIG_OCV
+ if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
+ struct ieee802_11_elems elems;
+ struct wpa_channel_info ci;
+
+ if (ieee802_11_parse_elems(data + 1 + WLAN_SA_QUERY_TR_ID_LEN,
+ len - 1 - WLAN_SA_QUERY_TR_ID_LEN,
+ &elems, 1) == ParseFailed) {
+ wpa_printf(MSG_DEBUG,
+ "SA Query: Failed to parse elements");
+ return;
+ }
+
+ if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info to validate received OCI in SA Query Action frame");
+ return;
+ }
+
+ if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
+ channel_width_to_int(ci.chanwidth),
+ ci.seg1_idx) != 0) {
+ wpa_printf(MSG_WARNING, "%s", ocv_errorstr);
+ return;
+ }
+ }
+#endif /* CONFIG_OCV */
+
+ if (data[0] == WLAN_SA_QUERY_REQUEST)
+ sme_process_sa_query_request(wpa_s, sa, data, len);
+ else if (data[0] == WLAN_SA_QUERY_RESPONSE)
+ sme_process_sa_query_response(wpa_s, sa, data, len);
+}
+
#endif /* CONFIG_IEEE80211W */
diff --git a/contrib/wpa/wpa_supplicant/sme.h b/contrib/wpa/wpa_supplicant/sme.h
index fd5c3b4e1ed8..1a7f9e8320c7 100644
--- a/contrib/wpa/wpa_supplicant/sme.h
+++ b/contrib/wpa/wpa_supplicant/sme.h
@@ -28,6 +28,7 @@ void sme_event_disassoc(struct wpa_supplicant *wpa_s,
struct disassoc_info *info);
void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
const u8 *da, u16 reason_code);
+void sme_event_ch_switch(struct wpa_supplicant *wpa_s);
void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
const u8 *data, size_t len);
void sme_state_changed(struct wpa_supplicant *wpa_s);
@@ -38,6 +39,10 @@ void sme_deinit(struct wpa_supplicant *wpa_s);
int sme_proc_obss_scan(struct wpa_supplicant *wpa_s);
void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable);
+void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data);
+void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
+ const u8 *auth_frame, size_t len);
#else /* CONFIG_SME */
@@ -85,6 +90,10 @@ static inline void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s,
{
}
+static inline void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
+{
+}
+
static inline void sme_state_changed(struct wpa_supplicant *wpa_s)
{
}
@@ -113,6 +122,16 @@ static inline void sme_sched_obss_scan(struct wpa_supplicant *wpa_s,
{
}
+static inline void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+}
+
+static inline void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
+ const u8 *auth_frame, size_t len)
+{
+}
+
#endif /* CONFIG_SME */
#endif /* SME_H */
diff --git a/contrib/wpa/wpa_supplicant/systemd/wpa_supplicant.service.in b/contrib/wpa/wpa_supplicant/systemd/wpa_supplicant.service.in
index bc5d49af8655..75a37a8cdbd3 100644
--- a/contrib/wpa/wpa_supplicant/systemd/wpa_supplicant.service.in
+++ b/contrib/wpa/wpa_supplicant/systemd/wpa_supplicant.service.in
@@ -5,9 +5,9 @@ Wants=network.target
[Service]
Type=dbus
-BusName=@DBUS_INTERFACE@
+BusName=fi.w1.wpa_supplicant1
ExecStart=@BINDIR@/wpa_supplicant -u
[Install]
WantedBy=multi-user.target
-Alias=dbus-@DBUS_INTERFACE@.service
+Alias=dbus-fi.w1.wpa_supplicant1.service
diff --git a/contrib/wpa/wpa_supplicant/utils/log2pcap.py b/contrib/wpa/wpa_supplicant/utils/log2pcap.py
index 65e2fa109cbb..141aecbe5178 100755
--- a/contrib/wpa/wpa_supplicant/utils/log2pcap.py
+++ b/contrib/wpa/wpa_supplicant/utils/log2pcap.py
@@ -28,7 +28,7 @@ if __name__ == "__main__":
input = sys.argv[1]
pcap = sys.argv[2]
except IndexError:
- print "Usage: %s <log file> <pcap file>" % sys.argv[0]
+ print("Usage: %s <log file> <pcap file>" % sys.argv[0])
sys.exit(2)
input_file = open(input, 'r')
diff --git a/contrib/wpa/wpa_supplicant/wifi_display.c b/contrib/wpa/wpa_supplicant/wifi_display.c
index c363b21b92b1..c94e4610893a 100644
--- a/contrib/wpa/wpa_supplicant/wifi_display.c
+++ b/contrib/wpa/wpa_supplicant/wifi_display.c
@@ -86,6 +86,7 @@ static int wifi_display_update_wfd_ie(struct wpa_global *global)
p2p_set_wfd_ie_prov_disc_resp(global->p2p, NULL);
p2p_set_wfd_ie_go_neg(global->p2p, NULL);
p2p_set_wfd_dev_info(global->p2p, NULL);
+ p2p_set_wfd_r2_dev_info(global->p2p, NULL);
p2p_set_wfd_assoc_bssid(global->p2p, NULL);
p2p_set_wfd_coupled_sink_info(global->p2p, NULL);
return 0;
@@ -93,6 +94,8 @@ static int wifi_display_update_wfd_ie(struct wpa_global *global)
p2p_set_wfd_dev_info(global->p2p,
global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO]);
+ p2p_set_wfd_r2_dev_info(
+ global->p2p, global->wfd_subelem[WFD_SUBELEM_R2_DEVICE_INFO]);
p2p_set_wfd_assoc_bssid(
global->p2p,
global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID]);
@@ -133,6 +136,11 @@ static int wifi_display_update_wfd_ie(struct wpa_global *global)
if (global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO])
len += wpabuf_len(global->wfd_subelem[
WFD_SUBELEM_DEVICE_INFO]);
+
+ if (global->wfd_subelem[WFD_SUBELEM_R2_DEVICE_INFO])
+ len += wpabuf_len(global->wfd_subelem[
+ WFD_SUBELEM_R2_DEVICE_INFO]);
+
if (global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID])
len += wpabuf_len(global->wfd_subelem[
WFD_SUBELEM_ASSOCIATED_BSSID]);
@@ -151,6 +159,11 @@ static int wifi_display_update_wfd_ie(struct wpa_global *global)
if (global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO])
wpabuf_put_buf(buf,
global->wfd_subelem[WFD_SUBELEM_DEVICE_INFO]);
+
+ if (global->wfd_subelem[WFD_SUBELEM_R2_DEVICE_INFO])
+ wpabuf_put_buf(buf,
+ global->wfd_subelem[WFD_SUBELEM_R2_DEVICE_INFO]);
+
if (global->wfd_subelem[WFD_SUBELEM_ASSOCIATED_BSSID])
wpabuf_put_buf(buf, global->wfd_subelem[
WFD_SUBELEM_ASSOCIATED_BSSID]);
diff --git a/contrib/wpa/wpa_supplicant/wmm_ac.c b/contrib/wpa/wpa_supplicant/wmm_ac.c
index 5625d36638b5..38800cc77fb7 100644
--- a/contrib/wpa/wpa_supplicant/wmm_ac.c
+++ b/contrib/wpa/wpa_supplicant/wmm_ac.c
@@ -87,13 +87,10 @@ static int wmm_ac_add_ts(struct wpa_supplicant *wpa_s, const u8 *addr,
}
/* copy tspec */
- _tspec = os_malloc(sizeof(*_tspec));
+ _tspec = os_memdup(tspec, sizeof(*_tspec));
if (!_tspec)
return -1;
- /* store the admitted TSPEC */
- os_memcpy(_tspec, tspec, sizeof(*_tspec));
-
if (dir != WMM_AC_DIR_DOWNLINK) {
ret = wpa_drv_add_ts(wpa_s, tsid, addr, up, admitted_time);
wpa_printf(MSG_DEBUG,
@@ -474,13 +471,8 @@ static int wmm_ac_init(struct wpa_supplicant *wpa_s, const u8 *ies,
return -1;
}
- if (!ies) {
- wpa_printf(MSG_ERROR, "WMM AC: Missing IEs");
- return -1;
- }
-
- if (!(wmm_params->info_bitmap & WMM_PARAMS_UAPSD_QUEUES_INFO)) {
- wpa_printf(MSG_DEBUG, "WMM AC: Missing U-APSD configuration");
+ if (!ies || !(wmm_params->info_bitmap & WMM_PARAMS_UAPSD_QUEUES_INFO)) {
+ /* WMM AC not in use for this connection */
return -1;
}
@@ -525,7 +517,7 @@ static void wmm_ac_deinit(struct wpa_supplicant *wpa_s)
for (i = 0; i < WMM_AC_NUM; i++)
wmm_ac_del_ts(wpa_s, i, TS_DIR_IDX_ALL);
- /* delete pending add_ts requset */
+ /* delete pending add_ts request */
wmm_ac_del_req(wpa_s, 1);
os_free(wpa_s->wmm_ac_assoc_info);
diff --git a/contrib/wpa/wpa_supplicant/wnm_sta.c b/contrib/wpa/wpa_supplicant/wnm_sta.c
index 67a07ff7b1e7..22a21361ad8a 100644
--- a/contrib/wpa/wpa_supplicant/wnm_sta.c
+++ b/contrib/wpa/wpa_supplicant/wnm_sta.c
@@ -12,13 +12,16 @@
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/wpa_ctrl.h"
+#include "common/ocv.h"
#include "rsn_supp/wpa.h"
+#include "config.h"
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "scan.h"
#include "ctrl_iface.h"
#include "bss.h"
#include "wnm_sta.h"
+#include "notify.h"
#include "hs20_supplicant.h"
#define MAX_TFS_IE_LEN 1024
@@ -57,8 +60,8 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s,
int res;
size_t len;
struct wnm_sleep_element *wnmsleep_ie;
- u8 *wnmtfs_ie;
- u8 wnmsleep_ie_len;
+ u8 *wnmtfs_ie, *oci_ie;
+ u8 wnmsleep_ie_len, oci_ie_len;
u16 wnmtfs_ie_len; /* possibly multiple IE(s) */
enum wnm_oper tfs_oper = action == 0 ? WNM_SLEEP_TFS_REQ_IE_ADD :
WNM_SLEEP_TFS_REQ_IE_NONE;
@@ -84,12 +87,11 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s,
/* TFS IE(s) */
if (tfs_req) {
wnmtfs_ie_len = wpabuf_len(tfs_req);
- wnmtfs_ie = os_malloc(wnmtfs_ie_len);
+ wnmtfs_ie = os_memdup(wpabuf_head(tfs_req), wnmtfs_ie_len);
if (wnmtfs_ie == NULL) {
os_free(wnmsleep_ie);
return -1;
}
- os_memcpy(wnmtfs_ie, wpabuf_head(tfs_req), wnmtfs_ie_len);
} else {
wnmtfs_ie = os_zalloc(MAX_TFS_IE_LEN);
if (wnmtfs_ie == NULL) {
@@ -106,7 +108,41 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s,
wpa_hexdump(MSG_DEBUG, "WNM: TFS Request element",
(u8 *) wnmtfs_ie, wnmtfs_ie_len);
- mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len + wnmtfs_ie_len);
+ oci_ie = NULL;
+ oci_ie_len = 0;
+#ifdef CONFIG_OCV
+ if (action == WNM_SLEEP_MODE_EXIT && wpa_sm_ocv_enabled(wpa_s->wpa)) {
+ struct wpa_channel_info ci;
+
+ if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info for OCI element in WNM-Sleep Mode frame");
+ os_free(wnmsleep_ie);
+ os_free(wnmtfs_ie);
+ return -1;
+ }
+
+ oci_ie_len = OCV_OCI_EXTENDED_LEN;
+ oci_ie = os_zalloc(oci_ie_len);
+ if (!oci_ie) {
+ wpa_printf(MSG_WARNING,
+ "Failed to allocate buffer for for OCI element in WNM-Sleep Mode frame");
+ os_free(wnmsleep_ie);
+ os_free(wnmtfs_ie);
+ return -1;
+ }
+
+ if (ocv_insert_extended_oci(&ci, oci_ie) < 0) {
+ os_free(wnmsleep_ie);
+ os_free(wnmtfs_ie);
+ os_free(oci_ie);
+ return -1;
+ }
+ }
+#endif /* CONFIG_OCV */
+
+ mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len + wnmtfs_ie_len +
+ oci_ie_len);
if (mgmt == NULL) {
wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
"WNM-Sleep Request action frame");
@@ -131,8 +167,16 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s,
wnmsleep_ie_len, wnmtfs_ie, wnmtfs_ie_len);
}
+#ifdef CONFIG_OCV
+ /* copy OCV OCI here */
+ if (oci_ie_len > 0) {
+ os_memcpy(mgmt->u.action.u.wnm_sleep_req.variable +
+ wnmsleep_ie_len + wnmtfs_ie_len, oci_ie, oci_ie_len);
+ }
+#endif /* CONFIG_OCV */
+
len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_req) + wnmsleep_ie_len +
- wnmtfs_ie_len;
+ wnmtfs_ie_len + oci_ie_len;
res = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
wpa_s->own_addr, wpa_s->bssid,
@@ -145,6 +189,7 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s,
os_free(wnmsleep_ie);
os_free(wnmtfs_ie);
+ os_free(oci_ie);
os_free(mgmt);
return res;
@@ -256,6 +301,10 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_supplicant *wpa_s,
/* multiple TFS Resp IE (assuming consecutive) */
const u8 *tfsresp_ie_start = NULL;
const u8 *tfsresp_ie_end = NULL;
+#ifdef CONFIG_OCV
+ const u8 *oci_ie = NULL;
+ u8 oci_ie_len = 0;
+#endif /* CONFIG_OCV */
size_t left;
if (!wpa_s->wnmsleep_used) {
@@ -289,6 +338,12 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_supplicant *wpa_s,
if (!tfsresp_ie_start)
tfsresp_ie_start = pos;
tfsresp_ie_end = pos;
+#ifdef CONFIG_OCV
+ } else if (*pos == WLAN_EID_EXTENSION && ie_len >= 1 &&
+ pos[2] == WLAN_EID_EXT_OCV_OCI) {
+ oci_ie = pos + 3;
+ oci_ie_len = ie_len - 1;
+#endif /* CONFIG_OCV */
} else
wpa_printf(MSG_DEBUG, "EID %d not recognized", *pos);
pos += ie_len + 2;
@@ -299,6 +354,26 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_supplicant *wpa_s,
return;
}
+#ifdef CONFIG_OCV
+ if (wnmsleep_ie->action_type == WNM_SLEEP_MODE_EXIT &&
+ wpa_sm_ocv_enabled(wpa_s->wpa)) {
+ struct wpa_channel_info ci;
+
+ if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
+ wpa_msg(wpa_s, MSG_WARNING,
+ "Failed to get channel info to validate received OCI in WNM-Sleep Mode frame");
+ return;
+ }
+
+ if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci,
+ channel_width_to_int(ci.chanwidth),
+ ci.seg1_idx) != 0) {
+ wpa_msg(wpa_s, MSG_WARNING, "WNM: %s", ocv_errorstr);
+ return;
+ }
+ }
+#endif /* CONFIG_OCV */
+
wpa_s->wnmsleep_used = 0;
if (wnmsleep_ie->status == WNM_STATUS_SLEEP_ACCEPT ||
@@ -338,6 +413,9 @@ void wnm_deallocate_memory(struct wpa_supplicant *wpa_s)
wpa_s->wnm_num_neighbor_report = 0;
os_free(wpa_s->wnm_neighbor_report_elements);
wpa_s->wnm_neighbor_report_elements = NULL;
+
+ wpabuf_free(wpa_s->coloc_intf_elems);
+ wpa_s->coloc_intf_elems = NULL;
}
@@ -501,10 +579,128 @@ static void wnm_parse_neighbor_report(struct wpa_supplicant *wpa_s,
}
+static void wnm_clear_acceptable(struct wpa_supplicant *wpa_s)
+{
+ unsigned int i;
+
+ for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++)
+ wpa_s->wnm_neighbor_report_elements[i].acceptable = 0;
+}
+
+
+static struct wpa_bss * get_first_acceptable(struct wpa_supplicant *wpa_s)
+{
+ unsigned int i;
+ struct neighbor_report *nei;
+
+ for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
+ nei = &wpa_s->wnm_neighbor_report_elements[i];
+ if (nei->acceptable)
+ return wpa_bss_get_bssid(wpa_s, nei->bssid);
+ }
+
+ return NULL;
+}
+
+
+#ifdef CONFIG_MBO
static struct wpa_bss *
-compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs)
+get_mbo_transition_candidate(struct wpa_supplicant *wpa_s,
+ enum mbo_transition_reject_reason *reason)
{
+ struct wpa_bss *target = NULL;
+ struct wpa_bss_trans_info params;
+ struct wpa_bss_candidate_info *info = NULL;
+ struct neighbor_report *nei = wpa_s->wnm_neighbor_report_elements;
+ u8 *first_candidate_bssid = NULL, *pos;
+ unsigned int i;
+
+ params.mbo_transition_reason = wpa_s->wnm_mbo_transition_reason;
+ params.n_candidates = 0;
+ params.bssid = os_calloc(wpa_s->wnm_num_neighbor_report, ETH_ALEN);
+ if (!params.bssid)
+ return NULL;
+ pos = params.bssid;
+ for (i = 0; i < wpa_s->wnm_num_neighbor_report; nei++, i++) {
+ if (nei->is_first)
+ first_candidate_bssid = nei->bssid;
+ if (!nei->acceptable)
+ continue;
+ os_memcpy(pos, nei->bssid, ETH_ALEN);
+ pos += ETH_ALEN;
+ params.n_candidates++;
+ }
+
+ if (!params.n_candidates)
+ goto end;
+
+ info = wpa_drv_get_bss_trans_status(wpa_s, &params);
+ if (!info) {
+ /* If failed to get candidate BSS transition status from driver,
+ * get the first acceptable candidate from wpa_supplicant.
+ */
+ target = wpa_bss_get_bssid(wpa_s, params.bssid);
+ goto end;
+ }
+
+ /* Get the first acceptable candidate from driver */
+ for (i = 0; i < info->num; i++) {
+ if (info->candidates[i].is_accept) {
+ target = wpa_bss_get_bssid(wpa_s,
+ info->candidates[i].bssid);
+ goto end;
+ }
+ }
+
+ /* If Disassociation Imminent is set and driver rejects all the
+ * candidate select first acceptable candidate which has
+ * rssi > disassoc_imminent_rssi_threshold
+ */
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
+ for (i = 0; i < info->num; i++) {
+ target = wpa_bss_get_bssid(wpa_s,
+ info->candidates[i].bssid);
+ if (target &&
+ (target->level <
+ wpa_s->conf->disassoc_imminent_rssi_threshold))
+ continue;
+ goto end;
+ }
+ }
+
+ /* While sending BTM reject use reason code of the first candidate
+ * received in BTM request frame
+ */
+ if (reason) {
+ for (i = 0; i < info->num; i++) {
+ if (first_candidate_bssid &&
+ os_memcmp(first_candidate_bssid,
+ info->candidates[i].bssid, ETH_ALEN) == 0)
+ {
+ *reason = info->candidates[i].reject_reason;
+ break;
+ }
+ }
+ }
+
+ target = NULL;
+
+end:
+ os_free(params.bssid);
+ if (info) {
+ os_free(info->candidates);
+ os_free(info);
+ }
+ return target;
+}
+#endif /* CONFIG_MBO */
+
+
+static struct wpa_bss *
+compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs,
+ enum mbo_transition_reject_reason *reason)
+{
u8 i;
struct wpa_bss *bss = wpa_s->current_bss;
struct wpa_bss *target;
@@ -515,6 +711,8 @@ compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs)
wpa_printf(MSG_DEBUG, "WNM: Current BSS " MACSTR " RSSI %d",
MAC2STR(wpa_s->bssid), bss->level);
+ wnm_clear_acceptable(wpa_s);
+
for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
struct neighbor_report *nei;
@@ -564,7 +762,7 @@ compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs)
if (wpa_s->current_ssid &&
!wpa_scan_res_match(wpa_s, 0, target, wpa_s->current_ssid,
- 1)) {
+ 1, 0)) {
wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
" (pref %d) does not match the current network profile",
MAC2STR(nei->bssid),
@@ -573,7 +771,7 @@ compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs)
continue;
}
- if (wpa_is_bss_tmp_disallowed(wpa_s, target->bssid)) {
+ if (wpa_is_bss_tmp_disallowed(wpa_s, target)) {
wpa_printf(MSG_DEBUG,
"MBO: Candidate BSS " MACSTR
" retry delay is not over yet",
@@ -591,14 +789,26 @@ compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs)
continue;
}
+ nei->acceptable = 1;
+ }
+
+#ifdef CONFIG_MBO
+ if (wpa_s->wnm_mbo_trans_reason_present)
+ target = get_mbo_transition_candidate(wpa_s, reason);
+ else
+ target = get_first_acceptable(wpa_s);
+#else /* CONFIG_MBO */
+ target = get_first_acceptable(wpa_s);
+#endif /* CONFIG_MBO */
+
+ if (target) {
wpa_printf(MSG_DEBUG,
"WNM: Found an acceptable preferred transition candidate BSS "
MACSTR " (RSSI %d)",
- MAC2STR(nei->bssid), target->level);
- return target;
+ MAC2STR(target->bssid), target->level);
}
- return NULL;
+ return target;
}
@@ -651,36 +861,40 @@ static u32 wnm_get_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
}
-static int wnm_add_nei_rep(u8 *buf, size_t len, const u8 *bssid, u32 bss_info,
- u8 op_class, u8 chan, u8 phy_type, u8 pref)
+static int wnm_add_nei_rep(struct wpabuf **buf, const u8 *bssid,
+ u32 bss_info, u8 op_class, u8 chan, u8 phy_type,
+ u8 pref)
{
- u8 *pos = buf;
+ if (wpabuf_len(*buf) + 18 >
+ IEEE80211_MAX_MMPDU_SIZE - IEEE80211_HDRLEN) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: No room in frame for Neighbor Report element");
+ return -1;
+ }
- if (len < 18) {
+ if (wpabuf_resize(buf, 18) < 0) {
wpa_printf(MSG_DEBUG,
- "WNM: Not enough room for Neighbor Report element");
+ "WNM: Failed to allocate memory for Neighbor Report element");
return -1;
}
- *pos++ = WLAN_EID_NEIGHBOR_REPORT;
+ wpabuf_put_u8(*buf, WLAN_EID_NEIGHBOR_REPORT);
/* length: 13 for basic neighbor report + 3 for preference subelement */
- *pos++ = 16;
- os_memcpy(pos, bssid, ETH_ALEN);
- pos += ETH_ALEN;
- WPA_PUT_LE32(pos, bss_info);
- pos += 4;
- *pos++ = op_class;
- *pos++ = chan;
- *pos++ = phy_type;
- *pos++ = WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE;
- *pos++ = 1;
- *pos++ = pref;
- return pos - buf;
+ wpabuf_put_u8(*buf, 16);
+ wpabuf_put_data(*buf, bssid, ETH_ALEN);
+ wpabuf_put_le32(*buf, bss_info);
+ wpabuf_put_u8(*buf, op_class);
+ wpabuf_put_u8(*buf, chan);
+ wpabuf_put_u8(*buf, phy_type);
+ wpabuf_put_u8(*buf, WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE);
+ wpabuf_put_u8(*buf, 1);
+ wpabuf_put_u8(*buf, pref);
+ return 0;
}
static int wnm_nei_rep_add_bss(struct wpa_supplicant *wpa_s,
- struct wpa_bss *bss, u8 *buf, size_t len,
+ struct wpa_bss *bss, struct wpabuf **buf,
u8 pref)
{
const u8 *ie;
@@ -729,20 +943,19 @@ static int wnm_nei_rep_add_bss(struct wpa_supplicant *wpa_s,
info = wnm_get_bss_info(wpa_s, bss);
- return wnm_add_nei_rep(buf, len, bss->bssid, info, op_class, chan,
- phy_type, pref);
+ return wnm_add_nei_rep(buf, bss->bssid, info, op_class, chan, phy_type,
+ pref);
}
-static int wnm_add_cand_list(struct wpa_supplicant *wpa_s, u8 *buf, size_t len)
+static void wnm_add_cand_list(struct wpa_supplicant *wpa_s, struct wpabuf **buf)
{
- u8 *pos = buf;
unsigned int i, pref = 255;
struct os_reltime now;
struct wpa_ssid *ssid = wpa_s->current_ssid;
if (!ssid)
- return 0;
+ return;
/*
* TODO: Define when scan results are no longer valid for the candidate
@@ -750,7 +963,7 @@ static int wnm_add_cand_list(struct wpa_supplicant *wpa_s, u8 *buf, size_t len)
*/
os_get_reltime(&now);
if (os_reltime_expired(&now, &wpa_s->last_scan, 10))
- return 0;
+ return;
wpa_printf(MSG_DEBUG,
"WNM: Add candidate list to BSS Transition Management Response frame");
@@ -758,93 +971,103 @@ static int wnm_add_cand_list(struct wpa_supplicant *wpa_s, u8 *buf, size_t len)
struct wpa_bss *bss = wpa_s->last_scan_res[i];
int res;
- if (wpa_scan_res_match(wpa_s, i, bss, ssid, 1)) {
- res = wnm_nei_rep_add_bss(wpa_s, bss, pos, len, pref--);
+ if (wpa_scan_res_match(wpa_s, i, bss, ssid, 1, 0)) {
+ res = wnm_nei_rep_add_bss(wpa_s, bss, buf, pref--);
if (res == -2)
continue; /* could not build entry for BSS */
if (res < 0)
break; /* no more room for candidates */
if (pref == 1)
break;
-
- pos += res;
- len -= res;
}
}
- wpa_hexdump(MSG_DEBUG,
- "WNM: BSS Transition Management Response candidate list",
- buf, pos - buf);
-
- return pos - buf;
+ wpa_hexdump_buf(MSG_DEBUG,
+ "WNM: BSS Transition Management Response candidate list",
+ *buf);
}
+#define BTM_RESP_MIN_SIZE 5 + ETH_ALEN
+
static void wnm_send_bss_transition_mgmt_resp(
struct wpa_supplicant *wpa_s, u8 dialog_token,
- enum bss_trans_mgmt_status_code status, u8 delay,
- const u8 *target_bssid)
+ enum bss_trans_mgmt_status_code status,
+ enum mbo_transition_reject_reason reason,
+ u8 delay, const u8 *target_bssid)
{
- u8 buf[2000], *pos;
- struct ieee80211_mgmt *mgmt;
- size_t len;
+ struct wpabuf *buf;
int res;
- wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Response "
- "to " MACSTR " dialog_token=%u status=%u delay=%d",
- MAC2STR(wpa_s->bssid), dialog_token, status, delay);
+ wpa_printf(MSG_DEBUG,
+ "WNM: Send BSS Transition Management Response to " MACSTR
+ " dialog_token=%u status=%u reason=%u delay=%d",
+ MAC2STR(wpa_s->bssid), dialog_token, status, reason, delay);
if (!wpa_s->current_bss) {
wpa_printf(MSG_DEBUG,
"WNM: Current BSS not known - drop response");
return;
}
- mgmt = (struct ieee80211_mgmt *) buf;
- os_memset(&buf, 0, sizeof(buf));
- os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
- os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
- os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
- mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_ACTION);
- mgmt->u.action.category = WLAN_ACTION_WNM;
- mgmt->u.action.u.bss_tm_resp.action = WNM_BSS_TRANS_MGMT_RESP;
- mgmt->u.action.u.bss_tm_resp.dialog_token = dialog_token;
- mgmt->u.action.u.bss_tm_resp.status_code = status;
- mgmt->u.action.u.bss_tm_resp.bss_termination_delay = delay;
- pos = mgmt->u.action.u.bss_tm_resp.variable;
+ buf = wpabuf_alloc(BTM_RESP_MIN_SIZE);
+ if (!buf) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Failed to allocate memory for BTM response");
+ return;
+ }
+
+ wpa_s->bss_tm_status = status;
+ wpas_notify_bss_tm_status(wpa_s);
+
+ wpabuf_put_u8(buf, WLAN_ACTION_WNM);
+ wpabuf_put_u8(buf, WNM_BSS_TRANS_MGMT_RESP);
+ wpabuf_put_u8(buf, dialog_token);
+ wpabuf_put_u8(buf, status);
+ wpabuf_put_u8(buf, delay);
if (target_bssid) {
- os_memcpy(pos, target_bssid, ETH_ALEN);
- pos += ETH_ALEN;
+ wpabuf_put_data(buf, target_bssid, ETH_ALEN);
} else if (status == WNM_BSS_TM_ACCEPT) {
/*
* P802.11-REVmc clarifies that the Target BSSID field is always
* present when status code is zero, so use a fake value here if
* no BSSID is yet known.
*/
- os_memset(pos, 0, ETH_ALEN);
- pos += ETH_ALEN;
+ wpabuf_put_data(buf, "\0\0\0\0\0\0", ETH_ALEN);
}
if (status == WNM_BSS_TM_ACCEPT)
- pos += wnm_add_cand_list(wpa_s, pos, buf + sizeof(buf) - pos);
+ wnm_add_cand_list(wpa_s, &buf);
#ifdef CONFIG_MBO
- if (status != WNM_BSS_TM_ACCEPT) {
- pos += wpas_mbo_ie_bss_trans_reject(
- wpa_s, pos, buf + sizeof(buf) - pos,
- MBO_TRANSITION_REJECT_REASON_UNSPECIFIED);
+ if (status != WNM_BSS_TM_ACCEPT &&
+ wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE)) {
+ u8 mbo[10];
+ size_t ret;
+
+ ret = wpas_mbo_ie_bss_trans_reject(wpa_s, mbo, sizeof(mbo),
+ reason);
+ if (ret) {
+ if (wpabuf_resize(&buf, ret) < 0) {
+ wpabuf_free(buf);
+ wpa_printf(MSG_DEBUG,
+ "WNM: Failed to allocate memory for MBO IE");
+ return;
+ }
+
+ wpabuf_put_data(buf, mbo, ret);
+ }
}
#endif /* CONFIG_MBO */
- len = pos - (u8 *) &mgmt->u.action.category;
-
res = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
wpa_s->own_addr, wpa_s->bssid,
- &mgmt->u.action.category, len, 0);
+ wpabuf_head_u8(buf), wpabuf_len(buf), 0);
if (res < 0) {
wpa_printf(MSG_DEBUG,
"WNM: Failed to send BSS Transition Management Response");
}
+
+ wpabuf_free(buf);
}
@@ -863,10 +1086,10 @@ static void wnm_bss_tm_connect(struct wpa_supplicant *wpa_s,
wpa_s->wnm_reply = 0;
wpa_printf(MSG_DEBUG,
"WNM: Sending successful BSS Transition Management Response");
- wnm_send_bss_transition_mgmt_resp(wpa_s,
- wpa_s->wnm_dialog_token,
- WNM_BSS_TM_ACCEPT,
- 0, bss->bssid);
+ wnm_send_bss_transition_mgmt_resp(
+ wpa_s, wpa_s->wnm_dialog_token, WNM_BSS_TM_ACCEPT,
+ MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0,
+ bss->bssid);
}
if (bss == wpa_s->current_bss) {
@@ -888,6 +1111,8 @@ int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail)
struct wpa_bss *bss;
struct wpa_ssid *ssid = wpa_s->current_ssid;
enum bss_trans_mgmt_status_code status = WNM_BSS_TM_REJECT_UNSPECIFIED;
+ enum mbo_transition_reject_reason reason =
+ MBO_TRANSITION_REJECT_REASON_UNSPECIFIED;
if (!wpa_s->wnm_neighbor_report_elements)
return 0;
@@ -909,7 +1134,7 @@ int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail)
}
/* Compare the Neighbor Report and scan results */
- bss = compare_scan_neighbor_results(wpa_s, 0);
+ bss = compare_scan_neighbor_results(wpa_s, 0, &reason);
if (!bss) {
wpa_printf(MSG_DEBUG, "WNM: No BSS transition candidate match found");
status = WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES;
@@ -930,7 +1155,7 @@ send_bss_resp_fail:
wpa_s->wnm_reply = 0;
wnm_send_bss_transition_mgmt_resp(wpa_s,
wpa_s->wnm_dialog_token,
- status, 0, NULL);
+ status, reason, 0, NULL);
}
wnm_deallocate_memory(wpa_s);
@@ -1118,7 +1343,7 @@ static int wnm_fetch_scan_results(struct wpa_supplicant *wpa_s)
return 0;
}
- bss = compare_scan_neighbor_results(wpa_s, WNM_SCAN_RESULT_AGE);
+ bss = compare_scan_neighbor_results(wpa_s, WNM_SCAN_RESULT_AGE, NULL);
if (!bss) {
wpa_dbg(wpa_s, MSG_DEBUG,
"WNM: Comparison of scan results against transition candidates did not find matches");
@@ -1144,6 +1369,11 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
if (end - pos < 5)
return;
+#ifdef CONFIG_MBO
+ wpa_s->wnm_mbo_trans_reason_present = 0;
+ wpa_s->wnm_mbo_transition_reason = 0;
+#endif /* CONFIG_MBO */
+
if (wpa_s->current_bss)
beacon_int = wpa_s->current_bss->beacon_int;
else
@@ -1166,10 +1396,10 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
wpa_printf(MSG_INFO,
"WNM: Testing - reject BSS Transition Management Request: reject_btm_req_reason=%d",
wpa_s->reject_btm_req_reason);
- wnm_send_bss_transition_mgmt_resp(wpa_s,
- wpa_s->wnm_dialog_token,
- wpa_s->reject_btm_req_reason,
- 0, NULL);
+ wnm_send_bss_transition_mgmt_resp(
+ wpa_s, wpa_s->wnm_dialog_token,
+ wpa_s->reject_btm_req_reason,
+ MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0, NULL);
return;
}
#endif /* CONFIG_MBO && CONFIG_TESTING_OPTIONS */
@@ -1248,6 +1478,15 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
wpa_s->wnm_num_neighbor_report];
wnm_parse_neighbor_report(wpa_s, pos, len, rep);
wpa_s->wnm_num_neighbor_report++;
+#ifdef CONFIG_MBO
+ if (wpa_s->wnm_mbo_trans_reason_present &&
+ wpa_s->wnm_num_neighbor_report == 1) {
+ rep->is_first = 1;
+ wpa_printf(MSG_DEBUG,
+ "WNM: First transition candidate is "
+ MACSTR, MAC2STR(rep->bssid));
+ }
+#endif /* CONFIG_MBO */
}
pos += len;
@@ -1259,7 +1498,8 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
wnm_send_bss_transition_mgmt_resp(
wpa_s, wpa_s->wnm_dialog_token,
WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES,
- 0, NULL);
+ MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0,
+ NULL);
return;
}
@@ -1322,19 +1562,21 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_INFO, "WNM: BSS Transition Management Request did not include candidates");
status = WNM_BSS_TM_REJECT_UNSPECIFIED;
}
- wnm_send_bss_transition_mgmt_resp(wpa_s,
- wpa_s->wnm_dialog_token,
- status, 0, NULL);
+ wnm_send_bss_transition_mgmt_resp(
+ wpa_s, wpa_s->wnm_dialog_token, status,
+ MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0, NULL);
}
}
+#define BTM_QUERY_MIN_SIZE 4
+
int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
- u8 query_reason, int cand_list)
+ u8 query_reason,
+ const char *btm_candidates,
+ int cand_list)
{
- u8 buf[2000], *pos;
- struct ieee80211_mgmt *mgmt;
- size_t len;
+ struct wpabuf *buf;
int ret;
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Query to "
@@ -1342,28 +1584,43 @@ int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
MAC2STR(wpa_s->bssid), query_reason,
cand_list ? " candidate list" : "");
- mgmt = (struct ieee80211_mgmt *) buf;
- os_memset(&buf, 0, sizeof(buf));
- os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
- os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
- os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
- mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_ACTION);
- mgmt->u.action.category = WLAN_ACTION_WNM;
- mgmt->u.action.u.bss_tm_query.action = WNM_BSS_TRANS_MGMT_QUERY;
- mgmt->u.action.u.bss_tm_query.dialog_token = 1;
- mgmt->u.action.u.bss_tm_query.query_reason = query_reason;
- pos = mgmt->u.action.u.bss_tm_query.variable;
+ buf = wpabuf_alloc(BTM_QUERY_MIN_SIZE);
+ if (!buf)
+ return -1;
+
+ wpabuf_put_u8(buf, WLAN_ACTION_WNM);
+ wpabuf_put_u8(buf, WNM_BSS_TRANS_MGMT_QUERY);
+ wpabuf_put_u8(buf, 1);
+ wpabuf_put_u8(buf, query_reason);
if (cand_list)
- pos += wnm_add_cand_list(wpa_s, pos, buf + sizeof(buf) - pos);
+ wnm_add_cand_list(wpa_s, &buf);
+
+ if (btm_candidates) {
+ const size_t max_len = 1000;
+
+ ret = wpabuf_resize(&buf, max_len);
+ if (ret < 0) {
+ wpabuf_free(buf);
+ return ret;
+ }
- len = pos - (u8 *) &mgmt->u.action.category;
+ ret = ieee802_11_parse_candidate_list(btm_candidates,
+ wpabuf_put(buf, 0),
+ max_len);
+ if (ret < 0) {
+ wpabuf_free(buf);
+ return ret;
+ }
+
+ wpabuf_put(buf, ret);
+ }
ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
wpa_s->own_addr, wpa_s->bssid,
- &mgmt->u.action.category, len, 0);
+ wpabuf_head_u8(buf), wpabuf_len(buf), 0);
+ wpabuf_free(buf);
return ret;
}
@@ -1468,6 +1725,32 @@ static void ieee802_11_rx_wnm_notif_req_wfa(struct wpa_supplicant *wpa_s,
pos = next;
continue;
}
+
+ if (ie == WLAN_EID_VENDOR_SPECIFIC && ie_len >= 5 &&
+ WPA_GET_BE24(pos) == OUI_WFA &&
+ pos[3] == HS20_WNM_T_C_ACCEPTANCE) {
+ const u8 *ie_end;
+ u8 url_len;
+ char *url;
+
+ ie_end = pos + ie_len;
+ pos += 4;
+ url_len = *pos++;
+ wpa_printf(MSG_DEBUG,
+ "WNM: HS 2.0 Terms and Conditions Acceptance (URL Length %u)",
+ url_len);
+ if (url_len > ie_end - pos)
+ break;
+ url = os_malloc(url_len + 1);
+ if (!url)
+ break;
+ os_memcpy(url, pos, url_len);
+ url[url_len] = '\0';
+ hs20_rx_t_c_acceptance(wpa_s, url);
+ os_free(url);
+ pos = next;
+ continue;
+ }
#endif /* CONFIG_HS20 */
pos = next;
@@ -1515,6 +1798,46 @@ static void ieee802_11_rx_wnm_notif_req(struct wpa_supplicant *wpa_s,
}
+static void ieee802_11_rx_wnm_coloc_intf_req(struct wpa_supplicant *wpa_s,
+ const u8 *sa, const u8 *frm,
+ int len)
+{
+ u8 dialog_token, req_info, auto_report, timeout;
+
+ if (!wpa_s->conf->coloc_intf_reporting)
+ return;
+
+ /* Dialog Token [1] | Request Info [1] */
+
+ if (len < 2)
+ return;
+ dialog_token = frm[0];
+ req_info = frm[1];
+ auto_report = req_info & 0x03;
+ timeout = req_info >> 2;
+
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WNM: Received Collocated Interference Request (dialog_token %u auto_report %u timeout %u sa " MACSTR ")",
+ dialog_token, auto_report, timeout, MAC2STR(sa));
+
+ if (dialog_token == 0)
+ return; /* only nonzero values are used for request */
+
+ if (wpa_s->wpa_state != WPA_COMPLETED ||
+ os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WNM: Collocated Interference Request frame not from current AP - ignore it");
+ return;
+ }
+
+ wpa_msg(wpa_s, MSG_INFO, COLOC_INTF_REQ "%u %u %u",
+ dialog_token, auto_report, timeout);
+ wpa_s->coloc_intf_dialog_token = dialog_token;
+ wpa_s->coloc_intf_auto_report = auto_report;
+ wpa_s->coloc_intf_timeout = timeout;
+}
+
+
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
const struct ieee80211_mgmt *mgmt, size_t len)
{
@@ -1548,8 +1871,75 @@ void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
case WNM_NOTIFICATION_REQ:
ieee802_11_rx_wnm_notif_req(wpa_s, mgmt->sa, pos, end - pos);
break;
+ case WNM_COLLOCATED_INTERFERENCE_REQ:
+ ieee802_11_rx_wnm_coloc_intf_req(wpa_s, mgmt->sa, pos,
+ end - pos);
+ break;
default:
wpa_printf(MSG_ERROR, "WNM: Unknown request");
break;
}
}
+
+
+int wnm_send_coloc_intf_report(struct wpa_supplicant *wpa_s, u8 dialog_token,
+ const struct wpabuf *elems)
+{
+ struct wpabuf *buf;
+ int ret;
+
+ if (wpa_s->wpa_state < WPA_ASSOCIATED || !elems)
+ return -1;
+
+ wpa_printf(MSG_DEBUG, "WNM: Send Collocated Interference Report to "
+ MACSTR " (dialog token %u)",
+ MAC2STR(wpa_s->bssid), dialog_token);
+
+ buf = wpabuf_alloc(3 + wpabuf_len(elems));
+ if (!buf)
+ return -1;
+
+ wpabuf_put_u8(buf, WLAN_ACTION_WNM);
+ wpabuf_put_u8(buf, WNM_COLLOCATED_INTERFERENCE_REPORT);
+ wpabuf_put_u8(buf, dialog_token);
+ wpabuf_put_buf(buf, elems);
+
+ ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head_u8(buf), wpabuf_len(buf), 0);
+ wpabuf_free(buf);
+ return ret;
+}
+
+
+void wnm_set_coloc_intf_elems(struct wpa_supplicant *wpa_s,
+ struct wpabuf *elems)
+{
+ wpabuf_free(wpa_s->coloc_intf_elems);
+ if (elems && wpabuf_len(elems) == 0) {
+ wpabuf_free(elems);
+ elems = NULL;
+ }
+ wpa_s->coloc_intf_elems = elems;
+
+ if (wpa_s->conf->coloc_intf_reporting && wpa_s->coloc_intf_elems &&
+ wpa_s->coloc_intf_dialog_token &&
+ (wpa_s->coloc_intf_auto_report == 1 ||
+ wpa_s->coloc_intf_auto_report == 3)) {
+ /* TODO: Check that there has not been less than
+ * wpa_s->coloc_intf_timeout * 200 TU from the last report.
+ */
+ wnm_send_coloc_intf_report(wpa_s,
+ wpa_s->coloc_intf_dialog_token,
+ wpa_s->coloc_intf_elems);
+ }
+}
+
+
+void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_WNM
+ wpa_s->coloc_intf_dialog_token = 0;
+ wpa_s->coloc_intf_auto_report = 0;
+#endif /* CONFIG_WNM */
+}
diff --git a/contrib/wpa/wpa_supplicant/wnm_sta.h b/contrib/wpa/wpa_supplicant/wnm_sta.h
index 81d815359634..29625f8ca943 100644
--- a/contrib/wpa/wpa_supplicant/wnm_sta.h
+++ b/contrib/wpa/wpa_supplicant/wnm_sta.h
@@ -43,6 +43,10 @@ struct neighbor_report {
unsigned int rm_capab_present:1;
unsigned int bearing_present:1;
unsigned int bss_term_present:1;
+ unsigned int acceptable:1;
+#ifdef CONFIG_MBO
+ unsigned int is_first:1;
+#endif /* CONFIG_MBO */
struct measurement_pilot *meas_pilot;
struct multiple_bssid *mul_bssid;
int freq;
@@ -56,13 +60,21 @@ void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
const struct ieee80211_mgmt *mgmt, size_t len);
int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
- u8 query_reason, int cand_list);
+ u8 query_reason,
+ const char *btm_candidates,
+ int cand_list);
+
void wnm_deallocate_memory(struct wpa_supplicant *wpa_s);
+int wnm_send_coloc_intf_report(struct wpa_supplicant *wpa_s, u8 dialog_token,
+ const struct wpabuf *elems);
+void wnm_set_coloc_intf_elems(struct wpa_supplicant *wpa_s,
+ struct wpabuf *elems);
#ifdef CONFIG_WNM
int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail);
+void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s);
#else /* CONFIG_WNM */
@@ -72,6 +84,10 @@ static inline int wnm_scan_process(struct wpa_supplicant *wpa_s,
return 0;
}
+static inline void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s)
+{
+}
+
#endif /* CONFIG_WNM */
#endif /* WNM_STA_H */
diff --git a/contrib/wpa/wpa_supplicant/wpa_cli.c b/contrib/wpa/wpa_supplicant/wpa_cli.c
index a848b7737db5..695fcbe04995 100644
--- a/contrib/wpa/wpa_supplicant/wpa_cli.c
+++ b/contrib/wpa/wpa_supplicant/wpa_cli.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant - command line interface for wpa_supplicant daemon
- * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -29,7 +29,7 @@
static const char *const wpa_cli_version =
"wpa_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> and contributors";
#define VENDOR_ELEM_FRAME_ID \
" 0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \
@@ -49,6 +49,7 @@ static int wpa_cli_last_id = 0;
static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
static const char *client_socket_dir = NULL;
static char *ctrl_ifname = NULL;
+static const char *global = NULL;
static const char *pid_file = NULL;
static const char *action_file = NULL;
static int ping_interval = 5;
@@ -60,6 +61,10 @@ static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
static DEFINE_DL_LIST(networks); /* struct cli_txt_entry */
+static DEFINE_DL_LIST(creds); /* struct cli_txt_entry */
+#ifdef CONFIG_AP
+static DEFINE_DL_LIST(stations); /* struct cli_txt_entry */
+#endif /* CONFIG_AP */
static void print_help(const char *cmd);
@@ -67,7 +72,10 @@ static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
static void wpa_cli_close_connection(void);
static char * wpa_cli_get_default_ifname(void);
static char ** wpa_list_cmd_list(void);
+static void update_creds(struct wpa_ctrl *ctrl);
static void update_networks(struct wpa_ctrl *ctrl);
+static void update_stations(struct wpa_ctrl *ctrl);
+static void update_ifnames(struct wpa_ctrl *ctrl);
static void usage(void)
@@ -214,7 +222,7 @@ static void wpa_cli_msg_cb(char *msg, size_t len)
}
-static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
+static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print)
{
char buf[4096];
size_t len;
@@ -250,7 +258,7 @@ static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
}
-static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
+static int wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd)
{
return _wpa_ctrl_command(ctrl, cmd, 1);
}
@@ -331,6 +339,39 @@ static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
}
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+
+static int wpa_cli_cmd_pmksa_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "PMKSA_GET", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_pmksa_add(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "PMKSA_ADD", 8, argc, argv);
+}
+
+
+#ifdef CONFIG_MESH
+
+static int wpa_cli_mesh_cmd_pmksa_get(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "MESH_PMKSA_GET", 1, argc, argv);
+}
+
+
+static int wpa_cli_mesh_cmd_pmksa_add(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "MESH_PMKSA_ADD", 4, argc, argv);
+}
+
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
+
static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
print_help(argc > 0 ? argv[0] : NULL);
@@ -437,11 +478,13 @@ static char ** wpa_cli_complete_set(const char *str, int pos)
#endif /* CONFIG_P2P */
"country", "bss_max_count", "bss_expiration_age",
"bss_expiration_scan_count", "filter_ssids", "filter_rssi",
- "max_num_sta", "disassoc_low_ack",
+ "max_num_sta", "disassoc_low_ack", "ap_isolate",
#ifdef CONFIG_HS20
"hs20",
#endif /* CONFIG_HS20 */
"interworking", "hessid", "access_network_type", "pbc_in_m1",
+ "go_interworking", "go_access_network_type", "go_internet",
+ "go_venue_group", "go_venue_type",
"autoscan", "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey",
"wps_nfc_dh_privkey", "wps_nfc_dev_pw", "ext_password_backend",
"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
@@ -455,6 +498,7 @@ static char ** wpa_cli_complete_set(const char *str, int pos)
#ifdef CONFIG_TESTING_OPTIONS
"ignore_auth_resp",
#endif /* CONFIG_TESTING_OPTIONS */
+ "relative_rssi", "relative_band_adjust",
};
int i, num_fields = ARRAY_SIZE(fields);
@@ -531,15 +575,18 @@ static char ** wpa_cli_complete_get(const char *str, int pos)
#endif /* CONFIG_P2P */
"bss_max_count", "bss_expiration_age",
"bss_expiration_scan_count", "filter_ssids", "filter_rssi",
- "max_num_sta", "disassoc_low_ack",
+ "max_num_sta", "disassoc_low_ack", "ap_isolate",
#ifdef CONFIG_HS20
"hs20",
#endif /* CONFIG_HS20 */
"interworking", "access_network_type", "pbc_in_m1", "autoscan",
+ "go_interworking", "go_access_network_type", "go_internet",
+ "go_venue_group", "go_venue_type",
"wps_nfc_dev_pw_id", "ext_password_backend",
"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
"dtim_period", "beacon_int", "ignore_old_scan_res",
"scan_cur_freq", "sched_scan_interval",
+ "sched_scan_start_delay",
"tdls_external_control", "osu_dir", "wowlan_triggers",
"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
"preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
@@ -639,13 +686,6 @@ static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
-static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
- char *argv[])
-{
- return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
-}
-
-
static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
@@ -1165,6 +1205,39 @@ static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
+static int wpa_cli_cmd_psk_passphrase(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char cmd[256], *pos, *end;
+ int i, ret;
+
+ if (argc < 2) {
+ printf("Invalid PSK_PASSPHRASE command: needs two arguments (network id and PSK/passphrase)\n");
+ return -1;
+ }
+
+ end = cmd + sizeof(cmd);
+ pos = cmd;
+ ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PSK_PASSPHRASE-%s:%s",
+ argv[0], argv[1]);
+ if (os_snprintf_error(end - pos, ret)) {
+ printf("Too long PSK_PASSPHRASE command.\n");
+ return -1;
+ }
+ pos += ret;
+ for (i = 2; i < argc; i++) {
+ ret = os_snprintf(pos, end - pos, " %s", argv[i]);
+ if (os_snprintf_error(end - pos, ret)) {
+ printf("Too long PSK_PASSPHRASE command.\n");
+ return -1;
+ }
+ pos += ret;
+ }
+
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
+
static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -1332,14 +1405,17 @@ static const char *network_fields[] = {
"ssid", "scan_ssid", "bssid", "bssid_blacklist",
"bssid_whitelist", "psk", "proto", "key_mgmt",
"bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq",
- "freq_list", "max_oper_chwidth",
+ "freq_list", "max_oper_chwidth", "ht40", "vht", "vht_center_freq1",
+ "vht_center_freq2", "ht",
#ifdef IEEE8021X_EAPOL
"eap", "identity", "anonymous_identity", "password", "ca_cert",
"ca_path", "client_cert", "private_key", "private_key_passwd",
"dh_file", "subject_match", "altsubject_match",
+ "check_cert_subject",
"domain_suffix_match", "domain_match", "ca_cert2", "ca_path2",
"client_cert2", "private_key2", "private_key2_passwd",
"dh_file2", "subject_match2", "altsubject_match2",
+ "check_cert_subject2",
"domain_suffix_match2", "domain_match2", "phase1", "phase2",
"pcsc", "pin", "engine_id", "key_id", "cert_id", "ca_cert_id",
"pin2", "engine2_id", "key2_id", "cert2_id", "ca_cert2_id",
@@ -1352,7 +1428,7 @@ static const char *network_fields[] = {
"eap_workaround", "pac_file", "fragment_size", "ocsp",
#endif /* IEEE8021X_EAPOL */
#ifdef CONFIG_MESH
- "mode", "no_auto_peer",
+ "mode", "no_auto_peer", "mesh_rssi_threshold",
#else /* CONFIG_MESH */
"mode",
#endif /* CONFIG_MESH */
@@ -1360,7 +1436,7 @@ static const char *network_fields[] = {
#ifdef CONFIG_IEEE80211W
"ieee80211w",
#endif /* CONFIG_IEEE80211W */
- "peerkey", "mixed_cell", "frequency", "fixed_freq",
+ "mixed_cell", "frequency", "fixed_freq",
#ifdef CONFIG_MESH
"mesh_basic_rates", "dot11MeshMaxRetries",
"dot11MeshRetryTimeout", "dot11MeshConfirmTimeout",
@@ -1373,7 +1449,7 @@ static const char *network_fields[] = {
#ifdef CONFIG_HT_OVERRIDES
"disable_ht", "disable_ht40", "disable_sgi", "disable_ldpc",
"ht40_intolerant", "disable_max_amsdu", "ampdu_factor",
- "ampdu_density", "ht_mcs",
+ "ampdu_density", "ht_mcs", "rx_stbc", "tx_stbc",
#endif /* CONFIG_HT_OVERRIDES */
#ifdef CONFIG_VHT_OVERRIDES
"disable_vht", "vht_capa", "vht_capa_mask", "vht_rx_mcs_nss_1",
@@ -1386,6 +1462,11 @@ static const char *network_fields[] = {
"ap_max_inactivity", "dtim_period", "beacon_int",
#ifdef CONFIG_MACSEC
"macsec_policy",
+ "macsec_integ_only",
+ "macsec_replay_protect",
+ "macsec_replay_window",
+ "macsec_port",
+ "mka_priority",
#endif /* CONFIG_MACSEC */
#ifdef CONFIG_HS20
"update_identifier",
@@ -1479,14 +1560,56 @@ static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
- return wpa_ctrl_command(ctrl, "ADD_CRED");
+ int res = wpa_ctrl_command(ctrl, "ADD_CRED");
+ if (interactive)
+ update_creds(ctrl);
+ return res;
}
static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
+ int res = wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
+ if (interactive)
+ update_creds(ctrl);
+ return res;
+}
+
+
+static const char * const cred_fields[] = {
+ "temporary", "priority", "sp_priority", "pcsc", "eap",
+ "update_identifier", "min_dl_bandwidth_home", "min_ul_bandwidth_home",
+ "min_dl_bandwidth_roaming", "min_ul_bandwidth_roaming", "max_bss_load",
+ "req_conn_capab", "ocsp", "sim_num", "realm", "username", "password",
+ "ca_cert", "client_cert", "private_key", "private_key_passwd", "imsi",
+ "milenage", "domain_suffix_match", "domain", "phase1", "phase2",
+ "roaming_consortium", "required_roaming_consortium", "excluded_ssid",
+ "roaming_partner", "provisioning_sp"
+};
+
+
+static char ** wpa_cli_complete_cred(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ int i, num_fields = ARRAY_SIZE(cred_fields);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ res = cli_txt_list_array(&creds);
+ break;
+ case 2:
+ res = os_calloc(num_fields + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ for (i = 0; i < num_fields; i++) {
+ res[i] = os_strdup(cred_fields[i]);
+ if (res[i] == NULL)
+ break;
+ }
+ }
+ return res;
}
@@ -1736,8 +1859,23 @@ static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
-static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
- char *addr, size_t addr_len)
+static char ** wpa_cli_complete_sta(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ res = cli_txt_list_array(&stations);
+ break;
+ }
+
+ return res;
+}
+
+
+static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, const char *cmd,
+ char *addr, size_t addr_len, int print)
{
char buf[4096], *pos;
size_t len;
@@ -1765,9 +1903,11 @@ static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
}
buf[len] = '\0';
- if (os_memcmp(buf, "FAIL", 4) == 0)
+ if (os_memcmp(buf, "FAIL", 4) == 0 ||
+ os_memcmp(buf, "UNKNOWN COMMAND", 15) == 0)
return -1;
- printf("%s", buf);
+ if (print)
+ printf("%s", buf);
pos = buf;
while (*pos != '\0' && *pos != '\n')
@@ -1782,16 +1922,33 @@ static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char addr[32], cmd[64];
- if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
+ if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 1))
return 0;
do {
os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
- } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
+ } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 1) == 0);
return -1;
}
+static int wpa_cli_cmd_list_sta(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char addr[32], cmd[64];
+
+ if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 0))
+ return 0;
+ do {
+ if (os_strcmp(addr, "") != 0)
+ printf("%s\n", addr);
+ os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
+ } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 0) == 0);
+
+ return 0;
+}
+
+
static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -1799,12 +1956,43 @@ static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
}
+static char ** wpa_cli_complete_deauthenticate(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ res = cli_txt_list_array(&stations);
+ break;
+ }
+
+ return res;
+}
+
+
static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
}
+
+static char ** wpa_cli_complete_disassociate(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ res = cli_txt_list_array(&stations);
+ break;
+ }
+
+ return res;
+}
+
+
static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -2176,7 +2364,7 @@ static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
}
-static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
+static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, const char *cmd,
char *addr, size_t addr_len,
int discovered)
{
@@ -2338,6 +2526,8 @@ static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
}
+#endif /* CONFIG_P2P */
+
static int wpa_cli_cmd_vendor_elem_add(struct wpa_ctrl *ctrl, int argc,
char *argv[])
@@ -2359,7 +2549,6 @@ static int wpa_cli_cmd_vendor_elem_remove(struct wpa_ctrl *ctrl, int argc,
return wpa_cli_cmd(ctrl, "VENDOR_ELEM_REMOVE", 2, argc, argv);
}
-#endif /* CONFIG_P2P */
#ifdef CONFIG_WIFI_DISPLAY
@@ -2726,6 +2915,108 @@ static int wpa_cli_cmd_p2p_lo_stop(struct wpa_ctrl *ctrl, int argc,
}
+#ifdef CONFIG_DPP
+
+static int wpa_cli_cmd_dpp_qr_code(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_QR_CODE", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_bootstrap_gen(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_GEN", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_bootstrap_remove(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_REMOVE", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_bootstrap_get_uri(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_GET_URI", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_INFO", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_AUTH_INIT", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_listen(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_LISTEN", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_stop_listen(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "DPP_STOP_LISTEN");
+}
+
+
+static int wpa_cli_cmd_dpp_configurator_add(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_ADD", 0, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_configurator_remove(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_REMOVE", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_configurator_get_key(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_GET_KEY", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_configurator_sign(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_SIGN", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_pkex_add(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_PKEX_ADD", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv);
+}
+
+#endif /* CONFIG_DPP */
+
+
enum wpa_cli_cmd_flags {
cli_cmd_flag_none = 0x00,
cli_cmd_flag_sensitive = 0x01
@@ -2798,6 +3089,22 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
{ "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
cli_cmd_flag_none,
"= flush PMKSA cache entries" },
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+ { "pmksa_get", wpa_cli_cmd_pmksa_get, NULL,
+ cli_cmd_flag_none,
+ "<network_id> = fetch all stored PMKSA cache entries" },
+ { "pmksa_add", wpa_cli_cmd_pmksa_add, NULL,
+ cli_cmd_flag_sensitive,
+ "<network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds> <expiration in seconds> <akmp> <opportunistic> = store PMKSA cache entry from external storage" },
+#ifdef CONFIG_MESH
+ { "mesh_pmksa_get", wpa_cli_mesh_cmd_pmksa_get, NULL,
+ cli_cmd_flag_none,
+ "<peer MAC address | any> = fetch all stored mesh PMKSA cache entries" },
+ { "mesh_pmksa_add", wpa_cli_mesh_cmd_pmksa_add, NULL,
+ cli_cmd_flag_sensitive,
+ "<BSSID> <PMKID> <PMK> <expiration in seconds> = store mesh PMKSA cache entry from external storage" },
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
{ "reassociate", wpa_cli_cmd_reassociate, NULL,
cli_cmd_flag_none,
"= force reassociation" },
@@ -2807,30 +3114,33 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
{ "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
cli_cmd_flag_none,
"<BSSID> = force preauthentication" },
- { "identity", wpa_cli_cmd_identity, NULL,
+ { "identity", wpa_cli_cmd_identity, wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> <identity> = configure identity for an SSID" },
- { "password", wpa_cli_cmd_password, NULL,
+ { "password", wpa_cli_cmd_password, wpa_cli_complete_network_id,
cli_cmd_flag_sensitive,
"<network id> <password> = configure password for an SSID" },
- { "new_password", wpa_cli_cmd_new_password, NULL,
- cli_cmd_flag_sensitive,
+ { "new_password", wpa_cli_cmd_new_password,
+ wpa_cli_complete_network_id, cli_cmd_flag_sensitive,
"<network id> <password> = change password for an SSID" },
- { "pin", wpa_cli_cmd_pin, NULL,
+ { "pin", wpa_cli_cmd_pin, wpa_cli_complete_network_id,
cli_cmd_flag_sensitive,
"<network id> <pin> = configure pin for an SSID" },
- { "otp", wpa_cli_cmd_otp, NULL,
+ { "otp", wpa_cli_cmd_otp, wpa_cli_complete_network_id,
cli_cmd_flag_sensitive,
"<network id> <password> = configure one-time-password for an SSID"
},
- { "passphrase", wpa_cli_cmd_passphrase, NULL,
+ { "psk_passphrase", wpa_cli_cmd_psk_passphrase,
+ wpa_cli_complete_network_id, cli_cmd_flag_sensitive,
+ "<network id> <PSK/passphrase> = configure PSK/passphrase for an SSID" },
+ { "passphrase", wpa_cli_cmd_passphrase, wpa_cli_complete_network_id,
cli_cmd_flag_sensitive,
"<network id> <passphrase> = configure private key passphrase\n"
" for an SSID" },
- { "sim", wpa_cli_cmd_sim, NULL,
+ { "sim", wpa_cli_cmd_sim, wpa_cli_complete_network_id,
cli_cmd_flag_sensitive,
"<network id> <pin> = report SIM operation result" },
- { "bssid", wpa_cli_cmd_bssid, NULL,
+ { "bssid", wpa_cli_cmd_bssid, wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> <BSSID> = set preferred BSSID for an SSID" },
{ "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
@@ -2884,10 +3194,10 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
{ "remove_cred", wpa_cli_cmd_remove_cred, NULL,
cli_cmd_flag_none,
"<cred id> = remove a credential" },
- { "set_cred", wpa_cli_cmd_set_cred, NULL,
+ { "set_cred", wpa_cli_cmd_set_cred, wpa_cli_complete_cred,
cli_cmd_flag_sensitive,
"<cred id> <variable> <value> = set credential variables" },
- { "get_cred", wpa_cli_cmd_get_cred, NULL,
+ { "get_cred", wpa_cli_cmd_get_cred, wpa_cli_complete_cred,
cli_cmd_flag_none,
"<cred id> <variable> = get credential variables" },
{ "save_config", wpa_cli_cmd_save_config, NULL,
@@ -2951,9 +3261,6 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
{ "bss_flush", wpa_cli_cmd_bss_flush, NULL,
cli_cmd_flag_none,
"<value> = set BSS flush age (0 by default)" },
- { "stkstart", wpa_cli_cmd_stkstart, NULL,
- cli_cmd_flag_none,
- "<addr> = request STK negotiation with <addr>" },
{ "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
cli_cmd_flag_none,
"<addr> = request over-the-DS FT with <addr>" },
@@ -3029,17 +3336,20 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
cli_cmd_flag_none,
"<addr> = request RSN authentication with <addr> in IBSS" },
#ifdef CONFIG_AP
- { "sta", wpa_cli_cmd_sta, NULL,
+ { "sta", wpa_cli_cmd_sta, wpa_cli_complete_sta,
cli_cmd_flag_none,
"<addr> = get information about an associated station (AP)" },
{ "all_sta", wpa_cli_cmd_all_sta, NULL,
cli_cmd_flag_none,
"= get information about all associated stations (AP)" },
- { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
+ { "list_sta", wpa_cli_cmd_list_sta, NULL,
cli_cmd_flag_none,
+ "= list all stations (AP)" },
+ { "deauthenticate", wpa_cli_cmd_deauthenticate,
+ wpa_cli_complete_deauthenticate, cli_cmd_flag_none,
"<addr> = deauthenticate a station" },
- { "disassociate", wpa_cli_cmd_disassociate, NULL,
- cli_cmd_flag_none,
+ { "disassociate", wpa_cli_cmd_disassociate,
+ wpa_cli_complete_disassociate, cli_cmd_flag_none,
"<addr> = disassociate a station" },
{ "chan_switch", wpa_cli_cmd_chanswitch, NULL,
cli_cmd_flag_none,
@@ -3168,6 +3478,7 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
{ "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
"<address|iface=address> = remove a peer from all groups" },
+#endif /* CONFIG_P2P */
{ "vendor_elem_add", wpa_cli_cmd_vendor_elem_add, NULL,
cli_cmd_flag_none,
"<frame id> <hexdump of elem(s)> = add vendor specific IEs to frame(s)\n"
@@ -3180,7 +3491,6 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
cli_cmd_flag_none,
"<frame id> <hexdump of elem(s)> = remove vendor specific IE(s) in frame(s)\n"
VENDOR_ELEM_FRAME_ID },
-#endif /* CONFIG_P2P */
#ifdef CONFIG_WIFI_DISPLAY
{ "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
cli_cmd_flag_none,
@@ -3285,7 +3595,9 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
{ "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
"<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
{ "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
- "<query reason> [list] = Send BSS Transition Management Query" },
+ "<query reason> [list]"
+ " [neighbor=<BSSID>,<BSSID information>,<operating class>,<channel number>,<PHY type>[,<hexdump of optional subelements>]"
+ " = Send BSS Transition Management Query" },
#endif /* CONFIG_WNM */
{ "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
"<params..> = Sent unprocessed command" },
@@ -3320,6 +3632,47 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
{ "p2p_lo_stop", wpa_cli_cmd_p2p_lo_stop, NULL,
cli_cmd_flag_none,
"= stop P2P listen offload" },
+#ifdef CONFIG_DPP
+ { "dpp_qr_code", wpa_cli_cmd_dpp_qr_code, NULL, cli_cmd_flag_none,
+ "report a scanned DPP URI from a QR Code" },
+ { "dpp_bootstrap_gen", wpa_cli_cmd_dpp_bootstrap_gen, NULL,
+ cli_cmd_flag_sensitive,
+ "type=<qrcode> [chan=..] [mac=..] [info=..] [curve=..] [key=..] = generate DPP bootstrap information" },
+ { "dpp_bootstrap_remove", wpa_cli_cmd_dpp_bootstrap_remove, NULL,
+ cli_cmd_flag_none,
+ "*|<id> = remove DPP bootstrap information" },
+ { "dpp_bootstrap_get_uri", wpa_cli_cmd_dpp_bootstrap_get_uri, NULL,
+ cli_cmd_flag_none,
+ "<id> = get DPP bootstrap URI" },
+ { "dpp_bootstrap_info", wpa_cli_cmd_dpp_bootstrap_info, NULL,
+ cli_cmd_flag_none,
+ "<id> = show DPP bootstrap information" },
+ { "dpp_auth_init", wpa_cli_cmd_dpp_auth_init, NULL, cli_cmd_flag_none,
+ "peer=<id> [own=<id>] = initiate DPP bootstrapping" },
+ { "dpp_listen", wpa_cli_cmd_dpp_listen, NULL, cli_cmd_flag_none,
+ "<freq in MHz> = start DPP listen" },
+ { "dpp_stop_listen", wpa_cli_cmd_dpp_stop_listen, NULL,
+ cli_cmd_flag_none,
+ "= stop DPP listen" },
+ { "dpp_configurator_add", wpa_cli_cmd_dpp_configurator_add, NULL,
+ cli_cmd_flag_sensitive,
+ "[curve=..] [key=..] = add DPP configurator" },
+ { "dpp_configurator_remove", wpa_cli_cmd_dpp_configurator_remove, NULL,
+ cli_cmd_flag_none,
+ "*|<id> = remove DPP configurator" },
+ { "dpp_configurator_get_key", wpa_cli_cmd_dpp_configurator_get_key,
+ NULL, cli_cmd_flag_none,
+ "<id> = Get DPP configurator's private key" },
+ { "dpp_configurator_sign", wpa_cli_cmd_dpp_configurator_sign, NULL,
+ cli_cmd_flag_none,
+ "conf=<role> configurator=<id> = generate self DPP configuration" },
+ { "dpp_pkex_add", wpa_cli_cmd_dpp_pkex_add, NULL,
+ cli_cmd_flag_sensitive,
+ "add PKEX code" },
+ { "dpp_pkex_remove", wpa_cli_cmd_dpp_pkex_remove, NULL,
+ cli_cmd_flag_none,
+ "*|<id> = remove DPP pkex information" },
+#endif /* CONFIG_DPP */
{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
};
@@ -3638,6 +3991,10 @@ static void wpa_cli_action_process(const char *msg)
wpa_cli_exec(action_file, ifname, pos);
} else if (str_starts(pos, WPS_EVENT_SUCCESS)) {
wpa_cli_exec(action_file, ifname, pos);
+ } else if (str_starts(pos, WPS_EVENT_ACTIVE)) {
+ wpa_cli_exec(action_file, ifname, pos);
+ } else if (str_starts(pos, WPS_EVENT_TIMEOUT)) {
+ wpa_cli_exec(action_file, ifname, pos);
} else if (str_starts(pos, WPS_EVENT_FAIL)) {
wpa_cli_exec(action_file, ifname, pos);
} else if (str_starts(pos, AP_STA_CONNECTED)) {
@@ -3650,6 +4007,8 @@ static void wpa_cli_action_process(const char *msg)
wpa_cli_exec(action_file, ifname, pos);
} else if (str_starts(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
wpa_cli_exec(action_file, ifname, pos);
+ } else if (str_starts(pos, HS20_T_C_ACCEPTANCE)) {
+ wpa_cli_exec(action_file, ifname, pos);
} else if (str_starts(pos, WPA_EVENT_TERMINATING)) {
printf("wpa_supplicant is terminating - stop monitoring\n");
wpa_cli_quit = 1;
@@ -3665,16 +4024,53 @@ static void wpa_cli_action_cb(char *msg, size_t len)
#endif /* CONFIG_ANSI_C_EXTRA */
+static int wpa_cli_open_global_ctrl(void)
+{
+#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
+ ctrl_conn = wpa_ctrl_open(NULL);
+#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
+ ctrl_conn = wpa_ctrl_open(global);
+#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
+ if (!ctrl_conn) {
+ fprintf(stderr,
+ "Failed to connect to wpa_supplicant global interface: %s error: %s\n",
+ global, strerror(errno));
+ return -1;
+ }
+
+ if (interactive) {
+ update_ifnames(ctrl_conn);
+ mon_conn = wpa_ctrl_open(global);
+ if (mon_conn) {
+ if (wpa_ctrl_attach(mon_conn) == 0) {
+ wpa_cli_attached = 1;
+ eloop_register_read_sock(
+ wpa_ctrl_get_fd(mon_conn),
+ wpa_cli_mon_receive,
+ NULL, NULL);
+ } else {
+ printf("Failed to open monitor connection through global control interface\n");
+ }
+ }
+ update_stations(ctrl_conn);
+ }
+
+ return 0;
+}
+
+
static void wpa_cli_reconnect(void)
{
wpa_cli_close_connection();
- if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
+ if ((global && wpa_cli_open_global_ctrl() < 0) ||
+ (!global && wpa_cli_open_connection(ctrl_ifname, 1) < 0))
return;
if (interactive) {
edit_clear_line();
printf("\rConnection to wpa_supplicant re-established\n");
edit_redraw();
+ update_stations(ctrl_conn);
}
}
@@ -3897,7 +4293,7 @@ static void update_bssid_list(struct wpa_ctrl *ctrl)
char buf[4096];
size_t len = sizeof(buf);
int ret;
- char *cmd = "BSS RANGE=ALL MASK=0x2";
+ const char *cmd = "BSS RANGE=ALL MASK=0x2";
char *pos, *end;
if (ctrl == NULL)
@@ -3928,7 +4324,7 @@ static void update_ifnames(struct wpa_ctrl *ctrl)
char buf[4096];
size_t len = sizeof(buf);
int ret;
- char *cmd = "INTERFACES";
+ const char *cmd = "INTERFACES";
char *pos, *end;
char txt[200];
@@ -3955,12 +4351,44 @@ static void update_ifnames(struct wpa_ctrl *ctrl)
}
+static void update_creds(struct wpa_ctrl *ctrl)
+{
+ char buf[4096];
+ size_t len = sizeof(buf);
+ int ret;
+ const char *cmd = "LIST_CREDS";
+ char *pos, *end;
+ int header = 1;
+
+ cli_txt_list_flush(&creds);
+
+ if (ctrl == NULL)
+ return;
+ ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
+ if (ret < 0)
+ return;
+ buf[len] = '\0';
+
+ pos = buf;
+ while (pos) {
+ end = os_strchr(pos, '\n');
+ if (end == NULL)
+ break;
+ *end = '\0';
+ if (!header)
+ cli_txt_list_add_word(&creds, pos, '\t');
+ header = 0;
+ pos = end + 1;
+ }
+}
+
+
static void update_networks(struct wpa_ctrl *ctrl)
{
char buf[4096];
size_t len = sizeof(buf);
int ret;
- char *cmd = "LIST_NETWORKS";
+ const char *cmd = "LIST_NETWORKS";
char *pos, *end;
int header = 1;
@@ -3987,6 +4415,27 @@ static void update_networks(struct wpa_ctrl *ctrl)
}
+static void update_stations(struct wpa_ctrl *ctrl)
+{
+#ifdef CONFIG_AP
+ char addr[32], cmd[64];
+
+ if (!ctrl || !interactive)
+ return;
+
+ cli_txt_list_flush(&stations);
+
+ if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 0))
+ return;
+ do {
+ if (os_strcmp(addr, "") != 0)
+ cli_txt_list_add(&stations, addr);
+ os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
+ } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 0) == 0);
+#endif /* CONFIG_AP */
+}
+
+
static void try_connection(void *eloop_ctx, void *timeout_ctx)
{
if (ctrl_conn)
@@ -4007,7 +4456,9 @@ static void try_connection(void *eloop_ctx, void *timeout_ctx)
}
update_bssid_list(ctrl_conn);
+ update_creds(ctrl_conn);
update_networks(ctrl_conn);
+ update_stations(ctrl_conn);
if (warning_displayed)
printf("Connection established.\n");
@@ -4029,6 +4480,7 @@ static void wpa_cli_interactive(void)
cli_txt_list_flush(&p2p_groups);
cli_txt_list_flush(&bsses);
cli_txt_list_flush(&ifnames);
+ cli_txt_list_flush(&creds);
cli_txt_list_flush(&networks);
if (edit_started)
edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
@@ -4170,7 +4622,6 @@ int main(int argc, char *argv[])
int c;
int daemonize = 0;
int ret = 0;
- const char *global = NULL;
if (os_program_init())
return -1;
@@ -4225,37 +4676,8 @@ int main(int argc, char *argv[])
if (eloop_init())
return -1;
- if (global) {
-#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
- ctrl_conn = wpa_ctrl_open(NULL);
-#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
- ctrl_conn = wpa_ctrl_open(global);
-#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
- if (ctrl_conn == NULL) {
- fprintf(stderr, "Failed to connect to wpa_supplicant "
- "global interface: %s error: %s\n",
- global, strerror(errno));
- return -1;
- }
-
- if (interactive) {
- update_ifnames(ctrl_conn);
- mon_conn = wpa_ctrl_open(global);
- if (mon_conn) {
- if (wpa_ctrl_attach(mon_conn) == 0) {
- wpa_cli_attached = 1;
- eloop_register_read_sock(
- wpa_ctrl_get_fd(mon_conn),
- wpa_cli_mon_receive,
- NULL, NULL);
- } else {
- printf("Failed to open monitor "
- "connection through global "
- "control interface\n");
- }
- }
- }
- }
+ if (global && wpa_cli_open_global_ctrl() < 0)
+ return -1;
eloop_register_signal_terminate(wpa_cli_terminate, NULL);
diff --git a/contrib/wpa/wpa_supplicant/wpa_passphrase.c b/contrib/wpa/wpa_supplicant/wpa_passphrase.c
index 9b568f0f7c67..adca1cce13ee 100644
--- a/contrib/wpa/wpa_supplicant/wpa_passphrase.c
+++ b/contrib/wpa/wpa_supplicant/wpa_passphrase.c
@@ -17,6 +17,7 @@ int main(int argc, char *argv[])
unsigned char psk[32];
int i;
char *ssid, *passphrase, buf[64], *pos;
+ size_t len;
if (argc < 2) {
printf("usage: wpa_passphrase <ssid> [passphrase]\n"
@@ -47,10 +48,15 @@ int main(int argc, char *argv[])
passphrase = buf;
}
- if (os_strlen(passphrase) < 8 || os_strlen(passphrase) > 63) {
+ len = os_strlen(passphrase);
+ if (len < 8 || len > 63) {
printf("Passphrase must be 8..63 characters\n");
return 1;
}
+ if (has_ctrl_char((u8 *) passphrase, len)) {
+ printf("Invalid passphrase character\n");
+ return 1;
+ }
pbkdf2_sha1(passphrase, (u8 *) ssid, os_strlen(ssid), 4096, psk, 32);
diff --git a/contrib/wpa/wpa_supplicant/wpa_priv.c b/contrib/wpa/wpa_supplicant/wpa_priv.c
index 511df4f18148..b3ad45eca516 100644
--- a/contrib/wpa/wpa_supplicant/wpa_priv.c
+++ b/contrib/wpa/wpa_supplicant/wpa_priv.c
@@ -21,6 +21,7 @@
#include "common/privsep_commands.h"
#include "common/ieee802_11_defs.h"
+#define WPA_PRIV_MAX_L2 3
struct wpa_priv_interface {
struct wpa_priv_interface *next;
@@ -35,11 +36,16 @@ struct wpa_priv_interface {
void *drv_priv;
void *drv_global_priv;
struct sockaddr_un drv_addr;
+ socklen_t drv_addr_len;
int wpas_registered;
- /* TODO: add support for multiple l2 connections */
- struct l2_packet_data *l2;
- struct sockaddr_un l2_addr;
+ struct l2_packet_data *l2[WPA_PRIV_MAX_L2];
+ struct sockaddr_un l2_addr[WPA_PRIV_MAX_L2];
+ socklen_t l2_addr_len[WPA_PRIV_MAX_L2];
+ struct wpa_priv_l2 {
+ struct wpa_priv_interface *parent;
+ int idx;
+ } l2_ctx[WPA_PRIV_MAX_L2];
};
struct wpa_priv_global {
@@ -48,8 +54,10 @@ struct wpa_priv_global {
static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
- struct sockaddr_un *from)
+ struct sockaddr_un *from, socklen_t fromlen)
{
+ int i;
+
if (iface->drv_priv) {
wpa_printf(MSG_DEBUG, "Cleaning up forgotten driver instance");
if (iface->driver->deinit)
@@ -62,11 +70,13 @@ static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
iface->wpas_registered = 0;
}
- if (iface->l2) {
- wpa_printf(MSG_DEBUG, "Cleaning up forgotten l2_packet "
- "instance");
- l2_packet_deinit(iface->l2);
- iface->l2 = NULL;
+ for (i = 0; i < WPA_PRIV_MAX_L2; i++) {
+ if (iface->l2[i]) {
+ wpa_printf(MSG_DEBUG,
+ "Cleaning up forgotten l2_packet instance");
+ l2_packet_deinit(iface->l2[i]);
+ iface->l2[i] = NULL;
+ }
}
if (iface->driver->init2) {
@@ -96,7 +106,8 @@ static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
wpa_printf(MSG_DEBUG, "Driver wrapper '%s' initialized for interface "
"'%s'", iface->driver_name, iface->ifname);
- os_memcpy(&iface->drv_addr, from, sizeof(iface->drv_addr));
+ os_memcpy(&iface->drv_addr, from, fromlen);
+ iface->drv_addr_len = fromlen;
iface->wpas_registered = 1;
if (iface->driver->set_param &&
@@ -123,18 +134,43 @@ static void wpa_priv_cmd_unregister(struct wpa_priv_interface *iface,
static void wpa_priv_cmd_scan(struct wpa_priv_interface *iface,
- char *buf, size_t len)
+ void *buf, size_t len)
{
struct wpa_driver_scan_params params;
+ struct privsep_cmd_scan *scan;
+ unsigned int i;
+ int freqs[PRIVSEP_MAX_SCAN_FREQS + 1];
if (iface->drv_priv == NULL)
return;
+ if (len < sizeof(*scan)) {
+ wpa_printf(MSG_DEBUG, "Invalid scan request");
+ return;
+ }
+
+ scan = buf;
+
os_memset(&params, 0, sizeof(params));
- if (len) {
- params.ssids[0].ssid = (u8 *) buf;
- params.ssids[0].ssid_len = len;
- params.num_ssids = 1;
+ if (scan->num_ssids > WPAS_MAX_SCAN_SSIDS) {
+ wpa_printf(MSG_DEBUG, "Invalid scan request (num_ssids)");
+ return;
+ }
+ params.num_ssids = scan->num_ssids;
+ for (i = 0; i < scan->num_ssids; i++) {
+ params.ssids[i].ssid = scan->ssids[i];
+ params.ssids[i].ssid_len = scan->ssid_lens[i];
+ }
+
+ if (scan->num_freqs > PRIVSEP_MAX_SCAN_FREQS) {
+ wpa_printf(MSG_DEBUG, "Invalid scan request (num_freqs)");
+ return;
+ }
+ if (scan->num_freqs) {
+ for (i = 0; i < scan->num_freqs; i++)
+ freqs[i] = scan->freqs[i];
+ freqs[i] = 0;
+ params.freqs = freqs;
}
if (iface->driver->scan2)
@@ -143,7 +179,8 @@ static void wpa_priv_cmd_scan(struct wpa_priv_interface *iface,
static void wpa_priv_get_scan_results2(struct wpa_priv_interface *iface,
- struct sockaddr_un *from)
+ struct sockaddr_un *from,
+ socklen_t fromlen)
{
struct wpa_scan_results *res;
u8 *buf = NULL, *pos, *end;
@@ -165,7 +202,7 @@ static void wpa_priv_get_scan_results2(struct wpa_priv_interface *iface,
for (i = 0; i < res->num; i++) {
struct wpa_scan_res *r = res->res[i];
- val = sizeof(*r) + r->ie_len;
+ val = sizeof(*r) + r->ie_len + r->beacon_ie_len;
if (end - pos < (int) sizeof(int) + val)
break;
os_memcpy(pos, &val, sizeof(int));
@@ -174,8 +211,7 @@ static void wpa_priv_get_scan_results2(struct wpa_priv_interface *iface,
pos += val;
}
- sendto(iface->fd, buf, pos - buf, 0, (struct sockaddr *) from,
- sizeof(*from));
+ sendto(iface->fd, buf, pos - buf, 0, (struct sockaddr *) from, fromlen);
os_free(buf);
wpa_scan_results_free(res);
@@ -184,21 +220,21 @@ static void wpa_priv_get_scan_results2(struct wpa_priv_interface *iface,
fail:
os_free(buf);
wpa_scan_results_free(res);
- sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, sizeof(*from));
+ sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, fromlen);
}
static void wpa_priv_cmd_get_scan_results(struct wpa_priv_interface *iface,
- struct sockaddr_un *from)
+ struct sockaddr_un *from,
+ socklen_t fromlen)
{
if (iface->drv_priv == NULL)
return;
if (iface->driver->get_scan_results2)
- wpa_priv_get_scan_results2(iface, from);
+ wpa_priv_get_scan_results2(iface, from, fromlen);
else
- sendto(iface->fd, "", 0, 0, (struct sockaddr *) from,
- sizeof(*from));
+ sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, fromlen);
}
@@ -218,7 +254,7 @@ static void wpa_priv_cmd_authenticate(struct wpa_priv_interface *iface,
}
auth = buf;
- if (sizeof(*auth) + auth->ie_len + auth->sae_data_len > len) {
+ if (sizeof(*auth) + auth->ie_len + auth->auth_data_len > len) {
wpa_printf(MSG_DEBUG, "Authentication request overflow");
return;
}
@@ -244,9 +280,9 @@ static void wpa_priv_cmd_authenticate(struct wpa_priv_interface *iface,
params.ie = (u8 *) (auth + 1);
params.ie_len = auth->ie_len;
}
- if (auth->sae_data_len) {
- params.sae_data = ((u8 *) (auth + 1)) + auth->ie_len;
- params.sae_data_len = auth->sae_data_len;
+ if (auth->auth_data_len) {
+ params.auth_data = ((u8 *) (auth + 1)) + auth->ie_len;
+ params.auth_data_len = auth->auth_data_len;
}
res = iface->driver->authenticate(iface->drv_priv, &params);
@@ -303,7 +339,7 @@ static void wpa_priv_cmd_associate(struct wpa_priv_interface *iface,
static void wpa_priv_cmd_get_bssid(struct wpa_priv_interface *iface,
- struct sockaddr_un *from)
+ struct sockaddr_un *from, socklen_t fromlen)
{
u8 bssid[ETH_ALEN];
@@ -315,16 +351,16 @@ static void wpa_priv_cmd_get_bssid(struct wpa_priv_interface *iface,
goto fail;
sendto(iface->fd, bssid, ETH_ALEN, 0, (struct sockaddr *) from,
- sizeof(*from));
+ fromlen);
return;
fail:
- sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, sizeof(*from));
+ sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, fromlen);
}
static void wpa_priv_cmd_get_ssid(struct wpa_priv_interface *iface,
- struct sockaddr_un *from)
+ struct sockaddr_un *from, socklen_t fromlen)
{
u8 ssid[sizeof(int) + SSID_MAX_LEN];
int res;
@@ -335,17 +371,18 @@ static void wpa_priv_cmd_get_ssid(struct wpa_priv_interface *iface,
if (iface->driver->get_ssid == NULL)
goto fail;
+ os_memset(ssid, 0, sizeof(ssid));
res = iface->driver->get_ssid(iface->drv_priv, &ssid[sizeof(int)]);
if (res < 0 || res > SSID_MAX_LEN)
goto fail;
os_memcpy(ssid, &res, sizeof(int));
sendto(iface->fd, ssid, sizeof(ssid), 0, (struct sockaddr *) from,
- sizeof(*from));
+ fromlen);
return;
fail:
- sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, sizeof(*from));
+ sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, fromlen);
}
@@ -378,7 +415,7 @@ static void wpa_priv_cmd_set_key(struct wpa_priv_interface *iface,
static void wpa_priv_cmd_get_capa(struct wpa_priv_interface *iface,
- struct sockaddr_un *from)
+ struct sockaddr_un *from, socklen_t fromlen)
{
struct wpa_driver_capa capa;
@@ -394,18 +431,19 @@ static void wpa_priv_cmd_get_capa(struct wpa_priv_interface *iface,
capa.extended_capa_mask = NULL;
capa.extended_capa_len = 0;
sendto(iface->fd, &capa, sizeof(capa), 0, (struct sockaddr *) from,
- sizeof(*from));
+ fromlen);
return;
fail:
- sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, sizeof(*from));
+ sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, fromlen);
}
static void wpa_priv_l2_rx(void *ctx, const u8 *src_addr, const u8 *buf,
size_t len)
{
- struct wpa_priv_interface *iface = ctx;
+ struct wpa_priv_l2 *l2_ctx = ctx;
+ struct wpa_priv_interface *iface = l2_ctx->parent;
struct msghdr msg;
struct iovec io[2];
@@ -417,8 +455,8 @@ static void wpa_priv_l2_rx(void *ctx, const u8 *src_addr, const u8 *buf,
os_memset(&msg, 0, sizeof(msg));
msg.msg_iov = io;
msg.msg_iovlen = 2;
- msg.msg_name = &iface->l2_addr;
- msg.msg_namelen = sizeof(iface->l2_addr);
+ msg.msg_name = &iface->l2_addr[l2_ctx->idx];
+ msg.msg_namelen = iface->l2_addr_len[l2_ctx->idx];
if (sendmsg(iface->fd, &msg, 0) < 0) {
wpa_printf(MSG_ERROR, "sendmsg(l2 rx): %s", strerror(errno));
@@ -426,14 +464,23 @@ static void wpa_priv_l2_rx(void *ctx, const u8 *src_addr, const u8 *buf,
}
+static int wpa_priv_allowed_l2_proto(u16 proto)
+{
+ return proto == ETH_P_EAPOL || proto == ETH_P_RSN_PREAUTH ||
+ proto == ETH_P_80211_ENCAP;
+}
+
+
static void wpa_priv_cmd_l2_register(struct wpa_priv_interface *iface,
struct sockaddr_un *from,
+ socklen_t fromlen,
void *buf, size_t len)
{
int *reg_cmd = buf;
u8 own_addr[ETH_ALEN];
int res;
u16 proto;
+ int idx;
if (len != 2 * sizeof(int)) {
wpa_printf(MSG_DEBUG, "Invalid l2_register length %lu",
@@ -442,50 +489,69 @@ static void wpa_priv_cmd_l2_register(struct wpa_priv_interface *iface,
}
proto = reg_cmd[0];
- if (proto != ETH_P_EAPOL && proto != ETH_P_RSN_PREAUTH &&
- proto != ETH_P_80211_ENCAP) {
+ if (!wpa_priv_allowed_l2_proto(proto)) {
wpa_printf(MSG_DEBUG, "Refused l2_packet connection for "
"ethertype 0x%x", proto);
return;
}
- if (iface->l2) {
- wpa_printf(MSG_DEBUG, "Cleaning up forgotten l2_packet "
- "instance");
- l2_packet_deinit(iface->l2);
- iface->l2 = NULL;
+ for (idx = 0; idx < WPA_PRIV_MAX_L2; idx++) {
+ if (!iface->l2[idx])
+ break;
+ }
+ if (idx == WPA_PRIV_MAX_L2) {
+ wpa_printf(MSG_DEBUG, "No free l2_packet connection found");
+ return;
}
- os_memcpy(&iface->l2_addr, from, sizeof(iface->l2_addr));
+ os_memcpy(&iface->l2_addr[idx], from, fromlen);
+ iface->l2_addr_len[idx] = fromlen;
- iface->l2 = l2_packet_init(iface->ifname, NULL, proto,
- wpa_priv_l2_rx, iface, reg_cmd[1]);
- if (iface->l2 == NULL) {
+ iface->l2_ctx[idx].idx = idx;
+ iface->l2_ctx[idx].parent = iface;
+ iface->l2[idx] = l2_packet_init(iface->ifname, NULL, proto,
+ wpa_priv_l2_rx, &iface->l2_ctx[idx],
+ reg_cmd[1]);
+ if (!iface->l2[idx]) {
wpa_printf(MSG_DEBUG, "Failed to initialize l2_packet "
"instance for protocol %d", proto);
return;
}
- if (l2_packet_get_own_addr(iface->l2, own_addr) < 0) {
+ if (l2_packet_get_own_addr(iface->l2[idx], own_addr) < 0) {
wpa_printf(MSG_DEBUG, "Failed to get own address from "
"l2_packet");
- l2_packet_deinit(iface->l2);
- iface->l2 = NULL;
+ l2_packet_deinit(iface->l2[idx]);
+ iface->l2[idx] = NULL;
return;
}
res = sendto(iface->fd, own_addr, ETH_ALEN, 0,
- (struct sockaddr *) from, sizeof(*from));
- wpa_printf(MSG_DEBUG, "L2 registration: res=%d", res);
+ (struct sockaddr *) from, fromlen);
+ wpa_printf(MSG_DEBUG, "L2 registration[idx=%d]: res=%d", idx, res);
}
static void wpa_priv_cmd_l2_unregister(struct wpa_priv_interface *iface,
- struct sockaddr_un *from)
+ struct sockaddr_un *from,
+ socklen_t fromlen)
{
- if (iface->l2) {
- l2_packet_deinit(iface->l2);
- iface->l2 = NULL;
+ int idx;
+
+ for (idx = 0; idx < WPA_PRIV_MAX_L2; idx++) {
+ if (iface->l2_addr_len[idx] == fromlen &&
+ os_memcmp(&iface->l2_addr[idx], from, fromlen) == 0)
+ break;
+ }
+ if (idx == WPA_PRIV_MAX_L2) {
+ wpa_printf(MSG_DEBUG,
+ "No registered l2_packet socket found for unregister request");
+ return;
+ }
+
+ if (iface->l2[idx]) {
+ l2_packet_deinit(iface->l2[idx]);
+ iface->l2[idx] = NULL;
}
}
@@ -493,20 +559,36 @@ static void wpa_priv_cmd_l2_unregister(struct wpa_priv_interface *iface,
static void wpa_priv_cmd_l2_notify_auth_start(struct wpa_priv_interface *iface,
struct sockaddr_un *from)
{
- if (iface->l2)
- l2_packet_notify_auth_start(iface->l2);
+ int idx;
+
+ for (idx = 0; idx < WPA_PRIV_MAX_L2; idx++) {
+ if (iface->l2[idx])
+ l2_packet_notify_auth_start(iface->l2[idx]);
+ }
}
static void wpa_priv_cmd_l2_send(struct wpa_priv_interface *iface,
- struct sockaddr_un *from,
+ struct sockaddr_un *from, socklen_t fromlen,
void *buf, size_t len)
{
u8 *dst_addr;
u16 proto;
int res;
+ int idx;
- if (iface->l2 == NULL)
+ for (idx = 0; idx < WPA_PRIV_MAX_L2; idx++) {
+ if (iface->l2_addr_len[idx] == fromlen &&
+ os_memcmp(&iface->l2_addr[idx], from, fromlen) == 0)
+ break;
+ }
+ if (idx == WPA_PRIV_MAX_L2) {
+ wpa_printf(MSG_DEBUG,
+ "No registered l2_packet socket found for send request");
+ return;
+ }
+
+ if (iface->l2[idx] == NULL)
return;
if (len < ETH_ALEN + 2) {
@@ -518,15 +600,15 @@ static void wpa_priv_cmd_l2_send(struct wpa_priv_interface *iface,
dst_addr = buf;
os_memcpy(&proto, buf + ETH_ALEN, 2);
- if (proto != ETH_P_EAPOL && proto != ETH_P_RSN_PREAUTH) {
+ if (!wpa_priv_allowed_l2_proto(proto)) {
wpa_printf(MSG_DEBUG, "Refused l2_packet send for ethertype "
"0x%x", proto);
return;
}
- res = l2_packet_send(iface->l2, dst_addr, proto, buf + ETH_ALEN + 2,
- len - ETH_ALEN - 2);
- wpa_printf(MSG_DEBUG, "L2 send: res=%d", res);
+ res = l2_packet_send(iface->l2[idx], dst_addr, proto,
+ buf + ETH_ALEN + 2, len - ETH_ALEN - 2);
+ wpa_printf(MSG_DEBUG, "L2 send[idx=%d]: res=%d", idx, res);
}
@@ -571,7 +653,7 @@ static void wpa_priv_receive(int sock, void *eloop_ctx, void *sock_ctx)
switch (cmd) {
case PRIVSEP_CMD_REGISTER:
- wpa_priv_cmd_register(iface, &from);
+ wpa_priv_cmd_register(iface, &from, fromlen);
break;
case PRIVSEP_CMD_UNREGISTER:
wpa_priv_cmd_unregister(iface, &from);
@@ -580,34 +662,35 @@ static void wpa_priv_receive(int sock, void *eloop_ctx, void *sock_ctx)
wpa_priv_cmd_scan(iface, cmd_buf, cmd_len);
break;
case PRIVSEP_CMD_GET_SCAN_RESULTS:
- wpa_priv_cmd_get_scan_results(iface, &from);
+ wpa_priv_cmd_get_scan_results(iface, &from, fromlen);
break;
case PRIVSEP_CMD_ASSOCIATE:
wpa_priv_cmd_associate(iface, cmd_buf, cmd_len);
break;
case PRIVSEP_CMD_GET_BSSID:
- wpa_priv_cmd_get_bssid(iface, &from);
+ wpa_priv_cmd_get_bssid(iface, &from, fromlen);
break;
case PRIVSEP_CMD_GET_SSID:
- wpa_priv_cmd_get_ssid(iface, &from);
+ wpa_priv_cmd_get_ssid(iface, &from, fromlen);
break;
case PRIVSEP_CMD_SET_KEY:
wpa_priv_cmd_set_key(iface, cmd_buf, cmd_len);
break;
case PRIVSEP_CMD_GET_CAPA:
- wpa_priv_cmd_get_capa(iface, &from);
+ wpa_priv_cmd_get_capa(iface, &from, fromlen);
break;
case PRIVSEP_CMD_L2_REGISTER:
- wpa_priv_cmd_l2_register(iface, &from, cmd_buf, cmd_len);
+ wpa_priv_cmd_l2_register(iface, &from, fromlen,
+ cmd_buf, cmd_len);
break;
case PRIVSEP_CMD_L2_UNREGISTER:
- wpa_priv_cmd_l2_unregister(iface, &from);
+ wpa_priv_cmd_l2_unregister(iface, &from, fromlen);
break;
case PRIVSEP_CMD_L2_NOTIFY_AUTH_START:
wpa_priv_cmd_l2_notify_auth_start(iface, &from);
break;
case PRIVSEP_CMD_L2_SEND:
- wpa_priv_cmd_l2_send(iface, &from, cmd_buf, cmd_len);
+ wpa_priv_cmd_l2_send(iface, &from, fromlen, cmd_buf, cmd_len);
break;
case PRIVSEP_CMD_SET_COUNTRY:
pos = cmd_buf;
@@ -625,8 +708,14 @@ static void wpa_priv_receive(int sock, void *eloop_ctx, void *sock_ctx)
static void wpa_priv_interface_deinit(struct wpa_priv_interface *iface)
{
- if (iface->drv_priv && iface->driver->deinit)
- iface->driver->deinit(iface->drv_priv);
+ int i;
+
+ if (iface->drv_priv) {
+ if (iface->driver->deinit)
+ iface->driver->deinit(iface->drv_priv);
+ if (iface->drv_global_priv)
+ iface->driver->global_deinit(iface->drv_global_priv);
+ }
if (iface->fd >= 0) {
eloop_unregister_read_sock(iface->fd);
@@ -634,8 +723,10 @@ static void wpa_priv_interface_deinit(struct wpa_priv_interface *iface)
unlink(iface->sock_name);
}
- if (iface->l2)
- l2_packet_deinit(iface->l2);
+ for (i = 0; i < WPA_PRIV_MAX_L2; i++) {
+ if (iface->l2[i])
+ l2_packet_deinit(iface->l2[i]);
+ }
os_free(iface->ifname);
os_free(iface->driver_name);
@@ -777,7 +868,7 @@ static int wpa_priv_send_event(struct wpa_priv_interface *iface, int event,
msg.msg_iov = io;
msg.msg_iovlen = data ? 2 : 1;
msg.msg_name = &iface->drv_addr;
- msg.msg_namelen = sizeof(iface->drv_addr);
+ msg.msg_namelen = iface->drv_addr_len;
if (sendmsg(iface->fd, &msg, 0) < 0) {
wpa_printf(MSG_ERROR, "sendmsg(wpas_socket): %s",
@@ -796,7 +887,7 @@ static void wpa_priv_send_auth(struct wpa_priv_interface *iface,
struct privsep_event_auth *auth;
u8 *buf, *pos;
- buf = os_malloc(buflen);
+ buf = os_zalloc(buflen);
if (buf == NULL)
return;
@@ -990,12 +1081,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
&data->pmkid_candidate,
sizeof(struct pmkid_candidate));
break;
- case EVENT_STKSTART:
- if (data == NULL)
- return;
- wpa_priv_send_event(iface, PRIVSEP_EVENT_STKSTART,
- &data->stkstart.peer, ETH_ALEN);
- break;
case EVENT_FT_RESPONSE:
wpa_priv_send_ft_response(iface, data);
break;
@@ -1061,7 +1146,7 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
msg.msg_iov = io;
msg.msg_iovlen = 3;
msg.msg_name = &iface->drv_addr;
- msg.msg_namelen = sizeof(iface->drv_addr);
+ msg.msg_namelen = iface->drv_addr_len;
if (sendmsg(iface->fd, &msg, 0) < 0)
wpa_printf(MSG_ERROR, "sendmsg(wpas_socket): %s",
@@ -1099,7 +1184,7 @@ static void wpa_priv_fd_workaround(void)
static void usage(void)
{
printf("wpa_priv v" VERSION_STR "\n"
- "Copyright (c) 2007-2016, Jouni Malinen <j@w1.fi> and "
+ "Copyright (c) 2007-2017, Jouni Malinen <j@w1.fi> and "
"contributors\n"
"\n"
"usage:\n"
diff --git a/contrib/wpa/wpa_supplicant/wpa_supplicant.c b/contrib/wpa/wpa_supplicant/wpa_supplicant.c
index 7361ee96d1df..96a3691cf3cf 100644
--- a/contrib/wpa/wpa_supplicant/wpa_supplicant.c
+++ b/contrib/wpa/wpa_supplicant/wpa_supplicant.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant
- * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -38,6 +38,8 @@
#include "common/wpa_ctrl.h"
#include "common/ieee802_11_defs.h"
#include "common/hw_features_common.h"
+#include "common/gas_server.h"
+#include "common/dpp.h"
#include "p2p/p2p.h"
#include "fst/fst.h"
#include "blacklist.h"
@@ -59,10 +61,15 @@
#include "wnm_sta.h"
#include "wpas_kay.h"
#include "mesh.h"
+#include "dpp_supplicant.h"
+#ifdef CONFIG_MESH
+#include "ap/ap_config.h"
+#include "ap/hostapd.h"
+#endif /* CONFIG_MESH */
const char *const wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> and contributors";
const char *const wpa_supplicant_license =
"This software may be distributed under the terms of the BSD license.\n"
@@ -112,6 +119,13 @@ const char *const wpa_supplicant_full_license5 =
"\n";
#endif /* CONFIG_NO_STDOUT_DEBUG */
+
+static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
+#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
+static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
+#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
+
+
/* Configure default/group WEP keys for static WEP */
int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
{
@@ -230,10 +244,30 @@ void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
"%d usec", sec, usec);
eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
+ wpa_s->last_auth_timeout_sec = sec;
eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
}
+/*
+ * wpas_auth_timeout_restart - Restart and change timeout for authentication
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @sec_diff: difference in seconds applied to original timeout value
+ */
+void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
+{
+ int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
+
+ if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Authentication timeout restart: %d sec", new_sec);
+ eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
+ eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
+ wpa_s, NULL);
+ }
+}
+
+
/**
* wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
* @wpa_s: Pointer to wpa_supplicant data
@@ -247,6 +281,9 @@ void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
wpa_blacklist_del(wpa_s, wpa_s->bssid);
+ os_free(wpa_s->last_con_fail_realm);
+ wpa_s->last_con_fail_realm = NULL;
+ wpa_s->last_con_fail_realm_len = 0;
}
@@ -329,7 +366,12 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
- ieee802_1x_alloc_kay_sm(wpa_s, ssid);
+#ifdef CONFIG_MACSEC
+ if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
+ ieee802_1x_create_preshared_mka(wpa_s, ssid);
+ else
+ ieee802_1x_alloc_kay_sm(wpa_s, ssid);
+#endif /* CONFIG_MACSEC */
#endif /* IEEE8021X_EAPOL */
}
@@ -403,18 +445,32 @@ void free_hw_features(struct wpa_supplicant *wpa_s)
}
-static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
+void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
{
struct wpa_bss_tmp_disallowed *bss, *prev;
dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
struct wpa_bss_tmp_disallowed, list) {
+ eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
dl_list_del(&bss->list);
os_free(bss);
}
}
+void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
+{
+ struct fils_hlp_req *req;
+
+ while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
+ list)) != NULL) {
+ dl_list_del(&req->list);
+ wpabuf_free(req->pkt);
+ os_free(req);
+ }
+}
+
+
static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
{
int i;
@@ -434,6 +490,10 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
#ifdef CONFIG_TESTING_OPTIONS
l2_packet_deinit(wpa_s->l2_test);
wpa_s->l2_test = NULL;
+ os_free(wpa_s->get_pref_freq_list_override);
+ wpa_s->get_pref_freq_list_override = NULL;
+ wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
+ wpa_s->last_assoc_req_wpa_ie = NULL;
#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_s->conf != NULL) {
@@ -448,6 +508,10 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
os_free(wpa_s->confanother);
wpa_s->confanother = NULL;
+ os_free(wpa_s->last_con_fail_realm);
+ wpa_s->last_con_fail_realm = NULL;
+ wpa_s->last_con_fail_realm_len = 0;
+
wpa_sm_set_eapol(wpa_s->wpa, NULL);
eapol_sm_deinit(wpa_s->eapol);
wpa_s->eapol = NULL;
@@ -506,6 +570,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
os_free(wpa_s->manual_scan_freqs);
wpa_s->manual_scan_freqs = NULL;
+ os_free(wpa_s->select_network_scan_freqs);
+ wpa_s->select_network_scan_freqs = NULL;
os_free(wpa_s->manual_sched_scan_freqs);
wpa_s->manual_sched_scan_freqs = NULL;
@@ -524,6 +590,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
radio_remove_works(wpa_s, "gas-query", 0);
gas_query_deinit(wpa_s->gas);
wpa_s->gas = NULL;
+ gas_server_deinit(wpa_s->gas_server);
+ wpa_s->gas_server = NULL;
free_hw_features(wpa_s);
@@ -580,6 +648,34 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
wpabuf_free(wpa_s->lci);
wpa_s->lci = NULL;
+ wpas_clear_beacon_rep_data(wpa_s);
+
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+#ifdef CONFIG_MESH
+ {
+ struct external_pmksa_cache *entry;
+
+ while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
+ struct external_pmksa_cache,
+ list)) != NULL) {
+ dl_list_del(&entry->list);
+ os_free(entry->pmksa_cache);
+ os_free(entry);
+ }
+ }
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
+ wpas_flush_fils_hlp_req(wpa_s);
+
+ wpabuf_free(wpa_s->ric_ies);
+ wpa_s->ric_ies = NULL;
+
+#ifdef CONFIG_DPP
+ wpas_dpp_deinit(wpa_s);
+ dpp_global_deinit(wpa_s->dpp);
+ wpa_s->dpp = NULL;
+#endif /* CONFIG_DPP */
}
@@ -753,6 +849,23 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
wpa_supplicant_state_txt(wpa_s->wpa_state),
wpa_supplicant_state_txt(state));
+ if (state == WPA_COMPLETED &&
+ os_reltime_initialized(&wpa_s->roam_start)) {
+ os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
+ wpa_s->roam_start.sec = 0;
+ wpa_s->roam_start.usec = 0;
+ wpas_notify_auth_changed(wpa_s);
+ wpas_notify_roam_time(wpa_s);
+ wpas_notify_roam_complete(wpa_s);
+ } else if (state == WPA_DISCONNECTED &&
+ os_reltime_initialized(&wpa_s->roam_start)) {
+ wpa_s->roam_start.sec = 0;
+ wpa_s->roam_start.usec = 0;
+ wpa_s->roam_time.sec = 0;
+ wpa_s->roam_time.usec = 0;
+ wpas_notify_roam_complete(wpa_s);
+ }
+
if (state == WPA_INTERFACE_DISABLED) {
/* Assure normal scan when interface is restored */
wpa_s->normal_scans = 0;
@@ -793,12 +906,24 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
if (state == WPA_COMPLETED && wpa_s->new_connection) {
struct wpa_ssid *ssid = wpa_s->current_ssid;
+ int fils_hlp_sent = 0;
+
+#ifdef CONFIG_SME
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ wpa_auth_alg_fils(wpa_s->sme.auth_alg))
+ fils_hlp_sent = 1;
+#endif /* CONFIG_SME */
+ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ wpa_auth_alg_fils(wpa_s->auth_alg))
+ fils_hlp_sent = 1;
+
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
- MACSTR " completed [id=%d id_str=%s]",
+ MACSTR " completed [id=%d id_str=%s%s]",
MAC2STR(wpa_s->bssid),
ssid ? ssid->id : -1,
- ssid && ssid->id_str ? ssid->id_str : "");
+ ssid && ssid->id_str ? ssid->id_str : "",
+ fils_hlp_sent ? " FILS_HLP_SENT" : "");
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
wpas_clear_temp_disabled(wpa_s, ssid, 1);
wpa_blacklist_clear(wpa_s);
@@ -813,6 +938,11 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
wpas_p2p_completed(wpa_s);
sme_sched_obss_scan(wpa_s, 1);
+
+#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
+ if (!fils_hlp_sent && ssid && ssid->eap.erp)
+ wpas_update_fils_connect_params(wpa_s);
+#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
} else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
state == WPA_ASSOCIATED) {
wpa_s->new_connection = 1;
@@ -831,7 +961,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
wpa_supplicant_stop_bgscan(wpa_s);
#endif /* CONFIG_BGSCAN */
- if (state == WPA_AUTHENTICATING)
+ if (state > WPA_SCANNING)
wpa_supplicant_stop_autoscan(wpa_s);
if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
@@ -927,7 +1057,13 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
"file '%s' - exiting", wpa_s->confname);
return -1;
}
- wpa_config_read(wpa_s->confanother, conf);
+ if (wpa_s->confanother &&
+ !wpa_config_read(wpa_s->confanother, conf)) {
+ wpa_msg(wpa_s, MSG_ERROR,
+ "Failed to parse the configuration file '%s' - exiting",
+ wpa_s->confanother);
+ return -1;
+ }
conf->changed_parameters = (unsigned int) -1;
@@ -953,7 +1089,9 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
* TODO: should notify EAPOL SM about changes in opensc_engine_path,
* pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
*/
- if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
+ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
/*
* Clear forced success to clear EAP state for next
* authentication.
@@ -1054,6 +1192,18 @@ static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
}
+static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
+ int freq)
+{
+ if (!ie->has_group)
+ ie->group_cipher = wpa_default_rsn_cipher(freq);
+ if (!ie->has_pairwise)
+ ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
+ return (ie->group_cipher & ssid->group_cipher) &&
+ (ie->pairwise_cipher & ssid->pairwise_cipher);
+}
+
+
/**
* wpa_supplicant_set_suites - Set authentication and encryption parameters
* @wpa_s: Pointer to wpa_supplicant data
@@ -1085,8 +1235,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
- (ie.group_cipher & ssid->group_cipher) &&
- (ie.pairwise_cipher & ssid->pairwise_cipher) &&
+ matching_ciphers(ssid, &ie, bss->freq) &&
(ie.key_mgmt & ssid->key_mgmt)) {
wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
proto = WPA_PROTO_RSN;
@@ -1098,14 +1247,20 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
proto = WPA_PROTO_WPA;
#ifdef CONFIG_HS20
- } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
+ } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
+ wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
+ (ie.group_cipher & ssid->group_cipher) &&
+ (ie.pairwise_cipher & ssid->pairwise_cipher) &&
+ (ie.key_mgmt & ssid->key_mgmt)) {
wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
- /* TODO: parse OSEN element */
- os_memset(&ie, 0, sizeof(ie));
- ie.group_cipher = WPA_CIPHER_CCMP;
- ie.pairwise_cipher = WPA_CIPHER_CCMP;
- ie.key_mgmt = WPA_KEY_MGMT_OSEN;
proto = WPA_PROTO_OSEN;
+ } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
+ wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
+ (ie.group_cipher & ssid->group_cipher) &&
+ (ie.pairwise_cipher & ssid->pairwise_cipher) &&
+ (ie.key_mgmt & ssid->key_mgmt)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
+ proto = WPA_PROTO_RSN;
#endif /* CONFIG_HS20 */
} else if (bss) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
@@ -1157,10 +1312,35 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
ie.pairwise_cipher = ssid->pairwise_cipher;
ie.key_mgmt = ssid->key_mgmt;
#ifdef CONFIG_IEEE80211W
- ie.mgmt_group_cipher =
- ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
- WPA_CIPHER_AES_128_CMAC : 0;
+ ie.mgmt_group_cipher = 0;
+ if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+ if (ssid->group_mgmt_cipher &
+ WPA_CIPHER_BIP_GMAC_256)
+ ie.mgmt_group_cipher =
+ WPA_CIPHER_BIP_GMAC_256;
+ else if (ssid->group_mgmt_cipher &
+ WPA_CIPHER_BIP_CMAC_256)
+ ie.mgmt_group_cipher =
+ WPA_CIPHER_BIP_CMAC_256;
+ else if (ssid->group_mgmt_cipher &
+ WPA_CIPHER_BIP_GMAC_128)
+ ie.mgmt_group_cipher =
+ WPA_CIPHER_BIP_GMAC_128;
+ else
+ ie.mgmt_group_cipher =
+ WPA_CIPHER_AES_128_CMAC;
+ }
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OWE
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
+ !ssid->owe_only &&
+ !bss_wpa && !bss_rsn && !bss_osen) {
+ wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
+ wpa_s->wpa_proto = 0;
+ *wpa_ie_len = 0;
+ return 0;
+ }
+#endif /* CONFIG_OWE */
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
"based on configuration");
} else
@@ -1195,6 +1375,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
#else /* CONFIG_NO_WPA */
sel = ie.group_cipher & ssid->group_cipher;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
+ ie.group_cipher, ssid->group_cipher, sel);
wpa_s->group_cipher = wpa_pick_group_cipher(sel);
if (wpa_s->group_cipher < 0) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
@@ -1205,6 +1388,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_cipher_txt(wpa_s->group_cipher));
sel = ie.pairwise_cipher & ssid->pairwise_cipher;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
+ ie.pairwise_cipher, ssid->pairwise_cipher, sel);
wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
if (wpa_s->pairwise_cipher < 0) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
@@ -1216,11 +1402,29 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_NO_WPA */
sel = ie.key_mgmt & ssid->key_mgmt;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
+ ie.key_mgmt, ssid->key_mgmt, sel);
#ifdef CONFIG_SAE
if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
#endif /* CONFIG_SAE */
if (0) {
+#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_SHA384
+ } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: using KEY_MGMT FT/802.1X-SHA384");
+ if (pmksa_cache_get_current(wpa_s->wpa)) {
+ /* PMKSA caching with FT is not fully functional, so
+ * disable the case for now. */
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: Disable PMKSA caching for FT/802.1X connection");
+ pmksa_cache_clear_current(wpa_s->wpa);
+ }
+#endif /* CONFIG_SHA384 */
+#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_SUITEB192
} else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
@@ -1233,22 +1437,52 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG,
"WPA: using KEY_MGMT 802.1X with Suite B");
#endif /* CONFIG_SUITEB */
+#ifdef CONFIG_FILS
+#ifdef CONFIG_IEEE80211R
+ } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
+ } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
+#endif /* CONFIG_IEEE80211R */
+ } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
+ } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
+#endif /* CONFIG_FILS */
#ifdef CONFIG_IEEE80211R
} else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
- } else if (sel & WPA_KEY_MGMT_FT_PSK) {
- wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
- wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
+ if (pmksa_cache_get_current(wpa_s->wpa)) {
+ /* PMKSA caching with FT is not fully functional, so
+ * disable the case for now. */
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: Disable PMKSA caching for FT/802.1X connection");
+ pmksa_cache_clear_current(wpa_s->wpa);
+ }
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_DPP
+ } else if (sel & WPA_KEY_MGMT_DPP) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
+#endif /* CONFIG_DPP */
#ifdef CONFIG_SAE
- } else if (sel & WPA_KEY_MGMT_SAE) {
- wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
- wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
} else if (sel & WPA_KEY_MGMT_FT_SAE) {
wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
+ } else if (sel & WPA_KEY_MGMT_SAE) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
#endif /* CONFIG_SAE */
+#ifdef CONFIG_IEEE80211R
+ } else if (sel & WPA_KEY_MGMT_FT_PSK) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
+#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
} else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
@@ -1273,6 +1507,11 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_OWE
+ } else if (sel & WPA_KEY_MGMT_OWE) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
+#endif /* CONFIG_OWE */
} else {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
"authenticated key management type");
@@ -1286,9 +1525,14 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_IEEE80211W
sel = ie.mgmt_group_cipher;
+ if (ssid->group_mgmt_cipher)
+ sel &= ssid->group_mgmt_cipher;
if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
!(ie.capabilities & WPA_CAPABILITY_MFPC))
sel = 0;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
+ ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
if (sel & WPA_CIPHER_AES_128_CMAC) {
wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
@@ -1314,23 +1558,44 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
wpas_get_ssid_pmf(wpa_s, ssid));
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
+#endif /* CONFIG_OCV */
if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
return -1;
}
- if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
+ if (0) {
+#ifdef CONFIG_DPP
+ } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
+ /* Use PMK from DPP network introduction (PMKSA entry) */
+ wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
+#endif /* CONFIG_DPP */
+ } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
int psk_set = 0;
+ int sae_only;
+
+ sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
+ WPA_KEY_MGMT_FT_PSK |
+ WPA_KEY_MGMT_PSK_SHA256)) == 0;
- if (ssid->psk_set) {
+ if (ssid->psk_set && !sae_only) {
+ wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
+ ssid->psk, PMK_LEN);
wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
NULL);
psk_set = 1;
}
+
+ if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
+ (ssid->sae_password || ssid->passphrase))
+ psk_set = 1;
+
#ifndef CONFIG_NO_PBKDF2
if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
- ssid->passphrase) {
+ ssid->passphrase && !sae_only) {
u8 psk[PMK_LEN];
pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
4096, psk, PMK_LEN);
@@ -1342,7 +1607,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_NO_PBKDF2 */
#ifdef CONFIG_EXT_PASSWORD
- if (ssid->ext_psk) {
+ if (ssid->ext_psk && !sae_only) {
struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
ssid->ext_psk);
char pw_str[64 + 1];
@@ -1388,6 +1653,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
ext_password_free(pw);
return -1;
}
+ wpa_hexdump_key(MSG_MSGDUMP,
+ "PSK (from external PSK)",
+ psk, PMK_LEN);
wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
NULL);
psk_set = 1;
@@ -1408,8 +1676,15 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
if (!psk_set) {
wpa_msg(wpa_s, MSG_INFO,
"No PSK available for association");
+ wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
return -1;
}
+#ifdef CONFIG_OWE
+ } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
+ /* OWE Diffie-Hellman exchange in (Re)Association
+ * Request/Response frames set the PMK, so do not override it
+ * here. */
+#endif /* CONFIG_OWE */
} else
wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
@@ -1425,6 +1700,10 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
case 0: /* Bits 0-7 */
break;
case 1: /* Bits 8-15 */
+ if (wpa_s->conf->coloc_intf_reporting) {
+ /* Bit 13 - Collocated Interference Reporting */
+ *pos |= 0x20;
+ }
break;
case 2: /* Bits 16-23 */
#ifdef CONFIG_WNM
@@ -1443,7 +1722,7 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
break;
case 4: /* Bits 32-39 */
#ifdef CONFIG_INTERWORKING
- if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
+ if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
*pos |= 0x01; /* Bit 32 - QoS Map */
#endif /* CONFIG_INTERWORKING */
break;
@@ -1466,6 +1745,12 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
if (wpa_s->conf->ftm_initiator)
*pos |= 0x80; /* Bit 71 - FTM initiator */
break;
+ case 9: /* Bits 72-79 */
+#ifdef CONFIG_FILS
+ if (!wpa_s->disable_fils)
+ *pos |= 0x01;
+#endif /* CONFIG_FILS */
+ break;
}
}
@@ -1473,11 +1758,8 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
{
u8 *pos = buf;
- u8 len = 6, i;
+ u8 len = 10, i;
- if (len < 9 &&
- (wpa_s->conf->ftm_initiator || wpa_s->conf->ftm_responder))
- len = 9;
if (len < wpa_s->extended_capa_len)
len = wpa_s->extended_capa_len;
if (buflen < (size_t) len + 2) {
@@ -1665,6 +1947,9 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
wmm_ac_clear_saved_tspecs(wpa_s);
wpa_s->reassoc_same_bss = 0;
wpa_s->reassoc_same_ess = 0;
+#ifdef CONFIG_TESTING_OPTIONS
+ wpa_s->testing_resend_assoc = 0;
+#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_s->last_ssid == ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
@@ -1672,12 +1957,16 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
if (wpa_s->current_bss && wpa_s->current_bss == bss) {
wmm_ac_save_tspecs(wpa_s);
wpa_s->reassoc_same_bss = 1;
+ } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
+ os_get_reltime(&wpa_s->roam_start);
}
- } else if (rand_style > 0) {
+ }
+
+ if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
if (wpas_update_random_addr(wpa_s, rand_style) < 0)
return;
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
- } else if (wpa_s->mac_addr_changed) {
+ } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
wpa_msg(wpa_s, MSG_INFO,
"Could not restore permanent MAC address");
@@ -1696,6 +1985,13 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_IBSS_RSN
ibss_rsn_deinit(wpa_s->ibss_rsn);
wpa_s->ibss_rsn = NULL;
+#else /* CONFIG_IBSS_RSN */
+ if (ssid->mode == WPAS_MODE_IBSS &&
+ !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "IBSS RSN not supported in the build");
+ return;
+ }
#endif /* CONFIG_IBSS_RSN */
if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
@@ -1737,6 +2033,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
ssid->id);
+ wpas_notify_mesh_group_started(wpa_s, ssid);
#else /* CONFIG_MESH */
wpa_msg(wpa_s, MSG_ERROR,
"mesh mode support not included in the build");
@@ -1744,6 +2041,20 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
return;
}
+ /*
+ * Set WPA state machine configuration to match the selected network now
+ * so that the information is available before wpas_start_assoc_cb()
+ * gets called. This is needed at least for RSN pre-authentication where
+ * candidate APs are added to a list based on scan result processing
+ * before completion of the first association.
+ */
+ wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
+
+#ifdef CONFIG_DPP
+ if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
+ return;
+#endif /* CONFIG_DPP */
+
#ifdef CONFIG_TDLS
if (bss)
wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
@@ -1766,6 +2077,13 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
return;
}
+#ifdef CONFIG_SME
+ if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
+ /* Clear possibly set auth_alg, if any, from last attempt. */
+ wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
+ }
+#endif /* CONFIG_SME */
+
wpas_abort_ongoing_scan(wpa_s);
cwork = os_zalloc(sizeof(*cwork));
@@ -1797,11 +2115,6 @@ static int drv_supports_vht(struct wpa_supplicant *wpa_s,
u8 channel;
int i;
-#ifdef CONFIG_HT_OVERRIDES
- if (ssid->disable_ht)
- return 0;
-#endif /* CONFIG_HT_OVERRIDES */
-
hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
if (hw_mode == NUM_HOSTAPD_MODES)
return 0;
@@ -1914,9 +2227,14 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
return;
+ freq->channel = pri_chan->chan;
+
#ifdef CONFIG_HT_OVERRIDES
- if (ssid->disable_ht40)
- return;
+ if (ssid->disable_ht40) {
+ if (ssid->disable_vht)
+ return;
+ goto skip_ht40;
+ }
#endif /* CONFIG_HT_OVERRIDES */
/* Check/setup HT40+/HT40- */
@@ -1941,8 +2259,6 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
return;
- freq->channel = pri_chan->chan;
-
if (ht40 == -1) {
if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
return;
@@ -1986,6 +2302,9 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
wpa_scan_results_free(scan_res);
}
+#ifdef CONFIG_HT_OVERRIDES
+skip_ht40:
+#endif /* CONFIG_HT_OVERRIDES */
wpa_printf(MSG_DEBUG,
"IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
freq->channel, freq->sec_channel_offset);
@@ -2000,6 +2319,13 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
vht_freq = *freq;
+#ifdef CONFIG_VHT_OVERRIDES
+ if (ssid->disable_vht) {
+ freq->vht_enabled = 0;
+ return;
+ }
+#endif /* CONFIG_VHT_OVERRIDES */
+
vht_freq.vht_enabled = vht_supported(mode);
if (!vht_freq.vht_enabled)
return;
@@ -2068,6 +2394,13 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
seg0 = 114;
}
+ } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_USE_HT) {
+ chwidth = VHT_CHANWIDTH_USE_HT;
+ seg0 = vht80[j] + 2;
+#ifdef CONFIG_HT_OVERRIDES
+ if (ssid->disable_ht40)
+ seg0 = 0;
+#endif /* CONFIG_HT_OVERRIDES */
}
if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
@@ -2084,147 +2417,177 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
}
-static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
+#ifdef CONFIG_FILS
+static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
+ size_t ie_buf_len)
{
- struct wpa_connect_work *cwork = work->ctx;
- struct wpa_bss *bss = cwork->bss;
- struct wpa_ssid *ssid = cwork->ssid;
- struct wpa_supplicant *wpa_s = work->wpa_s;
- u8 wpa_ie[200];
- size_t wpa_ie_len;
- int use_crypt, ret, i, bssid_changed;
- int algs = WPA_AUTH_ALG_OPEN;
- unsigned int cipher_pairwise, cipher_group;
- struct wpa_driver_associate_params params;
- int wep_keys_set = 0;
- int assoc_failed = 0;
- struct wpa_ssid *old_ssid;
- u8 prev_bssid[ETH_ALEN];
-#ifdef CONFIG_HT_OVERRIDES
- struct ieee80211_ht_capabilities htcaps;
- struct ieee80211_ht_capabilities htcaps_mask;
-#endif /* CONFIG_HT_OVERRIDES */
-#ifdef CONFIG_VHT_OVERRIDES
- struct ieee80211_vht_capabilities vhtcaps;
- struct ieee80211_vht_capabilities vhtcaps_mask;
-#endif /* CONFIG_VHT_OVERRIDES */
-#ifdef CONFIG_MBO
- const u8 *mbo = NULL;
-#endif /* CONFIG_MBO */
+ struct fils_hlp_req *req;
+ size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
+ const u8 *pos;
+ u8 *buf = ie_buf;
- if (deinit) {
- if (work->started) {
- wpa_s->connect_work = NULL;
+ dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
+ list) {
+ rem_len = ie_buf_len - ie_len;
+ pos = wpabuf_head(req->pkt);
+ hdr_len = 1 + 2 * ETH_ALEN + 6;
+ hlp_len = wpabuf_len(req->pkt);
- /* cancel possible auth. timeout */
- eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
- NULL);
+ if (rem_len < 2 + hdr_len + hlp_len) {
+ wpa_printf(MSG_ERROR,
+ "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
+ (unsigned long) rem_len,
+ (unsigned long) (2 + hdr_len + hlp_len));
+ break;
+ }
+
+ len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
+ /* Element ID */
+ *buf++ = WLAN_EID_EXTENSION;
+ /* Length */
+ *buf++ = len;
+ /* Element ID Extension */
+ *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
+ /* Destination MAC address */
+ os_memcpy(buf, req->dst, ETH_ALEN);
+ buf += ETH_ALEN;
+ /* Source MAC address */
+ os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
+ buf += ETH_ALEN;
+ /* LLC/SNAP Header */
+ os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
+ buf += 6;
+ /* HLP Packet */
+ os_memcpy(buf, pos, len - hdr_len);
+ buf += len - hdr_len;
+ pos += len - hdr_len;
+
+ hlp_len -= len - hdr_len;
+ ie_len += 2 + len;
+ rem_len -= 2 + len;
+
+ while (hlp_len) {
+ len = (hlp_len > 255) ? 255 : hlp_len;
+ if (rem_len < 2 + len)
+ break;
+ *buf++ = WLAN_EID_FRAGMENT;
+ *buf++ = len;
+ os_memcpy(buf, pos, len);
+ buf += len;
+ pos += len;
+
+ hlp_len -= len;
+ ie_len += 2 + len;
+ rem_len -= 2 + len;
}
- wpas_connect_work_free(cwork);
- return;
}
- wpa_s->connect_work = work;
+ return ie_len;
+}
- if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
- wpas_network_disabled(wpa_s, ssid)) {
- wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
- wpas_connect_work_done(wpa_s);
- return;
- }
- os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
- os_memset(&params, 0, sizeof(params));
- wpa_s->reassociate = 0;
- wpa_s->eap_expected_failure = 0;
- if (bss &&
- (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
-#ifdef CONFIG_IEEE80211R
- const u8 *ie, *md = NULL;
-#endif /* CONFIG_IEEE80211R */
- wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
- " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
- wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
- bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
- os_memset(wpa_s->bssid, 0, ETH_ALEN);
- os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
- if (bssid_changed)
- wpas_notify_bssid_changed(wpa_s);
-#ifdef CONFIG_IEEE80211R
- ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
- if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
- md = ie + 2;
- wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
- if (md) {
- /* Prepare for the next transition */
- wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
- }
-#endif /* CONFIG_IEEE80211R */
-#ifdef CONFIG_WPS
- } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
- wpa_s->conf->ap_scan == 2 &&
- (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
- /* Use ap_scan==1 style network selection to find the network
- */
- wpas_connect_work_done(wpa_s);
- wpa_s->scan_req = MANUAL_SCAN_REQ;
- wpa_s->reassociate = 1;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- return;
-#endif /* CONFIG_WPS */
- } else {
- wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
- if (bss)
- os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
- else
- os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
- }
- if (!wpa_s->pno)
- wpa_supplicant_cancel_sched_scan(wpa_s);
+int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
+{
+ return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
+ (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
+}
- wpa_supplicant_cancel_scan(wpa_s);
- /* Starting new association, so clear the possibly used WPA IE from the
- * previous association. */
- wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
+int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_FILS_SK_PFS
+ return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
+#else /* CONFIG_FILS_SK_PFS */
+ return 0;
+#endif /* CONFIG_FILS_SK_PFS */
+}
-#ifdef IEEE8021X_EAPOL
- if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
- if (ssid->leap) {
- if (ssid->non_leap == 0)
- algs = WPA_AUTH_ALG_LEAP;
- else
- algs |= WPA_AUTH_ALG_LEAP;
- }
+#endif /* CONFIG_FILS */
+
+
+static u8 * wpas_populate_assoc_ies(
+ struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss, struct wpa_ssid *ssid,
+ struct wpa_driver_associate_params *params,
+ enum wpa_drv_update_connect_params_mask *mask)
+{
+ u8 *wpa_ie;
+ size_t max_wpa_ie_len = 500;
+ size_t wpa_ie_len;
+ int algs = WPA_AUTH_ALG_OPEN;
+#ifdef CONFIG_MBO
+ const u8 *mbo_ie;
+#endif
+#ifdef CONFIG_SAE
+ int sae_pmksa_cached = 0;
+#endif /* CONFIG_SAE */
+#ifdef CONFIG_FILS
+ const u8 *realm, *username, *rrk;
+ size_t realm_len, username_len, rrk_len;
+ u16 next_seq_num;
+ struct fils_hlp_req *req;
+
+ dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
+ list) {
+ max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
+ 2 + 2 * wpabuf_len(req->pkt) / 255;
}
-#endif /* IEEE8021X_EAPOL */
- wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
- if (ssid->auth_alg) {
- algs = ssid->auth_alg;
- wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
- "0x%x", algs);
+#endif /* CONFIG_FILS */
+
+ wpa_ie = os_malloc(max_wpa_ie_len);
+ if (!wpa_ie) {
+ wpa_printf(MSG_ERROR,
+ "Failed to allocate connect IE buffer for %lu bytes",
+ (unsigned long) max_wpa_ie_len);
+ return NULL;
}
if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
wpa_key_mgmt_wpa(ssid->key_mgmt)) {
int try_opportunistic;
+ const u8 *cache_id = NULL;
+
try_opportunistic = (ssid->proactive_key_caching < 0 ?
wpa_s->conf->okc :
ssid->proactive_key_caching) &&
(ssid->proto & WPA_PROTO_RSN);
+#ifdef CONFIG_FILS
+ if (wpa_key_mgmt_fils(ssid->key_mgmt))
+ cache_id = wpa_bss_get_fils_cache_id(bss);
+#endif /* CONFIG_FILS */
if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
- ssid, try_opportunistic) == 0)
+ ssid, try_opportunistic,
+ cache_id, 0) == 0) {
eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
- wpa_ie_len = sizeof(wpa_ie);
+#ifdef CONFIG_SAE
+ sae_pmksa_cached = 1;
+#endif /* CONFIG_SAE */
+ }
+ wpa_ie_len = max_wpa_ie_len;
if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
wpa_ie, &wpa_ie_len)) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
"key management and encryption suites");
- wpas_connect_work_done(wpa_s);
- return;
+ os_free(wpa_ie);
+ return NULL;
}
+#ifdef CONFIG_HS20
+ } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
+ (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
+ /* No PMKSA caching, but otherwise similar to RSN/WPA */
+ wpa_ie_len = max_wpa_ie_len;
+ if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
+ wpa_ie, &wpa_ie_len)) {
+ wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
+ "key management and encryption suites");
+ os_free(wpa_ie);
+ return NULL;
+ }
+#endif /* CONFIG_HS20 */
} else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
/*
@@ -2236,20 +2599,20 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
wpa_ie_len = 0;
wpa_s->wpa_proto = 0;
} else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
- wpa_ie_len = sizeof(wpa_ie);
+ wpa_ie_len = max_wpa_ie_len;
if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
wpa_ie, &wpa_ie_len)) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
"key management and encryption suites (no "
"scan results)");
- wpas_connect_work_done(wpa_s);
- return;
+ os_free(wpa_ie);
+ return NULL;
}
#ifdef CONFIG_WPS
} else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
struct wpabuf *wps_ie;
wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
- if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
+ if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
wpa_ie_len = wpabuf_len(wps_ie);
os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
} else
@@ -2257,9 +2620,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
wpabuf_free(wps_ie);
wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
- params.wps = WPS_MODE_PRIVACY;
+ params->wps = WPS_MODE_PRIVACY;
else
- params.wps = WPS_MODE_OPEN;
+ params->wps = WPS_MODE_OPEN;
wpa_s->wpa_proto = 0;
#endif /* CONFIG_WPS */
} else {
@@ -2268,13 +2631,69 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
wpa_s->wpa_proto = 0;
}
+#ifdef IEEE8021X_EAPOL
+ if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
+ if (ssid->leap) {
+ if (ssid->non_leap == 0)
+ algs = WPA_AUTH_ALG_LEAP;
+ else
+ algs |= WPA_AUTH_ALG_LEAP;
+ }
+ }
+
+#ifdef CONFIG_FILS
+ /* Clear FILS association */
+ wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
+
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
+ ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
+ eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
+ &username_len, &realm, &realm_len,
+ &next_seq_num, &rrk, &rrk_len) == 0 &&
+ (!wpa_s->last_con_fail_realm ||
+ wpa_s->last_con_fail_realm_len != realm_len ||
+ os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
+ algs = WPA_AUTH_ALG_FILS;
+ params->fils_erp_username = username;
+ params->fils_erp_username_len = username_len;
+ params->fils_erp_realm = realm;
+ params->fils_erp_realm_len = realm_len;
+ params->fils_erp_next_seq_num = next_seq_num;
+ params->fils_erp_rrk = rrk;
+ params->fils_erp_rrk_len = rrk_len;
+
+ if (mask)
+ *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
+ }
+#endif /* CONFIG_FILS */
+#endif /* IEEE8021X_EAPOL */
+#ifdef CONFIG_SAE
+ if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
+ algs = WPA_AUTH_ALG_SAE;
+#endif /* CONFIG_SAE */
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
+ if (ssid->auth_alg) {
+ algs = ssid->auth_alg;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Overriding auth_alg selection: 0x%x", algs);
+ }
+
+#ifdef CONFIG_SAE
+ if (sae_pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
+ algs = WPA_AUTH_ALG_OPEN;
+ }
+#endif /* CONFIG_SAE */
+
#ifdef CONFIG_P2P
if (wpa_s->global->p2p) {
u8 *pos;
size_t len;
int res;
pos = wpa_ie + wpa_ie_len;
- len = sizeof(wpa_ie) - wpa_ie_len;
+ len = max_wpa_ie_len - wpa_ie_len;
res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
ssid->p2p_group);
if (res >= 0)
@@ -2299,21 +2718,12 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
#endif /* CONFIG_P2P */
-#ifdef CONFIG_MBO
if (bss) {
- mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
- if (mbo) {
- int len;
-
- len = wpas_mbo_supp_op_class_ie(wpa_s, bss->freq,
- wpa_ie + wpa_ie_len,
- sizeof(wpa_ie) -
- wpa_ie_len);
- if (len > 0)
- wpa_ie_len += len;
- }
+ wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss->freq,
+ wpa_ie + wpa_ie_len,
+ max_wpa_ie_len -
+ wpa_ie_len);
}
-#endif /* CONFIG_MBO */
/*
* Workaround: Add Extended Capabilities element only if the AP
@@ -2333,7 +2743,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
int ext_capab_len;
ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
sizeof(ext_capab));
- if (ext_capab_len > 0) {
+ if (ext_capab_len > 0 &&
+ wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
u8 *pos = wpa_ie;
if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
pos += 2 + pos[1];
@@ -2348,13 +2759,15 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
if (is_hs20_network(wpa_s, ssid, bss)) {
struct wpabuf *hs20;
- hs20 = wpabuf_alloc(20);
+ hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
if (hs20) {
int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
size_t len;
- wpas_hs20_add_indication(hs20, pps_mo_id);
- len = sizeof(wpa_ie) - wpa_ie_len;
+ wpas_hs20_add_indication(hs20, pps_mo_id,
+ get_hs20_version(bss));
+ wpas_hs20_add_roam_cons_sel(hs20, ssid);
+ len = max_wpa_ie_len - wpa_ie_len;
if (wpabuf_len(hs20) <= len) {
os_memcpy(wpa_ie + wpa_ie_len,
wpabuf_head(hs20), wpabuf_len(hs20));
@@ -2371,7 +2784,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
size_t len;
- len = sizeof(wpa_ie) - wpa_ie_len;
+ len = max_wpa_ie_len - wpa_ie_len;
if (wpabuf_len(buf) <= len) {
os_memcpy(wpa_ie + wpa_ie_len,
wpabuf_head(buf), wpabuf_len(buf));
@@ -2383,7 +2796,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
if (wpa_s->fst_ies) {
int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
- if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) {
+ if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
os_memcpy(wpa_ie + wpa_ie_len,
wpabuf_head(wpa_s->fst_ies), fst_ies_len);
wpa_ie_len += fst_ies_len;
@@ -2392,20 +2805,314 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
#endif /* CONFIG_FST */
#ifdef CONFIG_MBO
- if (mbo) {
+ mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
+ if (mbo_ie) {
int len;
len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
- sizeof(wpa_ie) - wpa_ie_len);
+ max_wpa_ie_len - wpa_ie_len,
+ !!mbo_attr_from_mbo_ie(mbo_ie,
+ OCE_ATTR_ID_CAPA_IND));
if (len >= 0)
wpa_ie_len += len;
}
#endif /* CONFIG_MBO */
+#ifdef CONFIG_FILS
+ if (algs == WPA_AUTH_ALG_FILS) {
+ size_t len;
+
+ len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
+ max_wpa_ie_len - wpa_ie_len);
+ wpa_ie_len += len;
+ }
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_OWE
+#ifdef CONFIG_TESTING_OPTIONS
+ if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
+ wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
+ } else
+#endif /* CONFIG_TESTING_OPTIONS */
+ if (algs == WPA_AUTH_ALG_OPEN &&
+ ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
+ struct wpabuf *owe_ie;
+ u16 group;
+
+ if (ssid->owe_group) {
+ group = ssid->owe_group;
+ } else if (wpa_s->assoc_status_code ==
+ WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
+ if (wpa_s->last_owe_group == 19)
+ group = 20;
+ else if (wpa_s->last_owe_group == 20)
+ group = 21;
+ else
+ group = OWE_DH_GROUP;
+ } else {
+ group = OWE_DH_GROUP;
+ }
+
+ wpa_s->last_owe_group = group;
+ wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
+ owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
+ if (owe_ie &&
+ wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
+ os_memcpy(wpa_ie + wpa_ie_len,
+ wpabuf_head(owe_ie), wpabuf_len(owe_ie));
+ wpa_ie_len += wpabuf_len(owe_ie);
+ }
+ wpabuf_free(owe_ie);
+ }
+#endif /* CONFIG_OWE */
+
+#ifdef CONFIG_DPP2
+ if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
+ ssid->dpp_netaccesskey) {
+ dpp_pfs_free(wpa_s->dpp_pfs);
+ wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
+ ssid->dpp_netaccesskey_len);
+ if (!wpa_s->dpp_pfs) {
+ wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
+ /* Try to continue without PFS */
+ goto pfs_fail;
+ }
+ if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
+ max_wpa_ie_len - wpa_ie_len) {
+ os_memcpy(wpa_ie + wpa_ie_len,
+ wpabuf_head(wpa_s->dpp_pfs->ie),
+ wpabuf_len(wpa_s->dpp_pfs->ie));
+ wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
+ }
+ }
+pfs_fail:
+#endif /* CONFIG_DPP2 */
+
+#ifdef CONFIG_IEEE80211R
+ /*
+ * Add MDIE under these conditions: the network profile allows FT,
+ * the AP supports FT, and the mobility domain ID matches.
+ */
+ if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
+ const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
+
+ if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
+ size_t len = 0;
+ const u8 *md = mdie + 2;
+ const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
+
+ if (os_memcmp(md, wpa_md,
+ MOBILITY_DOMAIN_ID_LEN) == 0) {
+ /* Add mobility domain IE */
+ len = wpa_ft_add_mdie(
+ wpa_s->wpa, wpa_ie + wpa_ie_len,
+ max_wpa_ie_len - wpa_ie_len, mdie);
+ wpa_ie_len += len;
+ }
+#ifdef CONFIG_SME
+ if (len > 0 && wpa_s->sme.ft_used &&
+ wpa_sm_has_ptk(wpa_s->wpa)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "SME: Trying to use FT over-the-air");
+ algs |= WPA_AUTH_ALG_FT;
+ }
+#endif /* CONFIG_SME */
+ }
+ }
+#endif /* CONFIG_IEEE80211R */
+
+ if (ssid->multi_ap_backhaul_sta) {
+ size_t multi_ap_ie_len;
+
+ multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
+ max_wpa_ie_len - wpa_ie_len,
+ MULTI_AP_BACKHAUL_STA);
+ if (multi_ap_ie_len == 0) {
+ wpa_printf(MSG_ERROR,
+ "Multi-AP: Failed to build Multi-AP IE");
+ os_free(wpa_ie);
+ return NULL;
+ }
+ wpa_ie_len += multi_ap_ie_len;
+ }
+
+ params->wpa_ie = wpa_ie;
+ params->wpa_ie_len = wpa_ie_len;
+ params->auth_alg = algs;
+ if (mask)
+ *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
+
+ return wpa_ie;
+}
+
+
+#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
+static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_driver_associate_params params;
+ enum wpa_drv_update_connect_params_mask mask = 0;
+ u8 *wpa_ie;
+
+ if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
+ return; /* nothing to do */
+
+ os_memset(&params, 0, sizeof(params));
+ wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
+ wpa_s->current_ssid, &params, &mask);
+ if (!wpa_ie)
+ return;
+
+ if (params.auth_alg != WPA_AUTH_ALG_FILS) {
+ os_free(wpa_ie);
+ return;
+ }
+
+ wpa_s->auth_alg = params.auth_alg;
+ wpa_drv_update_connect_params(wpa_s, &params, mask);
+ os_free(wpa_ie);
+}
+#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
+
+
+#ifdef CONFIG_MBO
+void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_driver_associate_params params;
+ u8 *wpa_ie;
+
+ /*
+ * Update MBO connect params only in case of change of MBO attributes
+ * when connected, if the AP support MBO.
+ */
+
+ if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
+ !wpa_s->current_bss ||
+ !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
+ return;
+
+ os_memset(&params, 0, sizeof(params));
+ wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
+ wpa_s->current_ssid, &params, NULL);
+ if (!wpa_ie)
+ return;
+
+ wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
+ os_free(wpa_ie);
+}
+#endif /* CONFIG_MBO */
+
+
+static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
+{
+ struct wpa_connect_work *cwork = work->ctx;
+ struct wpa_bss *bss = cwork->bss;
+ struct wpa_ssid *ssid = cwork->ssid;
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ u8 *wpa_ie;
+ int use_crypt, ret, i, bssid_changed;
+ unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
+ struct wpa_driver_associate_params params;
+ int wep_keys_set = 0;
+ int assoc_failed = 0;
+ struct wpa_ssid *old_ssid;
+ u8 prev_bssid[ETH_ALEN];
+#ifdef CONFIG_HT_OVERRIDES
+ struct ieee80211_ht_capabilities htcaps;
+ struct ieee80211_ht_capabilities htcaps_mask;
+#endif /* CONFIG_HT_OVERRIDES */
+#ifdef CONFIG_VHT_OVERRIDES
+ struct ieee80211_vht_capabilities vhtcaps;
+ struct ieee80211_vht_capabilities vhtcaps_mask;
+#endif /* CONFIG_VHT_OVERRIDES */
+
+ if (deinit) {
+ if (work->started) {
+ wpa_s->connect_work = NULL;
+
+ /* cancel possible auth. timeout */
+ eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
+ NULL);
+ }
+ wpas_connect_work_free(cwork);
+ return;
+ }
+
+ wpa_s->connect_work = work;
+
+ if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
+ wpas_network_disabled(wpa_s, ssid)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
+ wpas_connect_work_done(wpa_s);
+ return;
+ }
+
+ os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
+ os_memset(&params, 0, sizeof(params));
+ wpa_s->reassociate = 0;
+ wpa_s->eap_expected_failure = 0;
+ if (bss &&
+ (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
+#ifdef CONFIG_IEEE80211R
+ const u8 *ie, *md = NULL;
+#endif /* CONFIG_IEEE80211R */
+ wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
+ " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
+ wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
+ bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
+ os_memset(wpa_s->bssid, 0, ETH_ALEN);
+ os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
+ if (bssid_changed)
+ wpas_notify_bssid_changed(wpa_s);
+#ifdef CONFIG_IEEE80211R
+ ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
+ if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
+ md = ie + 2;
+ wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
+ if (md) {
+ /* Prepare for the next transition */
+ wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
+ }
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_WPS
+ } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
+ wpa_s->conf->ap_scan == 2 &&
+ (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
+ /* Use ap_scan==1 style network selection to find the network
+ */
+ wpas_connect_work_done(wpa_s);
+ wpa_s->scan_req = MANUAL_SCAN_REQ;
+ wpa_s->reassociate = 1;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ return;
+#endif /* CONFIG_WPS */
+ } else {
+ wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+ if (bss)
+ os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
+ else
+ os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
+ }
+ if (!wpa_s->pno)
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+
+ wpa_supplicant_cancel_scan(wpa_s);
+
+ /* Starting new association, so clear the possibly used WPA IE from the
+ * previous association. */
+ wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
+
+ wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
+ if (!wpa_ie) {
+ wpas_connect_work_done(wpa_s);
+ return;
+ }
+
wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
use_crypt = 1;
cipher_pairwise = wpa_s->pairwise_cipher;
cipher_group = wpa_s->group_cipher;
+ cipher_group_mgmt = wpa_s->mgmt_group_cipher;
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
@@ -2443,12 +3150,14 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
if (bss) {
params.ssid = bss->ssid;
params.ssid_len = bss->ssid_len;
- if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
+ if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
MACSTR " freq=%u MHz based on scan results "
- "(bssid_set=%d)",
+ "(bssid_set=%d wps=%d)",
MAC2STR(bss->bssid), bss->freq,
- ssid->bssid_set);
+ ssid->bssid_set,
+ wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
params.bssid = bss->bssid;
params.freq.freq = bss->freq;
}
@@ -2456,6 +3165,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
params.freq_hint = bss->freq;
params.pbss = bss_is_pbss(bss);
} else {
+ if (ssid->bssid_hint_set)
+ params.bssid_hint = ssid->bssid_hint;
+
params.ssid = ssid->ssid;
params.ssid_len = ssid->ssid_len;
params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
@@ -2480,13 +3192,12 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
params.beacon_int = wpa_s->conf->beacon_int;
}
- params.wpa_ie = wpa_ie;
- params.wpa_ie_len = wpa_ie_len;
params.pairwise_suite = cipher_pairwise;
params.group_suite = cipher_group;
+ params.mgmt_group_suite = cipher_group_mgmt;
params.key_mgmt_suite = wpa_s->key_mgmt;
params.wpa_proto = wpa_s->wpa_proto;
- params.auth_alg = algs;
+ wpa_s->auth_alg = params.auth_alg;
params.mode = ssid->mode;
params.bg_scan_period = ssid->bg_scan_period;
for (i = 0; i < NUM_WEP_KEYS; i++) {
@@ -2496,7 +3207,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
}
params.wep_tx_keyidx = ssid->wep_tx_keyidx;
- if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
(params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
params.passphrase = ssid->passphrase;
@@ -2504,6 +3215,13 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
params.psk = ssid->psk;
}
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
+ (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
+ params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
+ params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
+ params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
+ params.req_key_mgmt_offload = 1;
+
if (wpa_s->conf->key_mgmt_offload) {
if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
@@ -2536,6 +3254,11 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
"MFP: require MFP");
params.mgmt_frame_protection =
MGMT_FRAME_PROTECTION_REQUIRED;
+#ifdef CONFIG_OWE
+ } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
+ !ssid->owe_only) {
+ params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
+#endif /* CONFIG_OWE */
}
}
#endif /* CONFIG_IEEE80211W */
@@ -2578,6 +3301,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
if (wpas_p2p_handle_frequency_conflicts(
wpa_s, params.freq.freq, ssid) < 0) {
wpas_connect_work_done(wpa_s);
+ os_free(wpa_ie);
return;
}
}
@@ -2589,6 +3313,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
params.prev_bssid = prev_bssid;
ret = wpa_drv_associate(wpa_s, &params);
+ os_free(wpa_ie);
if (ret < 0) {
wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
"failed");
@@ -2724,14 +3449,22 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
zero_addr = 1;
}
+ if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
+ wpa_s->enabled_4addr_mode = 0;
+
#ifdef CONFIG_TDLS
wpa_tdls_teardown_peers(wpa_s->wpa);
#endif /* CONFIG_TDLS */
#ifdef CONFIG_MESH
if (wpa_s->ifmsh) {
+ struct mesh_conf *mconf;
+
+ mconf = wpa_s->ifmsh->mconf;
wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
wpa_s->ifname);
+ wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
+ mconf->meshid_len, reason_code);
wpa_supplicant_leave_mesh(wpa_s);
}
#endif /* CONFIG_MESH */
@@ -2756,6 +3489,7 @@ static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
return;
ssid->disabled = 0;
+ ssid->owe_transition_bss_select_count = 0;
wpas_clear_temp_disabled(wpa_s, ssid, 1);
wpas_notify_network_enabled_changed(wpa_s, ssid);
@@ -2921,13 +3655,19 @@ void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
wpas_notify_network_enabled_changed(
wpa_s, other_ssid);
}
- if (wpa_s->current_ssid)
+ if (wpa_s->current_ssid) {
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ }
} else if (ssid->disabled != 2) {
- if (ssid == wpa_s->current_ssid)
+ if (ssid == wpa_s->current_ssid) {
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ }
was_disabled = ssid->disabled;
@@ -3013,6 +3753,9 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
wpa_s->disconnected = 0;
wpa_s->reassociate = 1;
+ wpa_s->last_owe_group = 0;
+ if (ssid)
+ ssid->owe_transition_bss_select_count = 0;
if (wpa_s->connect_without_scan ||
wpa_supplicant_fast_associate(wpa_s) != 1) {
@@ -3230,6 +3973,41 @@ int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
}
+#ifdef CONFIG_OWE
+static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const u8 *entry_ssid, size_t entry_ssid_len)
+{
+ const u8 *owe, *pos, *end;
+ u8 ssid_len;
+ struct wpa_bss *bss;
+
+ /* Check network profile SSID aganst the SSID in the
+ * OWE Transition Mode element. */
+
+ bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
+ if (!bss)
+ return 0;
+
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+ if (!owe)
+ return 0;
+
+ pos = owe + 6;
+ end = owe + 2 + owe[1];
+
+ if (end - pos < ETH_ALEN + 1)
+ return 0;
+ pos += ETH_ALEN;
+ ssid_len = *pos++;
+ if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
+ return 0;
+
+ return entry_ssid_len == ssid_len &&
+ os_memcmp(pos, entry_ssid, ssid_len) == 0;
+}
+#endif /* CONFIG_OWE */
+
+
/**
* wpa_supplicant_get_ssid - Get a pointer to the current network structure
* @wpa_s: Pointer to wpa_supplicant data
@@ -3265,7 +4043,9 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
while (entry) {
if (!wpas_network_disabled(wpa_s, entry) &&
((ssid_len == entry->ssid_len &&
- os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
+ (!entry->ssid ||
+ os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
+ wired) &&
(!entry->bssid_set ||
os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
return entry;
@@ -3278,6 +4058,15 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
return entry;
#endif /* CONFIG_WPS */
+#ifdef CONFIG_OWE
+ if (!wpas_network_disabled(wpa_s, entry) &&
+ owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
+ entry->ssid_len) &&
+ (!entry->bssid_set ||
+ os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
+ return entry;
+#endif /* CONFIG_OWE */
+
if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
entry->ssid_len == 0 &&
os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
@@ -3385,16 +4174,6 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
}
#endif /* CONFIG_TESTING_OPTIONS */
-#ifdef CONFIG_PEERKEY
- if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
- wpa_s->current_ssid->peerkey &&
- !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
- wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
- wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
- return;
- }
-#endif /* CONFIG_PEERKEY */
-
if (wpa_s->wpa_state < WPA_ASSOCIATED ||
(wpa_s->last_eapol_matches_bssid &&
#ifdef CONFIG_AP
@@ -3444,7 +4223,7 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
}
if (wpa_s->eapol_received == 0 &&
- (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
+ (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
wpa_s->wpa_state != WPA_COMPLETED) &&
(wpa_s->current_ssid == NULL ||
@@ -3505,10 +4284,12 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
+ wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
+ wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
return;
wpa_drv_poll(wpa_s);
- if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
+ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
/*
@@ -3534,6 +4315,11 @@ int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
wpa_supplicant_rx_eapol, wpa_s, 0);
if (wpa_s->l2 == NULL)
return -1;
+
+ if (l2_packet_set_packet_filter(wpa_s->l2,
+ L2_PACKET_FILTER_PKTTYPE))
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Failed to attach pkt_type filter");
} else {
const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
if (addr)
@@ -3673,6 +4459,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent)
wpa_s->sched_scanning = 0;
dl_list_init(&wpa_s->bss_tmp_disallowed);
+ dl_list_init(&wpa_s->fils_hlp_req);
return wpa_s;
}
@@ -3700,8 +4487,11 @@ static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
+ long v;
+
errno = 0;
- long v = strtol(tmp, &end, 16);
+ v = strtol(tmp, &end, 16);
+
if (errno == 0) {
wpa_msg(wpa_s, MSG_DEBUG,
"htcap value[%i]: %ld end: %p tmp: %p",
@@ -3741,11 +4531,11 @@ static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
{
le16 msk;
- wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
-
if (disabled == -1)
return 0;
+ wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
+
msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
htcaps_mask->ht_capabilities_info |= msk;
if (disabled)
@@ -3762,11 +4552,11 @@ static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
struct ieee80211_ht_capabilities *htcaps_mask,
int factor)
{
- wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
-
if (factor == -1)
return 0;
+ wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
+
if (factor < 0 || factor > 3) {
wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
"Must be 0-3 or -1", factor);
@@ -3786,11 +4576,11 @@ static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
struct ieee80211_ht_capabilities *htcaps_mask,
int density)
{
- wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
-
if (density == -1)
return 0;
+ wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
+
if (density < 0 || density > 7) {
wpa_msg(wpa_s, MSG_ERROR,
"ampdu_density: %d out of range. Must be 0-7 or -1.",
@@ -3811,18 +4601,11 @@ static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
struct ieee80211_ht_capabilities *htcaps_mask,
int disabled)
{
- /* Masking these out disables HT40 */
- le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
- HT_CAP_INFO_SHORT_GI40MHZ);
-
- wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
-
if (disabled)
- htcaps->ht_capabilities_info &= ~msk;
- else
- htcaps->ht_capabilities_info |= msk;
+ wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
- htcaps_mask->ht_capabilities_info |= msk;
+ set_disable_ht40(htcaps, disabled);
+ set_disable_ht40(htcaps_mask, 0);
return 0;
}
@@ -3837,7 +4620,8 @@ static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
HT_CAP_INFO_SHORT_GI40MHZ);
- wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
+ if (disabled)
+ wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
if (disabled)
htcaps->ht_capabilities_info &= ~msk;
@@ -3858,7 +4642,8 @@ static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
/* Masking these out disables LDPC */
le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
- wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
+ if (disabled)
+ wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
if (disabled)
htcaps->ht_capabilities_info &= ~msk;
@@ -3871,6 +4656,58 @@ static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
}
+static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
+ struct ieee80211_ht_capabilities *htcaps,
+ struct ieee80211_ht_capabilities *htcaps_mask,
+ int tx_stbc)
+{
+ le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
+
+ if (tx_stbc == -1)
+ return 0;
+
+ wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
+
+ if (tx_stbc < 0 || tx_stbc > 1) {
+ wpa_msg(wpa_s, MSG_ERROR,
+ "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
+ return -EINVAL;
+ }
+
+ htcaps_mask->ht_capabilities_info |= msk;
+ htcaps->ht_capabilities_info &= ~msk;
+ htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
+
+ return 0;
+}
+
+
+static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
+ struct ieee80211_ht_capabilities *htcaps,
+ struct ieee80211_ht_capabilities *htcaps_mask,
+ int rx_stbc)
+{
+ le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
+
+ if (rx_stbc == -1)
+ return 0;
+
+ wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
+
+ if (rx_stbc < 0 || rx_stbc > 3) {
+ wpa_msg(wpa_s, MSG_ERROR,
+ "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
+ return -EINVAL;
+ }
+
+ htcaps_mask->ht_capabilities_info |= msk;
+ htcaps->ht_capabilities_info &= ~msk;
+ htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
+
+ return 0;
+}
+
+
void wpa_supplicant_apply_ht_overrides(
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
struct wpa_driver_associate_params *params)
@@ -3895,6 +4732,8 @@ void wpa_supplicant_apply_ht_overrides(
wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
+ wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
+ wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
if (ssid->ht40_intolerant) {
le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
@@ -3929,6 +4768,16 @@ void wpa_supplicant_apply_vht_overrides(
vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
#ifdef CONFIG_HT_OVERRIDES
+ if (ssid->disable_sgi) {
+ vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
+ VHT_CAP_SHORT_GI_160);
+ vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
+ VHT_CAP_SHORT_GI_160);
+ wpa_msg(wpa_s, MSG_DEBUG,
+ "disable-sgi override specified, vht-caps: 0x%x",
+ vhtcaps->vht_capabilities_info);
+ }
+
/* if max ampdu is <= 3, we have to make the HT cap the same */
if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
int max_ampdu;
@@ -4098,10 +4947,14 @@ static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
{
struct wpa_supplicant *wpa_s = ctx;
- WPA_ASSERT(os_memcmp(wpa_s->bssid, da, ETH_ALEN) == 0);
+ if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
+ wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
+ __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
+ return -1;
+ }
return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
- wpa_s->own_addr, wpa_s->bssid,
- wpabuf_head(data), wpabuf_len(data),
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head(data), wpabuf_len(data),
0);
}
@@ -4289,7 +5142,7 @@ static void radio_work_free(struct wpa_radio_work *work)
if (work->started) {
work->wpa_s->radio->num_active_works--;
wpa_dbg(work->wpa_s, MSG_DEBUG,
- "radio_work_free('%s'@%p: num_active_works --> %u",
+ "radio_work_free('%s'@%p): num_active_works --> %u",
work->type, work,
work->wpa_s->radio->num_active_works);
}
@@ -4299,6 +5152,20 @@ static void radio_work_free(struct wpa_radio_work *work)
}
+static int radio_work_is_connect(struct wpa_radio_work *work)
+{
+ return os_strcmp(work->type, "sme-connect") == 0 ||
+ os_strcmp(work->type, "connect") == 0;
+}
+
+
+static int radio_work_is_scan(struct wpa_radio_work *work)
+{
+ return os_strcmp(work->type, "scan") == 0 ||
+ os_strcmp(work->type, "p2p-scan") == 0;
+}
+
+
static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
{
struct wpa_radio_work *active_work = NULL;
@@ -4328,8 +5195,7 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
return NULL;
}
- if (os_strcmp(active_work->type, "sme-connect") == 0 ||
- os_strcmp(active_work->type, "connect") == 0) {
+ if (radio_work_is_connect(active_work)) {
/*
* If the active work is either connect or sme-connect,
* do not parallelize them with other radio works.
@@ -4348,10 +5214,20 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
* If connect or sme-connect are enqueued, parallelize only
* those operations ahead of them in the queue.
*/
- if (os_strcmp(tmp->type, "connect") == 0 ||
- os_strcmp(tmp->type, "sme-connect") == 0)
+ if (radio_work_is_connect(tmp))
break;
+ /* Serialize parallel scan and p2p_scan operations on the same
+ * interface since the driver_nl80211 mechanism for tracking
+ * scan cookies does not yet have support for this. */
+ if (active_work->wpa_s == tmp->wpa_s &&
+ radio_work_is_scan(active_work) &&
+ radio_work_is_scan(tmp)) {
+ wpa_dbg(active_work->wpa_s, MSG_DEBUG,
+ "Do not start work '%s' when another work '%s' is already scheduled",
+ tmp->type, active_work->type);
+ continue;
+ }
/*
* Check that the radio works are distinct and
* on different bands.
@@ -4473,6 +5349,22 @@ void radio_remove_works(struct wpa_supplicant *wpa_s,
}
+void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
+{
+ struct wpa_radio_work *work;
+ struct wpa_radio *radio = wpa_s->radio;
+
+ dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
+ if (work->ctx != ctx)
+ continue;
+ wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
+ work->type, work, work->started ? " (started)" : "");
+ radio_work_free(work);
+ break;
+ }
+}
+
+
static void radio_remove_interface(struct wpa_supplicant *wpa_s)
{
struct wpa_radio *radio = wpa_s->radio;
@@ -4625,7 +5517,7 @@ radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
static int wpas_init_driver(struct wpa_supplicant *wpa_s,
- struct wpa_interface *iface)
+ const struct wpa_interface *iface)
{
const char *ifname, *driver, *rn;
@@ -4673,11 +5565,47 @@ next_driver:
}
+#ifdef CONFIG_GAS_SERVER
+
+static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
+ unsigned int freq, const u8 *dst,
+ const u8 *src, const u8 *bssid,
+ const u8 *data, size_t data_len,
+ enum offchannel_send_action_result result)
+{
+ wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
+ " result=%s",
+ freq, MAC2STR(dst),
+ result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
+ (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
+ "FAILED"));
+ gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
+ result == OFFCHANNEL_SEND_ACTION_SUCCESS);
+}
+
+
+static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
+ struct wpabuf *buf, unsigned int wait_time)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ if (wait_time > wpa_s->max_remain_on_chan)
+ wait_time = wpa_s->max_remain_on_chan;
+
+ offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
+ wpabuf_head(buf), wpabuf_len(buf),
+ wait_time, wpas_gas_server_tx_status, 0);
+}
+
+#endif /* CONFIG_GAS_SERVER */
+
static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
- struct wpa_interface *iface)
+ const struct wpa_interface *iface)
{
struct wpa_driver_capa capa;
int capa_res;
+ u8 dfs_domain;
wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
"'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
@@ -4707,7 +5635,13 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
return -1;
}
wpa_s->confanother = os_rel2abs_path(iface->confanother);
- wpa_config_read(wpa_s->confanother, wpa_s->conf);
+ if (wpa_s->confanother &&
+ !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
+ wpa_printf(MSG_ERROR,
+ "Failed to read or parse configuration '%s'.",
+ wpa_s->confanother);
+ return -1;
+ }
/*
* Override ctrl_interface and driver_param if set on command
@@ -4805,7 +5739,8 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
&wpa_s->hw.num_modes,
- &wpa_s->hw.flags);
+ &wpa_s->hw.flags,
+ &dfs_domain);
if (wpa_s->hw.modes) {
u16 i;
@@ -4856,6 +5791,12 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
capa.mac_addr_rand_sched_scan_supported)
wpa_s->mac_addr_rand_supported |=
(MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
+
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
+ if (wpa_s->extended_capa &&
+ wpa_s->extended_capa_len >= 3 &&
+ wpa_s->extended_capa[2] & 0x40)
+ wpa_s->multi_bss_support = 1;
}
if (wpa_s->max_remain_on_chan == 0)
wpa_s->max_remain_on_chan = 1000;
@@ -4867,8 +5808,6 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
*/
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
wpa_s->p2p_mgmt = iface->p2p_mgmt;
- else
- iface->p2p_mgmt = 1;
if (wpa_s->num_multichan_concurrent == 0)
wpa_s->num_multichan_concurrent = 1;
@@ -4877,10 +5816,7 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
return -1;
#ifdef CONFIG_TDLS
- if ((!iface->p2p_mgmt ||
- !(wpa_s->drv_flags &
- WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
- wpa_tdls_init(wpa_s->wpa))
+ if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
return -1;
#endif /* CONFIG_TDLS */
@@ -4915,6 +5851,19 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
if (wpas_wps_init(wpa_s))
return -1;
+#ifdef CONFIG_GAS_SERVER
+ wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
+ if (!wpa_s->gas_server) {
+ wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
+ return -1;
+ }
+#endif /* CONFIG_GAS_SERVER */
+
+#ifdef CONFIG_DPP
+ if (wpas_dpp_init(wpa_s) < 0)
+ return -1;
+#endif /* CONFIG_DPP */
+
if (wpa_supplicant_init_eapol(wpa_s) < 0)
return -1;
wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
@@ -4939,7 +5888,9 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
return -1;
}
- if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
+ if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
+ wpa_s->p2p_mgmt) &&
+ wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
return -1;
}
@@ -4947,6 +5898,12 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
if (wpa_bss_init(wpa_s) < 0)
return -1;
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+#ifdef CONFIG_MESH
+ dl_list_init(&wpa_s->mesh_external_pmksa_cache);
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
/*
* Set Wake-on-WLAN triggers, if configured.
* Note: We don't restore/remove the triggers on shutdown (it doesn't
@@ -4958,8 +5915,8 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_EAP_PROXY
{
size_t len;
- wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
- &len);
+ wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
+ wpa_s->imsi, &len);
if (wpa_s->mnc_len > 0) {
wpa_s->imsi[len] = '\0';
wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
@@ -4984,6 +5941,17 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
hs20_init(wpa_s);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
+ if (wpa_s->conf->oce) {
+ if ((wpa_s->conf->oce & OCE_STA) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
+ wpa_s->enable_oce = OCE_STA;
+ if ((wpa_s->conf->oce & OCE_STA_CFON) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
+ /* TODO: Need to add STA-CFON support */
+ wpa_printf(MSG_ERROR,
+ "OCE STA-CFON feature is not yet supported");
+ }
+ }
wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
#endif /* CONFIG_MBO */
@@ -5248,6 +6216,7 @@ int wpa_supplicant_remove_iface(struct wpa_global *global,
#ifdef CONFIG_MESH
unsigned int mesh_if_created = wpa_s->mesh_if_created;
char *ifname = NULL;
+ struct wpa_supplicant *parent = wpa_s->parent;
#endif /* CONFIG_MESH */
/* Remove interface from the global list of interfaces */
@@ -5283,7 +6252,7 @@ int wpa_supplicant_remove_iface(struct wpa_global *global,
#ifdef CONFIG_MESH
if (mesh_if_created) {
- wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
+ wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
os_free(ifname);
}
#endif /* CONFIG_MESH */
@@ -5647,6 +6616,16 @@ void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
+ if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
+ struct wpa_driver_capa capa;
+ int res = wpa_drv_get_capa(wpa_s, &capa);
+
+ if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
+ wpa_printf(MSG_ERROR,
+ "Failed to update wowlan_triggers to '%s'",
+ wpa_s->conf->wowlan_triggers);
+ }
+
#ifdef CONFIG_WPS
wpas_wps_update_config(wpa_s);
#endif /* CONFIG_WPS */
@@ -5801,11 +6780,43 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
* TODO: if more than one possible AP is available in scan results,
* could try the other ones before requesting a new scan.
*/
+
+ /* speed up the connection attempt with normal scan */
+ wpa_s->normal_scans = 0;
wpa_supplicant_req_scan(wpa_s, timeout / 1000,
1000 * (timeout % 1000));
}
+#ifdef CONFIG_FILS
+void fils_connection_failure(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ const u8 *realm, *username, *rrk;
+ size_t realm_len, username_len, rrk_len;
+ u16 next_seq_num;
+
+ if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
+ eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
+ &username, &username_len,
+ &realm, &realm_len, &next_seq_num,
+ &rrk, &rrk_len) != 0 ||
+ !realm)
+ return;
+
+ wpa_hexdump_ascii(MSG_DEBUG,
+ "FILS: Store last connection failure realm",
+ realm, realm_len);
+ os_free(wpa_s->last_con_fail_realm);
+ wpa_s->last_con_fail_realm = os_malloc(realm_len);
+ if (wpa_s->last_con_fail_realm) {
+ wpa_s->last_con_fail_realm_len = realm_len;
+ os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
+ }
+}
+#endif /* CONFIG_FILS */
+
+
int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
{
return wpa_s->conf->ap_scan == 2 ||
@@ -5876,6 +6887,7 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
case WPA_CTRL_REQ_SIM:
str_clear_free(eap->external_sim_resp);
eap->external_sim_resp = os_strdup(value);
+ eap->pending_req_sim = 0;
break;
case WPA_CTRL_REQ_PSK_PASSPHRASE:
if (wpa_config_set(ssid, "psk", value, 0) < 0)
@@ -5944,6 +6956,7 @@ int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
(!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
+ !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
!ssid->mem_only_psk)
return 1;
@@ -6128,6 +7141,7 @@ void wpas_request_connection(struct wpa_supplicant *wpa_s)
wpa_s->extra_blacklist_count = 0;
wpa_s->disconnected = 0;
wpa_s->reassociate = 1;
+ wpa_s->last_owe_group = 0;
if (wpa_supplicant_fast_associate(wpa_s) != 1)
wpa_supplicant_req_scan(wpa_s, 0, 0);
@@ -6154,6 +7168,8 @@ void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
wpa_supplicant_cancel_scan(wpa_s);
wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+ radio_remove_works(wpa_s, "connect", 0);
+ radio_remove_works(wpa_s, "sme-connect", 0);
}
@@ -6254,489 +7270,6 @@ int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
}
-static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
-{
- struct rrm_data *rrm = data;
-
- if (!rrm->notify_neighbor_rep) {
- wpa_printf(MSG_ERROR,
- "RRM: Unexpected neighbor report timeout");
- return;
- }
-
- wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
- rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
-
- rrm->notify_neighbor_rep = NULL;
- rrm->neighbor_rep_cb_ctx = NULL;
-}
-
-
-/*
- * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
- * @wpa_s: Pointer to wpa_supplicant
- */
-void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
-{
- wpa_s->rrm.rrm_used = 0;
-
- eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
- NULL);
- if (wpa_s->rrm.notify_neighbor_rep)
- wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
- wpa_s->rrm.next_neighbor_rep_token = 1;
-}
-
-
-/*
- * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
- * @wpa_s: Pointer to wpa_supplicant
- * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
- * @report_len: Length of neighbor report buffer
- */
-void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
- const u8 *report, size_t report_len)
-{
- struct wpabuf *neighbor_rep;
-
- wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
- if (report_len < 1)
- return;
-
- if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
- wpa_printf(MSG_DEBUG,
- "RRM: Discarding neighbor report with token %d (expected %d)",
- report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
- return;
- }
-
- eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
- NULL);
-
- if (!wpa_s->rrm.notify_neighbor_rep) {
- wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
- return;
- }
-
- /* skipping the first byte, which is only an id (dialog token) */
- neighbor_rep = wpabuf_alloc(report_len - 1);
- if (neighbor_rep == NULL)
- return;
- wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
- wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
- report[0]);
- wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
- neighbor_rep);
- wpa_s->rrm.notify_neighbor_rep = NULL;
- wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
-}
-
-
-#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
-/* Workaround different, undefined for Windows, error codes used here */
-#define ENOTCONN -1
-#define EOPNOTSUPP -1
-#define ECANCELED -1
-#endif
-
-/* Measurement Request element + Location Subject + Maximum Age subelement */
-#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
-/* Measurement Request element + Location Civic Request */
-#define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
-
-
-/**
- * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
- * @wpa_s: Pointer to wpa_supplicant
- * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
- * is sent in the request.
- * @lci: if set, neighbor request will include LCI request
- * @civic: if set, neighbor request will include civic location request
- * @cb: Callback function to be called once the requested report arrives, or
- * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
- * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
- * the requester's responsibility to free it.
- * In the latter case NULL will be sent in 'neighbor_rep'.
- * @cb_ctx: Context value to send the callback function
- * Returns: 0 in case of success, negative error code otherwise
- *
- * In case there is a previous request which has not been answered yet, the
- * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
- * Request must contain a callback function.
- */
-int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
- const struct wpa_ssid_value *ssid,
- int lci, int civic,
- void (*cb)(void *ctx,
- struct wpabuf *neighbor_rep),
- void *cb_ctx)
-{
- struct wpabuf *buf;
- const u8 *rrm_ie;
-
- if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
- wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
- return -ENOTCONN;
- }
-
- if (!wpa_s->rrm.rrm_used) {
- wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
- return -EOPNOTSUPP;
- }
-
- rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
- WLAN_EID_RRM_ENABLED_CAPABILITIES);
- if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
- !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
- wpa_printf(MSG_DEBUG,
- "RRM: No network support for Neighbor Report.");
- return -EOPNOTSUPP;
- }
-
- if (!cb) {
- wpa_printf(MSG_DEBUG,
- "RRM: Neighbor Report request must provide a callback.");
- return -EINVAL;
- }
-
- /* Refuse if there's a live request */
- if (wpa_s->rrm.notify_neighbor_rep) {
- wpa_printf(MSG_DEBUG,
- "RRM: Currently handling previous Neighbor Report.");
- return -EBUSY;
- }
-
- /* 3 = action category + action code + dialog token */
- buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) +
- (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
- (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
- if (buf == NULL) {
- wpa_printf(MSG_DEBUG,
- "RRM: Failed to allocate Neighbor Report Request");
- return -ENOMEM;
- }
-
- wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
- (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
- wpa_s->rrm.next_neighbor_rep_token);
-
- wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
- wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
- wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
- if (ssid) {
- wpabuf_put_u8(buf, WLAN_EID_SSID);
- wpabuf_put_u8(buf, ssid->ssid_len);
- wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
- }
-
- if (lci) {
- /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
- wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
- wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
-
- /*
- * Measurement token; nonzero number that is unique among the
- * Measurement Request elements in a particular frame.
- */
- wpabuf_put_u8(buf, 1); /* Measurement Token */
-
- /*
- * Parallel, Enable, Request, and Report bits are 0, Duration is
- * reserved.
- */
- wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
- wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
-
- /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
- /* Location Subject */
- wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
-
- /* Optional Subelements */
- /*
- * IEEE P802.11-REVmc/D5.0 Figure 9-170
- * The Maximum Age subelement is required, otherwise the AP can
- * send only data that was determined after receiving the
- * request. Setting it here to unlimited age.
- */
- wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
- wpabuf_put_u8(buf, 2);
- wpabuf_put_le16(buf, 0xffff);
- }
-
- if (civic) {
- /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
- wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
- wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
-
- /*
- * Measurement token; nonzero number that is unique among the
- * Measurement Request elements in a particular frame.
- */
- wpabuf_put_u8(buf, 2); /* Measurement Token */
-
- /*
- * Parallel, Enable, Request, and Report bits are 0, Duration is
- * reserved.
- */
- wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
- /* Measurement Type */
- wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
-
- /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
- * Location Civic request */
- /* Location Subject */
- wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
- wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
- /* Location Service Interval Units: Seconds */
- wpabuf_put_u8(buf, 0);
- /* Location Service Interval: 0 - Only one report is requested
- */
- wpabuf_put_le16(buf, 0);
- /* No optional subelements */
- }
-
- wpa_s->rrm.next_neighbor_rep_token++;
-
- if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
- wpa_s->own_addr, wpa_s->bssid,
- wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
- wpa_printf(MSG_DEBUG,
- "RRM: Failed to send Neighbor Report Request");
- wpabuf_free(buf);
- return -ECANCELED;
- }
-
- wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
- wpa_s->rrm.notify_neighbor_rep = cb;
- eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
- wpas_rrm_neighbor_rep_timeout_handler,
- &wpa_s->rrm, NULL);
-
- wpabuf_free(buf);
- return 0;
-}
-
-
-static struct wpabuf * wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s,
- const u8 *request, size_t len,
- struct wpabuf *report)
-{
- u8 token, type, subject;
- u16 max_age = 0;
- struct os_reltime t, diff;
- unsigned long diff_l;
- u8 *ptoken;
- const u8 *subelem;
-
- if (!wpa_s->lci || len < 3 + 4)
- return report;
-
- token = *request++;
- /* Measurement request mode isn't used */
- request++;
- type = *request++;
- subject = *request++;
-
- wpa_printf(MSG_DEBUG,
- "Measurement request token %u type %u location subject %u",
- token, type, subject);
-
- if (type != MEASURE_TYPE_LCI || subject != LOCATION_SUBJECT_REMOTE) {
- wpa_printf(MSG_INFO,
- "Not building LCI report - bad type or location subject");
- return report;
- }
-
- /* Subelements are formatted exactly like elements */
- subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE);
- if (subelem && subelem[1] == 2)
- max_age = WPA_GET_LE16(subelem + 2);
-
- if (os_get_reltime(&t))
- return report;
-
- os_reltime_sub(&t, &wpa_s->lci_time, &diff);
- /* LCI age is calculated in 10th of a second units. */
- diff_l = diff.sec * 10 + diff.usec / 100000;
-
- if (max_age != 0xffff && max_age < diff_l)
- return report;
-
- if (wpabuf_resize(&report, 2 + wpabuf_len(wpa_s->lci)))
- return report;
-
- wpabuf_put_u8(report, WLAN_EID_MEASURE_REPORT);
- wpabuf_put_u8(report, wpabuf_len(wpa_s->lci));
- /* We'll override user's measurement token */
- ptoken = wpabuf_put(report, 0);
- wpabuf_put_buf(report, wpa_s->lci);
- *ptoken = token;
-
- return report;
-}
-
-
-void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
- const u8 *src,
- const u8 *frame, size_t len)
-{
- struct wpabuf *buf, *report;
- u8 token;
- const u8 *ie, *end;
-
- if (wpa_s->wpa_state != WPA_COMPLETED) {
- wpa_printf(MSG_INFO,
- "RRM: Ignoring radio measurement request: Not associated");
- return;
- }
-
- if (!wpa_s->rrm.rrm_used) {
- wpa_printf(MSG_INFO,
- "RRM: Ignoring radio measurement request: Not RRM network");
- return;
- }
-
- if (len < 3) {
- wpa_printf(MSG_INFO,
- "RRM: Ignoring too short radio measurement request");
- return;
- }
-
- end = frame + len;
-
- token = *frame++;
-
- /* Ignore number of repetitions because it's not used in LCI request */
- frame += 2;
-
- report = NULL;
- while ((ie = get_ie(frame, end - frame, WLAN_EID_MEASURE_REQUEST)) &&
- ie[1] >= 3) {
- u8 msmt_type;
-
- msmt_type = ie[4];
- wpa_printf(MSG_DEBUG, "RRM request %d", msmt_type);
-
- switch (msmt_type) {
- case MEASURE_TYPE_LCI:
- report = wpas_rrm_build_lci_report(wpa_s, ie + 2, ie[1],
- report);
- break;
- default:
- wpa_printf(MSG_INFO,
- "RRM: Unsupported radio measurement request %d",
- msmt_type);
- break;
- }
-
- frame = ie + ie[1] + 2;
- }
-
- if (!report)
- return;
-
- buf = wpabuf_alloc(3 + wpabuf_len(report));
- if (!buf) {
- wpabuf_free(report);
- return;
- }
-
- wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
- wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
- wpabuf_put_u8(buf, token);
-
- wpabuf_put_buf(buf, report);
- wpabuf_free(report);
-
- if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
- wpa_s->own_addr, wpa_s->bssid,
- wpabuf_head(buf), wpabuf_len(buf), 0)) {
- wpa_printf(MSG_ERROR,
- "RRM: Radio measurement report failed: Sending Action frame failed");
- }
- wpabuf_free(buf);
-}
-
-
-void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
- const u8 *src,
- const u8 *frame, size_t len,
- int rssi)
-{
- struct wpabuf *buf;
- const struct rrm_link_measurement_request *req;
- struct rrm_link_measurement_report report;
-
- if (wpa_s->wpa_state != WPA_COMPLETED) {
- wpa_printf(MSG_INFO,
- "RRM: Ignoring link measurement request. Not associated");
- return;
- }
-
- if (!wpa_s->rrm.rrm_used) {
- wpa_printf(MSG_INFO,
- "RRM: Ignoring link measurement request. Not RRM network");
- return;
- }
-
- if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
- wpa_printf(MSG_INFO,
- "RRM: Measurement report failed. TX power insertion not supported");
- return;
- }
-
- req = (const struct rrm_link_measurement_request *) frame;
- if (len < sizeof(*req)) {
- wpa_printf(MSG_INFO,
- "RRM: Link measurement report failed. Request too short");
- return;
- }
-
- os_memset(&report, 0, sizeof(report));
- report.tpc.eid = WLAN_EID_TPC_REPORT;
- report.tpc.len = 2;
- report.rsni = 255; /* 255 indicates that RSNI is not available */
- report.dialog_token = req->dialog_token;
-
- /*
- * It's possible to estimate RCPI based on RSSI in dBm. This
- * calculation will not reflect the correct value for high rates,
- * but it's good enough for Action frames which are transmitted
- * with up to 24 Mbps rates.
- */
- if (!rssi)
- report.rcpi = 255; /* not available */
- else if (rssi < -110)
- report.rcpi = 0;
- else if (rssi > 0)
- report.rcpi = 220;
- else
- report.rcpi = (rssi + 110) * 2;
-
- /* action_category + action_code */
- buf = wpabuf_alloc(2 + sizeof(report));
- if (buf == NULL) {
- wpa_printf(MSG_ERROR,
- "RRM: Link measurement report failed. Buffer allocation failed");
- return;
- }
-
- wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
- wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
- wpabuf_put_data(buf, &report, sizeof(report));
- wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
- wpabuf_head(buf), wpabuf_len(buf));
-
- if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
- wpa_s->own_addr, wpa_s->bssid,
- wpabuf_head(buf), wpabuf_len(buf), 0)) {
- wpa_printf(MSG_ERROR,
- "RRM: Link measurement report failed. Send action failed");
- }
- wpabuf_free(buf);
-}
-
-
struct wpa_supplicant *
wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
{
@@ -6850,19 +7383,55 @@ wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
}
+static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_bss_tmp_disallowed *tmp;
+ unsigned int num_bssid = 0;
+ u8 *bssids;
+ int ret;
+
+ bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
+ if (!bssids)
+ return -1;
+ dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
+ ETH_ALEN);
+ num_bssid++;
+ }
+ ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
+ os_free(bssids);
+ return ret;
+}
+
+
+static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
+
+ /* Make sure the bss is not already freed */
+ dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ if (bss == tmp) {
+ dl_list_del(&tmp->list);
+ os_free(tmp);
+ wpa_set_driver_tmp_disallow_list(wpa_s);
+ break;
+ }
+ }
+}
+
+
void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
- unsigned int sec)
+ unsigned int sec, int rssi_threshold)
{
struct wpa_bss_tmp_disallowed *bss;
- struct os_reltime until;
-
- os_get_reltime(&until);
- until.sec += sec;
bss = wpas_get_disallowed_bss(wpa_s, bssid);
if (bss) {
- bss->disallowed_until = until;
- return;
+ eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
+ goto finish;
}
bss = os_malloc(sizeof(*bss));
@@ -6872,38 +7441,35 @@ void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
return;
}
- bss->disallowed_until = until;
os_memcpy(bss->bssid, bssid, ETH_ALEN);
dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
+ wpa_set_driver_tmp_disallow_list(wpa_s);
+
+finish:
+ bss->rssi_threshold = rssi_threshold;
+ eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
+ wpa_s, bss);
}
-int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
+int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss)
{
- struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
- struct os_reltime now, age;
-
- os_get_reltime(&now);
+ struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
struct wpa_bss_tmp_disallowed, list) {
- if (!os_reltime_before(&now, &tmp->disallowed_until)) {
- /* This BSS is not disallowed anymore */
- dl_list_del(&tmp->list);
- os_free(tmp);
- continue;
- }
- if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
- bss = tmp;
+ if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
+ disallowed = tmp;
break;
}
}
- if (!bss)
+ if (!disallowed)
+ return 0;
+
+ if (disallowed->rssi_threshold != 0 &&
+ bss->level > disallowed->rssi_threshold)
return 0;
- os_reltime_sub(&bss->disallowed_until, &now, &age);
- wpa_printf(MSG_DEBUG,
- "BSS " MACSTR " disabled for %ld.%0ld seconds",
- MAC2STR(bss->bssid), age.sec, age.usec);
return 1;
}
diff --git a/contrib/wpa/wpa_supplicant/wpa_supplicant.conf b/contrib/wpa/wpa_supplicant/wpa_supplicant.conf
index b2e49d8ae325..f5c2cfcdb63c 100644
--- a/contrib/wpa/wpa_supplicant/wpa_supplicant.conf
+++ b/contrib/wpa/wpa_supplicant/wpa_supplicant.conf
@@ -87,9 +87,7 @@ eapol_version=1
# parameters (e.g., WPA IE generation); this mode can also be used with
# non-WPA drivers when using IEEE 802.1X mode; do not try to associate with
# APs (i.e., external program needs to control association). This mode must
-# also be used when using wired Ethernet drivers.
-# Note: macsec_qca driver is one type of Ethernet driver which implements
-# macsec feature.
+# also be used when using wired Ethernet drivers (including MACsec).
# 2: like 0, but associate with APs using security policy and SSID (but not
# BSSID); this can be used, e.g., with ndiswrapper and NDIS drivers to
# enable operation with hidden SSIDs and optimized roaming; in this mode,
@@ -173,13 +171,13 @@ fast_reauth=1
# OpenSSL cipher string
#
# This is an OpenSSL specific configuration option for configuring the default
-# ciphers. If not set, "DEFAULT:!EXP:!LOW" is used as the default.
+# ciphers. If not set, the value configured at build time ("DEFAULT:!EXP:!LOW"
+# by default) is used.
# See https://www.openssl.org/docs/apps/ciphers.html for OpenSSL documentation
# on cipher suite configuration. This is applicable only if wpa_supplicant is
# built to use OpenSSL.
#openssl_ciphers=DEFAULT:!EXP:!LOW
-
# Dynamic EAP methods
# If EAP methods were built dynamically as shared object files, they need to be
# loaded here before being used in the network blocks. By default, EAP methods
@@ -208,9 +206,15 @@ fast_reauth=1
# Wi-Fi Protected Setup (WPS) parameters
# Universally Unique IDentifier (UUID; see RFC 4122) of the device
-# If not configured, UUID will be generated based on the local MAC address.
+# If not configured, UUID will be generated based on the mechanism selected with
+# the auto_uuid parameter.
#uuid=12345678-9abc-def0-1234-56789abcdef0
+# Automatic UUID behavior
+# 0 = generate static value based on the local MAC address (default)
+# 1 = generate a random UUID every time wpa_supplicant starts
+#auto_uuid=0
+
# Device Name
# User-friendly description of device; up to 32 octets encoded in UTF-8
#device_name=Wireless Client
@@ -266,6 +270,14 @@ fast_reauth=1
# to external program(s)
#wps_cred_processing=0
+# Whether to enable SAE (WPA3-Personal transition mode) automatically for
+# WPA2-PSK credentials received using WPS.
+# 0 = only add the explicitly listed WPA2-PSK configuration (default)
+# 1 = add both the WPA2-PSK and SAE configuration and enable PMF so that the
+# station gets configured in WPA3-Personal transition mode (supports both
+# WPA2-Personal (PSK) and WPA3-Personal (SAE) APs).
+#wps_cred_add_sae=0
+
# Vendor attribute in WPS M1, e.g., Windows 7 Vertical Pairing
# The vendor attribute contents to be added in M1 (hex string)
#wps_vendor_ext_m1=000137100100020001
@@ -294,6 +306,15 @@ fast_reauth=1
# of APs when using ap_scan=1 mode.
#bss_max_count=200
+# BSS expiration age in seconds. A BSS will be removed from the local cache
+# if it is not in use and has not been seen for this time. Default is 180.
+#bss_expiration_age=180
+
+# BSS expiration after number of scans. A BSS will be removed from the local
+# cache if it is not seen in this number of scans.
+# Default is 2.
+#bss_expiration_scan_count=2
+
# Automatic scan
# This is an optional set of parameters for automatic scanning
# within an interface in following format:
@@ -361,11 +382,16 @@ fast_reauth=1
# Enabled SAE finite cyclic groups in preference order
# By default (if this parameter is not set), the mandatory group 19 (ECC group
-# defined over a 256-bit prime order field) is preferred, but other groups are
-# also enabled. If this parameter is set, the groups will be tried in the
-# indicated order. The group values are listed in the IANA registry:
+# defined over a 256-bit prime order field, NIST P-256) is preferred and groups
+# 20 (NIST P-384) and 21 (NIST P-521) are also enabled. If this parameter is
+# set, the groups will be tried in the indicated order.
+# The group values are listed in the IANA registry:
# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-9
-#sae_groups=21 20 19 26 25
+# Note that groups 1, 2, 5, 22, 23, and 24 should not be used in production
+# purposes due limited security (see RFC 8247). Groups that are not as strong as
+# group 19 (ECC, NIST P-256) are unlikely to be useful for production use cases
+# since all implementations are required to support group 19.
+#sae_groups=19 20 21
# Default value for DTIM period (if not overridden in network block)
#dtim_period=2
@@ -412,11 +438,50 @@ fast_reauth=1
# 2 = like 1, but maintain OUI (with local admin bit set)
#preassoc_mac_addr=0
+# MAC address policy for GAS operations
+# 0 = use permanent MAC address
+# 1 = use random MAC address
+# 2 = like 1, but maintain OUI (with local admin bit set)
+#gas_rand_mac_addr=0
+
+# Lifetime of GAS random MAC address in seconds (default: 60)
+#gas_rand_addr_lifetime=60
+
# Interworking (IEEE 802.11u)
# Enable Interworking
# interworking=1
+# Enable P2P GO advertisement of Interworking
+# go_interworking=1
+
+# P2P GO Interworking: 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
+#go_access_network_type=0
+
+# P2P GO Interworking: Whether the network provides connectivity to the Internet
+# 0 = Unspecified
+# 1 = Network provides connectivity to the Internet
+#go_internet=1
+
+# P2P GO Interworking: Group Venue Info (optional)
+# The available values are defined in IEEE Std 802.11-2016, 9.4.1.35.
+# Example values (group,type):
+# 0,0 = Unspecified
+# 1,7 = Convention Center
+# 1,13 = Coffee Shop
+# 2,0 = Unspecified Business
+# 7,1 Private Residence
+#go_venue_group=7
+#go_venue_type=1
+
# Homogenous ESS identifier
# If this is set, scans will be used to request response only from BSSes
# belonging to the specified Homogeneous ESS. This is used only if interworking
@@ -542,6 +607,20 @@ fast_reauth=1
# pre-configured with the credential since the NAI Realm information
# may not be available or fetched.
#
+# required_roaming_consortium: Required Roaming Consortium OI
+# If required_roaming_consortium_len is non-zero, this field contains the
+# Roaming Consortium OI that is required to be advertised by the AP for
+# the credential to be considered matching.
+#
+# roaming_consortiums: Roaming Consortium OI(s) memberships
+# This string field contains one or more comma delimited OIs (hexdump)
+# identifying the roaming consortiums of which the provider is a member.
+# The list is sorted from the most preferred one to the least preferred
+# one. A match between the Roaming Consortium OIs advertised by an AP and
+# the OIs in this list indicates that successful authentication is
+# possible.
+# (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/RoamingConsortiumOI)
+#
# eap: Pre-configured EAP method
# This optional field can be used to specify which EAP method will be
# used with this credential. If not set, the EAP method is selected
@@ -669,7 +748,7 @@ fast_reauth=1
# Format:
# non_pref_chan=<oper_class>:<chan>:<preference>:<reason>
# Example:
-# non_pref_chan="81:5:10:2 81:1:0:2 81:9:0:2"
+# non_pref_chan=81:5:10:2 81:1:0:2 81:9:0:2
# MBO Cellular Data Capabilities
# 1 = Cellular data connection available
@@ -677,6 +756,13 @@ fast_reauth=1
# 3 = Not cellular capable (default)
#mbo_cell_capa=3
+# Optimized Connectivity Experience (OCE)
+# oce: Enable OCE features (bitmap)
+# Set BIT(0) to Enable OCE in non-AP STA mode (default; disabled if the driver
+# does not indicate support for OCE in STA mode)
+# Set BIT(1) to Enable OCE in STA-CFON mode
+#oce=1
+
# network block
#
# Each network (usually AP's sharing the same SSID) is configured as a separate
@@ -789,6 +875,7 @@ fast_reauth=1
# proto: list of accepted protocols
# WPA = WPA/IEEE 802.11i/D3.0
# RSN = WPA2/IEEE 802.11i (also WPA2 can be used as an alias for RSN)
+# Note that RSN is used also for WPA3.
# If not set, this defaults to: WPA RSN
#
# key_mgmt: list of accepted authenticated key management protocols
@@ -801,15 +888,23 @@ fast_reauth=1
# instead)
# FT-PSK = Fast BSS Transition (IEEE 802.11r) with pre-shared key
# FT-EAP = Fast BSS Transition (IEEE 802.11r) with EAP authentication
+# FT-EAP-SHA384 = Fast BSS Transition (IEEE 802.11r) with EAP authentication
+# and using SHA384
# WPA-PSK-SHA256 = Like WPA-PSK but using stronger SHA256-based algorithms
# WPA-EAP-SHA256 = Like WPA-EAP but using stronger SHA256-based algorithms
# SAE = Simultaneous authentication of equals; pre-shared key/password -based
# authentication with stronger security than WPA-PSK especially when using
-# not that strong password
+# not that strong password; a.k.a. WPA3-Personal
# FT-SAE = SAE with FT
# WPA-EAP-SUITE-B = Suite B 128-bit level
# WPA-EAP-SUITE-B-192 = Suite B 192-bit level
# OSEN = Hotspot 2.0 Rel 2 online signup connection
+# FILS-SHA256 = Fast Initial Link Setup with SHA256
+# FILS-SHA384 = Fast Initial Link Setup with SHA384
+# FT-FILS-SHA256 = FT and Fast Initial Link Setup with SHA256
+# FT-FILS-SHA384 = FT and Fast Initial Link Setup with SHA384
+# OWE = Opportunistic Wireless Encryption (a.k.a. Enhanced Open)
+# DPP = Device Provisioning Protocol
# If not set, this defaults to: WPA-PSK WPA-EAP
#
# ieee80211w: whether management frame protection is enabled
@@ -822,6 +917,13 @@ fast_reauth=1
# PMF required: ieee80211w=2 and key_mgmt=WPA-EAP-SHA256
# (and similarly for WPA-PSK and WPA-WPSK-SHA256 if WPA2-Personal is used)
#
+# ocv: whether operating channel validation is enabled
+# This is a countermeasure against multi-channel man-in-the-middle attacks.
+# Enabling this automatically also enables ieee80211w, if not yet enabled.
+# 0 = disabled (default)
+# 1 = enabled
+#ocv=1
+#
# auth_alg: list of allowed IEEE 802.11 authentication algorithms
# OPEN = Open System authentication (required for WPA/WPA2)
# SHARED = Shared Key authentication (requires static WEP keys)
@@ -843,6 +945,14 @@ fast_reauth=1
# WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key [IEEE 802.11]
# If not set, this defaults to: CCMP TKIP WEP104 WEP40
#
+# group_mgmt: list of accepted group management ciphers for RSN (PMF)
+# AES-128-CMAC = BIP-CMAC-128
+# BIP-GMAC-128
+# BIP-GMAC-256
+# BIP-CMAC-256
+# If not set, no constraint on the cipher, i.e., accept whichever cipher the AP
+# indicates.
+#
# psk: WPA preshared key; 256-bit pre-shared key
# The key used in WPA-PSK mode can be entered either as 64 hex-digits, i.e.,
# 32 bytes or as an ASCII passphrase (in which case, the real PSK will be
@@ -860,22 +970,71 @@ fast_reauth=1
# 1 = do not store psk/passphrase to the configuration file
#mem_only_psk=0
#
+# sae_password: SAE password
+# This parameter can be used to set a password for SAE. By default, the
+# passphrase from the psk parameter is used if this separate parameter is not
+# used, but psk follows the WPA-PSK constraints (8..63 characters) even though
+# SAE passwords do not have such constraints.
+#
+# sae_password_id: SAE password identifier
+# This parameter can be used to set an identifier for the SAE password. By
+# default, no such identifier is used. If set, the specified identifier value
+# is used by the other peer to select which password to use for authentication.
+#
# eapol_flags: IEEE 802.1X/EAPOL options (bit field)
# Dynamic WEP key required for non-WPA mode
# bit0 (1): require dynamically generated unicast WEP key
# bit1 (2): require dynamically generated broadcast WEP key
# (3 = require both keys; default)
-# Note: When using wired authentication (including macsec_qca driver),
+# Note: When using wired authentication (including MACsec drivers),
# eapol_flags must be set to 0 for the authentication to be completed
# successfully.
#
# macsec_policy: IEEE 802.1X/MACsec options
-# This determines how sessions are secured with MACsec. It is currently
-# applicable only when using the macsec_qca driver interface.
+# This determines how sessions are secured with MACsec (only for MACsec
+# drivers).
# 0: MACsec not in use (default)
# 1: MACsec enabled - Should secure, accept key server's advice to
# determine whether to use a secure session or not.
#
+# macsec_integ_only: IEEE 802.1X/MACsec transmit mode
+# This setting applies only when MACsec is in use, i.e.,
+# - macsec_policy is enabled
+# - the key server has decided to enable MACsec
+# 0: Encrypt traffic (default)
+# 1: Integrity only
+#
+# macsec_replay_protect: IEEE 802.1X/MACsec replay protection
+# This setting applies only when MACsec is in use, i.e.,
+# - macsec_policy is enabled
+# - the key server has decided to enable MACsec
+# 0: Replay protection disabled (default)
+# 1: Replay protection enabled
+#
+# macsec_replay_window: IEEE 802.1X/MACsec replay protection window
+# This determines a window in which replay is tolerated, to allow receipt
+# of frames that have been misordered by the network.
+# This setting applies only when MACsec replay protection active, i.e.,
+# - macsec_replay_protect is enabled
+# - the key server has decided to enable MACsec
+# 0: No replay window, strict check (default)
+# 1..2^32-1: number of packets that could be misordered
+#
+# macsec_port: IEEE 802.1X/MACsec port
+# Port component of the SCI
+# Range: 1-65534 (default: 1)
+#
+# mka_cak, mka_ckn, and mka_priority: IEEE 802.1X/MACsec pre-shared key mode
+# This allows to configure MACsec with a pre-shared key using a (CAK,CKN) pair.
+# In this mode, instances of wpa_supplicant can act as MACsec peers. The peer
+# with lower priority will become the key server and start distributing SAKs.
+# mka_cak (CAK = Secure Connectivity Association Key) takes a 16-byte (128-bit)
+# hex-string (32 hex-digits) or a 32-byte (256-bit) hex-string (64 hex-digits)
+# mka_ckn (CKN = CAK Name) takes a 1..32-bytes (8..256 bit) hex-string
+# (2..64 hex-digits)
+# mka_priority (Priority of MKA Actor) is in 0..255 range with 255 being
+# default priority
+#
# mixed_cell: This option can be used to configure whether so called mixed
# cells, i.e., networks that use both plaintext and encryption in the same
# SSID, are allowed when selecting a BSS from scan results.
@@ -891,18 +1050,12 @@ fast_reauth=1
# hex without quotation, e.g., 0102030405)
# wep_tx_keyidx: Default WEP key index (TX) (0..3)
#
-# peerkey: Whether PeerKey negotiation for direct links (IEEE 802.11e DLS) is
-# allowed. This is only used with RSN/WPA2.
-# 0 = disabled (default)
-# 1 = enabled
-#peerkey=1
-#
# wpa_ptk_rekey: Maximum lifetime for PTK in seconds. This can be used to
# enforce rekeying of PTK to mitigate some attacks against TKIP deficiencies.
#
# group_rekey: Group rekeying time in seconds. This value, if non-zero, is used
# as the dot11RSNAConfigGroupRekeyTime parameter when operating in
-# Authenticator role in IBSS.
+# Authenticator role in IBSS, or in AP and mesh modes.
#
# Following fields are only used with internal EAP implementation.
# eap: space-separated list of accepted EAP methods
@@ -1024,6 +1177,12 @@ fast_reauth=1
# certificate may include additional sub-level labels in addition to the
# required labels.
#
+# More than one match string can be provided by using semicolons to
+# separate the strings (e.g., example.org;example.com). When multiple
+# strings are specified, a match with any one of the values is considered
+# a sufficient match for the certificate, i.e., the conditions are ORed
+# together.
+#
# For example, domain_suffix_match=example.com would match
# test.example.com but would not match test-example.com.
# domain_match: Constraint for server domain name
@@ -1036,6 +1195,12 @@ fast_reauth=1
# no subdomains or wildcard matches are allowed. Case-insensitive
# comparison is used, so "Example.com" matches "example.com", but would
# not match "test.Example.com".
+#
+# More than one match string can be provided by using semicolons to
+# separate the strings (e.g., example.org;example.com). When multiple
+# strings are specified, a match with any one of the values is considered
+# a sufficient match for the certificate, i.e., the conditions are ORed
+# together.
# phase1: Phase1 (outer authentication, i.e., TLS tunnel) parameters
# (string with field-value pairs, e.g., "peapver=0" or
# "peapver=1 peaplabel=1")
@@ -1097,16 +1262,28 @@ fast_reauth=1
# For EAP-FAST, this must be set to 0 (or left unconfigured for the
# default value to be used automatically).
# tls_disable_tlsv1_0=1 - disable use of TLSv1.0
+# tls_disable_tlsv1_0=0 - explicitly enable use of TLSv1.0 (this allows
+# systemwide TLS policies to be overridden)
# tls_disable_tlsv1_1=1 - disable use of TLSv1.1 (a workaround for AAA servers
# that have issues interoperating with updated TLS version)
+# tls_disable_tlsv1_1=0 - explicitly enable use of TLSv1.1 (this allows
+# systemwide TLS policies to be overridden)
# tls_disable_tlsv1_2=1 - disable use of TLSv1.2 (a workaround for AAA servers
# that have issues interoperating with updated TLS version)
+# tls_disable_tlsv1_2=0 - explicitly enable use of TLSv1.2 (this allows
+# systemwide TLS policies to be overridden)
+# tls_disable_tlsv1_3=1 - disable use of TLSv1.3 (a workaround for AAA servers
+# that have issues interoperating with updated TLS version)
+# tls_disable_tlsv1_3=0 - enable TLSv1.3 (experimental - disabled by default)
# tls_ext_cert_check=0 - No external server certificate validation (default)
# tls_ext_cert_check=1 - External server certificate validation enabled; this
# requires an external program doing validation of server certificate
# chain when receiving CTRL-RSP-EXT_CERT_CHECK event from the control
# interface and report the result of the validation with
# CTRL-RSP_EXT_CERT_CHECK.
+# tls_suiteb=0 - do not apply Suite B 192-bit constraints on TLS (default)
+# tls_suiteb=1 - apply Suite B 192-bit constraints on TLS; this is used in
+# particular when using Suite B with RSA keys of >= 3K (3072) bits
#
# Following certificate/private key fields are used in inner Phase2
# authentication when using EAP-TTLS or EAP-PEAP.
@@ -1175,6 +1352,10 @@ fast_reauth=1
# update_identifier: PPS MO ID
# (Hotspot 2.0 PerProviderSubscription/UpdateIdentifier)
+#
+# roaming_consortium_selection: Roaming Consortium Selection
+# The matching Roaming Consortium OI that was used to generate this
+# network profile.
# Station inactivity limit
#
@@ -1204,6 +1385,11 @@ fast_reauth=1
# 1 = WPS disabled
#wps_disabled=0
+# FILS DH Group
+# 0 = PFS disabled with FILS shared key authentication (default)
+# 1-65535 = DH Group to use for FILS PFS
+#fils_dh_group=0
+
# MAC address policy
# 0 = use permanent MAC address
# 1 = use random MAC address for each ESS connection
@@ -1248,6 +1434,20 @@ fast_reauth=1
# Treated as hint by the kernel.
# -1 = Do not make any changes.
# 0-3 = Set AMPDU density (aka factor) to specified value.
+#
+# tx_stbc: Allow overriding STBC support for TX streams
+# Value: 0-1, see IEEE Std 802.11-2016, 9.4.2.56.2.
+# -1 = Do not make any changes (default)
+# 0 = Set if not supported
+# 1 = Set if supported
+#
+# rx_stbc: Allow overriding STBC support for RX streams
+# Value: 0-3, see IEEE Std 802.11-2016, 9.4.2.56.2.
+# -1 = Do not make any changes (default)
+# 0 = Set if not supported
+# 1 = Set for support of one spatial stream
+# 2 = Set for support of one and two spatial streams
+# 3 = Set for support of one, two and three spatial streams
# disable_vht: Whether VHT should be disabled.
# 0 = VHT enabled (if AP supports it)
@@ -1263,6 +1463,13 @@ fast_reauth=1
# 2: MCS 0-9
# 3: not supported
+# multi_ap_backhaul_sta: Multi-AP backhaul STA functionality
+# 0 = normal STA (default)
+# 1 = backhaul STA
+# A backhaul STA sends the Multi-AP IE, fails to associate if the AP does not
+# support Multi-AP, and sets 4-address mode if it does. Thus, the netdev can be
+# added to a bridge to allow forwarding frames over this backhaul link.
+
##### Fast Session Transfer (FST) support #####################################
#
# The options in this section are only available when the build configuration
@@ -1662,15 +1869,26 @@ network={
}
-# Example MACsec configuration
-#network={
-# key_mgmt=IEEE8021X
-# eap=TTLS
-# phase2="auth=PAP"
-# anonymous_identity="anonymous@example.com"
-# identity="user@example.com"
-# password="secretr"
-# ca_cert="/etc/cert/ca.pem"
-# eapol_flags=0
-# macsec_policy=1
-#}
+# Example configuration using EAP-TTLS for authentication and key
+# generation for MACsec
+network={
+ key_mgmt=IEEE8021X
+ eap=TTLS
+ phase2="auth=PAP"
+ anonymous_identity="anonymous@example.com"
+ identity="user@example.com"
+ password="secretr"
+ ca_cert="/etc/cert/ca.pem"
+ eapol_flags=0
+ macsec_policy=1
+}
+
+# Example configuration for MACsec with preshared key
+network={
+ key_mgmt=NONE
+ eapol_flags=0
+ macsec_policy=1
+ mka_cak=0123456789ABCDEF0123456789ABCDEF
+ mka_ckn=6162636465666768696A6B6C6D6E6F707172737475767778797A303132333435
+ mka_priority=128
+}
diff --git a/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h b/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h
index ef9273d09a32..16e4db62aeef 100644
--- a/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h
+++ b/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h
@@ -9,6 +9,7 @@
#ifndef WPA_SUPPLICANT_I_H
#define WPA_SUPPLICANT_I_H
+#include "utils/bitfield.h"
#include "utils/list.h"
#include "common/defs.h"
#include "common/sae.h"
@@ -295,7 +296,7 @@ struct wpa_global {
#ifdef CONFIG_WIFI_DISPLAY
int wifi_display;
-#define MAX_WFD_SUBELEMS 10
+#define MAX_WFD_SUBELEMS 12
struct wpabuf *wfd_subelem[MAX_WFD_SUBELEMS];
#endif /* CONFIG_WIFI_DISPLAY */
@@ -344,6 +345,7 @@ int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
void radio_work_done(struct wpa_radio_work *work);
void radio_remove_works(struct wpa_supplicant *wpa_s,
const char *type, int remove_all);
+void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx);
void radio_work_check_next(struct wpa_supplicant *wpa_s);
struct wpa_radio_work *
radio_work_pending(struct wpa_supplicant *wpa_s, const char *type);
@@ -424,6 +426,12 @@ struct rrm_data {
/* next_neighbor_rep_token - Next request's dialog token */
u8 next_neighbor_rep_token;
+
+ /* token - Dialog token of the current radio measurement */
+ u8 token;
+
+ /* destination address of the current radio measurement request */
+ u8 dst_addr[ETH_ALEN];
};
enum wpa_supplicant_test_failure {
@@ -443,7 +451,30 @@ struct icon_entry {
struct wpa_bss_tmp_disallowed {
struct dl_list list;
u8 bssid[ETH_ALEN];
- struct os_reltime disallowed_until;
+ int rssi_threshold;
+};
+
+struct beacon_rep_data {
+ u8 token;
+ u8 last_indication;
+ struct wpa_driver_scan_params scan_params;
+ u8 ssid[SSID_MAX_LEN];
+ size_t ssid_len;
+ u8 bssid[ETH_ALEN];
+ enum beacon_report_detail report_detail;
+ struct bitfield *eids;
+};
+
+
+struct external_pmksa_cache {
+ struct dl_list list;
+ void *pmksa_cache;
+};
+
+struct fils_hlp_req {
+ struct dl_list list;
+ u8 dst[ETH_ALEN];
+ struct wpabuf *pkt;
};
/**
@@ -463,15 +494,16 @@ struct wpa_supplicant {
struct wpa_supplicant *next;
struct l2_packet_data *l2;
struct l2_packet_data *l2_br;
+ struct os_reltime roam_start;
+ struct os_reltime roam_time;
+ struct os_reltime session_start;
+ struct os_reltime session_length;
unsigned char own_addr[ETH_ALEN];
unsigned char perm_addr[ETH_ALEN];
char ifname[100];
#ifdef CONFIG_MATCH_IFACE
int matched;
#endif /* CONFIG_MATCH_IFACE */
-#ifdef CONFIG_CTRL_IFACE_DBUS
- char *dbus_path;
-#endif /* CONFIG_CTRL_IFACE_DBUS */
#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
char *dbus_new_path;
char *dbus_groupobj_path;
@@ -503,6 +535,8 @@ struct wpa_supplicant {
struct wpa_bss *current_bss;
int ap_ies_from_associnfo;
unsigned int assoc_freq;
+ u8 *last_con_fail_realm;
+ size_t last_con_fail_realm_len;
/* Selected configuration (based on Beacon/ProbeResp WPA IE) */
int pairwise_cipher;
@@ -639,6 +673,7 @@ struct wpa_supplicant {
struct os_reltime scan_min_time;
int scan_runs; /* number of scan runs since WPS was started */
int *next_scan_freqs;
+ int *select_network_scan_freqs;
int *manual_scan_freqs;
int *manual_sched_scan_freqs;
unsigned int manual_scan_passive:1;
@@ -652,6 +687,12 @@ struct wpa_supplicant {
int normal_scans; /* normal scans run before sched_scan */
int scan_for_connection; /* whether the scan request was triggered for
* finding a connection */
+ /*
+ * A unique cookie representing the vendor scan request. This cookie is
+ * returned from the driver interface. 0 indicates that there is no
+ * pending vendor scan request.
+ */
+ u64 curr_scan_cookie;
#define MAX_SCAN_ID 16
int scan_id[MAX_SCAN_ID];
unsigned int scan_id_count;
@@ -705,6 +746,12 @@ struct wpa_supplicant {
unsigned int mac_addr_changed:1;
unsigned int added_vif:1;
unsigned int wnmsleep_used:1;
+ unsigned int owe_transition_select:1;
+ unsigned int owe_transition_search:1;
+ unsigned int connection_set:1;
+ unsigned int connection_ht:1;
+ unsigned int connection_vht:1;
+ unsigned int connection_he:1;
struct os_reltime last_mac_addr_change;
int last_mac_addr_style;
@@ -715,13 +762,15 @@ struct wpa_supplicant {
int sta_uapsd;
int set_ap_uapsd;
int ap_uapsd;
+ int auth_alg;
+ u16 last_owe_group;
#ifdef CONFIG_SME
struct {
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
int freq;
- u8 assoc_req_ie[200];
+ u8 assoc_req_ie[1500];
size_t assoc_req_ie_len;
int mfp;
int ft_used;
@@ -752,6 +801,8 @@ struct wpa_supplicant {
struct wpabuf *sae_token;
int sae_group_index;
unsigned int sae_pmksa_caching:1;
+ u16 seq_num;
+ struct external_auth ext_auth;
#endif /* CONFIG_SAE */
} sme;
#endif /* CONFIG_SME */
@@ -770,6 +821,11 @@ struct wpa_supplicant {
unsigned int mesh_if_created:1;
unsigned int mesh_ht_enabled:1;
unsigned int mesh_vht_enabled:1;
+ struct wpa_driver_mesh_join_params *mesh_params;
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+ /* struct external_pmksa_cache::list */
+ struct dl_list mesh_external_pmksa_cache;
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
#endif /* CONFIG_MESH */
unsigned int off_channel_freq;
@@ -789,6 +845,7 @@ struct wpa_supplicant {
result);
unsigned int roc_waiting_drv_freq;
int action_tx_wait_time;
+ int action_tx_wait_time_used;
int p2p_mgmt;
@@ -856,11 +913,13 @@ struct wpa_supplicant {
unsigned int p2p_auto_join:1;
unsigned int p2p_auto_pd:1;
+ unsigned int p2p_go_do_acs:1;
unsigned int p2p_persistent_group:1;
unsigned int p2p_fallback_to_go_neg:1;
unsigned int p2p_pd_before_go_neg:1;
unsigned int p2p_go_ht40:1;
unsigned int p2p_go_vht:1;
+ unsigned int p2p_go_he:1;
unsigned int user_initiated_pd:1;
unsigned int p2p_go_group_formation_completed:1;
unsigned int group_formation_reported:1;
@@ -871,6 +930,7 @@ struct wpa_supplicant {
unsigned int p2p_disable_ip_addr_req:1;
unsigned int p2ps_method_config_any:1;
unsigned int p2p_cli_probe:1;
+ enum hostapd_hw_mode p2p_go_acs_band;
int p2p_persistent_go_freq;
int p2p_persistent_id;
int p2p_go_intent;
@@ -923,6 +983,7 @@ struct wpa_supplicant {
int best_overall_freq;
struct gas_query *gas;
+ struct gas_server *gas_server;
#ifdef CONFIG_INTERWORKING
unsigned int fetch_anqp_in_progress:1;
@@ -966,6 +1027,10 @@ struct wpa_supplicant {
/* WLAN_REASON_* reason codes. Negative if locally generated. */
int disconnect_reason;
+ /* WLAN_STATUS_* status codes from last received Authentication frame
+ * from the AP. */
+ u16 auth_status_code;
+
/* WLAN_STATUS_* status codes from (Re)Association Response frame. */
u16 assoc_status_code;
@@ -981,6 +1046,7 @@ struct wpa_supplicant {
unsigned int wmm_ac_supported:1;
unsigned int ext_work_in_progress:1;
unsigned int own_disconnect_req:1;
+ unsigned int ignore_post_flush_scan_res:1;
#define MAC_ADDR_RAND_SCAN BIT(0)
#define MAC_ADDR_RAND_SCHED_SCAN BIT(1)
@@ -1006,6 +1072,15 @@ struct wpa_supplicant {
struct neighbor_report *wnm_neighbor_report_elements;
struct os_reltime wnm_cand_valid_until;
u8 wnm_cand_from_bss[ETH_ALEN];
+ enum bss_trans_mgmt_status_code bss_tm_status;
+ struct wpabuf *coloc_intf_elems;
+ u8 coloc_intf_dialog_token;
+ u8 coloc_intf_auto_report;
+ u8 coloc_intf_timeout;
+#ifdef CONFIG_MBO
+ unsigned int wnm_mbo_trans_reason_present:1;
+ u8 wnm_mbo_transition_reason;
+#endif /* CONFIG_MBO */
#endif /* CONFIG_WNM */
#ifdef CONFIG_TESTING_GET_GTK
@@ -1024,10 +1099,19 @@ struct wpa_supplicant {
struct l2_packet_data *l2_test;
unsigned int extra_roc_dur;
enum wpa_supplicant_test_failure test_failure;
+ char *get_pref_freq_list_override;
unsigned int reject_btm_req_reason;
unsigned int p2p_go_csa_on_inv:1;
unsigned int ignore_auth_resp:1;
unsigned int ignore_assoc_disallow:1;
+ unsigned int testing_resend_assoc:1;
+ struct wpabuf *sae_commit_override;
+ enum wpa_alg last_tk_alg;
+ u8 last_tk_addr[ETH_ALEN];
+ int last_tk_key_idx;
+ u8 last_tk[WPA_TK_MAX_LEN];
+ size_t last_tk_len;
+ struct wpabuf *last_assoc_req_wpa_ie;
#endif /* CONFIG_TESTING_OPTIONS */
struct wmm_ac_assoc_data *wmm_ac_assoc_info;
@@ -1038,6 +1122,7 @@ struct wpa_supplicant {
u8 last_tspecs_count;
struct rrm_data rrm;
+ struct beacon_rep_data beacon_rep_data;
#ifdef CONFIG_FST
struct fst_iface *fst;
@@ -1055,6 +1140,14 @@ struct wpa_supplicant {
} *non_pref_chan;
size_t non_pref_chan_num;
u8 mbo_wnm_token;
+ /**
+ * enable_oce - Enable OCE if it is enabled by user and device also
+ * supports OCE.
+ * User can enable OCE with wpa_config's 'oce' parameter as follows -
+ * - Set BIT(0) to enable OCE in non-AP STA mode.
+ * - Set BIT(1) to enable OCE in STA-CFON mode.
+ */
+ u8 enable_oce;
#endif /* CONFIG_MBO */
/*
@@ -1069,6 +1162,95 @@ struct wpa_supplicant {
*/
struct wpabuf *lci;
struct os_reltime lci_time;
+
+ struct os_reltime beacon_rep_scan;
+
+ /* FILS HLP requests (struct fils_hlp_req) */
+ struct dl_list fils_hlp_req;
+
+ struct sched_scan_relative_params {
+ /**
+ * relative_rssi_set - Enable relatively preferred BSS reporting
+ *
+ * 0 = Disable reporting relatively preferred BSSs
+ * 1 = Enable reporting relatively preferred BSSs
+ */
+ int relative_rssi_set;
+
+ /**
+ * relative_rssi - Relative RSSI for reporting better BSSs
+ *
+ * Amount of RSSI by which a BSS should be better than the
+ * current connected BSS so that the new BSS can be reported
+ * to user space. This applies to sched_scan operations.
+ */
+ int relative_rssi;
+
+ /**
+ * relative_adjust_band - Band in which RSSI is to be adjusted
+ */
+ enum set_band relative_adjust_band;
+
+ /**
+ * relative_adjust_rssi - RSSI adjustment
+ *
+ * An amount of relative_adjust_rssi should be added to the
+ * BSSs that belong to the relative_adjust_band while comparing
+ * with other bands for BSS reporting.
+ */
+ int relative_adjust_rssi;
+ } srp;
+
+ /* RIC elements for FT protocol */
+ struct wpabuf *ric_ies;
+
+ int last_auth_timeout_sec;
+
+#ifdef CONFIG_DPP
+ struct dpp_global *dpp;
+ struct dpp_authentication *dpp_auth;
+ struct wpa_radio_work *dpp_listen_work;
+ unsigned int dpp_pending_listen_freq;
+ unsigned int dpp_listen_freq;
+ u8 dpp_allowed_roles;
+ int dpp_qr_mutual;
+ int dpp_netrole_ap;
+ int dpp_auth_ok_on_ack;
+ int dpp_in_response_listen;
+ int dpp_gas_client;
+ int dpp_gas_dialog_token;
+ u8 dpp_intro_bssid[ETH_ALEN];
+ void *dpp_intro_network;
+ struct dpp_pkex *dpp_pkex;
+ struct dpp_bootstrap_info *dpp_pkex_bi;
+ char *dpp_pkex_code;
+ char *dpp_pkex_identifier;
+ char *dpp_pkex_auth_cmd;
+ char *dpp_configurator_params;
+ struct os_reltime dpp_last_init;
+ struct os_reltime dpp_init_iter_start;
+ unsigned int dpp_init_max_tries;
+ unsigned int dpp_init_retry_time;
+ unsigned int dpp_resp_wait_time;
+ unsigned int dpp_resp_max_tries;
+ unsigned int dpp_resp_retry_time;
+#ifdef CONFIG_DPP2
+ struct dpp_pfs *dpp_pfs;
+#endif /* CONFIG_DPP2 */
+#ifdef CONFIG_TESTING_OPTIONS
+ char *dpp_config_obj_override;
+ char *dpp_discovery_override;
+ char *dpp_groups_override;
+ unsigned int dpp_ignore_netaccesskey_mismatch:1;
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_DPP */
+
+#ifdef CONFIG_FILS
+ unsigned int disable_fils:1;
+#endif /* CONFIG_FILS */
+ unsigned int ieee80211ac:1;
+ unsigned int enabled_4addr_mode:1;
+ unsigned int multi_bss_support:1;
};
@@ -1101,6 +1283,7 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s);
void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr);
void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
int sec, int usec);
+void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff);
void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s);
void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
enum wpa_states state);
@@ -1158,6 +1341,7 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s);
void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s);
void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid);
+void fils_connection_failure(struct wpa_supplicant *wpa_s);
int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s);
int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s);
void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason);
@@ -1183,22 +1367,30 @@ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
struct wpabuf *neighbor_rep),
void *cb_ctx);
void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
- const u8 *src,
+ const u8 *src, const u8 *dst,
const u8 *frame, size_t len);
void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
const u8 *src,
const u8 *frame, size_t len,
int rssi);
+void wpas_rrm_refuse_request(struct wpa_supplicant *wpa_s);
+int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *scan_res,
+ struct scan_info *info);
+void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s);
+void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s);
/* MBO functions */
-int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len);
+int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len,
+ int add_oce_capa);
+const u8 * mbo_attr_from_mbo_ie(const u8 *mbo_ie, enum mbo_attr_id attr);
const u8 * wpas_mbo_get_bss_attr(struct wpa_bss *bss, enum mbo_attr_id attr);
+const u8 * mbo_get_attr_from_ies(const u8 *ies, size_t ies_len,
+ enum mbo_attr_id attr);
int wpas_mbo_update_non_pref_chan(struct wpa_supplicant *wpa_s,
const char *non_pref_chan);
void wpas_mbo_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ie);
-int wpas_mbo_supp_op_class_ie(struct wpa_supplicant *wpa_s, int freq, u8 *pos,
- size_t len);
void wpas_mbo_ie_trans_req(struct wpa_supplicant *wpa_s, const u8 *ie,
size_t len);
size_t wpas_mbo_ie_bss_trans_reject(struct wpa_supplicant *wpa_s, u8 *pos,
@@ -1206,7 +1398,22 @@ size_t wpas_mbo_ie_bss_trans_reject(struct wpa_supplicant *wpa_s, u8 *pos,
enum mbo_transition_reject_reason reason);
void wpas_mbo_update_cell_capa(struct wpa_supplicant *wpa_s, u8 mbo_cell_capa);
struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s,
- struct wpa_bss *bss);
+ struct wpa_bss *bss, u32 mbo_subtypes);
+void mbo_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss, const u8 *sa,
+ const u8 *data, size_t slen);
+void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s);
+
+/* op_classes.c */
+enum chan_allowed {
+ NOT_ALLOWED, NO_IR, ALLOWED
+};
+
+enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 channel,
+ u8 bw);
+size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ int freq, u8 *pos, size_t len);
/**
* wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response
@@ -1238,6 +1445,9 @@ void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s);
int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s);
struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
struct wpa_ssid **selected_ssid);
+int wpas_temp_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s,
+ struct channel_list_changed *info);
/* eap_register.c */
int eap_register_methods(void);
@@ -1290,12 +1500,22 @@ struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
u16 num_modes, enum hostapd_hw_mode mode);
void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
- unsigned int sec);
-int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid);
+ unsigned int sec, int rssi_threshold);
+int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss);
+void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s);
struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
int i, struct wpa_bss *bss,
struct wpa_ssid *group,
- int only_first_ssid);
+ int only_first_ssid, int debug_print);
+
+int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
+ enum wpa_driver_if_type if_type,
+ unsigned int *num,
+ unsigned int *freq_list);
+
+int wpa_is_fils_supported(struct wpa_supplicant *wpa_s);
+int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s);
#endif /* WPA_SUPPLICANT_I_H */
diff --git a/contrib/wpa/wpa_supplicant/wpa_supplicant_template.conf b/contrib/wpa/wpa_supplicant/wpa_supplicant_template.conf
index f3f2a6417d2e..f55227f82685 100644
--- a/contrib/wpa/wpa_supplicant/wpa_supplicant_template.conf
+++ b/contrib/wpa/wpa_supplicant/wpa_supplicant_template.conf
@@ -4,3 +4,4 @@ eapol_version=1
ap_scan=1
fast_reauth=1
pmf=1
+p2p_add_cli_chan=1
diff --git a/contrib/wpa/wpa_supplicant/wpas_glue.c b/contrib/wpa/wpa_supplicant/wpas_glue.c
index f84c8b90ac2f..449e04acded8 100644
--- a/contrib/wpa/wpa_supplicant/wpas_glue.c
+++ b/contrib/wpa/wpa_supplicant/wpas_glue.c
@@ -10,6 +10,7 @@
#include "common.h"
#include "eapol_supp/eapol_supp_sm.h"
+#include "eap_peer/eap.h"
#include "rsn_supp/wpa.h"
#include "eloop.h"
#include "config.h"
@@ -145,6 +146,8 @@ static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf,
* extra copy here */
if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_DPP ||
wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
/* Current SSID is not using IEEE 802.1X/EAP, so drop possible
* EAPOL frames (mainly, EAPOL-Start) from EAPOL state
@@ -293,7 +296,7 @@ static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol,
}
if (result != EAPOL_SUPP_RESULT_SUCCESS ||
- !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X))
return;
if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt))
@@ -499,6 +502,16 @@ static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg,
wpa_s->last_gtk_len = key_len;
}
#endif /* CONFIG_TESTING_GET_GTK */
+#ifdef CONFIG_TESTING_OPTIONS
+ if (addr && !is_broadcast_ether_addr(addr)) {
+ wpa_s->last_tk_alg = alg;
+ os_memcpy(wpa_s->last_tk_addr, addr, ETH_ALEN);
+ wpa_s->last_tk_key_idx = key_idx;
+ if (key)
+ os_memcpy(wpa_s->last_tk, key, key_len);
+ wpa_s->last_tk_len = key_len;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
key, key_len);
}
@@ -513,17 +526,74 @@ static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr,
}
-static int wpa_supplicant_add_pmkid(void *wpa_s,
- const u8 *bssid, const u8 *pmkid)
+static struct wpa_ssid * wpas_get_network_ctx(struct wpa_supplicant *wpa_s,
+ void *network_ctx)
{
- return wpa_drv_add_pmkid(wpa_s, bssid, pmkid);
+ struct wpa_ssid *ssid;
+
+ for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+ if (network_ctx == ssid)
+ return ssid;
+ }
+
+ return NULL;
}
-static int wpa_supplicant_remove_pmkid(void *wpa_s,
- const u8 *bssid, const u8 *pmkid)
+static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx,
+ const u8 *bssid, const u8 *pmkid,
+ const u8 *fils_cache_id,
+ const u8 *pmk, size_t pmk_len)
{
- return wpa_drv_remove_pmkid(wpa_s, bssid, pmkid);
+ struct wpa_supplicant *wpa_s = _wpa_s;
+ struct wpa_ssid *ssid;
+ struct wpa_pmkid_params params;
+
+ os_memset(&params, 0, sizeof(params));
+ ssid = wpas_get_network_ctx(wpa_s, network_ctx);
+ if (ssid)
+ wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_ADDED MACSTR " %d",
+ MAC2STR(bssid), ssid->id);
+ if (ssid && fils_cache_id) {
+ params.ssid = ssid->ssid;
+ params.ssid_len = ssid->ssid_len;
+ params.fils_cache_id = fils_cache_id;
+ } else {
+ params.bssid = bssid;
+ }
+
+ params.pmkid = pmkid;
+ params.pmk = pmk;
+ params.pmk_len = pmk_len;
+
+ return wpa_drv_add_pmkid(wpa_s, &params);
+}
+
+
+static int wpa_supplicant_remove_pmkid(void *_wpa_s, void *network_ctx,
+ const u8 *bssid, const u8 *pmkid,
+ const u8 *fils_cache_id)
+{
+ struct wpa_supplicant *wpa_s = _wpa_s;
+ struct wpa_ssid *ssid;
+ struct wpa_pmkid_params params;
+
+ os_memset(&params, 0, sizeof(params));
+ ssid = wpas_get_network_ctx(wpa_s, network_ctx);
+ if (ssid)
+ wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_REMOVED MACSTR " %d",
+ MAC2STR(bssid), ssid->id);
+ if (ssid && fils_cache_id) {
+ params.ssid = ssid->ssid;
+ params.ssid_len = ssid->ssid_len;
+ params.fils_cache_id = fils_cache_id;
+ } else {
+ params.bssid = bssid;
+ }
+
+ params.pmkid = pmkid;
+
+ return wpa_drv_remove_pmkid(wpa_s, &params);
}
@@ -865,12 +935,13 @@ static void wpa_supplicant_eap_param_needed(void *ctx,
#ifdef CONFIG_EAP_PROXY
+
static void wpa_supplicant_eap_proxy_cb(void *ctx)
{
struct wpa_supplicant *wpa_s = ctx;
size_t len;
- wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol,
+ wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
wpa_s->imsi, &len);
if (wpa_s->mnc_len > 0) {
wpa_s->imsi[len] = '\0';
@@ -880,6 +951,52 @@ static void wpa_supplicant_eap_proxy_cb(void *ctx)
wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
}
}
+
+
+static void wpa_sm_sim_state_error_handler(struct wpa_supplicant *wpa_s)
+{
+ int i;
+ struct wpa_ssid *ssid;
+ const struct eap_method_type *eap_methods;
+
+ if (!wpa_s->conf)
+ return;
+
+ for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+ eap_methods = ssid->eap.eap_methods;
+ if (!eap_methods)
+ continue;
+
+ for (i = 0; eap_methods[i].method != EAP_TYPE_NONE; i++) {
+ if (eap_methods[i].vendor == EAP_VENDOR_IETF &&
+ (eap_methods[i].method == EAP_TYPE_SIM ||
+ eap_methods[i].method == EAP_TYPE_AKA ||
+ eap_methods[i].method == EAP_TYPE_AKA_PRIME)) {
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
+ break;
+ }
+ }
+ }
+}
+
+
+static void
+wpa_supplicant_eap_proxy_notify_sim_status(void *ctx,
+ enum eap_proxy_sim_state sim_state)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ wpa_printf(MSG_DEBUG, "eap_proxy: SIM card status %u", sim_state);
+ switch (sim_state) {
+ case SIM_STATE_ERROR:
+ wpa_sm_sim_state_error_handler(wpa_s);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "eap_proxy: SIM card status unknown");
+ break;
+ }
+}
+
#endif /* CONFIG_EAP_PROXY */
@@ -921,6 +1038,14 @@ static void wpa_supplicant_status_cb(void *ctx, const char *status,
}
+static void wpa_supplicant_eap_error_cb(void *ctx, int error_code)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ wpas_notify_eap_error(wpa_s, error_code);
+}
+
+
static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
@@ -990,12 +1115,15 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
ctx->eap_param_needed = wpa_supplicant_eap_param_needed;
#ifdef CONFIG_EAP_PROXY
ctx->eap_proxy_cb = wpa_supplicant_eap_proxy_cb;
+ ctx->eap_proxy_notify_sim_status =
+ wpa_supplicant_eap_proxy_notify_sim_status;
#endif /* CONFIG_EAP_PROXY */
ctx->port_cb = wpa_supplicant_port_cb;
ctx->cb = wpa_supplicant_eapol_cb;
ctx->cert_cb = wpa_supplicant_cert_cb;
ctx->cert_in_cb = wpa_s->conf->cert_in_cb;
ctx->status_cb = wpa_supplicant_status_cb;
+ ctx->eap_error_cb = wpa_supplicant_eap_error_cb;
ctx->set_anon_id = wpa_supplicant_set_anon_id;
ctx->cb_ctx = wpa_s;
wpa_s->eapol = eapol_sm_init(ctx);
@@ -1012,6 +1140,7 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
#ifndef CONFIG_NO_WPA
+
static void wpa_supplicant_set_rekey_offload(void *ctx,
const u8 *kek, size_t kek_len,
const u8 *kck, size_t kck_len,
@@ -1035,6 +1164,34 @@ static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk,
else
return 0;
}
+
+
+static void wpa_supplicant_fils_hlp_rx(void *ctx, const u8 *dst, const u8 *src,
+ const u8 *pkt, size_t pkt_len)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ char *hex;
+ size_t hexlen;
+
+ hexlen = pkt_len * 2 + 1;
+ hex = os_malloc(hexlen);
+ if (!hex)
+ return;
+ wpa_snprintf_hex(hex, hexlen, pkt, pkt_len);
+ wpa_msg(wpa_s, MSG_INFO, FILS_HLP_RX "dst=" MACSTR " src=" MACSTR
+ " frame=%s", MAC2STR(dst), MAC2STR(src), hex);
+ os_free(hex);
+}
+
+
+static int wpa_supplicant_channel_info(void *_wpa_s,
+ struct wpa_channel_info *ci)
+{
+ struct wpa_supplicant *wpa_s = _wpa_s;
+
+ return wpa_drv_channel_info(wpa_s, ci);
+}
+
#endif /* CONFIG_NO_WPA */
@@ -1084,6 +1241,8 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
#endif /* CONFIG_TDLS */
ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload;
ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk;
+ ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx;
+ ctx->channel_info = wpa_supplicant_channel_info;
wpa_s->wpa = wpa_sm_init(ctx);
if (wpa_s->wpa == NULL) {
@@ -1105,7 +1264,6 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
if (ssid) {
os_memset(&conf, 0, sizeof(conf));
conf.network_ctx = ssid;
- conf.peerkey_enabled = ssid->peerkey;
conf.allowed_pairwise_cipher = ssid->pairwise_cipher;
#ifdef IEEE8021X_EAPOL
conf.proactive_key_caching = ssid->proactive_key_caching < 0 ?
@@ -1133,6 +1291,11 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_P2P */
conf.wpa_rsc_relaxation = wpa_s->conf->wpa_rsc_relaxation;
+#ifdef CONFIG_FILS
+ if (wpa_key_mgmt_fils(wpa_s->key_mgmt))
+ conf.fils_cache_id =
+ wpa_bss_get_fils_cache_id(wpa_s->current_bss);
+#endif /* CONFIG_FILS */
}
wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
}
diff --git a/contrib/wpa/wpa_supplicant/wpas_kay.c b/contrib/wpa/wpa_supplicant/wpas_kay.c
index d6ec8c5090e9..41477d514d3f 100644
--- a/contrib/wpa/wpa_supplicant/wpas_kay.c
+++ b/contrib/wpa/wpa_supplicant/wpas_kay.c
@@ -5,7 +5,7 @@
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
-#include <openssl/ssl.h>
+
#include "utils/includes.h"
#include "utils/common.h"
@@ -38,12 +38,24 @@ static int wpas_macsec_deinit(void *priv)
}
+static int wpas_macsec_get_capability(void *priv, enum macsec_cap *cap)
+{
+ return wpa_drv_macsec_get_capability(priv, cap);
+}
+
+
static int wpas_enable_protect_frames(void *wpa_s, Boolean enabled)
{
return wpa_drv_enable_protect_frames(wpa_s, enabled);
}
+static int wpas_enable_encrypt(void *wpa_s, Boolean enabled)
+{
+ return wpa_drv_enable_encrypt(wpa_s, enabled);
+}
+
+
static int wpas_set_replay_protect(void *wpa_s, Boolean enabled, u32 window)
{
return wpa_drv_set_replay_protect(wpa_s, enabled, window);
@@ -62,30 +74,27 @@ static int wpas_enable_controlled_port(void *wpa_s, Boolean enabled)
}
-static int wpas_get_receive_lowest_pn(void *wpa_s, u32 channel,
- u8 an, u32 *lowest_pn)
+static int wpas_get_receive_lowest_pn(void *wpa_s, struct receive_sa *sa)
{
- return wpa_drv_get_receive_lowest_pn(wpa_s, channel, an, lowest_pn);
+ return wpa_drv_get_receive_lowest_pn(wpa_s, sa);
}
-static int wpas_get_transmit_next_pn(void *wpa_s, u32 channel,
- u8 an, u32 *next_pn)
+static int wpas_get_transmit_next_pn(void *wpa_s, struct transmit_sa *sa)
{
- return wpa_drv_get_transmit_next_pn(wpa_s, channel, an, next_pn);
+ return wpa_drv_get_transmit_next_pn(wpa_s, sa);
}
-static int wpas_set_transmit_next_pn(void *wpa_s, u32 channel,
- u8 an, u32 next_pn)
+static int wpas_set_transmit_next_pn(void *wpa_s, struct transmit_sa *sa)
{
- return wpa_drv_set_transmit_next_pn(wpa_s, channel, an, next_pn);
+ return wpa_drv_set_transmit_next_pn(wpa_s, sa);
}
-static int wpas_get_available_receive_sc(void *wpa_s, u32 *channel)
+static int wpas_set_receive_lowest_pn(void *wpa_s, struct receive_sa *sa)
{
- return wpa_drv_get_available_receive_sc(wpa_s, channel);
+ return wpa_drv_set_receive_lowest_pn(wpa_s, sa);
}
@@ -103,83 +112,79 @@ static unsigned int conf_offset_val(enum confidentiality_offset co)
}
-static int wpas_create_receive_sc(void *wpa_s, u32 channel,
- struct ieee802_1x_mka_sci *sci,
+static int wpas_create_receive_sc(void *wpa_s, struct receive_sc *sc,
enum validate_frames vf,
enum confidentiality_offset co)
{
- return wpa_drv_create_receive_sc(wpa_s, channel, sci->addr,
- be_to_host16(sci->port),
- conf_offset_val(co), vf);
+ return wpa_drv_create_receive_sc(wpa_s, sc, conf_offset_val(co), vf);
}
-static int wpas_delete_receive_sc(void *wpa_s, u32 channel)
+static int wpas_delete_receive_sc(void *wpa_s, struct receive_sc *sc)
{
- return wpa_drv_delete_receive_sc(wpa_s, channel);
+ return wpa_drv_delete_receive_sc(wpa_s, sc);
}
-static int wpas_create_receive_sa(void *wpa_s, u32 channel, u8 an,
- u32 lowest_pn, const u8 *sak)
+static int wpas_create_receive_sa(void *wpa_s, struct receive_sa *sa)
{
- return wpa_drv_create_receive_sa(wpa_s, channel, an, lowest_pn, sak);
+ return wpa_drv_create_receive_sa(wpa_s, sa);
}
-static int wpas_enable_receive_sa(void *wpa_s, u32 channel, u8 an)
+static int wpas_delete_receive_sa(void *wpa_s, struct receive_sa *sa)
{
- return wpa_drv_enable_receive_sa(wpa_s, channel, an);
+ return wpa_drv_delete_receive_sa(wpa_s, sa);
}
-static int wpas_disable_receive_sa(void *wpa_s, u32 channel, u8 an)
+static int wpas_enable_receive_sa(void *wpa_s, struct receive_sa *sa)
{
- return wpa_drv_disable_receive_sa(wpa_s, channel, an);
+ return wpa_drv_enable_receive_sa(wpa_s, sa);
}
-static int wpas_get_available_transmit_sc(void *wpa_s, u32 *channel)
+static int wpas_disable_receive_sa(void *wpa_s, struct receive_sa *sa)
{
- return wpa_drv_get_available_transmit_sc(wpa_s, channel);
+ return wpa_drv_disable_receive_sa(wpa_s, sa);
}
static int
-wpas_create_transmit_sc(void *wpa_s, u32 channel,
- const struct ieee802_1x_mka_sci *sci,
+wpas_create_transmit_sc(void *wpa_s, struct transmit_sc *sc,
enum confidentiality_offset co)
{
- return wpa_drv_create_transmit_sc(wpa_s, channel, sci->addr,
- be_to_host16(sci->port),
- conf_offset_val(co));
+ return wpa_drv_create_transmit_sc(wpa_s, sc, conf_offset_val(co));
}
-static int wpas_delete_transmit_sc(void *wpa_s, u32 channel)
+static int wpas_delete_transmit_sc(void *wpa_s, struct transmit_sc *sc)
{
- return wpa_drv_delete_transmit_sc(wpa_s, channel);
+ return wpa_drv_delete_transmit_sc(wpa_s, sc);
}
-static int wpas_create_transmit_sa(void *wpa_s, u32 channel, u8 an,
- u32 next_pn, Boolean confidentiality,
- const u8 *sak)
+static int wpas_create_transmit_sa(void *wpa_s, struct transmit_sa *sa)
{
- return wpa_drv_create_transmit_sa(wpa_s, channel, an, next_pn,
- confidentiality, sak);
+ return wpa_drv_create_transmit_sa(wpa_s, sa);
}
-static int wpas_enable_transmit_sa(void *wpa_s, u32 channel, u8 an)
+static int wpas_delete_transmit_sa(void *wpa_s, struct transmit_sa *sa)
{
- return wpa_drv_enable_transmit_sa(wpa_s, channel, an);
+ return wpa_drv_delete_transmit_sa(wpa_s, sa);
}
-static int wpas_disable_transmit_sa(void *wpa_s, u32 channel, u8 an)
+static int wpas_enable_transmit_sa(void *wpa_s, struct transmit_sa *sa)
{
- return wpa_drv_disable_transmit_sa(wpa_s, channel, an);
+ return wpa_drv_enable_transmit_sa(wpa_s, sa);
+}
+
+
+static int wpas_disable_transmit_sa(void *wpa_s, struct transmit_sa *sa)
+{
+ return wpa_drv_disable_transmit_sa(wpa_s, sa);
}
@@ -194,7 +199,14 @@ int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
if (!ssid || ssid->macsec_policy == 0)
return 0;
- policy = ssid->macsec_policy == 1 ? SHOULD_SECURE : DO_NOT_SECURE;
+ if (ssid->macsec_policy == 1) {
+ if (ssid->macsec_integ_only == 1)
+ policy = SHOULD_SECURE;
+ else
+ policy = SHOULD_ENCRYPT;
+ } else {
+ policy = DO_NOT_SECURE;
+ }
kay_ctx = os_zalloc(sizeof(*kay_ctx));
if (!kay_ctx)
@@ -204,32 +216,36 @@ int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
kay_ctx->macsec_init = wpas_macsec_init;
kay_ctx->macsec_deinit = wpas_macsec_deinit;
+ kay_ctx->macsec_get_capability = wpas_macsec_get_capability;
kay_ctx->enable_protect_frames = wpas_enable_protect_frames;
+ kay_ctx->enable_encrypt = wpas_enable_encrypt;
kay_ctx->set_replay_protect = wpas_set_replay_protect;
kay_ctx->set_current_cipher_suite = wpas_set_current_cipher_suite;
kay_ctx->enable_controlled_port = wpas_enable_controlled_port;
kay_ctx->get_receive_lowest_pn = wpas_get_receive_lowest_pn;
kay_ctx->get_transmit_next_pn = wpas_get_transmit_next_pn;
kay_ctx->set_transmit_next_pn = wpas_set_transmit_next_pn;
- kay_ctx->get_available_receive_sc = wpas_get_available_receive_sc;
+ kay_ctx->set_receive_lowest_pn = wpas_set_receive_lowest_pn;
kay_ctx->create_receive_sc = wpas_create_receive_sc;
kay_ctx->delete_receive_sc = wpas_delete_receive_sc;
kay_ctx->create_receive_sa = wpas_create_receive_sa;
+ kay_ctx->delete_receive_sa = wpas_delete_receive_sa;
kay_ctx->enable_receive_sa = wpas_enable_receive_sa;
kay_ctx->disable_receive_sa = wpas_disable_receive_sa;
- kay_ctx->get_available_transmit_sc = wpas_get_available_transmit_sc;
kay_ctx->create_transmit_sc = wpas_create_transmit_sc;
kay_ctx->delete_transmit_sc = wpas_delete_transmit_sc;
kay_ctx->create_transmit_sa = wpas_create_transmit_sa;
+ kay_ctx->delete_transmit_sa = wpas_delete_transmit_sa;
kay_ctx->enable_transmit_sa = wpas_enable_transmit_sa;
kay_ctx->disable_transmit_sa = wpas_disable_transmit_sa;
- res = ieee802_1x_kay_init(kay_ctx, policy, wpa_s->ifname,
+ res = ieee802_1x_kay_init(kay_ctx, policy, ssid->macsec_replay_protect,
+ ssid->macsec_replay_window, ssid->macsec_port,
+ ssid->mka_priority, wpa_s->ifname,
wpa_s->own_addr);
- if (res == NULL) {
- os_free(kay_ctx);
+ /* ieee802_1x_kay_init() frees kay_ctx on failure */
+ if (res == NULL)
return -1;
- }
wpa_s->kay = res;
@@ -260,7 +276,7 @@ static int ieee802_1x_auth_get_session_id(struct wpa_supplicant *wpa_s,
return -1;
}
- need_len = 1 + 2 * SSL3_RANDOM_SIZE;
+ need_len = 1 + 2 * 32 /* random size */;
if (need_len > id_len) {
wpa_printf(MSG_DEBUG, "EAP Session-Id not long enough");
return -1;
@@ -341,8 +357,8 @@ void * ieee802_1x_notify_create_actor(struct wpa_supplicant *wpa_s,
/* Derive CAK from MSK */
cak->len = DEFAULT_KEY_LEN;
- if (ieee802_1x_cak_128bits_aes_cmac(msk->key, wpa_s->own_addr,
- peer_addr, cak->key)) {
+ if (ieee802_1x_cak_aes_cmac(msk->key, msk->len, wpa_s->own_addr,
+ peer_addr, cak->key, cak->len)) {
wpa_printf(MSG_ERROR,
"IEEE 802.1X: Deriving CAK failed");
goto fail;
@@ -351,9 +367,8 @@ void * ieee802_1x_notify_create_actor(struct wpa_supplicant *wpa_s,
/* Derive CKN from MSK */
ckn->len = DEFAULT_CKN_LEN;
- if (ieee802_1x_ckn_128bits_aes_cmac(msk->key, wpa_s->own_addr,
- peer_addr, sid, sid_len,
- ckn->name)) {
+ if (ieee802_1x_ckn_aes_cmac(msk->key, msk->len, wpa_s->own_addr,
+ peer_addr, sid, sid_len, ckn->name)) {
wpa_printf(MSG_ERROR,
"IEEE 802.1X: Deriving CKN failed");
goto fail;
@@ -377,3 +392,49 @@ fail:
return res;
}
+
+
+void * ieee802_1x_create_preshared_mka(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+ struct mka_key *cak;
+ struct mka_key_name *ckn;
+ void *res = NULL;
+
+ if ((ssid->mka_psk_set & MKA_PSK_SET) != MKA_PSK_SET)
+ goto end;
+
+ ckn = os_zalloc(sizeof(*ckn));
+ if (!ckn)
+ goto end;
+
+ cak = os_zalloc(sizeof(*cak));
+ if (!cak)
+ goto free_ckn;
+
+ if (ieee802_1x_alloc_kay_sm(wpa_s, ssid) < 0 || !wpa_s->kay)
+ goto free_cak;
+
+ if (wpa_s->kay->policy == DO_NOT_SECURE)
+ goto dealloc;
+
+ cak->len = ssid->mka_cak_len;
+ os_memcpy(cak->key, ssid->mka_cak, cak->len);
+
+ ckn->len = ssid->mka_ckn_len;
+ os_memcpy(ckn->name, ssid->mka_ckn, ckn->len);
+
+ res = ieee802_1x_kay_create_mka(wpa_s->kay, ckn, cak, 0, PSK, FALSE);
+ if (res)
+ goto free_cak;
+
+dealloc:
+ /* Failed to create MKA */
+ ieee802_1x_dealloc_kay_sm(wpa_s);
+free_cak:
+ os_free(cak);
+free_ckn:
+ os_free(ckn);
+end:
+ return res;
+}
diff --git a/contrib/wpa/wpa_supplicant/wpas_kay.h b/contrib/wpa/wpa_supplicant/wpas_kay.h
index b7236d0776c4..81f8e0ce329e 100644
--- a/contrib/wpa/wpa_supplicant/wpas_kay.h
+++ b/contrib/wpa/wpa_supplicant/wpas_kay.h
@@ -17,6 +17,9 @@ void * ieee802_1x_notify_create_actor(struct wpa_supplicant *wpa_s,
const u8 *peer_addr);
void ieee802_1x_dealloc_kay_sm(struct wpa_supplicant *wpa_s);
+void * ieee802_1x_create_preshared_mka(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
+
#else /* CONFIG_MACSEC */
static inline int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s,
@@ -36,6 +39,13 @@ static inline void ieee802_1x_dealloc_kay_sm(struct wpa_supplicant *wpa_s)
{
}
+static inline void *
+ieee802_1x_create_preshared_mka(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+ return 0;
+}
+
#endif /* CONFIG_MACSEC */
#endif /* WPAS_KAY_H */
diff --git a/contrib/wpa/wpa_supplicant/wps_supplicant.c b/contrib/wpa/wpa_supplicant/wps_supplicant.c
index 74a420c671d0..057927410256 100644
--- a/contrib/wpa/wpa_supplicant/wps_supplicant.c
+++ b/contrib/wpa/wpa_supplicant/wps_supplicant.c
@@ -203,6 +203,9 @@ static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s,
if (ssid->ssid == NULL)
return;
bss = wpa_bss_get(wpa_s, cred->mac_addr, ssid->ssid, ssid->ssid_len);
+ if (!bss)
+ bss = wpa_bss_get(wpa_s, wpa_s->bssid,
+ ssid->ssid, ssid->ssid_len);
if (bss == NULL) {
wpa_printf(MSG_DEBUG, "WPS: The AP was not found from BSS "
"table - use credential as-is");
@@ -490,6 +493,16 @@ static int wpa_supplicant_wps_cred(void *ctx,
ssid->pairwise_cipher |= WPA_CIPHER_GCMP;
ssid->group_cipher |= WPA_CIPHER_GCMP;
}
+ if (wpa_s->drv_capa_known &&
+ (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP_256)) {
+ ssid->pairwise_cipher |= WPA_CIPHER_GCMP_256;
+ ssid->group_cipher |= WPA_CIPHER_GCMP_256;
+ }
+ if (wpa_s->drv_capa_known &&
+ (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_CCMP_256)) {
+ ssid->pairwise_cipher |= WPA_CIPHER_CCMP_256;
+ ssid->group_cipher |= WPA_CIPHER_CCMP_256;
+ }
break;
}
@@ -517,11 +530,18 @@ static int wpa_supplicant_wps_cred(void *ctx,
case WPS_AUTH_WPA2PSK:
ssid->auth_alg = WPA_AUTH_ALG_OPEN;
ssid->key_mgmt = WPA_KEY_MGMT_PSK;
+ if (wpa_s->conf->wps_cred_add_sae &&
+ cred->key_len != 2 * PMK_LEN) {
+ ssid->key_mgmt |= WPA_KEY_MGMT_SAE;
+#ifdef CONFIG_IEEE80211W
+ ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
+#endif /* CONFIG_IEEE80211W */
+ }
ssid->proto = WPA_PROTO_RSN;
break;
}
- if (ssid->key_mgmt == WPA_KEY_MGMT_PSK) {
+ if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
if (cred->key_len == 2 * PMK_LEN) {
if (hexstr2bin((const char *) cred->key, ssid->psk,
PMK_LEN)) {
@@ -1027,10 +1047,9 @@ static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s,
continue;
os_free(ssid->ssid);
- ssid->ssid = os_malloc(bss->ssid_len);
+ ssid->ssid = os_memdup(bss->ssid, bss->ssid_len);
if (ssid->ssid == NULL)
break;
- os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
ssid->ssid_len = bss->ssid_len;
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Picked SSID from "
"scan results",
@@ -1125,9 +1144,10 @@ static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
- int p2p_group)
+ int p2p_group, int multi_ap_backhaul_sta)
{
struct wpa_ssid *ssid;
+ char phase1[32];
#ifdef CONFIG_AP
if (wpa_s->ap_iface) {
@@ -1165,10 +1185,15 @@ int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
}
}
#endif /* CONFIG_P2P */
- if (wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0) < 0)
+ os_snprintf(phase1, sizeof(phase1), "pbc=1%s",
+ multi_ap_backhaul_sta ? " multi_ap=1" : "");
+ if (wpa_config_set_quoted(ssid, "phase1", phase1) < 0)
return -1;
if (wpa_s->wps_fragment_size)
ssid->eap.fragment_size = wpa_s->wps_fragment_size;
+ if (multi_ap_backhaul_sta)
+ ssid->multi_ap_backhaul_sta = 1;
+ wpa_supplicant_wps_event(wpa_s, WPS_EV_PBC_ACTIVE, NULL);
eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
wpa_s, NULL);
wpas_wps_reassoc(wpa_s, ssid, bssid, 0);
@@ -1481,6 +1506,9 @@ static void wpas_wps_set_uuid(struct wpa_supplicant *wpa_s,
wpa_s->global->ifaces->wps->uuid,
WPS_UUID_LEN);
src = "from the first interface";
+ } else if (wpa_s->conf->auto_uuid == 1) {
+ uuid_random(wps->uuid);
+ src = "based on random data";
} else {
uuid_gen_mac_addr(wpa_s->own_addr, wps->uuid);
src = "based on MAC address";
diff --git a/contrib/wpa/wpa_supplicant/wps_supplicant.h b/contrib/wpa/wpa_supplicant/wps_supplicant.h
index c8fe47e37279..0fbc85174f94 100644
--- a/contrib/wpa/wpa_supplicant/wps_supplicant.h
+++ b/contrib/wpa/wpa_supplicant/wps_supplicant.h
@@ -30,7 +30,7 @@ void wpas_wps_deinit(struct wpa_supplicant *wpa_s);
int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s);
enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid);
int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
- int p2p_group);
+ int p2p_group, int multi_ap_backhaul_sta);
int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
const char *pin, int p2p_group, u16 dev_pw_id);
void wpas_wps_pbc_overlap(struct wpa_supplicant *wpa_s);