cumilative patch from commit 795075444
Bug: 341971059
Bug: 387693074
Test: Connect to open, WPA2, WPA3 and OWE
Test: Establish P2P connection
Test: Basic SoftAp tests
Test: Ran above tests on Pixel6
Test: Regression test (b/387705228)
BYPASS_INCLUSIVE_LANGUAGE_REASON=Merged from open source
795075444 EAP-TEAP: Add a compatibility mode for FreeRADIUS
50af5c1c9 EAP-TEAP: Fix S-IMCK derivation based on RFC 7170bis
9e04dac3c WNM: A more explicit check for a connection
b9e798339 MBO: Get rid of the is_first flag in neighbor report array
1f4a2e825 WNM: Use standard BSS selection and enable abridged bit handling
f3a8e4284 WNM: Fix pre-scan rejection heuristic for BTM handling
42fe546e0 tests: get_bss_transition_status() driver op
53f9d6f69 WNM: Move driver MBO transition rejection into wnm_is_bss_excluded()
977edbdd9 EAP-TEAP: Remove deprecated PAC support
2d74d34d3 Clear the pending EAPOL RX on disconnection
84c904093 WPS: Fix a race condition on WPS_CANCEL handling
1888b7efd Use BSS-specific ACL configuration when setting up driver-based ACL
ce7b3c2ca MBSSID: Allow BSS Index and maximum number of BSSs to be configured
2fe7a2b80 Do not add extra IEs to scan request if they do not fit driver limit
66442d1bc nl80211: Fetch maximum length of extra IE(s) for Probe Request frames
df0b6fa90 Introduce DUMP_BEACON command
7b529aad9 EAP-TEAP: Don't complain about missing PAC when teap_provisioning=0
edd85280f Check last scan SSIDs before triggering new scan for hidden network
470e32c20 Update link to prplMesh repository
9d80d5d71 Handle CONFIG_NO_WPA for wpa_sm_has_ptk_installed()
3fa38e55c mka: Accept MKPDU sent to any multicast address
ee9cd7d74 OWE: Fix SSID comparison in transition mode case
093a01422 OWE: Accept only BSS entries with an actual SSID for ROAM command
38ccd0677 nl80211: Use wpa_msg() to report netlink errors
614d42a50 nl80211: Make drv pointer available to send_and_recv()
13a4d7b09 hostapd: Respect obss_interval on 40 MHz intolerant disconnect
f8b898244 P2P2: Use global interface for USD
75b25ffbe nl80211: Allow PASN Authentication frames on P2P device interface
abedecd14 P2P2: Fix frequency selection for auto GO join
546812862 P2P2: Make sure password is set when using non opportunistic methods
af7d1a012 P2P2: Report R2 information in P2P-DEVICE-FOUND event
53d15ddc5 NAN: Remove excessive debug print about the next timer
0c496d3c5 wpa_cli: Support NAN USD commands
06c5265f7 NAN: Fix A3 for unicast P2P2 USD
50c563785 NAN: Fix A3 for multicast P2P2 USD
c330b5820 Send CTRL-EVENT-SIGNAL-CHANGE message to control interfaces only
d17a85ea1 hostapd: hostapd_cleanup_iface_partial: Fix hw_features use after free
089e360cc Android: Wrap a P2P-specific chunk in CONFIG_P2P
44a0560f1 EAPOL: Fix PMK setting for driver-based FT-SHA384
d8772c195 DPP: Handle EVENT_TX_WAIT_EXPIRE path for push button
6b5e7c003 P2P2: Remove redundant enable_pairing_verification flag
a931a4782 Fix using invalid memory during driver deinit
f55b9c405 Update STA authorized flag for AP SME in driver cases for open network
65338c581 Fix CONFIG_NO_STDOUT_DEBUG=y build
fbc67eae4 Fix sae_pk_gen compilation
430bc89b9 Include base64 for hostapd CONFIG_SAE_PK builds
c9a3b3e75 ext_password_file: Do not use wpa_config_get_line()
0d3db4fe5 Fix nan_usd linker error
550513ee5 Comment out WPA related code additions with CONFIG_NO_WPA
631fbbcfc Use consistent ifdef CONFIG_NO_WPA blocks
6857b0c41 Add empty inline functions for CONFIG_NO_WPA
24df236ca Fix CONFIG_NO_WPA compile/link errors related to RSNXE
1f88e0463 Include HMAC-SHA384/512 KDF for SAE if SHA384/512 is included
4e8686cd1 hlr_auc_gw: Add TERMINATE command
b39a9cae8 AP MLD: Do not try to set hapd->mld multiple times
baeedceb0 hostapd: Fix wrong puncturing bitmap in Bandwidth Indication subelement
5a0572a49 hostapd: Move punct_bitmap into hostapd_freq_params
982c634ac hostapd: Fix length of Bandwidth Indication subelement
290a793b0 Avoid EAPOL trigger in reassoc path for AP with 4-way handshake offload
782b0c2ba AP MLD: Fix a crash in hostapd_driver_init()
4f05eead3 BSS: MLD: Parse all TBTT entries after an invalid link
26273daef BSS: MLD: Limit TBTT parsing to correct length
8e490da87 P2P: Consult driver capabilities before setting HE bit in GO's conf
ca0bb5cc9 mesh: Use the correct 6 GHz operating class 137 for 320 MHz bandwidth
01677c47f AP: Support disconnect with MLD
45f626113 P2P: Check P2P 6 GHz capability to start P2P GO
3e5d2dbea Add QCA vendor attributes to configure antenna selection
7c52ff140 P2P2: Allow P2P2 client to connect to GO with preconfigured credentials
305cd9049 P2P2: Handle join case without pending GO interface address
2552de375 EHT: Fix HE center frequency for EHT 320 MHz with puncturing
888c5b212 nl80211: Update channels unavailability for 320 MHz
338e79b6f AP MLD: Fix radar event processing
711e837fd EHT: Update legacy bandwidth when puncturing is set in 320 MHz
4bcf145ca EHT: Update legacy bandwidth for 320 MHz in Wide Bandwidth subelement
e3fe940ac nl80211: Use nl80211_bss_msg() helper wherever BSS is accessible
00c2c20d7 hostapd: Maintain single wpa_driver_nl80211_data (drv) object across interfaces
54eeaa075 Add a vendor attribute to disable DFS owner capability
7ff2ee8cd Remove empty line between vendor attribute documentation and definition
e833c5af3 Add new QCA vendor attributes for TWT session updatability
3f046c7ce QCA vendor attribute to configure operating type for monitor mode
c0e8b16a3 AP MLD: Fix max number of simultaneous links in MLE during CAC
acc35945a AP: Fix dangling pointer access during 6 GHz NO_IR channel list update
525f7d94c Force a global operating class to be used with Wi-Fi Agile Multiband
63d77c899 SAE: Reject association for no PMKID match only for PMKSA caching
04f4caad5 DPP: Deinit Configurator process if Config Requst is not received
93f623f74 AP MLD: Fix crash during config reload from non-ML to ML
5e6119234 AP: Handle (Re)Association Response frame if rsn_override_omit_rsnxe is set
9ec982cb4 AP MLD: Show maximum number of simultaneous links info for non-AP MLDs
4cbbcd3b6 AP MLD: Show AP MLD Type Indication in STATUS command
4c3b32932 AP MLD: Show puncture bitmap in STATUS command
64ac39354 P2P: Avoid infinite loop with radio_remove_works(p2p-listen)
ae5ef60ed AP MLD: Remove common elements from per STA profile
7855b6d60 AP MLD: Send EML capabilities of an ML station to the driver
e0aac2cd3 AP MLD: Add NULL check for mld pointer during MLD link removal
a158fecc9 AP MLD: Remove unnecessary wpa_group get and put for ML cases
6637b44a9 AP MLD: Remove unnecessary outer for loop in authorizing ML STA
475f50d71 P2P2: Allow op class and channel override for Invitation Response
ebffcffd7 P2P2: Set P2P mode (R1 vs. R2) in the driver
61a36a226 P2P2: P2P connection compatibility mode with RSN overriding
007d3f01b RSNO: Allow RSN overriding to be enabled for a specific network
89455cc07 Add new QCA vendor attributes for TWT setup parameters
b74e8c1b1 Add new QCA vendor TWT capability values
374b73d4d Add a new QCA vendor attribute for TWT session suspendability
25d29d65a P2P: Clear wpa_s->p2p2 for NFC cases
59c608bd8 wlantest: Use AP's RSNXOE for capabilities when RSNO is used
0c147e622 NAN USD: Do not start pause state for P2P2 on Subscribe message RX
cd8b3ad8d NAN USD: Use different group address for P2P2
0806c21db P2P2: Allow PASN-PTK to be fetched for testing purposes
bd010a7ec P2P2: Allow P2P-PMK to be extracted for testing purposes
4ebca723f P2P2: Allow device address change when reinvoking a persistent group
df37010ad P2P2: Command to remove all P2P2 identity keys
7f6fbba23 P2P2: Store device identity key in wpa_supplicant configuration
1525e84d4 Helper functions for fetching PMK and PMKID
d0e2570a7 P2P2: Store WPA3 connection credentials in the configuration
95c195014 P2P2: Fix memory leak in awork deinit case for PASN authentication
29912be14 hostapd: Pass link ID for non-link agnostic Action frames
65d865e62 AP: Avoid double free of key data buffer if AES unwrap fails
422c5dc91 AP: NULL pointer check for bssid in hostapd_mgmt_tx_cb()
37061ef86 nl80211: NULL pointer check for msg in i802_flush()
9fdbc5901 dbus: NAN USD: Actually use freq_list parameter in NANPublish
5920e2b97 Automatic generation of supported WFA generational capabilities on STA
d4cd22ac9 Convert wpa_s->hw_capab into a bitmap and add HE and EHT
8f5ae8801 Wi-Fi Generational Capabilities Indication transmission on STA
c97b35bd9 Wi-Fi Generational Capabilities Indication reception on AP
a0ba416e7 Definitions for Wi-Fi Alliance generational capabilities indication
74792088b AP: Update the list of Action frame categories that are not robust
e9fc4eec3 nl80211: Register to receive Vendor Specific Protected action frames
2c46ebfd2 Control interface command to generate new random MAC address
eea566cfa NAN: Do not expire USD services based on last TX/RX message
77ac40275 NAN: Wait on the channel with publisher is in pauseState
3d6360fb5 NAN: Limit pauseState to be within service lifetime
2817554a3 NAN: Print a debug entry on TX wait time expiration
296141fe9 NAN: Make DE aware of maximum driver supported listen time
b752dfc1d NAN: Do not unpause publisher on fixed Follow-up message timeout
4ea2c336d P2P2: Add wpa_supplicant configuration parameters for P2P2
5f507ffcc dbus: Increment introspection buffer size
e9daa3fca P2P2: Enable TWT and Channel Usage support by default
b62bef8c2 Channel Usage, peer-to-peer TWT and TWT requester support
41d09f844 P2P2: Configuration of channel switch request for testing purposes
c2f90ef35 Avoid undefined behavior in RSNXE capability bit checker
c009ac474 P2P2: Validate DIRA and configure PMK
417c67468 P2P2: Add device identity block to wpa_supplicant configuration
72e154dbd P2P2: Update P2P Device Address when changing netdev address
a9c33fa0d P2P: Print dst/src/bssid in Action frame TX debug message
ea4e0116d SAE: Do not allow password identifier to be used without H2E
afd120d03 SAE: Send Commit message with unknown-password-id from Nothing state
90a3b4a91 SAE: Do not use the wpa_passphrase if SAE password identifier was used
d3b5887f3 Add new QCA vendor attributes for TWT statistics
6742284dc Add new QCA vendor TWT status values
999ef0499 Reserve QCA vendor sub command id 255
75e767666 Add QCA vendor interface for additional TWT Setup command types
9ff75554a dbus: Notify P2P2 bootstrapping request and completed events
319c4b4e9 P2P2: Configure PMK/PMKID to the driver on the GO
f35c8a9ff P2P2: Enable PASN on a P2P GO
ae36944a9 Control interface command to flush NAN publish and subscribe sessions
e5c8774e4 P2P2: Fix pairing verification without encrypted elements
103314d55 P2P2: Determine PASN KEK derivation based on peer capabilities
be8f31acb PASN: Mark PMK and PMKID const in functions adding PMKSA entries
e5edc8a6f P2P2: Remember password from connect command to starting after scan
a01652bd5 P2P2: Start client for join without WPS
bfd799126 P2P2: Support for GO to allow a client to join the group
a2f634be8 P2P2: Provisioning step on GO when a client joins
ba5bf4a34 P2P2: Fix a typo in function documentation
564c969a5 P2P2: Fix peer entry generation based on USD
07ee3e8b0 Remove STA entries if association is not completed in 60 seconds
28ebad01e SAE: More robust password identifier checks for AP mode
8a3351055 SAE: Reject unexpected password identifier in commit message parser
18e8a525b SAE: Avoid duplicated debug entries for IEs in SAE commit messages
161327f91 hostapd: Fix clearing up settings for color switch
914f3fe8d P2P2: Do not add WPS IE to join-a-group scan
b41138a13 P2P2: Use PASN for joining a group
ebdc3b53b P2P2: Allow group to be added for P2P2 as autonomous GO
d91466a4f P2P2: Add PMKSA entry on successful group formation
b80b37910 P2P2: Fix to check if sae_password is present
96e48a05a P2P2: Invitation using pairing verification
4efc0bd02 P2P2: Do not override peer_addr from BSSID in pairing verification
eed859cdf P2P2: Indicate P2P2 group in GO parameters
050618c88 P2P2: Set up PMKSA for pairing verification
29ad7ffe7 P2P2: Export p2p_build_inviation_req()
e6a96dbce P2P2: Do not add WSC IE for P2P2 Invitation Request
ff02a87c1 P2P2: Fetch PMK and PMKID for invitation using pairing verification
431053e39 P2P2: Stop invitation process before sending out Invitation Request
71b443a98 P2P2: Indication on whether P2P2 is used with P2P_INVITE
7ba52f6a4 P2P2: Parameter setting for testing purpose
9d0aad0fa P2P2: Enable GCMP-256 as a pairwise cipher
c55d1f9e8 P2P2: Clone P2P2 and bootstrapping state to group interfaces
cf30af7c2 P2P2: Start P2P Client appropriately for P2P2 group
339f39e10 P2P2: Add P2P2 IE for groups using P2P2
fa4b6e37b P2P2: Start GO with suitable parameters for P2P2
240e1297d P2P2: Indicate SAE password and PMK from pairing with GO negotiation
6efcc17cb P2P: Clear GO negotiation results from stack after use
84a4e0004 P2P2: Select PMKSA based on P2P Device Address and PMKID match
048c30cb4 P2P2: Function callbacks for PASN
394beb560 P2P2: Add a SAE password in PASN Encrypted Data element
626a73a6a P2P2: Parse and store peer's SAE password
3207ad1ca P2P2: Parser function for PASN Encrypted Data element and DevIK
b787d1621 FILS: Verify RSNXE when processing (Re)Association Response frame
d1337b159 RSNO: Omit RSNXE in (Re)Association Response frame like in Beacon frame
a041777ff FT: Omit RSNXE from Reassociation Response frame only with FT protocol
ae6d2a5c0 AP: Use helper functions in ap_sta_disconnect()
dc9616f58 AP: Clean up MLD changes that modified skipping DMG deauthentication
6aef223ce Avoid memcmp() with NULL pointer even if for zero length
5b4c8bdd2 wpa_supplicant: 320 MHz bandwidth support for mesh
5834062c2 AP MLD: Allow link ID to be specified for Action frame TX operations
bfc89d757 nl80211: Handle radar event properly during MLO
2657e97c5 nl80211: Send link ID when starting CAC for radar detection
00daadff9 hostapd: Fix clearing old BSS during config reload
8035c11df Remove unused arguments in ieee802_11_parse_link_assoc_req()
b83859c78 scan: Pass correct link ID in all cases
9bc75ef93 Add a QCA vendor event to indicate status of the idle shutdown
a9e562b29 Update documentation of the QCA vendor ACS channel list attributes
23e8a42ca wlantest: Fix BIP replay protection check
ea2ff4b3f FT: Do not omit RSNXE from FT initial mobility domain association
ec198cfae SAE: Allow network profile sae_pwe to be configured
2e061a909 P2P2: PASN Authentication frame TX status handling
c449b2e09 P2P2: Initiate PASN on bootstrapping completion
e147d24a0 P2P2: Add support for GO Negotiation wrapped in PASN auth frame
9304e899f PASN: Store PASN authentication frames 1 and 2
8cef9b1b1 PASN: Extend maximum buffer length in 3rd auth frame
e15242565 PASN: Routines for generating and processing encrypted data
0ff802a51 P2P2: Set DevIK expiration time to 24 hours
5fb90cf3f SAE: Use sae_pwe in network profile for STA mode
f46eb8d3f SAE: Extend Basic MLE Recognition to external auth case
4d6ad78d0 Extend EAPOL frames processing workaround for reassociation to same AP
e09358447 STA: Update driver roaming policy on connection completion
8a257f9a5 Add QCA vendor command to fetch offload scan data from firmware
7cd1f3c0a Add TEST_RSNXE_DATA for RSNXE testing of AP functionality
bb1316baa Allow forced enabling of EAPOL-Key msg 2/4 key info bits for testing
236d25e75 QCA vendor interface to exclude 6 GHz non-PSC channels as primary channel in ACS
eb529b0b5 Add QCA vendor status for TWT termination due to multiple MLO links activated
9e22afa48 Fix STA's SSID protection capability when AP SME is offloaded to driver
85cd98976 dbus: Methods for NAN USD
dcf58aec8 dbus: Signals for NAN USD
d2408e303 dbus: Dict helpers for fetching integers of any type
fd1a149d9 NAN: Fix UpdatePublish offload to driver
b3bd49f3c NAN: Handle A3 copying internally to simplify control interface
fbbc9cb9e NAN: Update A3 for USD to use NAN Network ID or NAN Cluster ID in A3
e0496580a hostapd: Add drv_send_action variant for forcing A3
83f9dcbb3 NAN: Process received NAN SDFs with NAN Network ID in A3 on AP
ccba6921d SAE: Recognize Basic MLE in Authentication frames even without H2E
c97168f58 FT: Discard EAPOL-Start frames when FT was used for association
f54359915 nl80211: Remove nl_msg free on send failure for NAN USD commands
61960e6c6 P2P2: Add alternative PASN RX handler
7d13410a8 SAE: Mark the groups argument to sae_derive_pt() const
9edd8b441 nl80211: Fix conditional checks of nlmsg attributes for NAN publish
Change-Id: If300ab0f4e93d221e7e576a08e11825cb0fd0bf9
Signed-off-by: Sunil Ravi <sunilravi@google.com>
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 581d907..1b5ea81 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -329,6 +329,7 @@
ifdef CONFIG_NAN_USD
OBJS += src/common/nan_de.c
OBJS += nan_usd.c
+NEED_OFFCHANNEL=y
L_CFLAGS += -DCONFIG_NAN_USD
endif
@@ -763,7 +764,7 @@
EAPDYN += src/eap_common/eap_teap_common.c
else
L_CFLAGS += -DEAP_TEAP
-OBJS += src/eap_peer/eap_teap.c src/eap_peer/eap_teap_pac.c
+OBJS += src/eap_peer/eap_teap.c
OBJS += src/eap_common/eap_teap_common.c
endif
TLS_FUNCS=y
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 8bec178..49c1793 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -320,6 +320,7 @@
ifdef CONFIG_NAN_USD
OBJS += ../src/common/nan_de.o
OBJS += nan_usd.o
+NEED_OFFCHANNEL=y
CFLAGS += -DCONFIG_NAN_USD
endif
@@ -763,7 +764,7 @@
ifdef CONFIG_EAP_TEAP
# EAP-TEAP
-SRC_EAP_TEAP = ../src/eap_peer/eap_teap.c ../src/eap_peer/eap_teap_pac.c
+SRC_EAP_TEAP = ../src/eap_peer/eap_teap.c
SRC_EAP_TEAP += ../src/eap_common/eap_teap_common.c
ifeq ($(CONFIG_EAP_TEAP), dyn)
CFLAGS += -DEAP_TEAP_DYNAMIC
diff --git a/wpa_supplicant/aidl/vendor/p2p_iface.cpp b/wpa_supplicant/aidl/vendor/p2p_iface.cpp
index fa176a4..8590693 100644
--- a/wpa_supplicant/aidl/vendor/p2p_iface.cpp
+++ b/wpa_supplicant/aidl/vendor/p2p_iface.cpp
@@ -191,7 +191,8 @@
if (wpas_p2p_group_add_persistent(
wpa_s, wpa_network, 0, 0, freq, 0, ht40, vht,
CONF_OPER_CHWIDTH_USE_HT, he, 0, NULL, 0, 0, is6GhzAllowed(wpa_s),
- P2P_JOIN_LIMIT, isAnyEtherAddr(group_owner_bssid) ? NULL : group_owner_bssid)) {
+ P2P_JOIN_LIMIT, isAnyEtherAddr(group_owner_bssid) ? NULL : group_owner_bssid,
+ NULL, NULL, NULL, 0)) {
ret = -1;
}
@@ -1139,7 +1140,7 @@
wpa_s, peer_address.data(), pin, wps_method, persistent, false,
join_existing_group, false, go_intent_signed, 0, 0, -1, false, ht40,
vht, CONF_OPER_CHWIDTH_USE_HT, he, edmg, nullptr, 0, is6GhzAllowed(wpa_s),
- false, 0, NULL);
+ false, 0, NULL, false);
if (new_pin < 0) {
return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
}
@@ -1263,7 +1264,7 @@
}
if (wpas_p2p_invite(
wpa_s, peer_address.data(), ssid, NULL, 0, 0, ht40, vht,
- CONF_OPER_CHWIDTH_USE_HT, 0, he, edmg, is6GhzAllowed(wpa_s))) {
+ CONF_OPER_CHWIDTH_USE_HT, 0, he, edmg, is6GhzAllowed(wpa_s), false)) {
return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
}
return ndk::ScopedAStatus::ok();
@@ -1726,7 +1727,8 @@
if (ssid == NULL) {
if (wpas_p2p_group_add(
wpa_s, persistent, 0, 0, ht40, vht,
- CONF_OPER_CHWIDTH_USE_HT, he, edmg, is6GhzAllowed(wpa_s))) {
+ CONF_OPER_CHWIDTH_USE_HT, he, edmg, is6GhzAllowed(wpa_s),
+ false, WPA_P2P_MODE_WFD_R1)) {
return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
} else {
return ndk::ScopedAStatus::ok();
@@ -1735,7 +1737,8 @@
if (wpas_p2p_group_add_persistent(
wpa_s, ssid, 0, 0, 0, 0, ht40, vht,
CONF_OPER_CHWIDTH_USE_HT, he, edmg, NULL, 0, 0,
- is6GhzAllowed(wpa_s), 0, NULL)) {
+ is6GhzAllowed(wpa_s), 0, NULL,
+ NULL, NULL, NULL, 0)) {
return createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN);
} else {
return ndk::ScopedAStatus::ok();
@@ -1785,7 +1788,8 @@
if (wpas_p2p_group_add(
wpa_s, persistent, freq, 0, ht40, vht,
- CONF_OPER_CHWIDTH_USE_HT, he, edmg, is6GhzAllowed(wpa_s))) {
+ CONF_OPER_CHWIDTH_USE_HT, he, edmg, is6GhzAllowed(wpa_s),
+ false, WPA_P2P_MODE_WFD_R1)) {
return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
}
return ndk::ScopedAStatus::ok();
diff --git a/wpa_supplicant/aidl/vendor/sta_iface.cpp b/wpa_supplicant/aidl/vendor/sta_iface.cpp
index 9e76f56..fe6738c 100644
--- a/wpa_supplicant/aidl/vendor/sta_iface.cpp
+++ b/wpa_supplicant/aidl/vendor/sta_iface.cpp
@@ -2104,7 +2104,7 @@
#endif
AidlManager *aidl_manager = AidlManager::getInstance();
WPA_ASSERT(aidl_manager);
- if (aidl_manager->isAidlServiceVersionAtLeast(4) && wpas_rsn_overriding(wpa_s)) {
+ if (aidl_manager->isAidlServiceVersionAtLeast(4) && wpas_rsn_overriding(wpa_s, NULL)) {
mask |= static_cast<uint32_t>(WpaDriverCapabilitiesMask::RSN_OVERRIDING);
}
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 69a0e5e..de18a68 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -540,12 +540,6 @@
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->extended_key_id = wpa_s->conf->extended_key_id;
bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk;
@@ -582,6 +576,18 @@
else
bss->wpa_key_mgmt = ssid->key_mgmt;
bss->wpa_pairwise = ssid->pairwise_cipher;
+
+#ifdef CONFIG_P2P
+ if (ssid->p2p_mode == WPA_P2P_MODE_WFD_PCC) {
+ bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
+ bss->rsn_override_key_mgmt = WPA_KEY_MGMT_SAE |
+ WPA_KEY_MGMT_PASN;
+ bss->wpa_pairwise = WPA_CIPHER_CCMP;
+ bss->rsn_override_pairwise = WPA_CIPHER_CCMP;
+ bss->rsn_override_mfp = 2;
+ }
+#endif /* CONFIG_P2P */
+
if (wpa_key_mgmt_sae(bss->wpa_key_mgmt) && ssid->passphrase) {
bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase);
} else if (ssid->psk_set) {
@@ -638,10 +644,7 @@
bss->sae_passwords = pw;
}
- if (ssid->sae_pwe != DEFAULT_SAE_PWE)
- bss->sae_pwe = ssid->sae_pwe;
- else
- bss->sae_pwe = wpa_s->conf->sae_pwe;
+ bss->sae_pwe = wpas_get_ssid_sae_pwe(wpa_s, ssid);
#endif /* CONFIG_SAE */
if (wpa_s->conf->go_interworking) {
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index 39de8ba..10ebab0 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -316,7 +316,8 @@
&owe_ssid_len))
continue;
- if (owe_ssid_len == ssid_len &&
+ if (bss->ssid_len &&
+ owe_ssid_len == ssid_len &&
os_memcmp(owe_ssid, ssid, ssid_len) == 0)
return bss;
#endif /* CONFIG_OWE */
@@ -1083,6 +1084,7 @@
if (wpa_s->reassoc_same_ess &&
wpa_s->wpa_state != WPA_COMPLETED &&
wpa_s->last_ssid &&
+ wpa_s->last_ssid->ssid &&
bss->ssid_len == wpa_s->last_ssid->ssid_len &&
os_memcmp(bss->ssid, wpa_s->last_ssid->ssid,
bss->ssid_len) == 0)
@@ -1588,7 +1590,7 @@
end = pos + len;
pos += sizeof(*ap_info);
- for (i = 0; i < count; i++) {
+ for (i = 0; i < count; i++, pos += ap_info->tbtt_info_len) {
u8 bss_params;
if (end - pos < ap_info->tbtt_info_len)
@@ -1599,7 +1601,7 @@
link_id = *(mld_params + 1) & EHT_ML_LINK_ID_MSK;
if (link_id >= MAX_NUM_MLD_LINKS)
- return;
+ continue;
if (*mld_params != mbssid_idx) {
wpa_printf(MSG_DEBUG,
@@ -1637,8 +1639,6 @@
RNR_TBTT_INFO_MLD_PARAM2_LINK_DISABLED;
}
}
-
- pos += ap_info->tbtt_info_len;
}
}
@@ -1711,11 +1711,11 @@
const u8 *rsne;
size_t rsne_len;
- if (elems.rsne_override_2 && wpas_rsn_overriding(wpa_s)) {
+ if (elems.rsne_override_2 && wpas_rsn_overriding(wpa_s, ssid)) {
rsne = elems.rsne_override_2;
rsne_len = elems.rsne_override_2_len;
} else if (elems.rsne_override &&
- wpas_rsn_overriding(wpa_s)) {
+ wpas_rsn_overriding(wpa_s, ssid)) {
rsne = elems.rsne_override;
rsne_len = elems.rsne_override_len;
} else {
@@ -1822,8 +1822,8 @@
goto out;
wpa_bss_parse_ml_rnr_ap_info(wpa_s, bss, mbssid_idx,
- ap_info, len, &seen,
- &missing, ssid);
+ ap_info, ap_info_len,
+ &seen, &missing, ssid);
pos += ap_info_len;
len -= ap_info_len;
@@ -1931,6 +1931,8 @@
}
+#ifndef CONFIG_NO_WPA
+
static bool wpa_bss_supported_cipher(struct wpa_supplicant *wpa_s,
int pairwise_cipher)
{
@@ -2056,14 +2058,17 @@
return true;
}
+#endif /* CONFIG_NO_WPA */
+
const u8 * wpa_bss_get_rsne(struct wpa_supplicant *wpa_s,
const struct wpa_bss *bss, struct wpa_ssid *ssid,
bool mlo)
{
+#ifndef CONFIG_NO_WPA
const u8 *ie;
- if (wpas_rsn_overriding(wpa_s)) {
+ if (wpas_rsn_overriding(wpa_s, ssid)) {
if (!ssid)
ssid = wpa_s->current_ssid;
@@ -2087,6 +2092,7 @@
return ie;
}
}
+#endif /* CONFIG_NO_WPA */
return wpa_bss_get_ie(bss, WLAN_EID_RSN);
}
@@ -2098,7 +2104,7 @@
{
const u8 *ie;
- if (wpas_rsn_overriding(wpa_s)) {
+ if (wpas_rsn_overriding(wpa_s, ssid)) {
ie = wpa_bss_get_vendor_ie(bss, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
if (ie) {
const u8 *tmp;
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 5b08478..9fe83a5 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2529,6 +2529,7 @@
{ INT(mem_only_psk) },
{ STR_KEY(sae_password) },
{ STR(sae_password_id) },
+ { INT(sae_pwe) },
{ FUNC(proto) },
{ FUNC(key_mgmt) },
{ INT(bg_scan_period) },
@@ -2543,7 +2544,7 @@
{ INT_RANGE(he, 0, 1) },
{ INT_RANGE(ht40, -1, 1) },
{ INT_RANGE(max_oper_chwidth, CONF_OPER_CHWIDTH_USE_HT,
- CONF_OPER_CHWIDTH_80P80MHZ) },
+ CONF_OPER_CHWIDTH_320MHZ) },
{ INT(vht_center_freq1) },
{ INT(vht_center_freq2) },
#ifdef IEEE8021X_EAPOL
@@ -2757,6 +2758,7 @@
{ INT_RANGE(enable_4addr_mode, 0, 1)},
{ INT_RANGE(max_idle, 0, 65535)},
{ INT_RANGE(ssid_protection, 0, 1)},
+ { INT_RANGE(rsn_overriding, 0, 2)},
};
#undef OFFSET
@@ -3028,6 +3030,7 @@
{
struct wpa_ssid *ssid, *prev = NULL;
struct wpa_cred *cred, *cprev;
+ struct wpa_dev_ik *identity, *iprev;
int i;
ssid = config->ssid;
@@ -3044,6 +3047,13 @@
wpa_config_free_cred(cprev);
}
+ identity = config->identity;
+ while (identity) {
+ iprev = identity;
+ identity = identity->next;
+ wpa_config_free_identity(iprev);
+ }
+
wpa_config_flush_blobs(config);
wpabuf_free(config->wps_vendor_ext_m1);
@@ -3097,6 +3107,8 @@
os_free(config->dpp_extra_conf_req_name);
os_free(config->dpp_extra_conf_req_value);
wpabuf_free(config->dik);
+ wpabuf_free(config->wfa_gen_capa_supp);
+ wpabuf_free(config->wfa_gen_capa_cert);
os_free(config);
}
@@ -3282,6 +3294,7 @@
#endif /* CONFIG_MACSEC */
ssid->mac_addr = WPAS_MAC_ADDR_STYLE_NOT_SET;
ssid->max_oper_chwidth = DEFAULT_MAX_OPER_CHWIDTH;
+ ssid->rsn_overriding = RSN_OVERRIDING_NOT_SET;
}
@@ -5497,6 +5510,14 @@
{ INT(p2p_interface_random_mac_addr), 0 },
{ INT(p2p_6ghz_disable), 0 },
{ INT(p2p_dfs_chan_enable), 0 },
+ { INT_RANGE(p2p_pairing_setup, 0, 1), 0 },
+ { INT_RANGE(p2p_pairing_cache, 0, 1), 0 },
+ { INT(p2p_bootstrap_methods), 0 },
+ { INT(p2p_pasn_type), 0 },
+ { INT(p2p_comeback_after), 0 },
+ { INT_RANGE(p2p_twt_power_mgmt, 0, 1), 0 },
+ { INT_RANGE(p2p_chan_switch_req_enable, 0, 1), 0 },
+ { INT(p2p_reg_info), 0 },
{ INT(dik_cipher), 0},
{ BIN(dik), 0 },
#endif /* CONFIG_P2P */
@@ -5577,6 +5598,7 @@
{ INT(gas_address3), 0 },
{ INT_RANGE(ftm_responder, 0, 1), 0 },
{ INT_RANGE(ftm_initiator, 0, 1), 0 },
+ { INT_RANGE(twt_requester, 0, 1), 0 },
{ INT(gas_rand_addr_lifetime), 0 },
{ INT_RANGE(gas_rand_mac_addr, 0, 2), 0 },
#ifdef CONFIG_DPP
@@ -5607,6 +5629,9 @@
{ FUNC(mld_connect_bssid_pref), 0 },
#endif /* CONFIG_TESTING_OPTIONS */
{ INT_RANGE(ft_prepend_pmkid, 0, 1), CFG_CHANGED_FT_PREPEND_PMKID },
+ { INT_RANGE(wfa_gen_capa, 0, 2), 0},
+ { BIN(wfa_gen_capa_supp), 0 },
+ { BIN(wfa_gen_capa_cert), 0 },
/* NOTE: When adding new parameters here, add_interface() in
* wpa_supplicant/dbus_new_introspect.c may need to be modified to
* increase the size of the iface->xml buffer. */
@@ -5774,3 +5799,129 @@
return ret;
}
+
+
+int wpa_config_set_identity(struct wpa_dev_ik *identity, const char *var,
+ const char *value, int line)
+{
+ char *val;
+ size_t len;
+ int ret = 0;
+
+ if (os_strcmp(var, "dik_cipher") == 0) {
+ identity->dik_cipher = atoi(value);
+ return 0;
+ }
+
+ val = wpa_config_parse_string(value, &len);
+ if (!val) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid field '%s' string value '%s'.",
+ line, var, value);
+ return -1;
+ }
+
+ if (os_strcmp(var, "dik") == 0) {
+ wpabuf_free(identity->dik);
+ identity->dik = wpabuf_alloc_copy(val, len);
+ if (!identity->dik)
+ ret = -1;
+ } else if (os_strcmp(var, "pmk") == 0) {
+ wpabuf_free(identity->pmk);
+ identity->pmk = wpabuf_alloc_copy(val, len);
+ if (!identity->pmk)
+ ret = -1;
+ } else if (os_strcmp(var, "pmkid") == 0) {
+ if (len == PMKID_LEN) {
+ wpabuf_free(identity->pmkid);
+ identity->pmkid = wpabuf_alloc_copy(val, len);
+ if (!identity->pmkid)
+ ret = -1;
+ } else {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid field '%s' string value '%s'.",
+ line, var, value);
+ ret = -1;
+ }
+ } else if (line) {
+ wpa_printf(MSG_ERROR, "Line %d: unknown identity field '%s'.",
+ line, var);
+ ret = -1;
+ }
+
+ os_free(val);
+ return ret;
+}
+
+
+void wpa_config_free_identity(struct wpa_dev_ik *identity)
+{
+ wpabuf_clear_free(identity->dik);
+ wpabuf_clear_free(identity->pmk);
+ wpabuf_free(identity->pmkid);
+ os_free(identity);
+}
+
+
+/**
+ * wpa_config_add_identity - Add a new device identity with empty configuration
+ * @config: Configuration data from wpa_config_read()
+ * Returns: The new device identity or %NULL if operation failed
+ */
+struct wpa_dev_ik * wpa_config_add_identity(struct wpa_config *config)
+{
+ int id;
+ struct wpa_dev_ik *identity, *last = NULL;
+
+ id = -1;
+ identity = config->identity;
+ while (identity) {
+ if (identity->id > id)
+ id = identity->id;
+ last = identity;
+ identity = identity->next;
+ }
+ id++;
+
+ identity = os_zalloc(sizeof(*identity));
+ if (!identity)
+ return NULL;
+ identity->id = id;
+ if (last)
+ last->next = identity;
+ else
+ config->identity = identity;
+
+ return identity;
+}
+
+
+/**
+ * wpa_config_remove_identity - Remove a configured identity based on id
+ * @config: Configuration data from wpa_config_read()
+ * @id: Unique network id to search for
+ * Returns: 0 on success, or -1 if the network was not found
+ */
+int wpa_config_remove_identity(struct wpa_config *config, int id)
+{
+ struct wpa_dev_ik *identity, *prev = NULL;
+
+ identity = config->identity;
+ while (identity) {
+ if (id == identity->id)
+ break;
+ prev = identity;
+ identity = identity->next;
+ }
+
+ if (!identity)
+ return -1;
+
+ if (prev)
+ prev->next = identity->next;
+ else
+ config->identity = identity->next;
+
+ wpa_config_free_identity(identity);
+ return 0;
+}
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 1281786..0643114 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -430,6 +430,47 @@
int sim_num;
};
+struct wpa_dev_ik {
+ /**
+ * next - Next device identity in the list
+ *
+ * This pointer can be used to iterate over all device identity keys.
+ * The head of this list is stored in the dev_ik field of struct
+ * wpa_config.
+ */
+ struct wpa_dev_ik *next;
+
+ /**
+ * id - Unique id for the identity
+ *
+ * This identifier is used as a unique identifier for each identity
+ * block when using the control interface. Each identity is allocated
+ * an id when it is being created, either when reading the
+ * configuration file or when a new identity is added.
+ */
+ int id;
+
+ /**
+ * dik_cipher - Device identity key cipher version
+ */
+ int dik_cipher;
+
+ /**
+ * dik - Device identity key which is unique for the device
+ */
+ struct wpabuf *dik;
+
+ /**
+ * pmk - PMK associated with the previous connection with the device
+ */
+ struct wpabuf *pmk;
+
+ /**
+ * pmkid - PMKID used in the previous connection with the device
+ */
+ struct wpabuf *pmkid;
+};
+
#define CFG_CHANGED_DEVICE_NAME BIT(0)
#define CFG_CHANGED_CONFIG_METHODS BIT(1)
@@ -872,6 +913,14 @@
int p2p_optimize_listen_chan;
int p2p_6ghz_disable;
int p2p_dfs_chan_enable;
+ bool p2p_pairing_setup;
+ bool p2p_pairing_cache;
+ int p2p_bootstrap_methods;
+ int p2p_pasn_type;
+ int p2p_comeback_after;
+ bool p2p_twt_power_mgmt;
+ bool p2p_chan_switch_req_enable;
+ int p2p_reg_info;
struct wpabuf *wps_vendor_ext_m1;
@@ -1804,17 +1853,9 @@
int wowlan_disconnect_on_deinit;
/**
- * rsn_overriding - RSN overriding
- *
- * 0 = Disabled
- * 1 = Enabled automatically if the driver indicates support
- * 2 = Forced to be enabled even without driver capability indication
+ * rsn_overriding - RSN overriding (default behavior)
*/
- enum rsn_overriding {
- RSN_OVERRIDING_DISABLED = 0,
- RSN_OVERRIDING_AUTO = 1,
- RSN_OVERRIDING_ENABLED = 2,
- } rsn_overriding;
+ enum wpas_rsn_overriding rsn_overriding;
#ifdef CONFIG_PASN
#ifdef CONFIG_TESTING_OPTIONS
@@ -1849,6 +1890,55 @@
/* DevIK */
struct wpabuf *dik;
+
+ /**
+ * identity - P2P2 peer device identities
+ *
+ * This is the head for the list of all the paired devices.
+ */
+ struct wpa_dev_ik *identity;
+
+ /**
+ * twt_requester - Whether TWT Requester Support is enabled
+ *
+ * This is for setting the bit 77 of the Extended Capabilities element.
+ */
+ bool twt_requester;
+
+ /**
+ * wfa_gen_capa: Whether to indicate Wi-Fi generational capability to
+ * the AP
+ *
+ * 0 = do not indicate (default)
+ * 1 = indicate in protected Action frame
+ * 2 = indicate in unprotected (Re)Association Request frame
+ */
+ enum {
+ WFA_GEN_CAPA_DISABLED = 0,
+ WFA_GEN_CAPA_PROTECTED = 1,
+ WFA_GEN_CAPA_UNPROTECTED = 2,
+ } wfa_gen_capa;
+
+ /**
+ * wfa_gen_capa_supp: Supported Generations (hexdump of a bit field)
+ *
+ * A bit field of supported Wi-Fi generations. This is encoded as an
+ * little endian octt string.
+ * bit 0: Wi-Fi 4
+ * bit 1: Wi-Fi 5
+ * bit 2: Wi-Fi 6
+ * bit 3: Wi-Fi 7
+ */
+ struct wpabuf *wfa_gen_capa_supp;
+
+ /**
+ * wfa_gen_capa_cert: Certified Generations (hexdump of a bit field)
+ *
+ * This has the same format as wfa_gen_capa_supp. This is an optional
+ * field, but if included, shall have the same length as
+ * wfa_gen_capa_supp.
+ */
+ struct wpabuf *wfa_gen_capa_cert;
};
@@ -1895,6 +1985,12 @@
const char *value, int line);
char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var);
+int wpa_config_set_identity(struct wpa_dev_ik *identity, const char *var,
+ const char *value, int line);
+void wpa_config_free_identity(struct wpa_dev_ik *identity);
+struct wpa_dev_ik * wpa_config_add_identity(struct wpa_config *config);
+int wpa_config_remove_identity(struct wpa_config *config, int id);
+
struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
const char *driver_param);
#ifndef CONFIG_NO_STDOUT_DEBUG
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 53614ae..4029d49 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -296,6 +296,65 @@
#endif /* CONFIG_NO_CONFIG_BLOBS */
+static struct wpa_dev_ik * wpa_config_read_identity(FILE *f, int *line, int id)
+{
+ struct wpa_dev_ik *identity;
+ int errors = 0, end = 0;
+ char buf[256], *pos, *pos2;
+
+ wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new identity block",
+ *line);
+ identity = os_zalloc(sizeof(*identity));
+ if (!identity)
+ return NULL;
+ identity->id = id;
+
+ while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) {
+ if (os_strcmp(pos, "}") == 0) {
+ end = 1;
+ break;
+ }
+
+ pos2 = os_strchr(pos, '=');
+ if (!pos2) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid identity line '%s'.",
+ *line, pos);
+ errors++;
+ continue;
+ }
+
+ *pos2++ = '\0';
+ if (*pos2 == '"') {
+ if (os_strchr(pos2 + 1, '"') == NULL) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid quotation '%s'.",
+ *line, pos2);
+ errors++;
+ continue;
+ }
+ }
+
+ if (wpa_config_set_identity(identity, pos, pos2, *line) < 0)
+ errors++;
+ }
+
+ if (!end) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: identity block was not terminated properly.",
+ *line);
+ errors++;
+ }
+
+ if (errors) {
+ wpa_config_free_identity(identity);
+ identity = NULL;
+ }
+
+ return identity;
+}
+
+
struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp,
bool ro)
{
@@ -304,9 +363,11 @@
int errors = 0, line = 0;
struct wpa_ssid *ssid, *tail, *head;
struct wpa_cred *cred, *cred_tail, *cred_head;
+ struct wpa_dev_ik *identity, *identity_tail, *identity_head;
struct wpa_config *config;
static int id = 0;
static int cred_id = 0;
+ static int identity_id = 0;
if (name == NULL)
return NULL;
@@ -325,6 +386,9 @@
cred_tail = cred_head = config->cred;
while (cred_tail && cred_tail->next)
cred_tail = cred_tail->next;
+ identity_tail = identity_head = config->identity;
+ while (identity_tail && identity_tail->next)
+ identity_tail = identity_tail->next;
wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
f = fopen(name, "r");
@@ -383,6 +447,22 @@
continue;
}
#endif /* CONFIG_NO_CONFIG_BLOBS */
+ } else if (os_strcmp(pos, "identity={") == 0) {
+ identity = wpa_config_read_identity(f, &line,
+ identity_id++);
+ if (!identity) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: failed to parse identity block.",
+ line);
+ errors++;
+ continue;
+ }
+ if (!identity_head) {
+ identity_head = identity_tail = identity;
+ } else {
+ identity_tail->next = identity;
+ identity_tail = identity;
+ }
} else if (wpa_config_process_global(config, pos, line) < 0) {
wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "
"line '%s'.", line, pos);
@@ -396,6 +476,7 @@
config->ssid = head;
wpa_config_debug_dump_networks(config);
config->cred = cred_head;
+ config->identity = identity_head;
#ifndef WPA_IGNORE_CONFIG_ERRORS
if (errors) {
@@ -895,6 +976,7 @@
INT(enable_4addr_mode);
INT(max_idle);
INT(ssid_protection);
+ INT_DEF(rsn_overriding, RSN_OVERRIDING_NOT_SET);
#undef STR
#undef INT
@@ -1298,6 +1380,27 @@
if (config->p2p_6ghz_disable)
fprintf(f, "p2p_6ghz_disable=%d\n", config->p2p_6ghz_disable);
+ if (config->p2p_pairing_setup)
+ fprintf(f, "p2p_pairing_setup=%d\n", config->p2p_pairing_setup);
+ if (config->p2p_pairing_cache)
+ fprintf(f, "p2p_pairing_cache=%d\n", config->p2p_pairing_cache);
+ if (config->p2p_bootstrap_methods)
+ fprintf(f, "p2p_bootstrap_methods=%d\n",
+ config->p2p_bootstrap_methods);
+ if (config->p2p_pasn_type)
+ fprintf(f, "p2p_pasn_type=%d\n", config->p2p_pasn_type);
+ if (config->p2p_comeback_after)
+ fprintf(f, "p2p_comeback_after=%d\n",
+ config->p2p_comeback_after);
+ if (config->p2p_twt_power_mgmt)
+ fprintf(f, "p2p_twt_power_mgmt=%d\n",
+ config->p2p_twt_power_mgmt);
+ if (config->p2p_chan_switch_req_enable)
+ fprintf(f, "p2p_chan_switch_req_enable=%d\n",
+ config->p2p_chan_switch_req_enable);
+ if (config->p2p_reg_info)
+ fprintf(f, "p2p_reg_info=%d\n", config->p2p_reg_info);
+
if (WPA_GET_BE32(config->ip_addr_go))
fprintf(f, "ip_addr_go=%u.%u.%u.%u\n",
config->ip_addr_go[0], config->ip_addr_go[1],
@@ -1567,6 +1670,9 @@
if (config->ftm_initiator)
fprintf(f, "ftm_initiator=%d\n", config->ftm_initiator);
+ if (config->twt_requester)
+ fprintf(f, "twt_requester=%d\n", config->twt_requester);
+
if (config->osu_dir)
fprintf(f, "osu_dir=%s\n", config->osu_dir);
@@ -1639,6 +1745,24 @@
fprintf(f, "dik_cipher=%d\n", config->dik_cipher);
write_global_bin(f, "dik", config->dik);
}
+ if (config->wfa_gen_capa)
+ fprintf(f, "wfa_gen_capa=%d\n", config->wfa_gen_capa);
+ write_global_bin(f, "wfa_gen_capa_supp", config->wfa_gen_capa_supp);
+ write_global_bin(f, "wfa_gen_capa_cert", config->wfa_gen_capa_cert);
+}
+
+static void wpa_config_write_identity(FILE *f, struct wpa_dev_ik *dev_ik)
+{
+ fprintf(f, "\tdik_cipher=%d\n", dev_ik->dik_cipher);
+
+ if (dev_ik->dik)
+ write_global_bin(f, "\tdik", dev_ik->dik);
+
+ if (dev_ik->pmk)
+ write_global_bin(f, "\tpmk", dev_ik->pmk);
+
+ if (dev_ik->pmkid)
+ write_global_bin(f, "\tpmkid", dev_ik->pmkid);
}
#endif /* CONFIG_NO_CONFIG_WRITE */
@@ -1650,6 +1774,7 @@
FILE *f;
struct wpa_ssid *ssid;
struct wpa_cred *cred;
+ struct wpa_dev_ik *dev_ik;
#ifndef CONFIG_NO_CONFIG_BLOBS
struct wpa_config_blob *blob;
#endif /* CONFIG_NO_CONFIG_BLOBS */
@@ -1697,13 +1822,20 @@
!ssid->psk_set && !ssid->passphrase)
continue; /* do not save invalid network */
if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
- !ssid->passphrase && !ssid->sae_password)
+ !ssid->passphrase && !ssid->sae_password &&
+ !ssid->pmk_valid)
continue; /* do not save invalid network */
fprintf(f, "\nnetwork={\n");
wpa_config_write_network(f, ssid);
fprintf(f, "}\n");
}
+ for (dev_ik = config->identity; dev_ik; dev_ik = dev_ik->next) {
+ fprintf(f, "\nidentity={\n");
+ wpa_config_write_identity(f, dev_ik);
+ fprintf(f, "}\n");
+ }
+
#ifndef CONFIG_NO_CONFIG_BLOBS
for (blob = config->blobs; blob; blob = blob->next) {
ret = wpa_config_write_blob(f, blob);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 3d1bc5e..92ee234 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -79,6 +79,20 @@
};
/**
+ * rsn_overriding - RSN overriding
+ *
+ * 0 = Disabled
+ * 1 = Enabled automatically if the driver indicates support
+ * 2 = Forced to be enabled even without driver capability indication
+ */
+enum wpas_rsn_overriding {
+ RSN_OVERRIDING_NOT_SET = -1,
+ RSN_OVERRIDING_DISABLED = 0,
+ RSN_OVERRIDING_AUTO = 1,
+ RSN_OVERRIDING_ENABLED = 2,
+};
+
+/**
* struct wpa_ssid - Network configuration data
*
* This structure includes all the configuration variables for a network. This
@@ -232,6 +246,11 @@
char *passphrase;
/**
+ * pmk_valid - Whether PMK is valid in case of P2P2 derived from PASN
+ */
+ bool pmk_valid;
+
+ /**
* sae_password - SAE password
*
* This parameter can be used to set a password for SAE. By default, the
@@ -1282,6 +1301,17 @@
* ssid_protection - Whether to use SSID protection in 4-way handshake
*/
bool ssid_protection;
+
+ /**
+ * rsn_overriding - RSN overriding (per-network override for the global
+ * parameter with the same name)
+ */
+ enum wpas_rsn_overriding rsn_overriding;
+
+ /**
+ * p2p_mode - P2P R1 only, P2P R2 only, or PCC mode
+ */
+ enum wpa_p2p_mode p2p_mode;
};
#endif /* CONFIG_SSID_H */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index a8fc962..43d1a66 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -881,6 +881,8 @@
} else if (os_strcasecmp(cmd, "dpp_test") == 0) {
dpp_test = atoi(value);
#endif /* CONFIG_DPP */
+ } else if (os_strcasecmp(cmd, "eapol_2_key_info_set_mask") == 0) {
+ wpa_s->eapol_2_key_info_set_mask = strtoul(value, NULL, 0x10);
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_FILS
} else if (os_strcasecmp(cmd, "disable_fils") == 0) {
@@ -6354,6 +6356,29 @@
}
+static bool bootstrap_pwd_required(u16 bootstrap)
+{
+ switch (bootstrap) {
+ case P2P_PBMA_OPPORTUNISTIC:
+ return false;
+ case P2P_PBMA_PIN_CODE_DISPLAY:
+ case P2P_PBMA_PASSPHRASE_DISPLAY:
+ case P2P_PBMA_QR_DISPLAY:
+ case P2P_PBMA_NFC_TAG:
+ case P2P_PBMA_PIN_CODE_KEYPAD:
+ case P2P_PBMA_PASSPHRASE_KEYPAD:
+ case P2P_PBMA_QR_SCAN:
+ case P2P_PBMA_NFC_READER:
+ return true;
+ case P2P_PBMA_SERVICE_MANAGED:
+ case P2P_PBMA_HANDSHAKE_SKIP:
+ return false;
+ }
+
+ return false;
+}
+
+
static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
char *buf, size_t buflen)
{
@@ -6376,7 +6401,7 @@
size_t group_ssid_len = 0;
int he;
bool allow_6ghz;
- bool p2p2;
+ bool p2p2, skip_prov;
u16 bootstrap = 0;
const char *password = NULL;
char *token, *context = NULL;
@@ -6393,7 +6418,7 @@
* [persistent|persistent=<network id>]
* [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
* [ht40] [vht] [he] [edmg] [auto] [ssid=<hexdump>]
- * [p2p2] [bstrapmethod=<value>] [password=<string>]
+ * [p2p2] [skip_prov] [bstrapmethod=<value>] [password=<string>]
*/
if (hwaddr_aton(cmd, addr))
@@ -6429,6 +6454,7 @@
he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
p2p2 = os_strstr(pos, " p2p2") != NULL;
+ skip_prov = os_strstr(pos, " skip_prov") != NULL;
pos2 = os_strstr(pos, " go_intent=");
if (pos2) {
@@ -6515,12 +6541,18 @@
}
}
+ if (bootstrap_pwd_required(bootstrap) && !password) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL_IFACE: This P2P2 bootstrap method requires password");
+ return -1;
+ }
+
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, he, edmg,
group_ssid, group_ssid_len, allow_6ghz, p2p2,
- bootstrap, password);
+ bootstrap, password, skip_prov);
if (new_pin == -2) {
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
return 25;
@@ -7073,6 +7105,7 @@
int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
int edmg;
bool allow_6ghz;
+ bool p2p2;
id = atoi(cmd);
pos = os_strstr(cmd, " peer=");
@@ -7129,9 +7162,11 @@
if (allow_6ghz && chwidth == 40)
max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
+ p2p2 = os_strstr(cmd, " p2p2") != NULL;
+
return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
max_oper_chwidth, pref_freq, he, edmg,
- allow_6ghz);
+ allow_6ghz, p2p2);
}
@@ -7200,13 +7235,15 @@
vht_center_freq2, ht40, vht,
vht_chwidth, he, edmg,
NULL, 0, 0, allow_6ghz, 0,
- go_bssid);
+ go_bssid, NULL, NULL, NULL, 0);
}
static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
{
int freq = 0, persistent = 0, group_id = -1;
+ bool p2p2 = false;
+ int p2pmode = WPA_P2P_MODE_WFD_R1;
bool allow_6ghz = false;
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
@@ -7222,7 +7259,8 @@
while ((token = str_token(cmd, " ", &context))) {
if (sscanf(token, "freq2=%d", &freq2) == 1 ||
sscanf(token, "persistent=%d", &group_id) == 1 ||
- sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
+ sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1 ||
+ sscanf(token, "p2pmode=%d", &p2pmode) == 1) {
continue;
#ifdef CONFIG_ACS
} else if (os_strcmp(token, "freq=acs") == 0) {
@@ -7243,6 +7281,8 @@
persistent = 1;
} else if (os_strcmp(token, "allow_6ghz") == 0) {
allow_6ghz = true;
+ } else if (os_strcmp(token, "p2p2") == 0) {
+ p2p2 = true;
} else if (os_strncmp(token, "go_bssid=", 9) == 0) {
if (hwaddr_aton(token + 9, go_bssid_buf))
return -1;
@@ -7293,8 +7333,12 @@
edmg, allow_6ghz,
go_bssid);
+ if (p2pmode < WPA_P2P_MODE_WFD_R1 || p2pmode > WPA_P2P_MODE_WFD_PCC)
+ return -1;
+
return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
- max_oper_chwidth, he, edmg, allow_6ghz);
+ max_oper_chwidth, he, edmg, allow_6ghz, p2p2,
+ (enum wpa_p2p_mode) p2pmode);
}
@@ -7697,6 +7741,53 @@
return 0;
}
+#ifdef CONFIG_TESTING_OPTIONS
+ if (os_strcmp(cmd, "pairing_setup") == 0) {
+ p2p_set_pairing_setup(wpa_s->global->p2p, atoi(param));
+ return 0;
+ }
+
+ if (os_strcmp(cmd, "pairing_cache") == 0) {
+ p2p_set_pairing_cache(wpa_s->global->p2p, atoi(param));
+ return 0;
+ }
+
+ if (os_strcmp(cmd, "supported_bootstrapmethods") == 0) {
+ p2p_set_bootstrapmethods(wpa_s->global->p2p, atoi(param));
+ return 0;
+ }
+
+ if (os_strcmp(cmd, "pasn_type") == 0) {
+ p2p_set_pasn_type(wpa_s->global->p2p, atoi(param));
+ return 0;
+ }
+
+ if (os_strcmp(cmd, "comeback_after") == 0) {
+ p2p_set_comeback_after(wpa_s->global->p2p, atoi(param));
+ return 0;
+ }
+
+ if (os_strcmp(cmd, "reginfo") == 0) {
+ p2p_set_reg_info(wpa_s->global->p2p, atoi(param));
+ return 0;
+ }
+
+ if (os_strcmp(cmd, "twt_power_mgmt") == 0) {
+ p2p_set_twt_power_mgmt(wpa_s->global->p2p, atoi(param));
+ return 0;
+ }
+
+ if (os_strcmp(cmd, "chan_switch_req_enable") == 0) {
+ p2p_set_chan_switch_req_enable(wpa_s->global->p2p, atoi(param));
+ return 0;
+ }
+
+ if (os_strcmp(cmd, "inv_oper_freq") == 0) {
+ p2p_set_invitation_op_freq(wpa_s->global->p2p, atoi(param));
+ return 0;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
cmd);
@@ -7712,12 +7803,15 @@
#ifdef CONFIG_TESTING_OPTIONS
os_free(wpa_s->get_pref_freq_list_override);
wpa_s->get_pref_freq_list_override = NULL;
+ p2p_set_invitation_op_freq(wpa_s->global->p2p, -1);
#endif /* CONFIG_TESTING_OPTIONS */
wpas_p2p_stop_find(wpa_s);
wpa_s->parent->p2ps_method_config_any = 0;
if (wpa_s->global->p2p)
p2p_flush(wpa_s->global->p2p);
+
+ wpa_s->p2p2 = false;
}
@@ -7804,6 +7898,26 @@
return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
}
+
+#ifdef CONFIG_TESTING_OPTIONS
+static int p2p_ctrl_pmk_get(struct wpa_supplicant *wpa_s, char *buf,
+ size_t buflen)
+{
+ const u8 *pmk;
+ size_t pmk_len;
+
+ /* Return the PMK from the first identity entry. This assumes test
+ * cases to remove all indentities at the beginning so that only one
+ * entry is available. */
+ if (!wpa_s->conf->identity || !wpa_s->conf->identity->pmk)
+ return -1;
+
+ pmk_len = wpabuf_len(wpa_s->conf->identity->pmk);
+ pmk = wpabuf_head(wpa_s->conf->identity->pmk);
+
+ return wpa_snprintf_hex(buf, buflen, pmk, pmk_len);
+}
+#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_P2P */
@@ -8676,6 +8790,7 @@
ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
#ifdef CONFIG_P2P
if (ret == 0) {
+#ifdef CONFIG_P2P
if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
struct p2p_data *p2p = wpa_s->global->p2p;
if (p2p) {
@@ -8686,6 +8801,7 @@
p2p_set_country(p2p, country);
}
}
+#endif /* CONFIG_P2P */
ret = os_snprintf(buf, buflen, "%s\n", "OK");
if (os_snprintf_error(buflen, ret))
ret = -1;
@@ -8931,6 +9047,7 @@
wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, NULL);
wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, NULL);
+ wpa_sm_set_test_rsnxe_data(wpa_s->wpa, NULL, NULL);
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2, 0);
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4, 0);
os_free(wpa_s->get_pref_freq_list_override);
@@ -8959,6 +9076,7 @@
wpa_s->oci_freq_override_fils_assoc = 0;
wpa_s->oci_freq_override_wnm_sleep = 0;
wpa_s->disable_eapol_g2_tx = 0;
+ wpa_s->eapol_2_key_info_set_mask = 0;
wpa_s->test_assoc_comeback_type = -1;
#ifdef CONFIG_DPP
os_free(wpa_s->dpp_config_obj_override);
@@ -10302,6 +10420,29 @@
}
+static int wpas_ctrl_test_rsnxe_data(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ struct wpabuf *data = NULL, *mask = NULL;
+ char *pos;
+
+ pos = os_strchr(cmd, ' ');
+ if (!pos)
+ return -1;
+ *pos++ = '\0';
+
+ if (wpas_get_hex_buf(cmd, &data) < 0 ||
+ wpas_get_hex_buf(pos, &mask) < 0 ||
+ wpa_sm_set_test_rsnxe_data(wpa_s->wpa, data, mask) < 0) {
+ wpabuf_free(data);
+ wpabuf_free(mask);
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
{
u8 zero[WPA_TK_MAX_LEN];
@@ -10856,6 +10997,24 @@
#endif /* CONFIG_AP */
}
+#ifdef CONFIG_P2P
+#ifdef CONFIG_PASN
+
+#ifdef CONFIG_TESTING_OPTIONS
+static int p2p_ctrl_get_pasn_ptk(struct wpa_supplicant *wpa_s, char *buf,
+ size_t buflen)
+{
+ const u8 *ptk;
+ size_t ptk_len;
+
+ if (wpas_p2p_get_pasn_ptk(wpa_s, &ptk, &ptk_len))
+ return -1;
+ return wpa_snprintf_hex(buf, buflen, ptk, ptk_len);
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+#endif /* CONFIG_PASN */
+#endif /* CONFIG_P2P */
#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
@@ -12870,6 +13029,12 @@
reply_len = -1;
} else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
+#ifdef CONFIG_PASN
+#ifdef CONFIG_TESTING_OPTIONS
+ } else if (os_strcmp(buf, "P2P_GET_PASNPTK") == 0) {
+ reply_len = p2p_ctrl_get_pasn_ptk(wpa_s, reply, reply_size);
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_PASN */
} else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
reply_size);
@@ -12936,6 +13101,13 @@
} else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
if (wpas_p2p_lo_stop(wpa_s))
reply_len = -1;
+ } else if (os_strcmp(buf, "P2P_REMOVE_IDENTITY") == 0) {
+ if (wpas_p2p_remove_all_identity(wpa_s))
+ reply_len = -1;
+#ifdef CONFIG_TESTING_OPTIONS
+ } else if (os_strncmp(buf, "P2P_PMK_GET", 12) == 0) {
+ reply_len = p2p_ctrl_pmk_get(wpa_s, reply, reply_size);
+#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_P2P */
#ifdef CONFIG_WIFI_DISPLAY
} else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
@@ -13387,6 +13559,9 @@
} else if (os_strncmp(buf, "ML_PROBE_REQ ", 13) == 0) {
if (wpas_ctrl_ml_probe(wpa_s, buf + 13))
reply_len = -1;
+ } else if (os_strncmp(buf, "TEST_RSNXE_DATA ", 16) == 0) {
+ if (wpas_ctrl_test_rsnxe_data(wpa_s, buf + 16) < 0)
+ reply_len = -1;
#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)
@@ -13593,6 +13768,8 @@
} else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) {
if (wpas_ctrl_nan_transmit(wpa_s, buf + 13) < 0)
reply_len = -1;
+ } else if (os_strcmp(buf, "NAN_FLUSH") == 0) {
+ wpas_nan_usd_flush(wpa_s);
#endif /* CONFIG_NAN_USD */
#ifdef CONFIG_PASN
} else if (os_strncmp(buf, "PASN_START ", 11) == 0) {
@@ -13631,6 +13808,14 @@
} else if (os_strcmp(buf, "MLO_SIGNAL_POLL") == 0) {
reply_len = wpas_ctrl_iface_mlo_signal_poll(wpa_s, reply,
reply_size);
+ } else if (os_strcmp(buf, "NEW_RANDOM_MAC_ADDRESS") == 0) {
+ enum wpas_mac_addr_style mac_addr_style =
+ wpa_s->conf->preassoc_mac_addr;
+
+ wpa_s->conf->preassoc_mac_addr = WPAS_MAC_ADDR_STYLE_RANDOM;
+ if (wpas_update_random_addr_disassoc(wpa_s) != 1)
+ reply_len = -1;
+ wpa_s->conf->preassoc_mac_addr = mac_addr_style;
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
@@ -13986,6 +14171,7 @@
"NFC_REPORT_HANDOVER ",
"P2P_ASP_PROVISION ",
"P2P_ASP_PROVISION_RESP ",
+ "NAN_",
#ifdef CONFIG_AP
"STA ",
"STA-NEXT ",
diff --git a/wpa_supplicant/dbus/dbus_dict_helpers.c b/wpa_supplicant/dbus/dbus_dict_helpers.c
index 27003eb..a3f32c3 100644
--- a/wpa_supplicant/dbus/dbus_dict_helpers.c
+++ b/wpa_supplicant/dbus/dbus_dict_helpers.c
@@ -1159,3 +1159,38 @@
os_memset(entry, 0, sizeof(struct wpa_dbus_dict_entry));
}
+
+
+dbus_bool_t wpa_dbus_dict_entry_is_int(const struct wpa_dbus_dict_entry *entry)
+{
+ return entry->type == DBUS_TYPE_BYTE ||
+ entry->type == DBUS_TYPE_INT16 ||
+ entry->type == DBUS_TYPE_UINT16 ||
+ entry->type == DBUS_TYPE_INT32 ||
+ entry->type == DBUS_TYPE_UINT32 ||
+ entry->type == DBUS_TYPE_INT64 ||
+ entry->type == DBUS_TYPE_UINT64;
+}
+
+
+int wpa_dbus_dict_entry_get_int(const struct wpa_dbus_dict_entry *entry)
+{
+ switch (entry->type) {
+ case DBUS_TYPE_BYTE:
+ return entry->byte_value;
+ case DBUS_TYPE_INT16:
+ return entry->int16_value;
+ case DBUS_TYPE_UINT16:
+ return entry->uint16_value;
+ case DBUS_TYPE_INT32:
+ return entry->int32_value;
+ case DBUS_TYPE_UINT32:
+ return entry->uint32_value;
+ case DBUS_TYPE_INT64:
+ return entry->int64_value;
+ case DBUS_TYPE_UINT64:
+ return entry->uint64_value;
+ }
+
+ return -1;
+}
diff --git a/wpa_supplicant/dbus/dbus_dict_helpers.h b/wpa_supplicant/dbus/dbus_dict_helpers.h
index 1d33689..15c8aba 100644
--- a/wpa_supplicant/dbus/dbus_dict_helpers.h
+++ b/wpa_supplicant/dbus/dbus_dict_helpers.h
@@ -158,4 +158,7 @@
void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry);
+dbus_bool_t wpa_dbus_dict_entry_is_int(const struct wpa_dbus_dict_entry *entry);
+int wpa_dbus_dict_entry_get_int(const struct wpa_dbus_dict_entry *entry);
+
#endif /* DBUS_DICT_HELPERS_H */
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 5ad5bcd..ff7e003 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -2332,6 +2332,113 @@
}
+/**
+ * wpas_dbus_signal_p2p_bootstrap_req - Signals BootstrappingRequest event
+ * @wpa_s: %wpa_supplicant network interface data
+ * @src: Source address of the message triggering this notification
+ * @bootstrap_method: Peer's bootstrap method
+ *
+ * Sends a signal to notify that a peer P2P Device is requesting bootstrapping
+ * negotiation with us.
+ */
+void wpas_dbus_signal_p2p_bootstrap_req(struct wpa_supplicant *wpa_s,
+ const u8 *src, u16 bootstrap_method)
+{
+ DBusMessage *msg;
+ DBusMessageIter iter;
+ struct wpas_dbus_priv *iface;
+ char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+
+ iface = wpa_s->global->dbus;
+
+ /* Do nothing if the control interface is not turned on */
+ if (!iface)
+ return;
+
+ if (wpa_s->p2p_mgmt)
+ wpa_s = wpa_s->parent;
+ if (!wpa_s->dbus_new_path)
+ return;
+
+ os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+ "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
+ wpa_s->dbus_new_path, MAC2STR(src));
+ path = peer_obj_path;
+
+ msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+ "BootstrappingRequest");
+ if (!msg)
+ return;
+
+ dbus_message_iter_init_append(msg, &iter);
+
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+ &path) ||
+ !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
+ &bootstrap_method))
+ wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+ else
+ dbus_connection_send(iface->con, msg, NULL);
+
+ dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_p2p_bootstrap_completed - Signals BootstrappingCompleted event
+ * event
+ * @wpa_s: %wpa_supplicant network interface data
+ * @src: Source address of the peer with which bootstrapping is done
+ * @status: Status of Bootstrapping handshake
+ *
+ * Sends a signal to notify that a peer P2P Device is requesting bootstrapping
+ * negotiation with us.
+ */
+void wpas_dbus_signal_p2p_bootstrap_completed(struct wpa_supplicant *wpa_s,
+ const u8 *src, int status)
+{
+ DBusMessage *msg;
+ DBusMessageIter iter;
+ struct wpas_dbus_priv *iface;
+ char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+
+ iface = wpa_s->global->dbus;
+
+ /* Do nothing if the control interface is not turned on */
+ if (!iface)
+ return;
+
+ if (wpa_s->p2p_mgmt)
+ wpa_s = wpa_s->parent;
+ if (!wpa_s->dbus_new_path)
+ return;
+
+ os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+ "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
+ wpa_s->dbus_new_path, MAC2STR(src));
+ path = peer_obj_path;
+
+ msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+ "BootstrappingCompleted");
+ if (!msg)
+ return;
+
+ dbus_message_iter_init_append(msg, &iter);
+
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+ &path) ||
+ !dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32,
+ &status))
+ wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+ else
+ dbus_connection_send(iface->con, msg, NULL);
+
+ dbus_message_unref(msg);
+}
+
+
#endif /* CONFIG_P2P */
@@ -3771,6 +3878,52 @@
},
},
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_NAN_USD
+ { "NANPublish", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_nan_publish,
+ {
+ { "args", "a{sv}", ARG_IN },
+ { "publish_id", "u", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { "NANCancelPublish", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_nan_cancel_publish,
+ {
+ { "publish_id", "u", ARG_IN },
+ END_ARGS
+ }
+ },
+ { "NANUpdatePublish", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_nan_update_publish,
+ {
+ { "args", "a{sv}", ARG_IN },
+ END_ARGS
+ }
+ },
+ { "NANSubscribe", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_nan_subscribe,
+ {
+ { "args", "a{sv}", ARG_IN },
+ { "subscribe_id", "u", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { "NANCancelSubscribe", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_nan_cancel_subscribe,
+ {
+ { "subscribe_id", "u", ARG_IN },
+ END_ARGS
+ }
+ },
+ { "NANTransmit", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_nan_transmit,
+ {
+ { "args", "a{sv}", ARG_IN },
+ END_ARGS
+ }
+ },
+#endif /* CONFIG_NAN_USD */
{ NULL, NULL, NULL, { END_ARGS } }
};
@@ -4273,6 +4426,20 @@
END_ARGS
}
},
+ { "BootstrappingRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+ {
+ { "path", "o", ARG_OUT },
+ { "bootstrap_method", "q", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { "BootstrappingCompleted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+ {
+ { "path", "o", ARG_OUT },
+ { "status", "i", ARG_OUT },
+ END_ARGS
+ }
+ },
#endif /* CONFIG_P2P */
#ifdef CONFIG_AP
{ "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
@@ -4384,6 +4551,40 @@
}
},
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_NAN_USD
+ { "NANDiscoveryResult", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ {
+ { "args", "a{sv}", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { "NANReplied", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ {
+ { "args", "a{sv}", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { "NANReceive", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ {
+ { "args", "a{sv}", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { "NANPublishTerminated", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ {
+ { "publish_id", "u", ARG_OUT },
+ { "reason", "s", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { "NANSubscribeTerminated", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ {
+ { "subscribe_id", "u", ARG_OUT },
+ { "reason", "s", ARG_OUT },
+ END_ARGS
+ }
+ },
+#endif /* CONFIG_NAN_USD */
{ NULL, NULL, { END_ARGS } }
};
@@ -5253,3 +5454,259 @@
dbus_message_unref(msg);
}
#endif /* CONFIG_HS20 */
+
+
+#ifdef CONFIG_NAN_USD
+
+/**
+ * wpas_dbus_signal_nan_discovery_result - Send NANDiscoveryResult signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @srv_proto_type: Service Protocol Type
+ * @subscribe_id: Subscribe ID of the session
+ * @peer_publish_id: Publish ID of the sender
+ * @peer_addr: MAC address of the peer device
+ * @ssi: Service specific information payload
+ * @ssi_len: Length of the SSI field
+ *
+ * This is used to indicate the NAN DE DiscoveryResult event.
+ */
+void wpas_dbus_signal_nan_discovery_result(struct wpa_supplicant *wpa_s,
+ enum nan_service_protocol_type
+ srv_proto_type,
+ int subscribe_id,
+ int peer_publish_id,
+ const u8 *peer_addr,
+ bool fsd, bool fsd_gas,
+ const u8 *ssi, size_t ssi_len)
+{
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+ DBusMessageIter iter, dict_iter;
+ char addr_str[20];
+
+ iface = wpa_s->global->dbus;
+ /* Do nothing if the 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_INTERFACE,
+ "NANDiscoveryResult");
+ if (!msg)
+ return;
+
+ snprintf(addr_str, sizeof(addr_str), MACSTR, MAC2STR(peer_addr));
+
+ dbus_message_iter_init_append(msg, &iter);
+
+ if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
+ !wpa_dbus_dict_append_uint32(&dict_iter, "subscribe_id",
+ subscribe_id) ||
+ !wpa_dbus_dict_append_uint32(&dict_iter, "publish_id",
+ peer_publish_id) ||
+ !wpa_dbus_dict_append_string(&dict_iter, "peer_addr", addr_str) ||
+ !wpa_dbus_dict_append_bool(&dict_iter, "fsd", fsd) ||
+ !wpa_dbus_dict_append_bool(&dict_iter, "fsd_gas", fsd_gas) ||
+ !wpa_dbus_dict_append_uint32(&dict_iter, "srv_proto_type",
+ srv_proto_type) ||
+ (ssi &&
+ !wpa_dbus_dict_append_byte_array(&dict_iter,
+ "ssi",
+ (const char *) ssi,
+ ssi_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);
+}
+
+
+/**
+ * wpas_dbus_signal_nan_replied - Send NANReplied signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @srv_proto_type: Service Protocol Type
+ * @publish_id: Publish id of the session
+ * @peer_subscribe_id: Subscribe id of the sender
+ * @peer_addr: MAC address of the peer device
+ * @ssi: Service specific information payload
+ * @ssi_len: Length of the SSI field
+ *
+ * This is used to indicate the NAN DE Replied event.
+ */
+void wpas_dbus_signal_nan_replied(struct wpa_supplicant *wpa_s,
+ enum nan_service_protocol_type srv_proto_type,
+ int publish_id,
+ int peer_subscribe_id,
+ const u8 *peer_addr,
+ const u8 *ssi, size_t ssi_len)
+{
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+ DBusMessageIter iter, dict_iter;
+ char addr_str[20];
+
+ iface = wpa_s->global->dbus;
+ /* Do nothing if the 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_INTERFACE,
+ "NANReplied");
+ if (!msg)
+ return;
+
+ snprintf(addr_str, sizeof(addr_str), MACSTR, MAC2STR(peer_addr));
+
+ dbus_message_iter_init_append(msg, &iter);
+
+ if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
+ !wpa_dbus_dict_append_uint32(&dict_iter, "publish_id",
+ publish_id) ||
+ !wpa_dbus_dict_append_uint32(&dict_iter, "subscribe_id",
+ peer_subscribe_id) ||
+ !wpa_dbus_dict_append_string(&dict_iter, "peer_addr", addr_str) ||
+ !wpa_dbus_dict_append_uint32(&dict_iter, "srv_proto_type",
+ srv_proto_type) ||
+ (ssi &&
+ !wpa_dbus_dict_append_byte_array(&dict_iter, "ssi",
+ (const char *) ssi,
+ ssi_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);
+}
+
+
+/**
+ * wpas_dbus_signal_nan_receive - Send NANReceive signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @id: The original publish_id or subscribe_id
+ * @peer_id: Peer instance identifier
+ * @peer_addr: Address of the sender
+ * @ssi: Service specific information payload
+ * @ssi_len: Length of the SSI
+ *
+ * This is used to indicate the NAN DE Receive event to notify reception of a
+ * follow-up frame.
+ */
+void wpas_dbus_signal_nan_receive(struct wpa_supplicant *wpa_s,
+ int id, int peer_id, const u8 *peer_addr,
+ const u8 *ssi, size_t ssi_len)
+{
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+ DBusMessageIter iter, dict_iter;
+ char addr_str[20];
+
+ iface = wpa_s->global->dbus;
+ /* Do nothing if the 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_INTERFACE,
+ "NANReceive");
+ if (!msg)
+ return;
+
+ snprintf(addr_str, sizeof(addr_str), MACSTR, MAC2STR(peer_addr));
+
+ dbus_message_iter_init_append(msg, &iter);
+
+ if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
+ !wpa_dbus_dict_append_uint32(&dict_iter, "id", id) ||
+ !wpa_dbus_dict_append_uint32(&dict_iter, "peer_id", peer_id) ||
+ !wpa_dbus_dict_append_string(&dict_iter, "peer_addr", addr_str) ||
+ (ssi &&
+ !wpa_dbus_dict_append_byte_array(&dict_iter, "ssi",
+ (const char *) ssi,
+ ssi_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);
+}
+
+
+/**
+ * wpas_dbus_signal_nan_publish_terminated - Send NANPublishTerminated signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @publish_id: The publish_id of the session
+ * @reason: The reason of the termination
+ *
+ * This is used to indicate the NAN DE PublishTerminated event to notify when
+ * the session has expired.
+ */
+void wpas_dbus_signal_nan_publish_terminated(struct wpa_supplicant *wpa_s,
+ int publish_id,
+ const char *reason)
+{
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+ dbus_uint32_t pub_id = publish_id;
+
+ iface = wpa_s->global->dbus;
+ /* Do nothing if the 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_INTERFACE,
+ "NANPublishTerminated");
+ if (!msg)
+ return;
+
+ if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &pub_id,
+ DBUS_TYPE_INVALID) ||
+ !dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
+ DBUS_TYPE_INVALID))
+ wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+ else
+ dbus_connection_send(iface->con, msg, NULL);
+ dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_nan_subscribe_terminated - Send NANSubscribeTerminated signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @subscribe_id: The subscribe_id of the session
+ * @reason: The reason of the termination
+ *
+ * This is used to indicate the NAN DE SubscribeTerminated event to notify when
+ * the session has expired.
+ */
+void wpas_dbus_signal_nan_subscribe_terminated(struct wpa_supplicant *wpa_s,
+ int subscribe_id,
+ const char *reason)
+{
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+ dbus_uint32_t sub_id = subscribe_id;
+
+ iface = wpa_s->global->dbus;
+ /* Do nothing if the 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_INTERFACE,
+ "NANSubscribeTerminated");
+ if (!msg)
+ return;
+
+ if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &sub_id,
+ DBUS_TYPE_INVALID) ||
+ !dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
+ DBUS_TYPE_INVALID))
+ wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+ else
+ dbus_connection_send(iface->con, msg, NULL);
+ dbus_message_unref(msg);
+}
+
+#endif /* CONFIG_NAN_USD */
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index 1db5fe8..f9ff636 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -21,6 +21,7 @@
struct wps_event_m2d;
struct wps_event_fail;
struct wps_credential;
+enum nan_service_protocol_type;
enum wpas_dbus_prop {
WPAS_DBUS_PROP_AP_SCAN,
@@ -265,6 +266,10 @@
const u8 *sa, const u8 *dev_addr,
const u8 *bssid, int id,
int op_freq);
+void wpas_dbus_signal_p2p_bootstrap_req(struct wpa_supplicant *wpa_s,
+ const u8 *src, u16 bootstrap_method);
+void wpas_dbus_signal_p2p_bootstrap_completed(struct wpa_supplicant *wpa_s,
+ const u8 *src, int status);
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,
@@ -285,6 +290,28 @@
const u8 *dst, const char *result);
void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
const char *url);
+void wpas_dbus_signal_nan_discovery_result(struct wpa_supplicant *wpa_s,
+ enum nan_service_protocol_type
+ srv_proto_type,
+ int subscribe_id,
+ int peer_publish_id,
+ const u8 *peer_addr,
+ bool fsd, bool fsd_gas,
+ const u8 *ssi, size_t ssi_len);
+void wpas_dbus_signal_nan_replied(struct wpa_supplicant *wpa_s,
+ enum nan_service_protocol_type srv_proto_type,
+ int publish_id, int peer_subscribe_id,
+ const u8 *peer_addr,
+ const u8 *ssi, size_t ssi_len);
+void wpas_dbus_signal_nan_receive(struct wpa_supplicant *wpa_s, int id,
+ int peer_id, const u8 *peer_addr,
+ const u8 *ssi, size_t ssi_len);
+void wpas_dbus_signal_nan_publish_terminated(struct wpa_supplicant *wpa_s,
+ int publish_id,
+ const char *reason);
+void wpas_dbus_signal_nan_subscribe_terminated(struct wpa_supplicant *wpa_s,
+ int subscribe_id,
+ const char *reason);
#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
@@ -617,6 +644,18 @@
}
static inline
+void wpas_dbus_signal_p2p_bootstrap_req(struct wpa_supplicant *wpa_s,
+ const u8 *src, u16 bootstrap_method)
+{
+}
+
+static inline
+void wpas_dbus_signal_p2p_bootstrap_completed(struct wpa_supplicant *wpa_s,
+ const u8 *src, int status)
+{
+}
+
+static inline
void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
@@ -668,6 +707,45 @@
{
}
+static inline void
+wpas_dbus_signal_nan_discovery_result(struct wpa_supplicant *wpa_s,
+ enum nan_service_protocol_type
+ srv_proto_type,
+ int subscribe_id,
+ int peer_publish_id, const u8 *peer_addr,
+ bool fsd, bool fsd_gas,
+ const u8 *ssi, size_t ssi_len)
+{
+}
+
+static inline void
+wpas_dbus_signal_nan_replied(struct wpa_supplicant *wpa_s,
+ enum nan_service_protocol_type srv_proto_type,
+ int publish_id, int peer_subscribe_id,
+ const u8 *peer_addr, const u8 *ssi, size_t ssi_len)
+{
+}
+
+
+static inline void
+wpas_dbus_signal_nan_receive(struct wpa_supplicant *wpa_s,
+ int id, int peer_id, const u8 *peer_addr,
+ const u8 *ssi, size_t ssi_len)
+{
+}
+
+static inline void
+wpas_dbus_signal_nan_publish_terminated(struct wpa_supplicant *wpa_s,
+ int publish_id, const char *reason)
+{
+}
+
+static inline void
+wpas_dbus_signal_nan_subscribe_terminated(struct wpa_supplicant *wpa_s,
+ int subscribe_id, const char *reason)
+{
+}
+
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
#endif /* CTRL_IFACE_DBUS_H_NEW */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index 52e35a7..2fad8dd 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -12,6 +12,7 @@
#include "common.h"
#include "common/ieee802_11_defs.h"
+#include "common/nan_de.h"
#include "eap_peer/eap_methods.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "rsn_supp/wpa.h"
@@ -27,6 +28,7 @@
#include "../autoscan.h"
#include "../ap.h"
#include "../interworking.h"
+#include "../nan_usd.h"
#include "dbus_new_helpers.h"
#include "dbus_new.h"
#include "dbus_new_handlers.h"
@@ -6485,3 +6487,514 @@
}
return TRUE;
}
+
+
+#ifdef CONFIG_NAN_USD
+
+/*
+ * wpas_dbus_handler_nan_publish - Send out NAN publish messages
+ * @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 "NANPublish" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_nan_publish(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ DBusMessageIter iter, iter_dict;
+ struct wpa_dbus_dict_entry entry;
+ DBusMessage *reply = NULL;
+ int publish_id;
+ char *srv_name = NULL;
+ enum nan_service_protocol_type srv_proto_type = 0;
+ bool p2p = false;
+ struct nan_publish_params params;
+ int *freq_list = NULL;
+ struct wpabuf *ssi = NULL;
+ dbus_uint32_t id;
+
+ wpa_printf(MSG_DEBUG, "dbus: NANPublish");
+ if (!wpa_s->nan_de)
+ return NULL;
+
+ os_memset(¶ms, 0, sizeof(params));
+ /* USD shall use both solicited and unsolicited transmissions */
+ params.unsolicited = true;
+ params.solicited = true;
+ /* USD shall require FSD without GAS */
+ params.fsd = true;
+ params.freq = NAN_USD_DEFAULT_FREQ;
+
+ dbus_message_iter_init(message, &iter);
+
+ if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
+ goto fail;
+ while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+ if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+ goto fail;
+ if (os_strcmp(entry.key, "srv_name") == 0 &&
+ entry.type == DBUS_TYPE_STRING) {
+ os_free(srv_name);
+ srv_name = os_strdup(entry.str_value);
+ wpa_dbus_dict_entry_clear(&entry);
+ if (!srv_name)
+ goto oom;
+ } else if (os_strcmp(entry.key, "srv_proto_type") == 0 &&
+ wpa_dbus_dict_entry_is_int(&entry)) {
+ srv_proto_type = wpa_dbus_dict_entry_get_int(&entry);
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "solicited") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ params.solicited = entry.bool_value;
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "unsolicited") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ params.unsolicited = entry.bool_value;
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "solicited_multicast") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ params.solicited_multicast = entry.bool_value;
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "ttl") == 0 &&
+ wpa_dbus_dict_entry_is_int(&entry)) {
+ params.ttl = wpa_dbus_dict_entry_get_int(&entry);
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "disable_events") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ params.disable_events = entry.bool_value;
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "fsd") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ params.fsd = entry.bool_value;
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "fsd_gas") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ params.fsd_gas = entry.bool_value;
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "p2p") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ p2p = entry.bool_value;
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "freq") == 0 &&
+ wpa_dbus_dict_entry_is_int(&entry)) {
+ params.freq = wpa_dbus_dict_entry_get_int(&entry);
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "announcement_period") == 0 &&
+ wpa_dbus_dict_entry_is_int(&entry)) {
+ params.announcement_period =
+ wpa_dbus_dict_entry_get_int(&entry);
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "ssi") == 0 &&
+ entry.type == DBUS_TYPE_ARRAY &&
+ entry.array_type == DBUS_TYPE_BYTE) {
+ wpabuf_free(ssi);
+ ssi = wpabuf_alloc_copy(entry.bytearray_value,
+ entry.array_len);
+ wpa_dbus_dict_entry_clear(&entry);
+ if (!ssi)
+ goto oom;
+ } else if (os_strcmp(entry.key, "freq_list") == 0 &&
+ entry.type == DBUS_TYPE_ARRAY &&
+ entry.array_type == DBUS_TYPE_UINT16) {
+ unsigned int i;
+
+ for (i = 0; i < entry.array_len; i++)
+ int_array_add_unique(
+ &freq_list, entry.uint16array_value[i]);
+ params.freq_list = freq_list;
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "dbus: NANPublish - unsupported dict entry '%s'",
+ entry.key);
+ reply = wpas_dbus_error_invalid_args(message,
+ entry.key);
+ wpa_dbus_dict_entry_clear(&entry);
+ goto fail;
+ }
+ }
+
+ if (!srv_name)
+ goto fail;
+
+ publish_id = wpas_nan_usd_publish(wpa_s, srv_name, srv_proto_type, ssi,
+ ¶ms, p2p);
+ if (publish_id < 0) {
+ reply = wpas_dbus_error_unknown_error(
+ message, "error publishing NAN USD");
+ goto out;
+ }
+
+ id = publish_id;
+ reply = dbus_message_new_method_return(message);
+ if (!reply) {
+ reply = wpas_dbus_error_no_memory(message);
+ goto out;
+ }
+
+ dbus_message_append_args(reply, DBUS_TYPE_UINT32,
+ &id, DBUS_TYPE_INVALID);
+
+out:
+ wpabuf_free(ssi);
+ os_free(freq_list);
+ os_free(srv_name);
+ return reply;
+fail:
+ reply = wpas_dbus_error_invalid_args(message,
+ "failed to parse NANPublish");
+ goto out;
+oom:
+ reply = wpas_dbus_error_no_memory(message);
+ goto out;
+}
+
+
+/*
+ * wpas_dbus_handler_nan_cancel_publish - Cancel a NAN publish
+ * @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 "NANCancelPublish" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_nan_cancel_publish(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ dbus_uint32_t publish_id;
+
+ if (!wpa_s->nan_de)
+ return NULL;
+
+ if (!dbus_message_get_args(message, NULL,
+ DBUS_TYPE_UINT32, &publish_id,
+ DBUS_TYPE_INVALID)) {
+ wpa_printf(MSG_DEBUG,
+ "dbus: NANCancelPublish failed to get args");
+ return wpas_dbus_error_invalid_args(message, NULL);
+ }
+
+ wpa_printf(MSG_DEBUG, "dbus: NANCancelPublish: id=%u", publish_id);
+ nan_de_cancel_publish(wpa_s->nan_de, publish_id);
+ return NULL;
+}
+
+
+/*
+ * wpas_dbus_handler_nan_update_publish - Update the SSI for a NAN publish
+ * @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 "NANUpdatePublish" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_nan_update_publish(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ DBusMessageIter iter, iter_dict;
+ struct wpa_dbus_dict_entry entry;
+ DBusMessage *reply = NULL;
+ int publish_id = -1;
+ struct wpabuf *ssi = NULL;
+
+ wpa_printf(MSG_DEBUG, "dbus: NANUpdatePublish");
+ if (!wpa_s->nan_de)
+ return NULL;
+
+ dbus_message_iter_init(message, &iter);
+
+ if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
+ goto fail;
+ while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+ if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+ goto fail;
+ if (os_strcmp(entry.key, "publish_id") == 0 &&
+ entry.type == DBUS_TYPE_UINT32) {
+ publish_id = entry.uint32_value;
+ wpa_dbus_dict_entry_clear(&entry);
+ wpa_printf(MSG_DEBUG, "dbus: publish_id=%d",
+ publish_id);
+ } else if (os_strcmp(entry.key, "ssi") == 0 &&
+ entry.type == DBUS_TYPE_ARRAY &&
+ entry.array_type == DBUS_TYPE_BYTE) {
+ wpabuf_free(ssi);
+ ssi = wpabuf_alloc_copy(entry.bytearray_value,
+ entry.array_len);
+ wpa_dbus_dict_entry_clear(&entry);
+ if (!ssi) {
+ reply = wpas_dbus_error_no_memory(message);
+ goto out;
+ }
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "dbus: NANTransmit - unsupported dict entry '%s'",
+ entry.key);
+ reply = wpas_dbus_error_invalid_args(message,
+ entry.key);
+ wpa_dbus_dict_entry_clear(&entry);
+ goto out;
+ }
+ }
+
+ if (publish_id < 0)
+ goto fail;
+
+ if (nan_de_update_publish(wpa_s->nan_de, publish_id, ssi) < 0)
+ reply = wpas_dbus_error_unknown_error(
+ message, "error updating NAN USD publish ssi");
+
+out:
+ wpabuf_free(ssi);
+ return reply;
+fail:
+ reply = wpas_dbus_error_invalid_args(
+ message,
+ "failed to parse NANUpdatePublish");
+ goto out;
+}
+
+
+/*
+ * wpas_dbus_handler_nan_subscribe - Send out NAN USD subscribe messages
+ * @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 "NANSubscribe" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_nan_subscribe(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ DBusMessageIter iter, iter_dict;
+ struct wpa_dbus_dict_entry entry;
+ DBusMessage *reply = NULL;
+ int subscribe_id;
+ char *srv_name = NULL;
+ struct nan_subscribe_params params;
+ enum nan_service_protocol_type srv_proto_type = 0;
+ bool p2p = false;
+ struct wpabuf *ssi = NULL;
+ int *freq_list = NULL;
+
+ wpa_printf(MSG_DEBUG, "dbus: NANSubscribe");
+ if (!wpa_s->nan_de)
+ return NULL;
+
+ os_memset(¶ms, 0, sizeof(params));
+ params.freq = NAN_USD_DEFAULT_FREQ;
+
+ dbus_message_iter_init(message, &iter);
+
+ if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
+ goto fail;
+ while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+ if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+ goto fail;
+ if (os_strcmp(entry.key, "srv_name") == 0 &&
+ entry.type == DBUS_TYPE_STRING) {
+ os_free(srv_name);
+ srv_name = os_strdup(entry.str_value);
+ wpa_dbus_dict_entry_clear(&entry);
+ if (!srv_name)
+ goto oom;
+ } else if (os_strcmp(entry.key, "srv_proto_type") == 0 &&
+ wpa_dbus_dict_entry_is_int(&entry)) {
+ srv_proto_type = wpa_dbus_dict_entry_get_int(&entry);
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "active") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ params.active = entry.bool_value;
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "p2p") == 0 &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ p2p = entry.bool_value;
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "ttl") == 0 &&
+ wpa_dbus_dict_entry_is_int(&entry)) {
+ params.ttl = wpa_dbus_dict_entry_get_int(&entry);
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "freq") == 0 &&
+ wpa_dbus_dict_entry_is_int(&entry)) {
+ params.freq = wpa_dbus_dict_entry_get_int(&entry);
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "query_period") == 0 &&
+ wpa_dbus_dict_entry_is_int(&entry)) {
+ params.query_period =
+ wpa_dbus_dict_entry_get_int(&entry);
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "ssi") == 0 &&
+ entry.type == DBUS_TYPE_ARRAY &&
+ entry.array_type == DBUS_TYPE_BYTE) {
+ wpabuf_free(ssi);
+ ssi = wpabuf_alloc_copy(entry.bytearray_value,
+ entry.array_len);
+ wpa_dbus_dict_entry_clear(&entry);
+ if (!ssi)
+ goto oom;
+ } else if (os_strcmp(entry.key, "freq_list") == 0 &&
+ entry.type == DBUS_TYPE_ARRAY &&
+ entry.array_type == DBUS_TYPE_UINT16) {
+ unsigned int i;
+
+ for (i = 0; i < entry.array_len; i++)
+ int_array_add_unique(
+ &freq_list, entry.uint16array_value[i]);
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "dbus: NANSubscribe - unsupported dict entry '%s'",
+ entry.key);
+ reply = wpas_dbus_error_invalid_args(message,
+ entry.key);
+ wpa_dbus_dict_entry_clear(&entry);
+ goto fail;
+ }
+ }
+
+ if (!srv_name)
+ goto fail;
+
+ subscribe_id = wpas_nan_usd_subscribe(wpa_s, srv_name, srv_proto_type,
+ ssi, ¶ms, p2p);
+ if (subscribe_id < 0) {
+ reply = wpas_dbus_error_unknown_error(
+ message, "error subscribing NAN USD");
+ goto out;
+ }
+
+ reply = dbus_message_new_method_return(message);
+ dbus_message_append_args(reply, DBUS_TYPE_UINT32,
+ &subscribe_id, DBUS_TYPE_INVALID);
+out:
+ wpabuf_free(ssi);
+ os_free(freq_list);
+ os_free(srv_name);
+ return reply;
+fail:
+ reply = wpas_dbus_error_invalid_args(message,
+ "failed to parse NANSubscribe");
+ goto out;
+oom:
+ reply = wpas_dbus_error_no_memory(message);
+ goto out;
+}
+
+
+/*
+ * wpas_dbus_handler_nan_cancel_subscribe - Cancel a NAN subscription
+ * @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 "NANCancelSubscribe" method call of network interface.
+ */
+DBusMessage *
+wpas_dbus_handler_nan_cancel_subscribe(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ dbus_uint32_t subscribe_id;
+
+ if (!wpa_s->nan_de)
+ return NULL;
+
+ if (!dbus_message_get_args(message, NULL,
+ DBUS_TYPE_UINT32, &subscribe_id,
+ DBUS_TYPE_INVALID)) {
+ wpa_printf(MSG_DEBUG,
+ "dbus: NANCancelSubscribe failed to get args");
+ return wpas_dbus_error_invalid_args(message, NULL);
+ }
+
+ wpa_printf(MSG_DEBUG, "dbus: NANCancelSubscribe: id=%u", subscribe_id);
+ nan_de_cancel_subscribe(wpa_s->nan_de, subscribe_id);
+ return NULL;
+}
+
+
+/*
+ * wpas_dbus_handler_nan_transmit - Send out NAN followup frames
+ * @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 "NANTransmit" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_nan_transmit(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ DBusMessageIter iter, iter_dict;
+ struct wpa_dbus_dict_entry entry;
+ DBusMessage *reply = NULL;
+ int handle = -1;
+ int req_instance_id = -1;
+ u8 peer_addr[ETH_ALEN];
+ bool peer_addr_set = false;
+ struct wpabuf *ssi = NULL;
+
+ wpa_printf(MSG_DEBUG, "dbus: NANTransmit");
+ if (!wpa_s->nan_de)
+ return NULL;
+
+ dbus_message_iter_init(message, &iter);
+
+ if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
+ goto fail;
+ while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+ if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+ goto fail;
+ if (os_strcmp(entry.key, "handle") == 0 &&
+ entry.type == DBUS_TYPE_UINT32) {
+ handle = entry.uint32_value;
+ wpa_dbus_dict_entry_clear(&entry);
+ wpa_printf(MSG_DEBUG, "dbus: handle=%d", handle);
+ } else if (os_strcmp(entry.key, "req_instance_id") == 0 &&
+ entry.type == DBUS_TYPE_UINT32) {
+ req_instance_id = entry.uint32_value;
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "peer_addr") == 0 &&
+ entry.type == DBUS_TYPE_STRING) {
+ if (hwaddr_aton(entry.str_value, peer_addr) < 0) {
+ wpa_dbus_dict_entry_clear(&entry);
+ goto fail;
+ }
+ peer_addr_set = true;
+ wpa_dbus_dict_entry_clear(&entry);
+ } else if (os_strcmp(entry.key, "ssi") == 0 &&
+ entry.type == DBUS_TYPE_ARRAY &&
+ entry.array_type == DBUS_TYPE_BYTE) {
+ wpabuf_free(ssi);
+ ssi = wpabuf_alloc_copy(entry.bytearray_value,
+ entry.array_len);
+ wpa_dbus_dict_entry_clear(&entry);
+ if (!ssi) {
+ reply = wpas_dbus_error_no_memory(message);
+ goto out;
+ }
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "dbus: NANTransmit - unsupported dict entry '%s'",
+ entry.key);
+ reply = wpas_dbus_error_invalid_args(message,
+ entry.key);
+ wpa_dbus_dict_entry_clear(&entry);
+ goto fail;
+ }
+ }
+
+ if (handle < 0 || req_instance_id < 0 || !peer_addr_set || !ssi)
+ goto fail;
+
+ if (wpas_nan_usd_transmit(wpa_s, handle, ssi, NULL, peer_addr,
+ req_instance_id) < 0)
+ reply = wpas_dbus_error_unknown_error(
+ message, "failed to transmit follow-up");
+out:
+ wpabuf_free(ssi);
+ return reply;
+
+fail:
+ reply = wpas_dbus_error_invalid_args(message,
+ "failed to parse NANTransmit");
+ goto out;
+}
+
+#endif /* CONFIG_NAN_USD */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
index 7faf70a..a526090 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -290,4 +290,18 @@
DBusMessage * wpas_dbus_handler_unsubscribe_preq(
DBusMessage *message, struct wpa_supplicant *wpa_s);
+DBusMessage * wpas_dbus_handler_nan_publish(DBusMessage *message,
+ struct wpa_supplicant *wpa_s);
+DBusMessage * wpas_dbus_handler_nan_cancel_publish(
+ DBusMessage *message, struct wpa_supplicant *wpa_s);
+DBusMessage * wpas_dbus_handler_nan_update_publish(
+ DBusMessage *message, struct wpa_supplicant *wpa_s);
+DBusMessage * wpas_dbus_handler_nan_subscribe(DBusMessage *message,
+ struct wpa_supplicant *wpa_s);
+DBusMessage *
+wpas_dbus_handler_nan_cancel_subscribe(DBusMessage *message,
+ struct wpa_supplicant *wpa_s);
+DBusMessage * wpas_dbus_handler_nan_transmit(DBusMessage *message,
+ struct wpa_supplicant *wpa_s);
+
#endif /* CTRL_IFACE_DBUS_HANDLERS_NEW_H */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 65bd478..ce49bce 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -477,7 +477,8 @@
freq2, ht40, vht,
max_oper_chwidth, he, edmg,
NULL, 0, 0, allow_6ghz,
- retry_limit, go_bssid)) {
+ retry_limit, go_bssid, NULL,
+ NULL, NULL, 0)) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
@@ -485,7 +486,7 @@
}
} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, freq2,
ht40, vht, max_oper_chwidth, he, edmg,
- allow_6ghz))
+ allow_6ghz, wpa_s->p2p2, wpa_s->p2p_mode))
goto inv_args;
out:
@@ -706,7 +707,7 @@
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, 0, 0,
- NULL, 0, false, 0, 0, NULL);
+ NULL, 0, false, 0, 0, NULL, false);
if (new_pin >= 0) {
char npin[9];
@@ -866,7 +867,7 @@
goto err;
if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
- 0, 0, 0, false) < 0) {
+ 0, 0, 0, false, false) < 0) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
diff --git a/wpa_supplicant/dbus/dbus_new_introspect.c b/wpa_supplicant/dbus/dbus_new_introspect.c
index a8c0d28..bfdc3e2 100644
--- a/wpa_supplicant/dbus/dbus_new_introspect.c
+++ b/wpa_supplicant/dbus/dbus_new_introspect.c
@@ -38,7 +38,7 @@
if (!iface)
return NULL;
iface->dbus_interface = os_strdup(dbus_interface);
- iface->xml = wpabuf_alloc(16000);
+ iface->xml = wpabuf_alloc(18000);
if (iface->dbus_interface == NULL || iface->xml == NULL) {
os_free(iface->dbus_interface);
wpabuf_free(iface->xml);
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index 1b2c756..70f7a3b 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -59,6 +59,9 @@
struct dpp_authentication *auth);
static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth);
#endif /* CONFIG_DPP2 */
+#ifdef CONFIG_DPP3
+static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx);
+#endif /* CONFIG_DPP3 */
static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -1347,6 +1350,16 @@
struct dpp_authentication *auth = wpa_s->dpp_auth;
int freq;
+#ifdef CONFIG_DPP3
+ if (wpa_s->dpp_pb_announcement && wpa_s->dpp_pb_discovery_done) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Failed to send push button announcement");
+ if (eloop_register_timeout(0, 0, wpas_dpp_pb_next,
+ wpa_s, NULL) < 0)
+ wpas_dpp_push_button_stop(wpa_s);
+ }
+#endif /* CONFIG_DPP3 */
+
if (wpa_s->dpp_listen_on_tx_expire && auth && auth->neg_freq) {
wpa_printf(MSG_DEBUG,
"DPP: Start listen on neg_freq %u MHz based on TX wait expiration on the previous channel",
@@ -5545,7 +5558,6 @@
#define DPP_PB_ANNOUNCE_PER_CHAN 3
static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq);
-static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx);
static void wpas_dpp_pb_tx_status(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index b6c7f50..43847cf 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -16,9 +16,17 @@
static inline void * wpa_drv_init(struct wpa_supplicant *wpa_s,
const char *ifname)
{
- if (wpa_s->driver->init2)
+ if (wpa_s->driver->init2) {
+ enum wpa_p2p_mode p2p_mode = WPA_P2P_MODE_WFD_R1;
+
+#ifdef CONFIG_P2P
+ p2p_mode = wpa_s->p2p_mode;
+#endif /* CONFIG_P2P */
+
return wpa_s->driver->init2(wpa_s, ifname,
- wpa_s->global_drv_priv);
+ wpa_s->global_drv_priv,
+ p2p_mode);
+ }
if (wpa_s->driver->init) {
return wpa_s->driver->init(wpa_s, ifname);
}
@@ -104,6 +112,8 @@
static inline int wpa_drv_scan(struct wpa_supplicant *wpa_s,
struct wpa_driver_scan_params *params)
{
+ params->link_id = -1;
+
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_s->test_failure == WPAS_TEST_FAILURE_SCAN_TRIGGER)
return -EBUSY;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 2a665d7..30176a0 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -437,6 +437,9 @@
wpa_s->ssid_verified = false;
wpa_s->bigtk_set = false;
+
+ wpabuf_free(wpa_s->pending_eapol_rx);
+ wpa_s->pending_eapol_rx = NULL;
}
@@ -1045,7 +1048,7 @@
#ifdef CONFIG_SAE
if (flagged && ((rate_ie[j] & 0x7f) ==
BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY)) {
- if (wpa_s->conf->sae_pwe ==
+ if (wpas_get_ssid_sae_pwe(wpa_s, ssid) ==
SAE_PWE_HUNT_AND_PECK &&
!ssid->sae_password_id &&
!is_6ghz_freq(bss->freq) &&
@@ -1163,7 +1166,8 @@
if (wpas_network_disabled(wpa_s, ssid))
continue;
if (ssid->ssid_len == *ret_ssid_len &&
- os_memcmp(ssid->ssid, ret_ssid, *ret_ssid_len) == 0) {
+ os_memcmp(ssid->ssid, *ret_ssid, *ret_ssid_len) ==
+ 0) {
/* OWE BSS in transition mode for a currently
* enabled OWE network. */
wpa_dbg(wpa_s, MSG_DEBUG,
@@ -1267,12 +1271,15 @@
{
int res;
bool wpa, check_ssid, osen, rsn_osen = false;
+#ifndef CONFIG_NO_WPA
struct wpa_ie_data data;
+#endif /* CONFIG_NO_WPA */
#ifdef CONFIG_MBO
const u8 *assoc_disallow;
#endif /* CONFIG_MBO */
#ifdef CONFIG_SAE
u8 rsnxe_capa = 0;
+ enum sae_pwe sae_pwe;
#endif /* CONFIG_SAE */
const u8 *ie;
@@ -1280,9 +1287,11 @@
wpa = ie && ie[1];
ie = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
wpa |= ie && ie[1];
+#ifndef CONFIG_NO_WPA
if (ie && wpa_parse_wpa_ie_rsn(ie, 2 + ie[1], &data) == 0 &&
(data.key_mgmt & WPA_KEY_MGMT_OSEN))
rsn_osen = true;
+#endif /* CONFIG_NO_WPA */
ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
osen = ie != NULL;
@@ -1449,9 +1458,10 @@
#ifdef CONFIG_SAE
/* When using SAE Password Identifier and when operationg on the 6 GHz
* band, only H2E is allowed. */
- if ((wpa_s->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
+ sae_pwe = wpas_get_ssid_sae_pwe(wpa_s, ssid);
+ if ((sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
is_6ghz_freq(bss->freq) || ssid->sae_password_id) &&
- wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK &&
+ sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK &&
wpa_key_mgmt_sae(ssid->key_mgmt) &&
#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
!(wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt)) &&
@@ -1737,7 +1747,7 @@
}
-static struct wpa_bss *
+struct wpa_bss *
wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
struct wpa_ssid *group,
struct wpa_ssid **selected_ssid,
@@ -2167,7 +2177,8 @@
int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s,
struct wpa_bss *current_bss,
- struct wpa_bss *selected)
+ struct wpa_bss *selected,
+ bool poll_current)
{
int min_diff, diff;
int cur_band_score, sel_band_score;
@@ -2222,7 +2233,7 @@
* scan results may be a bit old, since we can very quickly get fresh
* information about our currently associated AP.
*/
- if (wpa_drv_signal_poll(wpa_s, &si) == 0 &&
+ if (poll_current && wpa_drv_signal_poll(wpa_s, &si) == 0 &&
(si.data.avg_beacon_signal || si.data.avg_signal)) {
/*
* Normalize avg_signal to the RSSI over 20 MHz, as the
@@ -2395,7 +2406,7 @@
#ifndef CONFIG_NO_ROAMING
return wpa_supplicant_need_to_roam_within_ess(wpa_s, current_bss,
- selected);
+ selected, true);
#else /* CONFIG_NO_ROAMING */
return 0;
#endif /* CONFIG_NO_ROAMING */
@@ -2557,7 +2568,27 @@
}
#endif /* CONFIG_NO_RANDOM_POOL */
- wpa_s->last_scan_external = data && data->scan_info.external_scan;
+ if (data) {
+ size_t idx;
+
+ wpa_s->last_scan_external = data->scan_info.external_scan;
+ wpa_s->last_scan_num_ssids = data->scan_info.num_ssids;
+ for (idx = 0; idx < wpa_s->last_scan_num_ssids; idx++) {
+ /* Copy the SSID and its length */
+ if (idx >= WPAS_MAX_SCAN_SSIDS ||
+ data->scan_info.ssids[idx].ssid_len > SSID_MAX_LEN)
+ continue;
+
+ os_memcpy(wpa_s->last_scan_ssids[idx].ssid,
+ data->scan_info.ssids[idx].ssid,
+ data->scan_info.ssids[idx].ssid_len);
+ wpa_s->last_scan_ssids[idx].ssid_len =
+ data->scan_info.ssids[idx].ssid_len;
+ }
+ } else {
+ wpa_s->last_scan_external = false;
+ wpa_s->last_scan_num_ssids = 0;
+ }
if (update_only) {
ret = 1;
@@ -3470,7 +3501,7 @@
#endif /* CONFIG_WNM */
interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len);
- if (wpa_s->hw_capab == CAPAB_VHT &&
+ if ((wpa_s->hw_capab & BIT(CAPAB_VHT)) &&
get_ie(data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP))
wpa_s->ieee80211ac = 1;
@@ -5698,7 +5729,8 @@
WPA_GET_BE32(&payload[1]) == NAN_SDF_VENDOR_TYPE) {
payload += 5;
plen -= 5;
- wpas_nan_usd_rx_sdf(wpa_s, mgmt->sa, freq, payload, plen);
+ wpas_nan_usd_rx_sdf(wpa_s, mgmt->sa, mgmt->bssid, freq,
+ payload, plen);
return;
}
#endif /* CONFIG_NAN_USD */
@@ -6271,6 +6303,37 @@
#endif /* MAINLINE_SUPPLICANT */
+#ifdef CONFIG_PASN
+static int wpas_pasn_auth(struct wpa_supplicant *wpa_s,
+ const struct ieee80211_mgmt *mgmt, size_t len,
+ int freq)
+{
+#ifdef CONFIG_P2P
+ struct ieee802_11_elems elems;
+
+ if (len < 24) {
+ wpa_printf(MSG_DEBUG, "nl80211: Too short Management frame");
+ return -2;
+ }
+
+ if (ieee802_11_parse_elems(mgmt->u.auth.variable,
+ len - offsetof(struct ieee80211_mgmt,
+ u.auth.variable),
+ &elems, 1) == ParseFailed) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Failed parsing Authentication frame");
+ return -2;
+ }
+
+ if (elems.p2p2_ie && elems.p2p2_ie_len)
+ return wpas_p2p_pasn_auth_rx(wpa_s, mgmt, len, freq);
+#endif /* CONFIG_P2P */
+
+ return wpas_pasn_auth_rx(wpa_s, mgmt, len);
+}
+#endif /* CONFIG_PASN */
+
+
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data)
{
@@ -6509,6 +6572,17 @@
break;
#endif /* CONFIG_WNM */
#ifdef CONFIG_PASN
+#ifdef CONFIG_P2P
+ if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
+ data->tx_status.stype == WLAN_FC_STYPE_AUTH &&
+ !wpa_s->pasn_auth_work &&
+ wpa_s->p2p_pasn_auth_work &&
+ wpas_p2p_pasn_auth_tx_status(wpa_s,
+ data->tx_status.data,
+ data->tx_status.data_len,
+ data->tx_status.ack) == 0)
+ break;
+#endif /* CONFIG_P2P */
if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
data->tx_status.stype == WLAN_FC_STYPE_AUTH &&
wpas_pasn_auth_tx_status(wpa_s, data->tx_status.data,
@@ -6792,8 +6866,8 @@
}
#ifdef CONFIG_PASN
if (stype == WLAN_FC_STYPE_AUTH &&
- wpas_pasn_auth_rx(wpa_s, mgmt,
- data->rx_mgmt.frame_len) != -2)
+ wpas_pasn_auth(wpa_s, mgmt, data->rx_mgmt.frame_len,
+ data->rx_mgmt.freq) != -2)
break;
#endif /* CONFIG_PASN */
@@ -6897,12 +6971,12 @@
data->eapol_rx.encrypted);
break;
case EVENT_SIGNAL_CHANGE:
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SIGNAL_CHANGE
- "above=%d signal=%d noise=%d txrate=%lu",
- data->signal_change.above_threshold,
- data->signal_change.data.signal,
- data->signal_change.current_noise,
- data->signal_change.data.current_tx_rate);
+ wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SIGNAL_CHANGE
+ "above=%d signal=%d noise=%d txrate=%lu",
+ data->signal_change.above_threshold,
+ data->signal_change.data.signal,
+ data->signal_change.current_noise,
+ data->signal_change.data.current_tx_rate);
wpa_bss_update_level(wpa_s->current_bss,
data->signal_change.data.signal);
bgscan_notify_signal_change(
diff --git a/wpa_supplicant/mbo.c b/wpa_supplicant/mbo.c
index 80fbe01..273bd25 100644
--- a/wpa_supplicant/mbo.c
+++ b/wpa_supplicant/mbo.c
@@ -460,6 +460,10 @@
{
u8 *len;
+ if (wpa_s->drv_max_probe_req_ie_len <
+ 9 + ((wpa_s->enable_oce & OCE_STA) ? 3 : 0))
+ return;
+
wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
len = wpabuf_put(ie, 1);
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 85c1ea8..869f0b3 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -464,6 +464,9 @@
case 160:
conf->op_class = 134;
break;
+ case 320:
+ conf->op_class = 137;
+ break;
default:
conf->op_class = 131;
break;
@@ -602,7 +605,8 @@
/* EID + 0-length (wildcard) mesh-id */
size_t ielen = 2;
- if (wpabuf_resize(extra_ie, ielen) == 0) {
+ if (ielen <= wpa_s->drv_max_probe_req_ie_len &&
+ wpabuf_resize(extra_ie, ielen) == 0) {
wpabuf_put_u8(*extra_ie, WLAN_EID_MESH_ID);
wpabuf_put_u8(*extra_ie, 0);
}
diff --git a/wpa_supplicant/nan_usd.c b/wpa_supplicant/nan_usd.c
index 1125f95..577c8ac 100644
--- a/wpa_supplicant/nan_usd.c
+++ b/wpa_supplicant/nan_usd.c
@@ -321,7 +321,8 @@
cb.process_p2p_usd_elems = wpas_nan_process_p2p_usd_elems;
#endif /* CONFIG_P2P */
- wpa_s->nan_de = nan_de_init(wpa_s->own_addr, offload, false, &cb);
+ wpa_s->nan_de = nan_de_init(wpa_s->own_addr, offload, false,
+ wpa_s->max_remain_on_chan, &cb);
if (!wpa_s->nan_de)
return -1;
return 0;
@@ -336,11 +337,12 @@
void wpas_nan_usd_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *a3,
unsigned int freq, const u8 *buf, size_t len)
{
if (!wpa_s->nan_de)
return;
- nan_de_rx_sdf(wpa_s->nan_de, src, freq, buf, len);
+ nan_de_rx_sdf(wpa_s->nan_de, src, a3, freq, buf, len);
}
@@ -409,7 +411,7 @@
return -1;
ret = nan_de_update_publish(wpa_s->nan_de, publish_id, ssi);
if (ret == 0 && (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
- wpas_drv_nan_cancel_publish(wpa_s, publish_id) < 0)
+ wpas_drv_nan_update_publish(wpa_s, publish_id, ssi) < 0)
return -1;
return ret;
}
diff --git a/wpa_supplicant/nan_usd.h b/wpa_supplicant/nan_usd.h
index ecb4973..59c0989 100644
--- a/wpa_supplicant/nan_usd.h
+++ b/wpa_supplicant/nan_usd.h
@@ -16,6 +16,7 @@
int wpas_nan_usd_init(struct wpa_supplicant *wpa_s);
void wpas_nan_usd_deinit(struct wpa_supplicant *wpa_s);
void wpas_nan_usd_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *a3,
unsigned int freq, const u8 *buf, size_t len);
void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s);
int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 0cd7c63..d5a34c5 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -122,6 +122,8 @@
enum wpa_states new_state,
enum wpa_states old_state)
{
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+
if (wpa_s->p2p_mgmt)
return;
@@ -138,10 +140,14 @@
}
#endif /* CONFIG_FST */
- if (new_state == WPA_COMPLETED)
+ if (new_state == WPA_COMPLETED) {
wpas_p2p_notif_connected(wpa_s);
- else if (old_state >= WPA_ASSOCIATED && new_state < WPA_ASSOCIATED)
+ if (ssid)
+ wpa_drv_roaming(wpa_s, !ssid->bssid_set,
+ ssid->bssid_set ? ssid->bssid : NULL);
+ } else if (old_state >= WPA_ASSOCIATED && new_state < WPA_ASSOCIATED) {
wpas_p2p_notif_disconnected(wpa_s);
+ }
sme_state_changed(wpa_s);
@@ -918,6 +924,18 @@
id, op_freq);
}
+void wpas_notify_p2p_bootstrap_req(struct wpa_supplicant *wpa_s,
+ const u8 *src, u16 bootstrap_method)
+{
+ wpas_dbus_signal_p2p_bootstrap_req(wpa_s, src, bootstrap_method);
+}
+
+void wpas_notify_p2p_bootstrap_completed(struct wpa_supplicant *wpa_s,
+ const u8 *src, int status)
+{
+ wpas_dbus_signal_p2p_bootstrap_completed(wpa_s, src, status);
+}
+
#endif /* CONFIG_P2P */
@@ -1506,15 +1524,20 @@
return;
if (ssi)
wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
- wpa_msg(wpa_s, MSG_INFO, NAN_DISCOVERY_RESULT
- "subscribe_id=%d publish_id=%d address=" MACSTR
- " fsd=%d fsd_gas=%d srv_proto_type=%u ssi=%s",
- subscribe_id, peer_publish_id, MAC2STR(peer_addr),
- fsd, fsd_gas, srv_proto_type, ssi_hex);
+ wpa_msg_global(wpa_s, MSG_INFO, NAN_DISCOVERY_RESULT
+ "subscribe_id=%d publish_id=%d address=" MACSTR
+ " fsd=%d fsd_gas=%d srv_proto_type=%u ssi=%s",
+ subscribe_id, peer_publish_id, MAC2STR(peer_addr),
+ fsd, fsd_gas, srv_proto_type, ssi_hex);
os_free(ssi_hex);
wpas_aidl_notify_usd_service_discovered(wpa_s, srv_proto_type,
subscribe_id, peer_publish_id, peer_addr, fsd, ssi, ssi_len);
+
+ wpas_dbus_signal_nan_discovery_result(wpa_s, srv_proto_type,
+ subscribe_id, peer_publish_id,
+ peer_addr, fsd, fsd_gas,
+ ssi, ssi_len);
}
@@ -1531,15 +1554,19 @@
return;
if (ssi)
wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
- wpa_msg(wpa_s, MSG_INFO, NAN_REPLIED
- "publish_id=%d address=" MACSTR
- " subscribe_id=%d srv_proto_type=%u ssi=%s",
- publish_id, MAC2STR(peer_addr), peer_subscribe_id,
- srv_proto_type, ssi_hex);
+ wpa_msg_global(wpa_s, MSG_INFO, NAN_REPLIED
+ "publish_id=%d address=" MACSTR
+ " subscribe_id=%d srv_proto_type=%u ssi=%s",
+ publish_id, MAC2STR(peer_addr), peer_subscribe_id,
+ srv_proto_type, ssi_hex);
os_free(ssi_hex);
wpas_aidl_notify_usd_publish_replied(wpa_s, srv_proto_type,
publish_id, peer_subscribe_id, peer_addr, ssi, ssi_len);
+
+ wpas_dbus_signal_nan_replied(wpa_s, srv_proto_type, publish_id,
+ peer_subscribe_id, peer_addr,
+ ssi, ssi_len);
}
@@ -1554,13 +1581,16 @@
return;
if (ssi)
wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
- wpa_msg(wpa_s, MSG_INFO, NAN_RECEIVE
- "id=%d peer_instance_id=%d address=" MACSTR " ssi=%s",
- id, peer_instance_id, MAC2STR(peer_addr), ssi_hex);
+ wpa_msg_global(wpa_s, MSG_INFO, NAN_RECEIVE
+ "id=%d peer_instance_id=%d address=" MACSTR " ssi=%s",
+ id, peer_instance_id, MAC2STR(peer_addr), ssi_hex);
os_free(ssi_hex);
wpas_aidl_notify_usd_message_received(wpa_s, id, peer_instance_id,
peer_addr, ssi, ssi_len);
+
+ wpas_dbus_signal_nan_receive(wpa_s, id, peer_instance_id, peer_addr,
+ ssi, ssi_len);
}
@@ -1583,10 +1613,14 @@
int publish_id,
enum nan_de_reason reason)
{
- wpa_msg(wpa_s, MSG_INFO, NAN_PUBLISH_TERMINATED
- "publish_id=%d reason=%s",
- publish_id, nan_reason_txt(reason));
+ wpa_msg_global(wpa_s, MSG_INFO, NAN_PUBLISH_TERMINATED
+ "publish_id=%d reason=%s",
+ publish_id, nan_reason_txt(reason));
+
wpas_aidl_notify_usd_publish_terminated(wpa_s, publish_id, reason);
+
+ wpas_dbus_signal_nan_publish_terminated(wpa_s, publish_id,
+ nan_reason_txt(reason));
}
@@ -1594,10 +1628,14 @@
int subscribe_id,
enum nan_de_reason reason)
{
- wpa_msg(wpa_s, MSG_INFO, NAN_SUBSCRIBE_TERMINATED
- "subscribe_id=%d reason=%s",
- subscribe_id, nan_reason_txt(reason));
+ wpa_msg_global(wpa_s, MSG_INFO, NAN_SUBSCRIBE_TERMINATED
+ "subscribe_id=%d reason=%s",
+ subscribe_id, nan_reason_txt(reason));
+
wpas_aidl_notify_usd_subscribe_terminated(wpa_s, subscribe_id, reason);
+
+ wpas_dbus_signal_nan_subscribe_terminated(wpa_s, subscribe_id,
+ nan_reason_txt(reason));
}
#endif /* CONFIG_NAN_USD */
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index 4e172de..5775e37 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -166,6 +166,10 @@
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_p2p_bootstrap_req(struct wpa_supplicant *wpa_s,
+ const u8 *src, u16 bootstrap_method);
+void wpas_notify_p2p_bootstrap_completed(struct wpa_supplicant *wpa_s,
+ const u8 *src, int status);
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,
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 768b917..0c88e17 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -23,8 +23,10 @@
#include "ap/wps_hostapd.h"
#include "ap/p2p_hostapd.h"
#include "ap/dfs.h"
+#include "ap/wpa_auth.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "rsn_supp/wpa.h"
+#include "rsn_supp/pmksa_cache.h"
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "ap.h"
@@ -1229,12 +1231,18 @@
s->bssid_set = 1;
os_memcpy(s->bssid, go_dev_addr, ETH_ALEN);
s->mode = ssid->mode;
- s->auth_alg = WPA_AUTH_ALG_OPEN;
- s->key_mgmt = WPA_KEY_MGMT_PSK;
- s->proto = WPA_PROTO_RSN;
+ s->auth_alg = ssid->auth_alg;
+ s->key_mgmt = ssid->key_mgmt;
+ s->proto = ssid->proto;
s->pbss = ssid->pbss;
+ s->pmk_valid = ssid->pmk_valid;
s->pairwise_cipher = ssid->pbss ? WPA_CIPHER_GCMP : WPA_CIPHER_CCMP;
s->export_keys = 1;
+
+ if (ssid->sae_password) {
+ os_free(s->sae_password);
+ s->sae_password = os_strdup(ssid->sae_password);
+ }
if (ssid->passphrase) {
os_free(s->passphrase);
s->passphrase = os_strdup(ssid->passphrase);
@@ -1392,6 +1400,106 @@
}
+int wpas_p2p_remove_all_identity(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_dev_ik *ik;
+
+ for (ik = wpa_s->conf->identity; ik; ik = ik->next)
+ wpa_config_remove_identity(wpa_s->conf, ik->id);
+
+ if (wpa_s->conf->update_config &&
+ wpa_config_write(wpa_s->confname, wpa_s->conf)) {
+ wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
+ return -1;
+ }
+ return 0;
+}
+
+
+static void wpas_p2p_store_identity(struct wpa_supplicant *wpa_s, u8 cipher,
+ const u8 *dik_data, size_t dik_len,
+ const u8 *pmk, size_t pmk_len,
+ const u8 *pmkid)
+{
+ struct wpa_dev_ik *ik;
+
+ for (ik = wpa_s->conf->identity; ik; ik = ik->next) {
+ if (dik_len == wpabuf_len(ik->dik) &&
+ os_memcmp(dik_data, wpabuf_head(ik->dik), dik_len) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "P2P: Remove previous device identity entry for matching DIK");
+ wpa_config_remove_identity(wpa_s->conf, ik->id);
+ break;
+ }
+ }
+
+ wpa_printf(MSG_DEBUG, "P2P: Create a new device identity entry");
+ ik = wpa_config_add_identity(wpa_s->conf);
+ if (!ik)
+ return;
+
+ ik->dik = wpabuf_alloc_copy(dik_data, dik_len);
+ if (!ik->dik)
+ goto fail;
+ ik->pmk = wpabuf_alloc_copy(pmk, pmk_len);
+ if (!ik->pmk)
+ goto fail;
+ ik->pmkid = wpabuf_alloc_copy(pmkid, PMKID_LEN);
+ if (!ik->pmkid)
+ goto fail;
+
+ ik->dik_cipher = cipher;
+
+ if (wpa_s->conf->update_config &&
+ wpa_config_write(wpa_s->confname, wpa_s->conf))
+ wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
+ return;
+
+fail:
+ wpa_config_remove_identity(wpa_s->conf, ik->id);
+}
+
+
+static void wpas_p2p_store_go_identity(struct wpa_supplicant *wpa_s,
+ const u8 *go_dev_addr, const u8 *bssid)
+{
+ int ret;
+ u8 cipher;
+ const u8 *dik_data, *pmk, *pmkid;
+ size_t dik_len, pmk_len;
+ u8 iface_addr[ETH_ALEN];
+ struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s;
+
+ if (!wpa_s->p2p2)
+ return;
+
+ ret = p2p_get_dev_identity_key(p2p_wpa_s->global->p2p, go_dev_addr,
+ &dik_data, &dik_len, &cipher);
+ if (ret)
+ return;
+
+ ret = p2p_get_interface_addr(p2p_wpa_s->global->p2p, go_dev_addr,
+ iface_addr);
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "P2P: Fetch PMK for GO BSSID " MACSTR,
+ MAC2STR(bssid));
+ os_memcpy(iface_addr, bssid, ETH_ALEN);
+ }
+ ret = wpa_sm_pmksa_get_pmk(wpa_s->wpa, iface_addr, &pmk, &pmk_len,
+ &pmkid);
+ if (ret)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "P2P: Storing Device identity of GO (Interface Addr " MACSTR
+ ")",
+ MAC2STR(iface_addr));
+ wpas_p2p_store_identity(p2p_wpa_s, cipher, dik_data, dik_len, pmk,
+ pmk_len, pmkid);
+}
+
+
static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
int success, int already_deleted)
{
@@ -1690,8 +1798,11 @@
if (listen_freq != (int) freq && send_freq != (int) freq) {
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);
+ wpa_printf(MSG_DEBUG,
+ "P2P: Schedule new radio work for Action frame TX (listen_freq=%d send_freq=%d freq=%u dst="
+ MACSTR " src=" MACSTR " bssid=" MACSTR,
+ listen_freq, send_freq, freq, MAC2STR(dst),
+ MAC2STR(src), MAC2STR(bssid));
res = wpas_send_action_work(wpa_s, freq, dst, src, bssid, buf,
len, wait_time);
if (res == 0 && scheduled)
@@ -1722,6 +1833,125 @@
}
+#ifdef CONFIG_PASN
+
+struct wpa_p2p_pasn_auth_work {
+ u8 peer_addr[ETH_ALEN];
+ int freq;
+ bool verify;
+ int force_freq;
+ int pref_freq;
+ enum p2p_invite_role role;
+ u8 *ssid;
+ size_t ssid_len;
+ u8 bssid[ETH_ALEN];
+ u8 go_dev_addr[ETH_ALEN];
+};
+
+
+static void wpas_p2p_pasn_free_auth_work(struct wpa_p2p_pasn_auth_work *awork)
+{
+ if (!awork)
+ return;
+ os_free(awork->ssid);
+ os_free(awork);
+}
+
+
+static void wpas_p2p_pasn_cancel_auth_work(struct wpa_supplicant *wpa_s)
+{
+ wpa_printf(MSG_DEBUG, "P2P PASN: Cancel p2p-pasn-start-auth work");
+
+ /* Remove pending/started work */
+ radio_remove_works(wpa_s, "p2p-pasn-start-auth", 0);
+}
+
+
+static void wpas_p2p_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
+{
+ int ret;
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ struct wpa_p2p_pasn_auth_work *awork = work->ctx;
+ struct p2p_data *p2p = wpa_s->global->p2p;
+ const u8 *peer_addr = NULL;
+ const u8 *bssid = NULL;
+ const u8 *go_dev_addr = NULL;
+
+ if (deinit) {
+ if (!work->started) {
+ eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
+ wpa_s->p2pdev, NULL);
+ }
+ wpas_p2p_pasn_free_auth_work(awork);
+ return;
+ }
+
+ if (!is_zero_ether_addr(awork->peer_addr))
+ peer_addr = awork->peer_addr;
+ if (!is_zero_ether_addr(awork->bssid))
+ bssid = awork->bssid;
+ if (!is_zero_ether_addr(awork->go_dev_addr))
+ go_dev_addr = awork->go_dev_addr;
+
+
+ if (awork->verify)
+ ret = p2p_initiate_pasn_verify(p2p, peer_addr, awork->freq,
+ awork->role, bssid, awork->ssid,
+ awork->ssid_len,
+ awork->force_freq, go_dev_addr,
+ awork->pref_freq);
+ else
+ ret = p2p_initiate_pasn_auth(p2p, peer_addr, awork->freq);
+
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "P2P PASN: Failed to start PASN authentication");
+ goto fail;
+ }
+ eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
+ wpa_s->p2pdev, NULL);
+ eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
+ wpas_p2p_group_formation_timeout,
+ wpa_s->p2pdev, NULL);
+ wpa_s->p2p_pasn_auth_work = work;
+ return;
+
+fail:
+ wpas_p2p_pasn_free_auth_work(awork);
+ work->ctx = NULL;
+ radio_work_done(work);
+}
+
+
+static int wpas_p2p_initiate_pasn_auth(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr, int freq)
+{
+ struct wpa_p2p_pasn_auth_work *awork;
+
+ wpas_p2p_pasn_cancel_auth_work(wpa_s);
+ wpa_s->p2p_pasn_auth_work = NULL;
+
+ awork = os_zalloc(sizeof(*awork));
+ if (!awork)
+ return -1;
+
+ awork->freq = freq;
+ os_memcpy(awork->peer_addr, peer_addr, ETH_ALEN);
+
+ if (radio_add_work(wpa_s, freq, "p2p-pasn-start-auth", 1,
+ wpas_p2p_pasn_auth_start_cb, awork) < 0) {
+ wpas_p2p_pasn_free_auth_work(awork);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "P2P PASN: Authentication work successfully added");
+ return 0;
+}
+
+#endif /* CONFIG_PASN */
+
+
static int wpas_copy_go_neg_results(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *params)
{
@@ -1735,6 +1965,101 @@
}
+static void wpas_start_gc(struct wpa_supplicant *wpa_s,
+ struct p2p_go_neg_results *res)
+{
+ struct os_reltime now;
+ struct wpa_ssid *ssid;
+ struct rsn_pmksa_cache_entry *entry;
+
+ if (!res->ssid_len) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: SSID info not present");
+ return;
+ }
+
+ wpa_s->group_formation_reported = 0;
+ wpa_printf(MSG_DEBUG, "P2P: Start connect for peer " MACSTR
+ " dev_addr " MACSTR,
+ MAC2STR(res->peer_interface_addr),
+ MAC2STR(res->peer_device_addr));
+ wpa_hexdump_ascii(MSG_DEBUG, "P2P: Start connect for SSID",
+ res->ssid, res->ssid_len);
+ wpa_supplicant_ap_deinit(wpa_s);
+ wpas_copy_go_neg_results(wpa_s, res);
+
+ ssid = wpa_config_add_network(wpa_s->conf);
+ if (!ssid) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Could not add network for client");
+ return;
+ }
+ os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN);
+ wpa_config_set_network_defaults(ssid);
+ ssid->temporary = 1;
+ ssid->p2p_group = 1;
+
+ ssid->ssid = os_memdup(res->ssid, res->ssid_len);
+ if (!ssid->ssid)
+ return;
+ ssid->ssid_len = res->ssid_len;
+
+ os_memcpy(ssid->bssid, res->peer_interface_addr, ETH_ALEN);
+
+ if (res->akmp == WPA_KEY_MGMT_PASN && res->sae_password[0]) {
+ ssid->auth_alg = WPA_AUTH_ALG_SAE;
+ ssid->sae_password = os_strdup(res->sae_password);
+ if (!ssid->sae_password)
+ return;
+ } else if (res->akmp == WPA_KEY_MGMT_SAE && res->pmk_len) {
+ ssid->auth_alg = WPA_AUTH_ALG_OPEN;
+ entry = os_zalloc(sizeof(*entry));
+ if (!entry)
+ return;
+ os_memcpy(entry->aa, res->peer_interface_addr, ETH_ALEN);
+ os_memcpy(entry->pmkid, res->pmkid, PMKID_LEN);
+ entry->pmk_len = res->pmk_len;
+ os_memcpy(entry->pmk, res->pmk, res->pmk_len);
+ entry->akmp = res->akmp;
+ os_get_reltime(&now);
+ entry->expiration = now.sec + 43200;
+ entry->reauth_time = now.sec + 43200 * 70 / 100;
+ entry->network_ctx = ssid;
+ os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
+
+ wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
+ ssid->pmk_valid = true;
+ } else if (res->akmp == WPA_KEY_MGMT_SAE && res->sae_password[0]) {
+ ssid->auth_alg = WPA_AUTH_ALG_SAE;
+ ssid->sae_password = os_strdup(res->sae_password);
+ if (!ssid->sae_password)
+ return;
+ }
+
+ if (res->psk_set) {
+ os_memcpy(ssid->psk, res->psk, 32);
+ ssid->psk_set = 1;
+ }
+ ssid->proto = WPA_PROTO_RSN;
+ ssid->key_mgmt = WPA_KEY_MGMT_SAE;
+ ssid->pairwise_cipher = WPA_CIPHER_CCMP;
+ ssid->group_cipher = WPA_CIPHER_CCMP;
+ if (res->cipher)
+ ssid->pairwise_cipher |= res->cipher;
+ ssid->sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
+ ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+ ssid->disabled = 0;
+ wpa_s->show_group_started = 1;
+ wpa_s->p2p_in_invitation = 1;
+ wpa_s->p2p_go_group_formation_completed = 0;
+ wpa_s->global->p2p_group_formation = wpa_s;
+ ssid->rsn_overriding = RSN_OVERRIDING_ENABLED;
+
+ wpa_s->current_ssid = ssid;
+ wpa_supplicant_update_scan_results(wpa_s, res->peer_interface_addr);
+ wpa_supplicant_select_network(wpa_s, ssid);
+}
+
+
static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *res)
{
@@ -1879,6 +2204,19 @@
return;
}
+ if (wpa_s->ap_iface && params->p2p2 &&
+ params->akmp == WPA_KEY_MGMT_SAE) {
+ struct hostapd_data *hapd = wpa_s->ap_iface->bss[0];
+
+ wpa_auth_pmksa_add_sae(hapd->wpa_auth,
+ params->peer_device_addr,
+ params->pmk, params->pmk_len,
+ params->pmkid, WPA_KEY_MGMT_SAE);
+ hostapd_add_pmkid(hapd, params->peer_device_addr,
+ params->pmk, params->pmk_len,
+ params->pmkid, WPA_KEY_MGMT_SAE);
+ }
+
p2p_go_save_group_common_freqs(wpa_s, params);
p2p_go_dump_common_freqs(wpa_s);
@@ -1944,13 +2282,21 @@
return;
}
- wpa_printf(MSG_DEBUG, "P2P: Setting up WPS for GO provisioning");
if (wpa_supplicant_ap_mac_addr_filter(wpa_s,
params->peer_interface_addr)) {
wpa_printf(MSG_DEBUG, "P2P: Failed to setup MAC address "
"filtering");
return;
}
+
+ if (params->p2p2) {
+ wpas_group_formation_completed(wpa_s, 1, 0);
+ wpa_printf(MSG_DEBUG,
+ "P2P2: Group formation completed - first connection in progress");
+ goto out;
+ }
+
+ wpa_printf(MSG_DEBUG, "P2P: Setting up WPS for GO provisioning");
if (params->wps_method == WPS_PBC) {
wpa_supplicant_ap_wps_pbc(wpa_s, params->peer_interface_addr,
params->peer_device_addr);
@@ -1971,6 +2317,7 @@
} else if (wpa_s->p2p_pin[0])
wpa_supplicant_ap_wps_pin(wpa_s, params->peer_interface_addr,
wpa_s->p2p_pin, NULL, 0, 0);
+out:
os_free(wpa_s->go_params);
wpa_s->go_params = NULL;
}
@@ -2053,9 +2400,9 @@
}
-static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
- struct p2p_go_neg_results *params,
- int group_formation)
+static void wpas_start_go(struct wpa_supplicant *wpa_s,
+ struct p2p_go_neg_results *params,
+ int group_formation, enum wpa_p2p_mode p2p_mode)
{
struct wpa_ssid *ssid;
@@ -2150,6 +2497,24 @@
wpa_config_update_psk(ssid);
ssid->ap_max_inactivity = wpa_s->p2pdev->conf->p2p_go_max_inactivity;
+ ssid->p2p_mode = p2p_mode;
+ if (params->p2p2) {
+ if (params->akmp == WPA_KEY_MGMT_SAE)
+ ssid->auth_alg = WPA_AUTH_ALG_OPEN;
+ else
+ ssid->auth_alg |= WPA_AUTH_ALG_SAE;
+
+ ssid->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PASN;
+ ssid->sae_password = os_strdup(params->sae_password);
+ /* In PCC, RSNE indicates PMF to be disabled while RSNOE/RSNO2E
+ * requires PMF for SAE. */
+ if (ssid->p2p_mode != WPA_P2P_MODE_WFD_PCC)
+ ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+ ssid->sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
+ if (params->cipher)
+ ssid->pairwise_cipher |= params->cipher;
+ }
+
wpa_s->ap_configured_cb = p2p_go_configured;
wpa_s->ap_configured_cb_ctx = wpa_s;
wpa_s->ap_configured_cb_data = wpa_s->go_params;
@@ -2364,6 +2729,7 @@
wpa_s->global->pending_group_iface_for_p2ps = 0;
wpas_p2p_clone_config(group_wpa_s, wpa_s);
+ group_wpa_s->p2p2 = wpa_s->p2p2;
if (wpa_s->conf->p2p_interface_random_mac_addr) {
if (wpa_drv_set_mac_addr(group_wpa_s,
@@ -2396,6 +2762,14 @@
void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
+
+#ifdef CONFIG_PASN
+ if (wpa_s->p2p_pasn_auth_work) {
+ wpas_p2p_pasn_cancel_auth_work(wpa_s);
+ wpa_s->p2p_pasn_auth_work = NULL;
+ }
+#endif /* CONFIG_PASN */
+
wpa_printf(MSG_DEBUG, "P2P: Group Formation timed out");
wpas_p2p_group_formation_failed(wpa_s, 0);
}
@@ -2450,6 +2824,49 @@
}
+static void wpas_set_go_security_config(void *ctx,
+ struct p2p_go_neg_results *params)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ struct wpa_supplicant *tmp, *ifs = NULL;
+ struct hostapd_data *hapd;
+
+ if (!params->p2p2)
+ return;
+
+ dl_list_for_each(tmp, &wpa_s->radio->ifaces, struct wpa_supplicant,
+ radio_list) {
+ struct wpa_ssid *ssid = tmp->current_ssid;
+
+ if (ssid && ssid->mode == WPAS_MODE_P2P_GO &&
+ ssid->ssid && ssid->ssid_len == params->ssid_len &&
+ os_memcmp(ssid->ssid, params->ssid, params->ssid_len) == 0)
+ {
+ ifs = tmp;
+ break;
+ }
+ }
+
+ if (!ifs || !ifs->ap_iface)
+ return;
+
+ hapd = ifs->ap_iface->bss[0];
+ hapd->conf->wps_state = 0;
+
+ if (params->akmp == WPA_KEY_MGMT_SAE) {
+ wpa_printf(MSG_DEBUG, "P2P: Adding PMK for peer: " MACSTR,
+ MAC2STR(params->peer_device_addr));
+ wpa_auth_pmksa_add_sae(hapd->wpa_auth,
+ params->peer_device_addr,
+ params->pmk, params->pmk_len,
+ params->pmkid, WPA_KEY_MGMT_SAE);
+ hostapd_add_pmkid(hapd, params->peer_device_addr,
+ params->pmk, params->pmk_len,
+ params->pmkid, WPA_KEY_MGMT_SAE);
+ }
+}
+
+
static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
{
struct wpa_supplicant *wpa_s = ctx;
@@ -2461,6 +2878,13 @@
wpa_s->roc_waiting_drv_freq = 0;
}
+#ifdef CONFIG_PASN
+ if (wpa_s->p2p_pasn_auth_work) {
+ wpas_p2p_pasn_cancel_auth_work(wpa_s);
+ wpa_s->p2p_pasn_auth_work = NULL;
+ }
+#endif /* CONFIG_PASN */
+
if (res->status) {
wpa_msg_global(wpa_s, MSG_INFO,
P2P_EVENT_GO_NEG_FAILURE "status=%d",
@@ -2534,12 +2958,18 @@
os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin,
sizeof(group_wpa_s->p2p_pin));
group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method;
+ group_wpa_s->p2p2 = res->p2p2;
+ group_wpa_s->p2p_bootstrap = wpa_s->p2p_bootstrap;
}
+
if (res->role_go) {
- wpas_start_wps_go(group_wpa_s, res, 1);
+ wpas_start_go(group_wpa_s, res, 1, group_wpa_s->p2p_mode);
} else {
os_get_reltime(&group_wpa_s->scan_min_time);
- wpas_start_wps_enrollee(group_wpa_s, res);
+ if (res->p2p2)
+ wpas_start_gc(group_wpa_s, res);
+ else
+ wpas_start_wps_enrollee(group_wpa_s, res);
}
wpa_s->global->p2p_long_listen = 0;
@@ -2646,8 +3076,7 @@
wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_FOUND MACSTR
" p2p_dev_addr=" MACSTR
- " pri_dev_type=%s name='%s' config_methods=0x%x "
- "dev_capab=0x%x group_capab=0x%x%s%s%s%s%s new=%d",
+ " pri_dev_type=%s name='%s' config_methods=0x%x dev_capab=0x%x group_capab=0x%x%s%s%s%s%s new=%d pcea_cap_info=0x%x bootstrap_methods=0x%x pasn_type=0x%x",
MAC2STR(addr), MAC2STR(info->p2p_device_addr),
wps_dev_type_bin2str(info->pri_dev_type, devtype,
sizeof(devtype)),
@@ -2658,7 +3087,9 @@
wfd_r2_dev_info_hex ? " wfd_r2_dev_info=0x" : "",
wfd_r2_dev_info_hex ? wfd_r2_dev_info_hex : "",
info->vendor_elems ? " vendor_elems=1" : "",
- new_device);
+ new_device, info->pcea_cap_info,
+ info->pairing_config.bootstrap_methods,
+ info->pairing_config.pasn_type);
done:
os_free(wfd_dev_info_hex);
@@ -2831,10 +3262,13 @@
wpas_p2p_listen_work_done(wpa_s);
- if (radio_work_pending(wpa_s, "p2p-listen")) {
+ if (!wpa_s->p2p_removing_listen_work &&
+ radio_work_pending(wpa_s, "p2p-listen")) {
+ wpa_s->p2p_removing_listen_work = true;
wpa_printf(MSG_DEBUG,
"P2P: p2p-listen is still pending - remove it");
radio_remove_works(wpa_s, "p2p-listen", 0);
+ wpa_s->p2p_removing_listen_work = false;
}
}
@@ -3217,7 +3651,7 @@
size_t ssid_len, int *go, u8 *group_bssid,
int *force_freq, int persistent_group,
const struct p2p_channels *channels,
- int dev_pw_id)
+ int dev_pw_id, bool p2p2)
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *s;
@@ -3281,7 +3715,7 @@
for (s = wpa_s->conf->ssid; s; s = s->next) {
if (s->disabled == 2 &&
- ether_addr_equal(s->bssid, go_dev_addr) &&
+ (p2p2 || ether_addr_equal(s->bssid, go_dev_addr)) &&
s->ssid_len == ssid_len &&
os_memcmp(ssid, s->ssid, ssid_len) == 0)
break;
@@ -3376,7 +3810,8 @@
static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
const u8 *ssid, size_t ssid_len,
const u8 *go_dev_addr, u8 status,
- int op_freq)
+ int op_freq, const u8 *pmkid,
+ const u8 *pmk, size_t pmk_len)
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *s;
@@ -3416,7 +3851,7 @@
wpa_s->conf->p2p_go_edmg, NULL,
go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0,
1, is_p2p_allow_6ghz(wpa_s->global->p2p), 0,
- NULL);
+ bssid, sa, pmkid, pmk, pmk_len);
} else if (bssid) {
wpa_s->user_initiated_pd = 0;
wpa_msg_global(wpa_s, MSG_INFO,
@@ -3534,12 +3969,20 @@
static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
const struct p2p_channels *channels,
const u8 *peer, int neg_freq,
- int peer_oper_freq)
+ int peer_oper_freq, const u8 *pmkid,
+ const u8 *pmk, size_t pmk_len)
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *ssid;
int freq;
+#ifdef CONFIG_PASN
+ if (wpa_s->p2p_pasn_auth_work) {
+ wpas_p2p_pasn_cancel_auth_work(wpa_s);
+ wpa_s->p2p_pasn_auth_work = NULL;
+ }
+#endif /* CONFIG_PASN */
+
if (bssid) {
wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
"status=%d " MACSTR,
@@ -3647,7 +4090,7 @@
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
0, 1,
is_p2p_allow_6ghz(wpa_s->global->p2p), 0,
- NULL);
+ bssid, peer, pmkid, pmk, pmk_len);
}
@@ -4716,10 +5159,13 @@
persistent_go->mode ==
WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
- 0, 0, false, 0, NULL);
+ 0, 0, false, 0, NULL, NULL, NULL, NULL,
+ 0);
} else if (response_done) {
wpas_p2p_group_add(wpa_s, 1, freq,
- 0, 0, 0, 0, 0, 0, false);
+ 0, 0, 0, 0, 0, 0, false,
+ wpa_s->p2p2,
+ WPA_P2P_MODE_WFD_R1);
}
if (passwd_id == DEV_PW_P2PS_DEFAULT) {
@@ -4839,10 +5285,12 @@
NULL,
persistent_go->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0,
- is_p2p_allow_6ghz(wpa_s->global->p2p), 0, NULL);
+ is_p2p_allow_6ghz(wpa_s->global->p2p), 0, NULL, NULL,
+ NULL, NULL, 0);
} else {
wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0, 0,
- is_p2p_allow_6ghz(wpa_s->global->p2p));
+ is_p2p_allow_6ghz(wpa_s->global->p2p),
+ wpa_s->p2p2, WPA_P2P_MODE_WFD_R1);
}
return 1;
@@ -4877,7 +5325,7 @@
wpa_s->p2p_go_he,
wpa_s->p2p_go_edmg,
NULL, 0, is_p2p_allow_6ghz(wpa_s->global->p2p),
- wpa_s->p2p2, wpa_s->p2p_bootstrap, NULL);
+ wpa_s->p2p2, wpa_s->p2p_bootstrap, NULL, false);
}
@@ -4903,6 +5351,8 @@
wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_BOOTSTRAP_REQUEST MACSTR
" bootstrap_method=%u", MAC2STR(addr), bootstrap_method);
+
+ wpas_notify_p2p_bootstrap_req(wpa_s, addr, bootstrap_method);
}
@@ -4911,18 +5361,175 @@
{
struct wpa_supplicant *wpa_s = ctx;
+ wpas_notify_p2p_bootstrap_completed(wpa_s, addr, status);
+
if (status) {
wpa_msg_global(wpa_s, MSG_INFO,
P2P_EVENT_BOOTSTRAP_FAILURE MACSTR " status=%d",
MAC2STR(addr), status);
- } else {
- wpa_msg_global(wpa_s, MSG_INFO,
- P2P_EVENT_BOOTSTRAP_SUCCESS MACSTR " status=%d",
- MAC2STR(addr), status);
+ return;
}
+
+ wpa_msg_global(wpa_s, MSG_INFO,
+ P2P_EVENT_BOOTSTRAP_SUCCESS MACSTR " status=%d",
+ MAC2STR(addr), status);
+
+#ifdef CONFIG_PASN
+ wpas_p2p_initiate_pasn_auth(wpa_s, addr, freq);
+#endif /* CONFIG_PASN */
}
+static void wpas_validate_dira(void *ctx, const u8 *peer_addr,
+ const u8 *dira, size_t dira_len)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ int ret;
+ u8 tag[DEVICE_MAX_HASH_LEN];
+ struct wpa_dev_ik *ik;
+ const u8 *addr[3];
+ size_t len[3];
+ const char *label = "DIR";
+
+ if (dira_len < 1 || dira[0] != DIRA_CIPHER_VERSION_128) {
+ wpa_printf(MSG_ERROR,
+ "P2P2: Unsupported DIRA cipher version %d", dira[0]);
+ return;
+ }
+
+ if (dira_len < 1 + DEVICE_IDENTITY_NONCE_LEN + DEVICE_IDENTITY_TAG_LEN)
+ {
+ wpa_printf(MSG_INFO, "P2P2: Truncated DIRA (length %zu)",
+ dira_len);
+ return;
+ }
+
+ addr[0] = (const u8 *) label;
+ len[0] = DIR_STR_LEN;
+ addr[1] = peer_addr;
+ len[1] = ETH_ALEN;
+ addr[2] = &dira[1];
+ len[2] = DEVICE_IDENTITY_NONCE_LEN;
+
+ for (ik = wpa_s->conf->identity; ik; ik = ik->next) {
+ if (wpabuf_len(ik->dik) != DEVICE_IDENTITY_KEY_LEN ||
+ ik->dik_cipher != DIRA_CIPHER_VERSION_128)
+ continue;
+
+ ret = hmac_sha256_vector(wpabuf_head(ik->dik),
+ DEVICE_IDENTITY_KEY_LEN,
+ 3, addr, len, tag);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR,
+ "P2P2: Failed to derive DIRA Tag");
+ return;
+ }
+
+ if (os_memcmp(tag, &dira[1 + DEVICE_IDENTITY_NONCE_LEN],
+ DEVICE_IDENTITY_TAG_LEN) == 0) {
+ wpa_printf(MSG_DEBUG, "P2P2: DIRA Tag matched");
+ break;
+ }
+ }
+
+ if (!ik)
+ return;
+
+#ifdef CONFIG_PASN
+ p2p_pasn_pmksa_set_pmk(wpa_s->global->p2p, wpa_s->global->p2p_dev_addr,
+ peer_addr,
+ wpabuf_head(ik->pmk), wpabuf_len(ik->pmk),
+ wpabuf_head(ik->pmkid));
+#endif /* CONFIG_PASN */
+}
+
+
+#ifdef CONFIG_PASN
+
+static int wpas_p2p_initiate_pasn_verify(struct wpa_supplicant *wpa_s,
+ const u8 *peer,
+ enum p2p_invite_role role,
+ const u8 *bssid, const u8 *ssid,
+ size_t ssid_len,
+ unsigned int force_freq,
+ const u8 *go_dev_addr,
+ unsigned int pref_freq)
+{
+ int freq;
+ struct wpa_p2p_pasn_auth_work *awork;
+
+ wpas_p2p_pasn_cancel_auth_work(wpa_s);
+ wpa_s->p2p_pasn_auth_work = NULL;
+
+ freq = p2p_get_listen_freq(wpa_s->global->p2p, peer);
+ if (freq == -1)
+ return -1;
+
+ awork = os_zalloc(sizeof(*awork));
+ if (!awork)
+ return -1;
+
+ awork->verify = 1;
+ awork->role = role;
+ awork->freq = freq;
+ awork->force_freq = force_freq;
+ awork->pref_freq = pref_freq;
+ os_memcpy(awork->peer_addr, peer, ETH_ALEN);
+ if (go_dev_addr)
+ os_memcpy(awork->go_dev_addr, go_dev_addr, ETH_ALEN);
+ if (bssid)
+ os_memcpy(awork->bssid, bssid, ETH_ALEN);
+ if (ssid_len) {
+ awork->ssid = os_zalloc(ssid_len);
+ if (!awork->ssid) {
+ os_free(awork);
+ return -1;
+ }
+ os_memcpy(awork->ssid, ssid, ssid_len);
+ awork->ssid_len = ssid_len;
+ }
+
+ if (radio_add_work(wpa_s, freq, "p2p-pasn-start-auth", 1,
+ wpas_p2p_pasn_auth_start_cb, awork) < 0) {
+ wpas_p2p_pasn_free_auth_work(awork);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "P2P PASN: Auth work successfully added");
+ return 0;
+}
+
+
+static int wpas_p2p_pasn_send_mgmt(void *ctx, const u8 *data, size_t data_len,
+ int noack, unsigned int freq,
+ unsigned int wait)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ return wpa_drv_send_mlme(wpa_s, data, data_len, noack, freq, wait);
+}
+
+
+static int wpas_p2p_prepare_data_element(void *ctx, const u8 *peer_addr)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ struct p2p_data *p2p = wpa_s->global->p2p;
+
+ return p2p_prepare_data_element(p2p, peer_addr);
+}
+
+
+static int wpas_p2p_parse_data_element(void *ctx, const u8 *data, size_t len)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ struct p2p_data *p2p = wpa_s->global->p2p;
+
+ return p2p_parse_data_element(p2p, data, len);
+}
+
+#endif /* CONFIG_PASN */
+
+
int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s)
{
int ret = 0;
@@ -5018,6 +5625,7 @@
p2p.send_action = wpas_send_action;
p2p.send_action_done = wpas_send_action_done;
p2p.go_neg_completed = wpas_go_neg_completed;
+ p2p.set_go_security_config = wpas_set_go_security_config;
p2p.go_neg_req_rx = wpas_go_neg_req_rx;
p2p.dev_found = wpas_dev_found;
p2p.dev_lost = wpas_dev_lost;
@@ -5050,6 +5658,12 @@
p2p.register_bootstrap_comeback = wpas_p2p_register_bootstrap_comeback;
p2p.bootstrap_req_rx = wpas_bootstrap_req_rx;
p2p.bootstrap_completed = wpas_bootstrap_completed;
+ p2p.validate_dira = wpas_validate_dira;
+#ifdef CONFIG_PASN
+ p2p.pasn_send_mgmt = wpas_p2p_pasn_send_mgmt;
+ p2p.prepare_data_element = wpas_p2p_prepare_data_element;
+ p2p.parse_data_element = wpas_p2p_parse_data_element;
+#endif /* CONFIG_PASN */
os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
@@ -5193,6 +5807,18 @@
"P2P: Failed to update configuration");
}
+ p2p.pairing_config.enable_pairing_setup =
+ wpa_s->conf->p2p_pairing_setup;
+ p2p.pairing_config.enable_pairing_cache =
+ wpa_s->conf->p2p_pairing_cache;
+ p2p.pairing_config.bootstrap_methods =
+ wpa_s->conf->p2p_bootstrap_methods;
+ p2p.pairing_config.pasn_type = wpa_s->conf->p2p_pasn_type;
+ p2p.comeback_after = wpa_s->conf->p2p_comeback_after;
+ p2p.reg_info = wpa_s->conf->p2p_reg_info;
+ p2p.twt_power_mgmt = wpa_s->conf->p2p_twt_power_mgmt;
+ p2p.chan_switch_req_enable = wpa_s->conf->p2p_chan_switch_req_enable;
+
global->p2p = p2p_init(&p2p);
if (global->p2p == NULL)
return -1;
@@ -5325,6 +5951,20 @@
}
+#ifdef CONFIG_PASN
+static int wpas_p2p_config_sae_password(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+ struct p2p_data *p2p = wpa_s->global->p2p;
+
+ if (wpa_s->global->p2p_disabled || !p2p || !ssid->sae_password)
+ return -2;
+
+ return p2p_config_sae_password(p2p, ssid->sae_password);
+}
+#endif /* CONFIG_PASN */
+
+
static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s,
const u8 *peer_addr,
enum p2p_wps_method wps_method,
@@ -5489,7 +6129,7 @@
if (scan_res)
wpas_p2p_scan_res_handler(wpa_s, scan_res);
- if (wpa_s->p2p_auto_pd) {
+ if (!wpa_s->p2p2 && wpa_s->p2p_auto_pd) {
int join = wpas_p2p_peer_go(wpa_s,
wpa_s->pending_join_dev_addr);
if (join == 0 &&
@@ -5530,15 +6170,22 @@
return;
}
- if (wpa_s->p2p_auto_join) {
+ if (wpa_s->p2p2 || wpa_s->p2p_auto_join) {
int join = wpas_p2p_peer_go(wpa_s,
wpa_s->pending_join_dev_addr);
- if (join < 0) {
- wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be "
- "running a GO -> use GO Negotiation");
- wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
- P2P_EVENT_FALLBACK_TO_GO_NEG
- "reason=peer-not-running-GO");
+
+ if (wpa_s->p2p2 || join < 0) {
+ if (join < 0) {
+ wpa_printf(MSG_DEBUG,
+ "P2P: Peer was not found to be running a GO -> use GO Negotiation");
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
+ P2P_EVENT_FALLBACK_TO_GO_NEG
+ "reason=peer-not-running-GO");
+ }
+
+ if (wpa_s->p2p2)
+ wpa_printf(MSG_DEBUG,
+ "P2P2: Initiate GO negotiation and provisioning using PASN Authentication");
wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr,
wpa_s->p2p_pin, wpa_s->p2p_wps_method,
wpa_s->p2p_persistent_group, 0, 0, 0,
@@ -5555,7 +6202,9 @@
NULL, 0,
is_p2p_allow_6ghz(wpa_s->global->p2p),
wpa_s->p2p2, wpa_s->p2p_bootstrap,
- NULL);
+ wpa_s->pending_join_password[0] ?
+ wpa_s->pending_join_password : NULL,
+ false);
return;
}
@@ -5709,7 +6358,7 @@
{
int ret;
struct wpa_driver_scan_params params;
- struct wpabuf *wps_ie, *ies;
+ struct wpabuf *wps_ie = NULL, *ies;
size_t ielen;
int freqs[2] = { 0, 0 };
unsigned int bands;
@@ -5729,13 +6378,16 @@
wpa_s->p2p_join_ssid_len = 0;
}
- wpa_s->wps->dev.p2p = 1;
- wps_ie = wps_build_probe_req_ie(DEV_PW_DEFAULT, &wpa_s->wps->dev,
- wpa_s->wps->uuid, WPS_REQ_ENROLLEE, 0,
- NULL);
- if (wps_ie == NULL) {
- wpas_p2p_scan_res_join(wpa_s, NULL);
- return;
+ if (!wpa_s->p2p2) {
+ wpa_s->wps->dev.p2p = 1;
+ wps_ie = wps_build_probe_req_ie(DEV_PW_DEFAULT,
+ &wpa_s->wps->dev,
+ wpa_s->wps->uuid,
+ WPS_REQ_ENROLLEE, 0, NULL);
+ if (!wps_ie) {
+ wpas_p2p_scan_res_join(wpa_s, NULL);
+ return;
+ }
}
if (!freq) {
@@ -5757,14 +6409,21 @@
}
ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
- ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
- if (ies == NULL) {
+
+ if (wps_ie)
+ ielen += wpabuf_len(wps_ie);
+
+ ies = wpabuf_alloc(ielen);
+ if (!ies) {
wpabuf_free(wps_ie);
wpas_p2p_scan_res_join(wpa_s, NULL);
return;
}
- wpabuf_put_buf(ies, wps_ie);
- wpabuf_free(wps_ie);
+
+ if (wps_ie) {
+ wpabuf_put_buf(ies, wps_ie);
+ wpabuf_free(wps_ie);
+ }
bands = wpas_get_bands(wpa_s, freqs);
p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands);
@@ -5847,6 +6506,7 @@
struct wpa_supplicant *group;
struct p2p_go_neg_results res;
struct wpa_bss *bss;
+ const u8 *iface_addr = NULL;
group = wpas_p2p_get_group_iface(wpa_s, 0, 0);
if (group == NULL)
@@ -5874,15 +6534,27 @@
os_memcpy(res.peer_device_addr, wpa_s->pending_join_dev_addr, ETH_ALEN);
os_memcpy(res.peer_interface_addr, wpa_s->pending_join_iface_addr,
ETH_ALEN);
+ if (!is_zero_ether_addr(wpa_s->pending_join_iface_addr))
+ iface_addr = wpa_s->pending_join_iface_addr;
+
+ if (wpa_s->pending_join_password[0]) {
+ res.akmp = WPA_KEY_MGMT_SAE;
+ os_strlcpy(res.sae_password, wpa_s->pending_join_password,
+ sizeof(res.sae_password));
+ os_memset(wpa_s->pending_join_password, 0,
+ sizeof(wpa_s->pending_join_password));
+ }
res.wps_method = wpa_s->pending_join_wps_method;
+ res.p2p2 = wpa_s->p2p2;
+ res.cipher = WPA_CIPHER_CCMP;
+
if (freq && ssid && ssid_len) {
res.freq = freq;
res.ssid_len = ssid_len;
os_memcpy(res.ssid, ssid, ssid_len);
} else {
if (ssid && ssid_len) {
- bss = wpa_bss_get(wpa_s, wpa_s->pending_join_iface_addr,
- ssid, ssid_len);
+ bss = wpa_bss_get(wpa_s, iface_addr, ssid, ssid_len);
} else {
bss = wpa_bss_get_bssid_latest(
wpa_s, wpa_s->pending_join_iface_addr);
@@ -5891,6 +6563,8 @@
res.freq = bss->freq;
res.ssid_len = bss->ssid_len;
os_memcpy(res.ssid, bss->ssid, bss->ssid_len);
+ os_memcpy(res.peer_interface_addr, bss->bssid,
+ ETH_ALEN);
wpa_printf(MSG_DEBUG, "P2P: Join target GO operating frequency from BSS table: %d MHz (SSID %s)",
bss->freq,
wpa_ssid_txt(bss->ssid, bss->ssid_len));
@@ -5909,7 +6583,10 @@
wpa_s->off_channel_freq = 0;
wpa_s->roc_waiting_drv_freq = 0;
}
- wpas_start_wps_enrollee(group, &res);
+ if (res.p2p2)
+ wpas_start_gc(group, &res);
+ else
+ wpas_start_wps_enrollee(group, &res);
/*
* Allow a longer timeout for join-a-running-group than normal 15
@@ -6127,8 +6804,9 @@
* @allow_6ghz: Allow P2P connection on 6 GHz channels
* @p2p2: Whether device is in P2P R2 mode
* @bootstrap: Requested bootstrap method for pairing in P2P2
- * @password: Password for pairing setup or NULL for oppurtunistic method
+ * @password: Password for pairing setup or NULL for opportunistic method
* in P2P2
+ * @skip_prov: Connect without provisioning
* Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
* failure, -2 on failure due to channel not currently available,
* -3 if forced channel is not supported
@@ -6141,7 +6819,7 @@
unsigned int vht_chwidth, int he, int edmg,
const u8 *group_ssid, size_t group_ssid_len,
bool allow_6ghz, bool p2p2, u16 bootstrap,
- const char *password)
+ const char *password, bool skip_prov)
{
int force_freq = 0, pref_freq = 0;
int ret = 0, res;
@@ -6162,6 +6840,7 @@
}
wpa_s->p2p2 = p2p2;
+ wpa_s->p2p_mode = p2p2 ? WPA_P2P_MODE_WFD_R2 : WPA_P2P_MODE_WFD_R1;
if (wpas_p2p_check_6ghz(wpa_s, peer_addr, allow_6ghz, freq))
return -2;
@@ -6169,6 +6848,7 @@
os_free(wpa_s->global->add_psk);
wpa_s->global->add_psk = NULL;
+ p2p_set_go_role(wpa_s->global->p2p, false);
wpa_s->global->p2p_fail_on_wps_complete = 0;
wpa_s->global->pending_p2ps_group = 0;
wpa_s->global->pending_p2ps_group_freq = 0;
@@ -6212,14 +6892,64 @@
} else
wpa_s->p2p_pin[0] = '\0';
+ if (!password)
+ os_memset(wpa_s->pending_join_password, 0,
+ sizeof(wpa_s->pending_join_password));
+
if (join || auto_join) {
u8 iface_addr[ETH_ALEN], dev_addr[ETH_ALEN];
if (auth) {
+#ifdef CONFIG_PASN
+ struct wpa_supplicant *ifs;
+#endif /* CONFIG_PASN */
+
wpa_printf(MSG_DEBUG, "P2P: Authorize invitation to "
"connect a running group from " MACSTR,
MAC2STR(peer_addr));
os_memcpy(wpa_s->p2p_auth_invite, peer_addr, ETH_ALEN);
+
+#ifdef CONFIG_PASN
+ if (!wpa_s->p2p2)
+ return ret;
+
+ wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s);
+ if (wpa_s->create_p2p_iface) {
+ if_addr = wpa_s->pending_interface_addr;
+ } else {
+ if (wpa_s->p2p_mgmt)
+ if_addr = wpa_s->parent->own_addr;
+ else
+ if_addr = wpa_s->own_addr;
+ os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN);
+ }
+
+ dl_list_for_each(ifs, &wpa_s->radio->ifaces,
+ struct wpa_supplicant, radio_list) {
+ if (!ifs->current_ssid ||
+ ifs->current_ssid->mode != WPAS_MODE_P2P_GO)
+ continue;
+
+ ssid = ifs->current_ssid;
+
+ if (bootstrap == P2P_PBMA_OPPORTUNISTIC &&
+ wpas_p2p_config_sae_password(wpa_s, ssid)) {
+ ssid = NULL;
+ continue;
+ }
+
+ force_freq = ifs->ap_iface->freq;
+ break;
+ }
+ p2p_set_go_role(wpa_s->global->p2p, true);
+ return wpas_p2p_auth_go_neg(wpa_s, peer_addr,
+ wps_method, 15, if_addr,
+ force_freq,
+ persistent_group, ssid,
+ pref_freq, bootstrap,
+ password);
+#else /* CONFIG_PASN */
return ret;
+#endif /* CONFIG_PASN */
}
os_memcpy(dev_addr, peer_addr, ETH_ALEN);
if (p2p_get_interface_addr(wpa_s->global->p2p, peer_addr,
@@ -6236,6 +6966,20 @@
wpa_s->p2p_auto_started.usec);
}
wpa_s->user_initiated_pd = 1;
+ if (password)
+ os_strlcpy(wpa_s->pending_join_password, password,
+ sizeof(wpa_s->pending_join_password));
+
+ if (skip_prov) {
+ if (!wpa_s->p2p2) {
+ wpa_printf(MSG_DEBUG,
+ "P2P: Join without provisioning not supported");
+ return -1;
+ }
+ /* Start join operation immediately */
+ return wpas_p2p_join_start(wpa_s, 0, group_ssid,
+ group_ssid_len);
+ }
if (wpas_p2p_join(wpa_s, iface_addr, dev_addr, wps_method,
auto_join, freq,
group_ssid, group_ssid_len) < 0)
@@ -6592,6 +7336,10 @@
const struct p2p_channels *channels,
int freq)
{
+ if (is_6ghz_freq(freq) &&
+ !is_p2p_6ghz_capable(wpa_s->global->p2p))
+ return 0;
+
if (!wpas_p2p_disallowed_freq(wpa_s->global, freq) &&
p2p_supported_freq_go(wpa_s->global->p2p, freq) &&
freq_included(wpa_s, channels, freq))
@@ -6699,6 +7447,7 @@
params->max_oper_chwidth = max_oper_chwidth;
params->vht_center_freq2 = vht_center_freq2;
params->edmg = edmg;
+ params->p2p2 = wpa_s->p2p2;
freqs = os_calloc(wpa_s->num_multichan_concurrent,
sizeof(struct wpa_used_freq_data));
@@ -7087,6 +7836,7 @@
* @vht_chwidth: channel bandwidth for GO operating with VHT support
* @edmg: Start GO with EDMG support
* @allow_6ghz: Allow P2P group creation on a 6 GHz channel
+ * @p2p_mode: Operation mode for GO (R1/R2/PCC)
* Returns: 0 on success, -1 on failure
*
* This function creates a new P2P group with the local end as the Group Owner,
@@ -7095,7 +7845,7 @@
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 he, int edmg,
- bool allow_6ghz)
+ bool allow_6ghz, bool p2p2, enum wpa_p2p_mode p2p_mode)
{
struct p2p_go_neg_results params;
int selected_freq = 0;
@@ -7107,6 +7857,8 @@
os_free(wpa_s->global->add_psk);
wpa_s->global->add_psk = NULL;
+ wpa_s->p2p2 = p2p2;
+ wpa_s->p2p_mode = p2p_mode;
/* Make sure we are not running find during connection establishment */
wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND");
@@ -7132,7 +7884,8 @@
return -1;
if (freq > 0)
wpa_s->p2p_go_no_pri_sec_switch = 1;
- wpas_start_wps_go(wpa_s, ¶ms, 0);
+ params.p2p2 = wpa_s->p2p2;
+ wpas_start_go(wpa_s, ¶ms, 0, p2p_mode);
return 0;
}
@@ -7141,11 +7894,14 @@
static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
struct wpa_ssid *params, int addr_allocated,
int freq, int force_scan, int retry_limit,
- const u8 *go_bssid)
+ const u8 *go_bssid, bool p2p2, const u8 *pmkid,
+ const u8 *pmk, size_t pmk_len)
{
+ struct os_reltime now;
struct wpa_ssid *ssid;
int other_iface_found = 0;
struct wpa_supplicant *ifs;
+ struct rsn_pmksa_cache_entry *entry;
wpa_s = wpas_p2p_get_group_iface(wpa_s, addr_allocated, 0);
if (wpa_s == NULL)
@@ -7199,6 +7955,34 @@
os_memcpy(ssid->bssid, go_bssid, ETH_ALEN);
}
+ if (p2p2) {
+ ssid->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PASN;
+ ssid->auth_alg = WPA_AUTH_ALG_OPEN;
+ ssid->sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
+ ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+ ssid->disabled = 0;
+
+ if (pmk && pmk_len && pmkid) {
+ entry = os_zalloc(sizeof(*entry));
+ if (!entry)
+ return -1;
+ os_memcpy(entry->aa, ssid->bssid, ETH_ALEN);
+ os_memcpy(entry->pmkid, pmkid, PMKID_LEN);
+ entry->pmk_len = pmk_len;
+ os_memcpy(entry->pmk, pmk, pmk_len);
+ entry->akmp = WPA_KEY_MGMT_SAE;
+ os_get_reltime(&now);
+ entry->expiration = now.sec + 43200;
+ entry->reauth_time = now.sec + 43200 * 70 / 100;
+ entry->network_ctx = ssid;
+ os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
+
+ wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
+ ssid->pmk_valid = true;
+ }
+ wpa_s->current_ssid = ssid;
+ }
+
wpa_s->show_group_started = 1;
wpa_s->p2p_in_invitation = 1;
wpa_s->p2p_retry_limit = retry_limit;
@@ -7246,7 +8030,9 @@
const struct p2p_channels *channels,
int connection_timeout, int force_scan,
bool allow_6ghz, int retry_limit,
- const u8 *go_bssid)
+ const u8 *go_bssid, const u8 *dev_addr,
+ const u8 *pmkid, const u8 *pmk,
+ size_t pmk_len)
{
struct p2p_go_neg_results params;
int go = 0, freq;
@@ -7315,7 +8101,8 @@
}
return wpas_start_p2p_client(wpa_s, ssid, addr_allocated, freq,
- force_scan, retry_limit, go_bssid);
+ force_scan, retry_limit, go_bssid,
+ wpa_s->p2p2, pmkid, pmk, pmk_len);
} else {
return -1;
}
@@ -7342,6 +8129,15 @@
params.ssid_len = ssid->ssid_len;
params.persistent_group = 1;
+ if (wpa_s->p2p2 && pmk_len && pmk && pmkid) {
+ os_memcpy(params.peer_device_addr, dev_addr, ETH_ALEN);
+ os_memcpy(params.pmkid, pmkid, PMKID_LEN);
+ os_memcpy(params.pmk, pmk, pmk_len);
+ params.pmk_len = pmk_len;
+ params.akmp = WPA_KEY_MGMT_SAE;
+ params.p2p2 = true;
+ }
+
wpa_s = wpas_p2p_get_group_iface(wpa_s, addr_allocated, 1);
if (wpa_s == NULL)
return -1;
@@ -7349,7 +8145,8 @@
p2p_channels_to_freqs(channels, params.freq_list, P2P_MAX_CHANNELS);
wpa_s->p2p_first_connection_timeout = connection_timeout;
- wpas_start_wps_go(wpa_s, ¶ms, 0);
+ params.p2p2 = wpa_s->p2p2;
+ wpas_start_go(wpa_s, ¶ms, 0, wpa_s->p2p_mode);
return 0;
}
@@ -7372,6 +8169,12 @@
}
wpabuf_free(hapd->p2p_probe_resp_ie);
hapd->p2p_probe_resp_ie = proberesp_ies;
+
+ if (wpa_s->p2p2) {
+ hapd->iconf->peer_to_peer_twt = true;
+ hapd->iconf->channel_usage = true;
+ }
+
} else {
wpabuf_free(beacon_ies);
wpabuf_free(proberesp_ies);
@@ -7430,6 +8233,7 @@
cfg->idle_update = wpas_p2p_idle_update;
cfg->ip_addr_alloc = WPA_GET_BE32(wpa_s->p2pdev->conf->ip_addr_start)
!= 0;
+ cfg->p2p2 = wpa_s->p2p2;
group = p2p_group_init(wpa_s->global->p2p, cfg);
if (group == NULL)
@@ -7879,7 +8683,7 @@
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 he, int edmg, bool allow_6ghz)
+ int pref_freq, int he, int edmg, bool allow_6ghz, bool p2p2)
{
enum p2p_invite_role role;
u8 *bssid = NULL;
@@ -7905,6 +8709,7 @@
wpa_s->p2p_go_max_oper_chwidth = max_chwidth;
wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
wpa_s->p2p_go_edmg = !!edmg;
+ wpa_s->p2p2 = p2p2;
if (ssid->mode == WPAS_MODE_P2P_GO) {
role = P2P_INVITE_ROLE_GO;
if (peer_addr == NULL) {
@@ -7927,7 +8732,8 @@
bssid = wpa_s->own_addr;
} else {
role = P2P_INVITE_ROLE_CLIENT;
- peer_addr = ssid->bssid;
+ if (!wpa_s->p2p2)
+ peer_addr = ssid->bssid;
}
wpa_s->pending_invite_ssid_id = ssid->id;
@@ -7958,9 +8764,23 @@
*/
wpas_p2p_stop_find_oper(wpa_s);
+#ifdef CONFIG_PASN
+ if (p2p2) {
+ if (wpas_p2p_initiate_pasn_verify(wpa_s, peer_addr, role, bssid,
+ ssid->ssid, ssid->ssid_len,
+ force_freq, go_dev_addr,
+ pref_freq) < 0) {
+ if (wpa_s->create_p2p_iface)
+ wpas_p2p_remove_pending_group_interface(wpa_s);
+ return -1;
+ }
+ return 0;
+ }
+#endif /* CONFIG_PASN */
+
return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
ssid->ssid, ssid->ssid_len, force_freq, go_dev_addr,
- 1, pref_freq, -1);
+ 1, pref_freq, -1, false);
}
@@ -8044,13 +8864,14 @@
return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
ssid->ssid, ssid->ssid_len, force_freq,
- go_dev_addr, persistent, pref_freq, -1);
+ go_dev_addr, persistent, pref_freq, -1, false);
}
void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
{
struct wpa_ssid *ssid = wpa_s->current_ssid;
+ const u8 *bssid;
u8 go_dev_addr[ETH_ALEN];
int persistent;
int freq;
@@ -8065,6 +8886,11 @@
if (!wpa_s->show_group_started || !ssid)
return;
+ if (wpa_s->go_params)
+ bssid = wpa_s->go_params->peer_interface_addr;
+ else
+ bssid = wpa_s->bssid;
+
wpa_s->show_group_started = 0;
if (!wpa_s->p2p_go_group_formation_completed &&
wpa_s->global->p2p_group_formation == wpa_s) {
@@ -8111,9 +8937,11 @@
ssid->passphrase, go_dev_addr, persistent,
ip_addr);
- if (persistent)
+ if (persistent) {
wpas_p2p_store_persistent_group(wpa_s->p2pdev,
ssid, go_dev_addr);
+ wpas_p2p_store_go_identity(wpa_s, go_dev_addr, bssid);
+ }
wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 1, ip_ptr);
}
@@ -8872,6 +9700,52 @@
}
+static void wpas_p2p_store_client_identity(struct wpa_supplicant *wpa_s,
+ const u8 *addr)
+{
+ u8 cipher;
+ size_t dik_len;
+ const u8 *dik_data;
+ const u8 *pmk, *pmkid;
+ size_t pmk_len;
+ u8 iface_addr[ETH_ALEN];
+ struct hostapd_data *hapd;
+ struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s;
+
+ if (!wpa_s->p2p2 || !wpa_s->ap_iface)
+ return;
+
+ hapd = wpa_s->ap_iface->bss[0];
+ if (!hapd)
+ return;
+
+ if (p2p_get_dev_identity_key(p2p_wpa_s->global->p2p, addr,
+ &dik_data, &dik_len, &cipher))
+ return;
+
+ wpa_printf(MSG_DEBUG, "P2P: Fetch PMK from client (Device Addr " MACSTR
+ ")", MAC2STR(addr));
+ if (wpa_auth_pmksa_get_pmk(hapd->wpa_auth, addr, &pmk, &pmk_len,
+ &pmkid)) {
+ if (p2p_get_interface_addr(p2p_wpa_s->global->p2p, addr,
+ iface_addr))
+ return;
+ wpa_printf(MSG_DEBUG,
+ "P2P: Fetch PMK from client (Interface Addr " MACSTR
+ ")", MAC2STR(iface_addr));
+ if (wpa_auth_pmksa_get_pmk(hapd->wpa_auth, iface_addr, &pmk,
+ &pmk_len, &pmkid))
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "P2P: Storing device identity of client (Device Addr "
+ MACSTR ")", MAC2STR(addr));
+ wpas_p2p_store_identity(p2p_wpa_s, cipher, dik_data, dik_len, pmk,
+ pmk_len, pmkid);
+}
+
+
void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
const u8 *addr)
{
@@ -8913,6 +9787,8 @@
wpa_s->global->p2p_go_wait_client.sec = 0;
if (addr == NULL)
return;
+
+ wpas_p2p_store_client_identity(wpa_s, addr);
wpas_p2p_add_persistent_group_client(wpa_s, addr);
}
@@ -8942,7 +9818,7 @@
wpa_s->p2p_go_he,
wpa_s->p2p_go_edmg,
NULL, 0, is_p2p_allow_6ghz(wpa_s->global->p2p),
- wpa_s->p2p2, wpa_s->p2p_bootstrap, NULL);
+ wpa_s->p2p2, wpa_s->p2p_bootstrap, NULL, false);
return ret;
}
@@ -9410,6 +10286,8 @@
return NULL;
}
+ wpa_s->p2p2 = false;
+
if (cli_freq == 0) {
wsc = wps_build_nfc_handover_req_p2p(
wpa_s->parent->wps, wpa_s->conf->wps_nfc_dh_pubkey);
@@ -9439,6 +10317,8 @@
&wpa_s->conf->wps_nfc_dh_privkey) < 0)
return NULL;
+ wpa_s->p2p2 = false;
+
if (cli_freq == 0) {
wsc = wps_build_nfc_handover_sel_p2p(
wpa_s->parent->wps,
@@ -9481,7 +10361,7 @@
wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
params->go_ssid_len ? params->go_ssid : NULL,
params->go_ssid_len, false, wpa_s->p2p2,
- wpa_s->p2p_bootstrap, NULL);
+ wpa_s->p2p_bootstrap, NULL, false);
}
@@ -9545,7 +10425,7 @@
P2P_INVITE_ROLE_ACTIVE_GO, wpa_s->own_addr,
ssid->ssid, ssid->ssid_len, ssid->frequency,
wpa_s->global->p2p_dev_addr, persistent, 0,
- wpa_s->p2pdev->p2p_oob_dev_pw_id);
+ wpa_s->p2pdev->p2p_oob_dev_pw_id, false);
}
@@ -9561,7 +10441,7 @@
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
NULL, 0, false, wpa_s->p2p2,
- wpa_s->p2p_bootstrap, NULL);
+ wpa_s->p2p_bootstrap, NULL, false);
}
@@ -9579,7 +10459,7 @@
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
NULL, 0, false, wpa_s->p2p2,
- wpa_s->p2p_bootstrap, NULL);
+ wpa_s->p2p_bootstrap, NULL, false);
if (res)
return res;
@@ -9707,6 +10587,8 @@
params.oob_dev_pw, WPS_OOB_PUBKEY_HASH_LEN);
wpa_s->p2p_peer_oob_pk_hash_known = 1;
+ wpa_s->p2p2 = false;
+
if (tag) {
if (id < 0x10) {
wpa_printf(MSG_DEBUG, "P2P: Static handover - invalid "
@@ -10469,3 +11351,54 @@
return;
p2p_process_usd_elems(p2p, buf, buf_len, peer_addr, freq);
}
+
+
+#ifdef CONFIG_PASN
+
+int wpas_p2p_pasn_auth_rx(struct wpa_supplicant *wpa_s,
+ const struct ieee80211_mgmt *mgmt, size_t len,
+ int freq)
+{
+ struct p2p_data *p2p = wpa_s->global->p2p;
+
+ if (wpa_s->global->p2p_disabled || !p2p)
+ return -2;
+ return p2p_pasn_auth_rx(p2p, mgmt, len, freq);
+}
+
+
+int wpas_p2p_pasn_auth_tx_status(struct wpa_supplicant *wpa_s, const u8 *data,
+ size_t data_len, bool acked)
+{
+ struct p2p_data *p2p = wpa_s->global->p2p;
+ struct wpa_p2p_pasn_auth_work *awork;
+
+ if (!wpa_s->p2p_pasn_auth_work)
+ return -1;
+ awork = wpa_s->p2p_pasn_auth_work->ctx;
+
+ return p2p_pasn_auth_tx_status(p2p, data, data_len, acked,
+ awork->verify);
+}
+
+
+#ifdef CONFIG_TESTING_OPTIONS
+int wpas_p2p_get_pasn_ptk(struct wpa_supplicant *wpa_s, const u8 **ptk,
+ size_t *ptk_len)
+{
+ struct p2p_data *p2p = wpa_s->global->p2p;
+
+ if (wpa_s->global->p2p_disabled || !p2p)
+ return -2;
+ return p2p_pasn_get_ptk(p2p, ptk, ptk_len);
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+#endif /* CONFIG_PASN */
+
+
+void wpas_p2p_update_dev_addr(struct wpa_supplicant *wpa_s)
+{
+ os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
+ p2p_set_dev_addr(wpa_s->global->p2p, wpa_s->own_addr);
+}
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index a0fbddc..888bce5 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -40,12 +40,13 @@
unsigned int vht_chwidth, int he, int edmg,
const u8 *group_ssid, size_t group_ssid_len,
bool allow_6ghz, bool p2p2, u16 bootstrap,
- const char *password);
+ const char *password, bool skip_prov);
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 he, int edmg, bool allow_6ghz);
+ int max_oper_chwidth, int he, int edmg, bool allow_6ghz,
+ bool p2p2, enum wpa_p2p_mode p2p_mode);
int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int addr_allocated,
int force_freq, int neg_freq,
@@ -54,7 +55,9 @@
const struct p2p_channels *channels,
int connection_timeout, int force_scan,
bool allow_6ghz, int retry_limit,
- const u8 *go_bssid);
+ const u8 *go_bssid, const u8 *dev_addr,
+ const u8 *pmkid, const u8 *pmk,
+ size_t pmk_len);
struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
enum wpas_p2p_prov_disc_use {
@@ -122,7 +125,8 @@
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 he, int edmg, bool allow_6ghz);
+ int pref_freq, int he, int edmg, bool allow_6ghz,
+ bool p2p2);
int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
const u8 *peer_addr, const u8 *go_dev_addr,
bool allow_6ghz);
@@ -182,6 +186,9 @@
void wpas_p2p_process_usd_elems(struct wpa_supplicant *wpa_s, const u8 *buf,
u16 buf_len, const u8 *peer_addr,
unsigned int freq);
+int wpas_p2p_pasn_auth_tx_status(struct wpa_supplicant *wpa_s, const u8 *data,
+ size_t data_len, bool acked);
+int wpas_p2p_remove_all_identity(struct wpa_supplicant *wpa_s);
#ifdef CONFIG_P2P
@@ -230,6 +237,12 @@
int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s);
int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s);
struct wpabuf * wpas_p2p_usd_elems(struct wpa_supplicant *wpa_s);
+void wpas_p2p_update_dev_addr(struct wpa_supplicant *wpa_s);
+int wpas_p2p_pasn_auth_rx(struct wpa_supplicant *wpa_s,
+ const struct ieee80211_mgmt *mgmt, size_t len,
+ int freq);
+int wpas_p2p_get_pasn_ptk(struct wpa_supplicant *wpa_s, const u8 **ptk,
+ size_t *ptk_len);
#else /* CONFIG_P2P */
@@ -361,6 +374,18 @@
return NULL;
}
+static inline void wpas_p2p_update_dev_addr(struct wpa_supplicant *wpa_s)
+{
+}
+
+#ifdef CONFIG_TESTING_OPTIONS
+static inline int wpas_p2p_get_pasn_ptk(struct wpa_supplicant *wpa_s,
+ const u8 **ptk, size_t *ptk_len)
+{
+ return 0;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
#endif /* CONFIG_P2P */
#endif /* P2P_SUPPLICANT_H */
diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c
index 89edad4..a46fe46 100644
--- a/wpa_supplicant/pasn_supplicant.c
+++ b/wpa_supplicant/pasn_supplicant.c
@@ -806,6 +806,9 @@
if (!wpa_s->pasn_auth_work)
return -2;
+ wpabuf_free(pasn->frame);
+ pasn->frame = NULL;
+
pasn_register_callbacks(pasn, wpa_s, wpas_pasn_send_mlme, NULL);
ret = wpa_pasn_auth_rx(pasn, (const u8 *) mgmt, len, &pasn_data);
if (ret == 0) {
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index f0ab122..ccedcc9 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -750,17 +750,20 @@
ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
sizeof(ext_capab), NULL);
if (ext_capab_len > 0 &&
+ (size_t) ext_capab_len < wpa_s->drv_max_probe_req_ie_len &&
wpabuf_resize(&extra_ie, ext_capab_len) == 0)
wpabuf_put_data(extra_ie, ext_capab, ext_capab_len);
#ifdef CONFIG_INTERWORKING
if (wpa_s->conf->interworking &&
+ wpa_s->drv_max_probe_req_ie_len >= 2 &&
wpabuf_resize(&extra_ie, 100) == 0)
wpas_add_interworking_elements(wpa_s, extra_ie);
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_MBO
- if (wpa_s->enable_oce & OCE_STA)
+ if ((wpa_s->enable_oce & OCE_STA) &&
+ wpa_s->drv_max_probe_req_ie_len >= 5)
wpas_fils_req_param_add_max_channel(wpa_s, &extra_ie);
#endif /* CONFIG_MBO */
@@ -774,17 +777,19 @@
&wpa_s->wps->dev,
wpa_s->wps->uuid, req_type,
0, NULL);
- if (wps_ie) {
- if (wpabuf_resize(&extra_ie, wpabuf_len(wps_ie)) == 0)
- wpabuf_put_buf(extra_ie, wps_ie);
- wpabuf_free(wps_ie);
- }
+ if (wps_ie &&
+ wpabuf_len(wps_ie) <= wpa_s->drv_max_probe_req_ie_len &&
+ wpabuf_resize(&extra_ie, wpabuf_len(wps_ie)) == 0)
+ wpabuf_put_buf(extra_ie, wps_ie);
+ wpabuf_free(wps_ie);
}
#ifdef CONFIG_P2P
if (wps) {
size_t ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
- if (wpabuf_resize(&extra_ie, ielen) == 0)
+
+ if (ielen <= wpa_s->drv_max_probe_req_ie_len &&
+ wpabuf_resize(&extra_ie, ielen) == 0)
wpas_p2p_scan_ie(wpa_s, extra_ie);
}
#endif /* CONFIG_P2P */
@@ -794,12 +799,14 @@
#endif /* CONFIG_WPS */
#ifdef CONFIG_HS20
- if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 9) == 0)
+ if (wpa_s->conf->hs20 && wpa_s->drv_max_probe_req_ie_len >= 9 &&
+ wpabuf_resize(&extra_ie, 9) == 0)
wpas_hs20_add_indication(extra_ie, -1, 0);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_FST
if (wpa_s->fst_ies &&
+ wpa_s->drv_max_probe_req_ie_len >= wpabuf_len(wpa_s->fst_ies) &&
wpabuf_resize(&extra_ie, wpabuf_len(wpa_s->fst_ies)) == 0)
wpabuf_put_buf(extra_ie, wpa_s->fst_ies);
#endif /* CONFIG_FST */
@@ -813,7 +820,8 @@
if (wpa_s->vendor_elem[VENDOR_ELEM_PROBE_REQ]) {
struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_PROBE_REQ];
- if (wpabuf_resize(&extra_ie, wpabuf_len(buf)) == 0)
+ if (wpa_s->drv_max_probe_req_ie_len >= wpabuf_len(buf) &&
+ wpabuf_resize(&extra_ie, wpabuf_len(buf)) == 0)
wpabuf_put_buf(extra_ie, buf);
}
@@ -2368,7 +2376,9 @@
int wpa_a, wpa_b;
int snr_a, snr_b, snr_a_full, snr_b_full;
size_t ies_len;
+#ifndef CONFIG_NO_WPA
const u8 *rsne_a, *rsne_b;
+#endif /* CONFIG_NO_WPA */
/* WPA/WPA2 support preferred */
wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
@@ -2412,6 +2422,7 @@
snr_b = snr_b_full = wb->level;
}
+#ifndef CONFIG_NO_WPA
/* If SNR of a SAE BSS is good or at least as high as the PSK BSS,
* prefer SAE over PSK for mixed WPA3-Personal transition mode and
* WPA2-Personal deployments */
@@ -2437,6 +2448,7 @@
(snr_b >= GREAT_SNR || snr_b >= snr_a))
return 1;
}
+#endif /* CONFIG_NO_WPA */
/* If SNR is close, decide by max rate or frequency band. For cases
* involving the 6 GHz band, use the throughput estimate irrespective
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index e4be388..0a0a50f 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -105,6 +105,7 @@
int key_mgmt = external ? wpa_s->sme.ext_auth_key_mgmt :
wpa_s->key_mgmt;
const u8 *addr = mld_addr ? mld_addr : bssid;
+ enum sae_pwe sae_pwe;
if (ret_use_pt)
*ret_use_pt = 0;
@@ -198,14 +199,16 @@
rsnxe_capa = rsnxe[2];
}
+ sae_pwe = wpas_get_ssid_sae_pwe(wpa_s, ssid);
+
if (ssid->sae_password_id &&
- wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
+ sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
use_pt = 1;
if (wpa_key_mgmt_sae_ext_key(key_mgmt) &&
- wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
+ sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
use_pt = 1;
if (bss && is_6ghz_freq(bss->freq) &&
- wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
+ sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
use_pt = 1;
#ifdef CONFIG_SAE_PK
if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) &&
@@ -225,14 +228,14 @@
}
#endif /* CONFIG_SAE_PK */
- if (use_pt || wpa_s->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
- wpa_s->conf->sae_pwe == SAE_PWE_BOTH) {
+ if (use_pt || sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
+ sae_pwe == SAE_PWE_BOTH) {
use_pt = !!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E));
- if ((wpa_s->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
+ if ((sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
ssid->sae_password_id ||
wpa_key_mgmt_sae_ext_key(key_mgmt)) &&
- wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK &&
+ sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK &&
!use_pt) {
wpa_printf(MSG_DEBUG,
"SAE: Cannot use H2E with the selected AP");
@@ -241,7 +244,7 @@
}
if (use_pt && !ssid->pt)
- wpa_s_setup_sae_pt(wpa_s->conf, ssid, true);
+ wpa_s_setup_sae_pt(wpa_s, ssid, true);
if (use_pt &&
sae_prepare_commit_pt(&wpa_s->sme.sae, ssid->pt,
wpa_s->own_addr, addr,
@@ -810,7 +813,6 @@
wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x",
md[0], md[1]);
- omit_rsnxe = !wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
if (wpa_s->sme.assoc_req_ie_len + 5 <
sizeof(wpa_s->sme.assoc_req_ie)) {
struct rsn_mdie *mdie;
@@ -830,6 +832,8 @@
wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
"over-the-air");
+ omit_rsnxe = !wpa_bss_get_rsnxe(wpa_s, bss, ssid,
+ false);
params.auth_alg = WPA_AUTH_ALG_FT;
params.ie = wpa_s->sme.ft_ies;
params.ie_len = wpa_s->sme.ft_ies_len;
@@ -1453,7 +1457,7 @@
os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0 &&
wpa_key_mgmt_sae(ssid->key_mgmt)) {
/* Make sure PT is derived */
- wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
+ wpa_s_setup_sae_pt(wpa_s, ssid, false);
wpa_s->sme.ext_auth_wpa_ssid = ssid;
break;
}
@@ -1729,6 +1733,30 @@
return -1;
}
token_len = elen - 1;
+#ifdef CONFIG_IEEE80211BE
+ } else if ((wpa_s->valid_links ||
+ (external && wpa_s->sme.ext_ml_auth)) &&
+ token_len > 12 &&
+ token_pos[token_len - 12] == WLAN_EID_EXTENSION &&
+ token_pos[token_len - 11] == 10 &&
+ token_pos[token_len - 10] ==
+ WLAN_EID_EXT_MULTI_LINK) {
+ /* IEEE P802.11be requires H2E to be used whenever SAE
+ * is used for ML association. However, some early
+ * Wi-Fi 7 APs enable MLO without H2E. Recognize this
+ * special case based on the fixed length Basic
+ * Multi-Link element being at the end of the data that
+ * would contain the unknown variable length
+ * Anti-Clogging Token field. The Basic Multi-Link
+ * element in Authentication frames include the MLD MAC
+ * addreess in the Common Info field and all subfields
+ * of the Presence Bitmap subfield of the Multi-Link
+ * Control field of the element zero and consequently,
+ * has a fixed length of 12 octets. */
+ wpa_printf(MSG_DEBUG,
+ "SME: Detected Basic Multi-Link element at the end of Anti-Clogging Token field");
+ token_len -= 12;
+#endif /* CONFIG_IEEE80211BE */
}
*ie_offset = token_pos + token_len - data;
@@ -2451,6 +2479,12 @@
mscs_fail:
#endif /* CONFIG_NO_ROBUST_AV */
+ wpa_s->sme.assoc_req_ie_len =
+ wpas_populate_wfa_capa(wpa_s, wpa_s->current_bss,
+ wpa_s->sme.assoc_req_ie,
+ wpa_s->sme.assoc_req_ie_len,
+ sizeof(wpa_s->sme.assoc_req_ie));
+
if (ssid && ssid->multi_ap_backhaul_sta) {
size_t multi_ap_ie_len;
struct multi_ap_params multi_ap = { 0 };
@@ -2472,10 +2506,10 @@
}
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE_SUPPORT,
- wpas_rsn_overriding(wpa_s));
+ wpas_rsn_overriding(wpa_s, ssid));
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
RSN_OVERRIDE_NOT_USED);
- if (wpas_rsn_overriding(wpa_s) &&
+ if (wpas_rsn_overriding(wpa_s, ssid) &&
wpas_ap_supports_rsn_overriding(wpa_s, wpa_s->current_bss) &&
wpa_s->sme.assoc_req_ie_len + 2 + 4 <=
sizeof(wpa_s->sme.assoc_req_ie)) {
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 3bb621d..31d1007 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -614,38 +614,37 @@
}
-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;
-}
-
-#ifdef CONFIG_MBO
-static struct wpa_bss *
-get_mbo_transition_candidate(struct wpa_supplicant *wpa_s,
+static void
+fetch_drv_mbo_candidate_info(struct wpa_supplicant *wpa_s,
enum mbo_transition_reject_reason *reason)
{
- struct wpa_bss *target = NULL;
+#ifdef CONFIG_MBO
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;
+ struct neighbor_report *nei;
+ u8 *pos;
unsigned int i;
+ if (!wpa_s->wnm_mbo_trans_reason_present)
+ return;
+
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;
+ return;
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)
+ for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
+ nei = &wpa_s->wnm_neighbor_report_elements[i];
+
+ nei->drv_mbo_reject = 0;
+
+ if (nei->preference_present && nei->preference == 0)
continue;
+
+ /* Should we query BSSIDs that we reject for other reasons? */
+
os_memcpy(pos, nei->bssid, ETH_ALEN);
pos += ETH_ALEN;
params.n_candidates++;
@@ -655,185 +654,36 @@
goto end;
info = wpa_drv_get_bss_trans_status(wpa_s, ¶ms);
- 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);
+ if (!info)
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;
- }
- }
+ int j;
- /* 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))
+ for (j = 0; j < wpa_s->wnm_num_neighbor_report; j++) {
+ nei = &wpa_s->wnm_neighbor_report_elements[j];
+
+ if (!ether_addr_equal(info->candidates[i].bssid,
+ nei->bssid))
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 &&
- ether_addr_equal(first_candidate_bssid,
- info->candidates[i].bssid)) {
+ nei->drv_mbo_reject = !info->candidates[i].is_accept;
+
+ /* Use the reject reason from the first candidate */
+ if (i == 0 && nei->drv_mbo_reject)
*reason = info->candidates[i].reject_reason;
- break;
- }
+
+ 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 * find_better_target(struct wpa_bss *a,
- struct wpa_bss *b)
-{
- if (!a)
- return b;
- if (!b)
- return a;
-
- if (a->est_throughput > b->est_throughput) {
- wpa_printf(MSG_DEBUG, "WNM: A is better: " MACSTR
- " est-tput: %d B: " MACSTR " est-tput: %d",
- MAC2STR(a->bssid), a->est_throughput,
- MAC2STR(b->bssid), b->est_throughput);
- return a;
- }
-
- wpa_printf(MSG_DEBUG, "WNM: B is better, A: " MACSTR
- " est-tput: %d B: " MACSTR " est-tput: %d",
- MAC2STR(a->bssid), a->est_throughput,
- MAC2STR(b->bssid), b->est_throughput);
- return b;
-}
-
-static struct wpa_bss *
-compare_scan_neighbor_results(struct wpa_supplicant *wpa_s,
- enum mbo_transition_reject_reason *reason)
-{
- u8 i;
- struct wpa_bss *bss = wpa_s->current_bss;
- struct wpa_bss *target;
- struct wpa_bss *best_target = NULL;
- struct wpa_bss *bss_in_list = NULL;
-
- if (!bss)
- return NULL;
-
- 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;
-
- nei = &wpa_s->wnm_neighbor_report_elements[i];
-
- target = wpa_bss_get_bssid(wpa_s, nei->bssid);
- if (!target) {
- wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
- " (pref %d) not found in scan results",
- MAC2STR(nei->bssid),
- nei->preference_present ? nei->preference :
- -1);
- continue;
- }
-
- /*
- * TODO: Could consider allowing transition to another ESS if
- * PMF was enabled for the association.
- */
- if (!wpa_scan_res_match(wpa_s, 0, target, wpa_s->current_ssid,
- 1, 0)) {
- wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
- " (pref %d) does not match the current network profile",
- MAC2STR(nei->bssid),
- nei->preference_present ? nei->preference :
- -1);
- continue;
- }
-
- if (target->level < bss->level && target->level < -80) {
- wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
- " (pref %d) does not have sufficient signal level (%d)",
- MAC2STR(nei->bssid),
- nei->preference_present ? nei->preference :
- -1,
- target->level);
- continue;
- }
-
- nei->acceptable = 1;
-
- best_target = find_better_target(target, best_target);
- if (target == bss)
- bss_in_list = bss;
- }
-
-#ifdef CONFIG_MBO
- if (wpa_s->wnm_mbo_trans_reason_present)
- target = get_mbo_transition_candidate(wpa_s, reason);
- else
- target = best_target;
-#else /* CONFIG_MBO */
- target = best_target;
-#endif /* CONFIG_MBO */
-
- if (!target)
- return NULL;
-
- wpa_printf(MSG_DEBUG,
- "WNM: Found an acceptable preferred transition candidate BSS "
- MACSTR " (RSSI %d, tput: %d bss-tput: %d)",
- MAC2STR(target->bssid), target->level,
- target->est_throughput, bss->est_throughput);
-
- if (!bss_in_list)
- return target;
-
- if ((!target->est_throughput && !bss_in_list->est_throughput) ||
- (target->est_throughput > bss_in_list->est_throughput &&
- target->est_throughput - bss_in_list->est_throughput >
- bss_in_list->est_throughput >> 4)) {
- /* It is more than 100/16 percent better, so switch. */
- return target;
- }
-
- wpa_printf(MSG_DEBUG,
- "WNM: Stay with our current BSS, not enough change in estimated throughput to switch");
- return bss_in_list;
}
@@ -1154,13 +1004,14 @@
int wnm_scan_process(struct wpa_supplicant *wpa_s, bool pre_scan_check)
{
- struct wpa_bss *bss;
+ struct wpa_bss *bss, *current_bss = wpa_s->current_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;
+ struct wpa_ssid *selected_ssid = NULL;
- if (!wpa_s->wnm_dialog_token)
+ if (!ssid || !wpa_s->wnm_dialog_token)
return 0;
wpa_dbg(wpa_s, MSG_DEBUG,
@@ -1178,8 +1029,45 @@
wpa_s->wnm_transition_scan = false;
+ /* Fetch MBO transition candidate rejection information from driver */
+ fetch_drv_mbo_candidate_info(wpa_s, &reason);
+
/* Compare the Neighbor Report and scan results */
- bss = compare_scan_neighbor_results(wpa_s, &reason);
+ bss = wpa_supplicant_select_bss(wpa_s, ssid, &selected_ssid, 1);
+#ifdef CONFIG_MBO
+ if (!bss && wpa_s->wnm_mbo_trans_reason_present &&
+ (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT)) {
+ int i;
+ bool changed = false;
+
+ /*
+ * We didn't find any candidate, the driver had a say about
+ * which targets to reject and disassociation is immiment.
+ *
+ * We should still try to roam, so retry after ignoring the
+ * driver reject for any BSS that has an RSSI better than
+ * disassoc_imminent_rssi_threshold.
+ */
+ for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
+ struct neighbor_report *nei;
+
+ nei = &wpa_s->wnm_neighbor_report_elements[i];
+ bss = wpa_bss_get_bssid(wpa_s, nei->bssid);
+ if (bss && bss->level >
+ wpa_s->conf->disassoc_imminent_rssi_threshold) {
+ nei->drv_mbo_reject = 0;
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Ignore driver rejection due to imminent disassociation and acceptable RSSI");
+ bss = wpa_supplicant_select_bss(wpa_s, ssid,
+ &selected_ssid, 1);
+ }
+ }
+#endif /* CONFIG_MBO */
/*
* If this is a pre-scan check, returning 0 will trigger a scan and
@@ -1202,20 +1090,35 @@
return 0;
#ifndef CONFIG_NO_ROAMING
- if (wpa_s->current_bss && bss != wpa_s->current_bss &&
- wpa_supplicant_need_to_roam_within_ess(wpa_s,
- wpa_s->current_bss,
- bss))
+ if (current_bss && bss != current_bss &&
+ wpa_supplicant_need_to_roam_within_ess(wpa_s, bss,
+ current_bss, false))
return 0;
#endif /* CONFIG_NO_ROAMING */
}
+#ifndef CONFIG_NO_ROAMING
+ /* Apply normal roaming rules if we can stay with the current BSS */
+ if (current_bss && bss != current_bss &&
+ wpa_scan_res_match(wpa_s, 0, current_bss, wpa_s->current_ssid,
+ 1, 0) &&
+ !wpa_supplicant_need_to_roam_within_ess(wpa_s, current_bss, bss,
+ true))
+ bss = current_bss;
+#endif /* CONFIG_NO_ROAMING */
+
if (!bss) {
wpa_printf(MSG_DEBUG, "WNM: No BSS transition candidate match found");
status = WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES;
goto send_bss_resp_fail;
}
+ wpa_printf(MSG_DEBUG,
+ "WNM: Found an acceptable preferred transition candidate BSS "
+ MACSTR " (RSSI %d, tput: %d bss-tput: %d)",
+ MAC2STR(bss->bssid), bss->level, bss->est_throughput,
+ current_bss ? (int) current_bss->est_throughput : -1);
+
/* Associate to the network */
wnm_bss_tm_connect(wpa_s, bss, ssid, 1);
return 1;
@@ -1409,15 +1312,6 @@
*num_valid_candidates += 1;
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;
@@ -2133,6 +2027,11 @@
if (nei->preference_present && nei->preference == 0)
return true;
+#ifdef CONFIG_MBO
+ if (nei->drv_mbo_reject)
+ return true;
+#endif /* CONFIG_MBO */
+
break;
}
diff --git a/wpa_supplicant/wnm_sta.h b/wpa_supplicant/wnm_sta.h
index 235a838..80928f7 100644
--- a/wpa_supplicant/wnm_sta.h
+++ b/wpa_supplicant/wnm_sta.h
@@ -44,9 +44,8 @@
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;
+ unsigned int drv_mbo_reject:1;
#endif /* CONFIG_MBO */
struct measurement_pilot *meas_pilot;
struct multiple_bssid *mul_bssid;
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index af00e79..2f57be8 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -3335,6 +3335,59 @@
}
+#ifdef CONFIG_NAN_USD
+
+static int wpa_cli_cmd_nan_publish(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "NAN_PUBLISH", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_nan_cancel_publish(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "NAN_CANCEL_PUBLISH", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_nan_update_publish(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "NAN_UPDATE_PUBLISH", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_nan_subscribe(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "NAN_SUBSCRIBE", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_nan_cancel_subscribe(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "NAN_CANCEL_SUBSCRIBE", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_nan_transmit(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "NAN_TRANSMIT", 3, argc, argv);
+}
+
+
+static int wpa_cli_cmd_nan_flush(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "NAN_FLUSH");
+}
+
+#endif /* CONFIG_NAN_USD */
+
+
enum wpa_cli_cmd_flags {
cli_cmd_flag_none = 0x00,
cli_cmd_flag_sensitive = 0x01
@@ -4084,6 +4137,24 @@
{ "mlo_signal_poll", wpa_cli_cmd_mlo_signal_poll, NULL,
cli_cmd_flag_none,
"= get mlo signal parameters" },
+#ifdef CONFIG_NAN_USD
+ { "nan_publish", wpa_cli_cmd_nan_publish, NULL,
+ cli_cmd_flag_none,
+ "service_name=<name> [ttl=<time-to-live-in-sec>] [freq=<in MHz>] [freq_list=<comma separate list of MHz>] [srv_proto_type=<type>] [ssi=<service specific information (hexdump)>] [solicited=0] [unsolicited=0] [fsd=0] [p2p=1] = Publish NAN service" },
+ { "nan_cancel_publish", wpa_cli_cmd_nan_cancel_publish, NULL,
+ cli_cmd_flag_none, "publish_id=<id from NAN_PUBLISH> = Cancel NAN USD publish instance" },
+ { "nan_update_publish", wpa_cli_cmd_nan_update_publish, NULL,
+ cli_cmd_flag_none, "publish_id=<id from NAN_PUBLISH> [ssi=<service specific information (hexdump)> = Update publish" },
+ { "nan_subscribe", wpa_cli_cmd_nan_subscribe, NULL,
+ cli_cmd_flag_none,
+ "service_name=<name> [active=1] [ttl=<time-to-live-in-sec>] [freq=<in MHz>] [srv_proto_type=<type>] [ssi=<service specific information (hexdump)>] [p2p=1] = Subscribe to NAN service" },
+ { "nan_cancel_subscribe", wpa_cli_cmd_nan_cancel_subscribe, NULL,
+ cli_cmd_flag_none, "subscribe_id=<id from NAN_PUBLISH> = Cancel NAN USD subscribe instance" },
+ { "nan_transmit", wpa_cli_cmd_nan_transmit, NULL,
+ cli_cmd_flag_none, "handle=<id from NAN_PUBLISH or NAN_SUBSCRIBE> req_instance_id=<peer's id> address=<peer's MAC address> [ssi=<service specific information (hexdump)>] = Transmit NAN follow up" },
+ { "nan_flush", wpa_cli_cmd_nan_flush, NULL,
+ cli_cmd_flag_none, "= Flush all NAN USD services" },
+#endif /* CONFIG_NAN_USD */
{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
};
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index e3ed858..9843679 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -507,6 +507,102 @@
}
+static struct wpabuf * wpas_wfa_gen_capab_attr(struct wpa_supplicant *wpa_s)
+{
+ struct wpabuf *attr;
+ size_t gen_len, supp_len;
+ const u8 *supp;
+ u8 supp_buf[1];
+ bool add_cert;
+
+ if (wpa_s->conf->wfa_gen_capa == WFA_GEN_CAPA_DISABLED)
+ return NULL;
+
+ if (!wpa_s->conf->wfa_gen_capa_supp ||
+ wpabuf_len(wpa_s->conf->wfa_gen_capa_supp) == 0) {
+ supp_len = 1;
+ supp_buf[0] = 0;
+ if (wpa_s->hw_capab & BIT(CAPAB_HT))
+ supp_buf[0] |= BIT(0); /* Wi-Fi 4 */
+ if (wpa_s->hw_capab & BIT(CAPAB_VHT))
+ supp_buf[0] |= BIT(1); /* Wi-Fi 5 */
+ if (wpa_s->hw_capab & BIT(CAPAB_HE))
+ supp_buf[0] |= BIT(2); /* Wi-Fi 6 */
+ if (wpa_s->hw_capab & BIT(CAPAB_EHT))
+ supp_buf[0] |= BIT(3); /* Wi-Fi 7 */
+ supp = supp_buf;
+ } else {
+ supp_len = wpabuf_len(wpa_s->conf->wfa_gen_capa_supp);
+ supp = wpabuf_head(wpa_s->conf->wfa_gen_capa_supp);
+ }
+
+ add_cert = wpa_s->conf->wfa_gen_capa_cert &&
+ wpabuf_len(wpa_s->conf->wfa_gen_capa_cert) == supp_len;
+
+ gen_len = 1 + supp_len;
+ if (add_cert) {
+ gen_len++;
+ gen_len += wpabuf_len(wpa_s->conf->wfa_gen_capa_cert);
+ }
+
+ attr = wpabuf_alloc(2 + gen_len);
+ if (!attr)
+ return NULL;
+
+ wpabuf_put_u8(attr, WFA_CAPA_ATTR_GENERATIONAL_CAPAB);
+ wpabuf_put_u8(attr, gen_len);
+ wpabuf_put_u8(attr, supp_len);
+ wpabuf_put_data(attr, supp, supp_len);
+ if (add_cert) {
+ wpabuf_put_u8(attr,
+ wpabuf_len(wpa_s->conf->wfa_gen_capa_cert));
+ wpabuf_put_buf(attr, wpa_s->conf->wfa_gen_capa_cert);
+ }
+
+ return attr;
+}
+
+
+
+static void wpas_wfa_capab_tx(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct wpabuf *attr, *buf;
+ size_t buf_len;
+
+ if (wpa_s->conf->wfa_gen_capa != WFA_GEN_CAPA_PROTECTED ||
+ wpa_s->wpa_state != WPA_COMPLETED ||
+ !pmf_in_use(wpa_s, wpa_s->bssid))
+ return;
+
+ attr = wpas_wfa_gen_capab_attr(wpa_s);
+ if (!attr)
+ return;
+
+ buf_len = 1 + 3 + 1 + 1 + wpabuf_len(attr);
+ buf = wpabuf_alloc(buf_len);
+ if (!buf) {
+ wpabuf_free(attr);
+ return;
+ }
+
+ wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED);
+ wpabuf_put_be32(buf, WFA_CAPAB_VENDOR_TYPE);
+ wpabuf_put_u8(buf, 0); /* Capabilities Length */
+ wpabuf_put_buf(buf, attr);
+ wpabuf_free(attr);
+
+ wpa_printf(MSG_DEBUG, "WFA: Send WFA Capabilities frame");
+ 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,
+ "WFA: Failed to send WFA Capabilities frame");
+
+ wpabuf_free(buf);
+}
+
+
void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
@@ -620,6 +716,7 @@
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
eloop_cancel_timeout(wpas_verify_ssid_beacon, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_wfa_capab_tx, wpa_s, NULL);
wpas_wps_deinit(wpa_s);
@@ -1148,6 +1245,12 @@
#ifdef CONFIG_HS20
hs20_configure_frame_filters(wpa_s);
#endif
+ if (wpa_s->conf->wfa_gen_capa == WFA_GEN_CAPA_PROTECTED &&
+ pmf_in_use(wpa_s, wpa_s->bssid)) {
+ eloop_cancel_timeout(wpas_wfa_capab_tx, wpa_s, NULL);
+ eloop_register_timeout(0, 100000, wpas_wfa_capab_tx,
+ wpa_s, NULL);
+ }
} else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
state == WPA_ASSOCIATED) {
wpa_s->new_connection = 1;
@@ -1581,6 +1684,9 @@
{
int akm_count = wpa_s->max_num_akms;
u8 capab = 0;
+#ifdef CONFIG_SAE
+ enum sae_pwe sae_pwe;
+#endif /* CONFIG_SAE */
if (akm_count < 2)
return;
@@ -1659,13 +1765,16 @@
return;
}
- if (wpa_s->conf->sae_pwe != SAE_PWE_HUNT_AND_PECK &&
- wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
+#ifdef CONFIG_SAE
+ sae_pwe = wpas_get_ssid_sae_pwe(wpa_s, ssid);
+ if (sae_pwe != SAE_PWE_HUNT_AND_PECK &&
+ sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
#ifdef CONFIG_SAE_PK
if (ssid->sae_pk)
capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
#endif /* CONFIG_SAE_PK */
+#endif /* CONFIG_SAE */
if (!((wpa_s->allowed_key_mgmts &
(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY)) && capab))
@@ -1704,7 +1813,9 @@
{
struct wpa_ie_data ie;
int sel, proto;
+#ifdef CONFIG_SAE
enum sae_pwe sae_pwe;
+#endif /* CONFIG_SAE */
const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
bool wmm;
@@ -2063,7 +2174,8 @@
(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
#endif /* CONFIG_OCV */
- sae_pwe = wpa_s->conf->sae_pwe;
+#ifdef CONFIG_SAE
+ sae_pwe = wpas_get_ssid_sae_pwe(wpa_s, ssid);
if ((ssid->sae_password_id ||
wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt)) &&
sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
@@ -2084,6 +2196,7 @@
(!ssid->sae_password && ssid->passphrase &&
sae_pk_valid_password(ssid->passphrase))));
#endif /* CONFIG_SAE_PK */
+#endif /* CONFIG_SAE */
if (bss && is_6ghz_freq(bss->freq) &&
wpas_get_ssid_pmf(wpa_s, ssid) != MGMT_FRAME_PROTECTION_REQUIRED) {
wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Force MFPR=1 on 6 GHz");
@@ -2103,6 +2216,9 @@
wpa_s->oci_freq_override_fils_assoc);
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
wpa_s->disable_eapol_g2_tx);
+ wpa_sm_set_param(wpa_s->wpa,
+ WPA_PARAM_EAPOL_2_KEY_INFO_SET_MASK,
+ wpa_s->eapol_2_key_info_set_mask);
#endif /* CONFIG_TESTING_OPTIONS */
/* Extended Key ID is only supported in infrastructure BSS so far */
@@ -2208,9 +2324,9 @@
(ssid->sae_password || ssid->passphrase || ssid->ext_psk))
psk_set = 1;
- if (!psk_set) {
+ if (!psk_set && !ssid->pmk_valid) {
wpa_msg(wpa_s, MSG_INFO,
- "No PSK available for association");
+ "No PSK/PMK available for association");
wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE", NULL);
return -1;
}
@@ -2340,6 +2456,8 @@
if (!wpa_s->disable_fils)
*pos |= 0x01;
#endif /* CONFIG_FILS */
+ if (wpa_s->conf->twt_requester)
+ *pos |= 0x20; /* Bit 77 - TWT Requester Support */
break;
case 10: /* Bits 80-87 */
#ifndef CONFIG_NO_ROBUST_AV
@@ -2526,6 +2644,8 @@
return -1;
}
+ wpas_p2p_update_dev_addr(wpa_s);
+
wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
MAC2STR(addr));
@@ -2544,13 +2664,15 @@
}
-void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid,
+void wpa_s_setup_sae_pt(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
bool force)
{
#ifdef CONFIG_SAE
+ struct wpa_config *conf = wpa_s->conf;
int *groups = conf->sae_groups;
int default_groups[] = { 19, 20, 21, 0 };
const char *password;
+ enum sae_pwe sae_pwe;
if (!groups || groups[0] <= 0)
groups = default_groups;
@@ -2559,13 +2681,15 @@
if (!password)
password = ssid->passphrase;
+ sae_pwe = wpas_get_ssid_sae_pwe(wpa_s, ssid);
+
if (!password ||
!wpa_key_mgmt_sae(ssid->key_mgmt) ||
- (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
+ (sae_pwe == SAE_PWE_HUNT_AND_PECK && !ssid->sae_password_id &&
!wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
!force &&
!sae_pk_valid_password(password)) ||
- conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
+ sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK) {
/* PT derivation not needed */
sae_deinit_pt(ssid->pt);
ssid->pt = NULL;
@@ -2616,6 +2740,9 @@
"Could not update MAC address information");
return -1;
}
+
+ wpas_p2p_update_dev_addr(wpa_s);
+
wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
return 0;
}
@@ -2686,7 +2813,7 @@
wpa_s_clear_sae_rejected(wpa_s);
#ifdef CONFIG_SAE
- wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
+ wpa_s_setup_sae_pt(wpa_s, ssid, false);
#endif /* CONFIG_SAE */
if (rand_style > WPAS_MAC_ADDR_STYLE_PERMANENT) {
@@ -3096,6 +3223,27 @@
}
+static int ibss_get_center_320mhz(int channel)
+{
+ int seg0;
+
+ if (channel >= 1 && channel <= 45)
+ seg0 = 31;
+ else if (channel >= 49 && channel <= 77)
+ seg0 = 63;
+ else if (channel >= 81 && channel <= 109)
+ seg0 = 95;
+ else if (channel >= 113 && channel <= 141)
+ seg0 = 127;
+ else if (channel >= 145 && channel <= 173)
+ seg0 = 159;
+ else
+ seg0 = 191;
+
+ return seg0;
+}
+
+
static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
const struct wpa_ssid *ssid,
struct hostapd_hw_modes *mode,
@@ -3109,6 +3257,11 @@
static const int bw160[] = {
5955, 6115, 6275, 6435, 6595, 6755, 6915
};
+ static const int bw320[]= {
+ 5955, 6255, 6115, 6415, 6275, 6575, 6435,
+ 6735, 6595, 6895, 6755, 7055
+ };
+
struct hostapd_freq_params vht_freq;
int i;
unsigned int j, k;
@@ -3169,6 +3322,26 @@
}
}
+ /* In 320 MHz, the initial four 20 MHz channels were validated
+ * above. If 320 MHz is supported, check the remaining 12 20 MHz
+ * channels for the total of 320 MHz bandwidth for 6 GHz.
+ */
+ if ((mode->eht_capab[ieee80211_mode].phy_cap[
+ EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &
+ EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK) && is_6ghz &&
+ ibss_mesh_is_80mhz_avail(channel + 16, mode) &&
+ ibss_mesh_is_80mhz_avail(channel + 32, mode) &&
+ ibss_mesh_is_80mhz_avail(channel + 48, mode)) {
+ for (j = 0; j < ARRAY_SIZE(bw320); j += 2) {
+ if (freq->freq >= bw320[j] &&
+ freq->freq <= bw320[j + 1]) {
+ chwidth = CONF_OPER_CHWIDTH_320MHZ;
+ seg0 = ibss_get_center_320mhz(freq->channel);
+ break;
+ }
+ }
+ }
+
if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
/* setup center_freq2, bandwidth */
for (k = 0; k < ARRAY_SIZE(bw80); k++) {
@@ -3413,13 +3586,12 @@
}
-static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
- struct wpa_bss *bss,
- u8 *wpa_ie, size_t wpa_ie_len,
- size_t max_wpa_ie_len)
+int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ u8 *wpa_ie, size_t wpa_ie_len, size_t max_wpa_ie_len)
{
- struct wpabuf *wfa_ie = NULL;
+ struct wpabuf *wfa_ie = NULL, *attr = NULL;
u8 wfa_capa[1];
+ u8 capab_len = 0;
size_t wfa_ie_len, buf_len;
os_memset(wfa_capa, 0, sizeof(wfa_capa));
@@ -3431,7 +3603,13 @@
if (wpa_is_non_eht_scs_traffic_desc_supported(bss))
wfa_capa[0] |= WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC;
- if (!wfa_capa[0])
+ if (wfa_capa[0])
+ capab_len = 1;
+
+ if (wpa_s->conf->wfa_gen_capa == WFA_GEN_CAPA_UNPROTECTED)
+ attr = wpas_wfa_gen_capab_attr(wpa_s);
+
+ if (capab_len == 0 && !attr)
return wpa_ie_len;
/* Wi-Fi Alliance element */
@@ -3440,17 +3618,23 @@
3 + /* OUI */
1 + /* OUI Type */
1 + /* Capabilities Length */
- sizeof(wfa_capa); /* Capabilities */
+ capab_len + /* Capabilities */
+ (attr ? wpabuf_len(attr) : 0) /* Attributes */;
wfa_ie = wpabuf_alloc(buf_len);
- if (!wfa_ie)
+ if (!wfa_ie) {
+ wpabuf_free(attr);
return wpa_ie_len;
+ }
wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
wpabuf_put_u8(wfa_ie, buf_len - 2);
wpabuf_put_be24(wfa_ie, OUI_WFA);
wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
- wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
- wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
+ wpabuf_put_u8(wfa_ie, capab_len);
+ wpabuf_put_data(wfa_ie, wfa_capa, capab_len);
+ if (attr)
+ wpabuf_put_buf(wfa_ie, attr);
+ wpabuf_free(attr);
wfa_ie_len = wpabuf_len(wfa_ie);
if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
@@ -3995,10 +4179,10 @@
}
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE_SUPPORT,
- wpas_rsn_overriding(wpa_s));
+ wpas_rsn_overriding(wpa_s, ssid));
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
RSN_OVERRIDE_NOT_USED);
- if (wpas_rsn_overriding(wpa_s) &&
+ if (wpas_rsn_overriding(wpa_s, ssid) &&
wpas_ap_supports_rsn_overriding(wpa_s, bss) &&
wpa_ie_len + 2 + 4 + 1 <= max_wpa_ie_len) {
u8 *pos = wpa_ie + wpa_ie_len, *start = pos;
@@ -4035,7 +4219,7 @@
wpa_ie_len += pos - start;
}
- params->rsn_overriding = wpas_rsn_overriding(wpa_s);
+ params->rsn_overriding = wpas_rsn_overriding(wpa_s, ssid);
params->wpa_ie = wpa_ie;
params->wpa_ie_len = wpa_ie_len;
params->auth_alg = algs;
@@ -4686,7 +4870,7 @@
params.prev_bssid = prev_bssid;
#ifdef CONFIG_SAE
- params.sae_pwe = wpa_s->conf->sae_pwe;
+ params.sae_pwe = wpas_get_ssid_sae_pwe(wpa_s, ssid);
#endif /* CONFIG_SAE */
ret = wpa_drv_associate(wpa_s, ¶ms);
@@ -5144,6 +5328,51 @@
}
+static bool ssid_in_last_scan(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+ size_t i;
+
+ /* Check if the previous scan included the selected network */
+ if (wpa_s->last_scan_num_ssids <= 1 ||
+ !ssid->ssid || ssid->ssid_len == 0)
+ return false;
+
+ /* Iterate through the previous scan SSIDs */
+ for (i = 0; i < wpa_s->last_scan_num_ssids; i++) {
+ if (os_memcmp(wpa_s->last_scan_ssids[i].ssid, ssid->ssid,
+ ssid->ssid_len) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+
+/**
+ * Checks whether an SSID was discovered in the last scan.
+ * @wpa_s: wpa_supplicant structure for a network interface.
+ * @ssid: wpa_ssid structure for a configured network.
+ * Returns: true if ssid found, false otherwise.
+ */
+static bool ssid_in_last_scan_res(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+ size_t i;
+
+ if (!wpa_s->last_scan_res || !ssid->ssid || ssid->ssid_len == 0)
+ return false;
+
+ for (i = 0; i < wpa_s->last_scan_res_used; i++) {
+ if (os_memcmp(wpa_s->last_scan_res[i]->ssid,
+ ssid->ssid, ssid->ssid_len) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+
/**
* wpa_supplicant_select_network - Attempt association with a network
* @wpa_s: wpa_supplicant structure for a network interface
@@ -5201,13 +5430,22 @@
(ssid->mode == WPAS_MODE_MESH ||
ssid->mode == WPAS_MODE_AP) ? ssid : NULL;
- if (ssid->scan_ssid &&
- (wpa_s->no_suitable_network || wpa_s->last_scan_external)) {
- wpa_printf(MSG_DEBUG,
- "Request a new scan for hidden network");
- request_new_scan = true;
- } else if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
- !ssid->owe_only) {
+ if (ssid->scan_ssid) {
+ if (ssid_in_last_scan(wpa_s, ssid)) {
+ wpa_printf(MSG_DEBUG,
+ "Hidden network was scanned for in last scan");
+ } else if (ssid_in_last_scan_res(wpa_s, ssid)) {
+ wpa_printf(MSG_DEBUG,
+ "Hidden network was found in last scan results");
+ } else {
+ request_new_scan = true;
+ wpa_printf(MSG_DEBUG,
+ "Request a new scan for hidden network");
+ }
+ }
+
+ if (!request_new_scan && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
+ !ssid->owe_only) {
wpa_printf(MSG_DEBUG,
"Request a new scan for OWE transition SSID");
request_new_scan = true;
@@ -5229,7 +5467,7 @@
wpa_s->last_owe_group = 0;
if (ssid) {
ssid->owe_transition_bss_select_count = 0;
- wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
+ wpa_s_setup_sae_pt(wpa_s, ssid, false);
}
if (wpa_s->connect_without_scan || request_new_scan ||
@@ -5765,6 +6003,7 @@
MACSTR ")",
wpa_supplicant_state_txt(wpa_s->wpa_state),
MAC2STR(connected_addr));
+ delay_processing:
wpabuf_free(wpa_s->pending_eapol_rx);
wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
if (wpa_s->pending_eapol_rx) {
@@ -5862,9 +6101,23 @@
encrypted) > 0)
return;
wpa_drv_poll(wpa_s);
- if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
- wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
- else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
+ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK)) {
+ if (wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len,
+ encrypted) == -2 &&
+#ifdef CONFIG_AP
+ !wpa_s->ap_iface &&
+#endif /* CONFIG_AP */
+ wpa_s->last_eapol_matches_bssid) {
+ /* Handle the case where reassociation occurs to the
+ * current connected AP */
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Delay processing of received EAPOL frame for reassociation to the current connected AP (state=%s connected_addr="
+ MACSTR ")",
+ wpa_supplicant_state_txt(wpa_s->wpa_state),
+ MAC2STR(connected_addr));
+ goto delay_processing;
+ }
+ } else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
/*
* Set portValid = true here since we are going to skip 4-way
* handshake processing which would normally set portValid. We
@@ -6119,6 +6372,10 @@
wpa_s->new_connection = 1;
wpa_s->parent = parent ? parent : wpa_s;
wpa_s->p2pdev = wpa_s->parent;
+#ifdef CONFIG_P2P
+ if (parent)
+ wpa_s->p2p_mode = parent->p2p_mode;
+#endif /* CONFIG_P2P */
wpa_s->sched_scanning = 0;
wpa_s->setband_mask = WPA_SETBAND_AUTO;
@@ -7470,17 +7727,16 @@
u16 i;
for (i = 0; i < wpa_s->hw.num_modes; i++) {
- if (wpa_s->hw.modes[i].vht_capab) {
- wpa_s->hw_capab = CAPAB_VHT;
- break;
- }
-
- if (wpa_s->hw.modes[i].ht_capab &
- HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
- wpa_s->hw_capab = CAPAB_HT40;
- else if (wpa_s->hw.modes[i].ht_capab &&
- wpa_s->hw_capab == CAPAB_NO_HT_VHT)
- wpa_s->hw_capab = CAPAB_HT;
+ if (wpa_s->hw.modes[i].eht_capab[IEEE80211_MODE_INFRA].
+ eht_supported)
+ wpa_s->hw_capab |= BIT(CAPAB_EHT);
+ if (wpa_s->hw.modes[i].he_capab[IEEE80211_MODE_INFRA].
+ he_supported)
+ wpa_s->hw_capab |= BIT(CAPAB_HE);
+ if (wpa_s->hw.modes[i].vht_capab)
+ wpa_s->hw_capab |= BIT(CAPAB_VHT);
+ if (wpa_s->hw.modes[i].ht_capab)
+ wpa_s->hw_capab |= BIT(CAPAB_HT);
}
wpa_s->support_6ghz = wpas_is_6ghz_supported(wpa_s, false);
}
@@ -7522,12 +7778,15 @@
capa.mac_addr_rand_sched_scan_supported)
wpa_s->mac_addr_rand_supported |=
(MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
+ wpa_s->drv_max_probe_req_ie_len = capa.max_probe_req_ie_len;
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;
+ } else {
+ wpa_s->drv_max_probe_req_ie_len = 1500;
}
#ifdef CONFIG_PASN
wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
@@ -8713,12 +8972,19 @@
}
-bool wpas_rsn_overriding(struct wpa_supplicant *wpa_s)
+bool wpas_rsn_overriding(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
{
- if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_DISABLED)
+ enum wpas_rsn_overriding rsno;
+
+ if (ssid && ssid->rsn_overriding != RSN_OVERRIDING_NOT_SET)
+ rsno = ssid->rsn_overriding;
+ else
+ rsno = wpa_s->conf->rsn_overriding;
+
+ if (rsno == RSN_OVERRIDING_DISABLED)
return false;
- if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_ENABLED)
+ if (rsno == RSN_OVERRIDING_ENABLED)
return true;
if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
@@ -8912,7 +9178,8 @@
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) &&
+ !(wpa_key_mgmt_sae(ssid->key_mgmt) &&
+ (ssid->sae_password || ssid->pmk_valid)) &&
!ssid->mem_only_psk)
return 1;
@@ -8981,6 +9248,16 @@
#ifdef CONFIG_SAE
+
+enum sae_pwe wpas_get_ssid_sae_pwe(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+ if (!ssid || ssid->sae_pwe == DEFAULT_SAE_PWE)
+ return wpa_s->conf->sae_pwe;
+ return ssid->sae_pwe;
+}
+
+
bool wpas_is_sae_avoided(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
const struct wpa_ie_data *ie)
@@ -8990,6 +9267,7 @@
(WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) ||
wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION);
}
+
#endif /* CONFIG_SAE */
@@ -9725,7 +10003,7 @@
}
return wpa_s->driver->send_action(wpa_s->drv_priv, freq, wait, dst, src,
- bssid, data, data_len, no_cck);
+ bssid, data, data_len, no_cck, -1);
}
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index abbe7d7..ae181ee 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -401,6 +401,50 @@
# it from taking 100% of radio resources. The default value is 500 ms.
#p2p_search_delay=500
+# Enable/disable P2P pairing setup
+#p2p_pairing_setup=0
+
+# Enable/disable P2P pairing cache for verification
+#p2p_pairing_cache=0
+
+# Enable/disable P2P pairing verification with cached NIK/NPK
+#p2p_pairing_verification=0
+
+# Supported P2P bootstrapping method bitmap
+# b0: whether opportunistic bootstrapping is supported
+# b1: whether PIN display is supported
+# b2: whether passphrase display is supported
+# b3: whether QR Code display is supported
+# b4: whether NFC tag is supported
+# b5: whether keypad (PIN only) is supported
+# b6: whether keypad (passphrase) is supported
+# b7: whether QR Code scan is supported
+# b8: whether NFC reader is supported
+# b14: whether service managed bootstrapping is supported
+# b15: whether bootstrapping handshakes skipped is supported
+#p2p_bootstrap_methods=0
+
+# Bitmap of supported PASN types
+# B0: whether DH Group 19 with unauthenticated PASN is supported
+# B1: whether DH Group 19 with authenticated PASN is supported
+# B2: whether DH Group 20 with unauthenticated PASN is supported
+# B3: whether DH Group 20 authenticated PASN is supported
+#p2p_pasn_type=0
+
+# Bootstrap request for unauthorized peer is asked to come back after
+# this many TUs.
+#p2p_comeback_after=977
+
+# Enable/disable TWT based power management for P2P
+#p2p_twt_power_mgmt=0
+
+# Enable/disable P2P client channel switch request
+#p2p_chan_switch_req_enable=0
+
+# Regulatory info encoding for operation in 6 GHz band
+# As defined in Table E-12 and E-13 of IEEE P802.11-REVme/D7.0.
+#p2p_reg_info=0
+
# Opportunistic Key Caching (also known as Proactive Key Caching) default
# This parameter can be used to set the default behavior for the
# proactive_key_caching parameter. By default, OKC is disabled unless enabled
@@ -608,6 +652,34 @@
# 1 = Publish
#ftm_initiator=0
+#twt_requester: Whether TWT requester is enabled
+# 0 = disabled (default)
+# 1 = enabled if supported by the driver
+#twt_requester=0
+
+# Wi-Fi Alliance generational capabilities indication
+#
+# wfa_gen_capa: Whether to indicate Wi-Fi generational capability to the AP
+# 0 = do not indicate (default)
+# 1 = indicate in protected Action frame
+# 2 = indicate in unprotected (Re)Association Request frame
+#wfa_gen_capa=0
+#
+# wfa_gen_capa_supp: Supported Generations (hexdump of a bit field)
+# A bit field of supported Wi-Fi generations. This is encoded as an little
+# endian octet string. If this is not set, the driver capabilities are
+# determined automatically.
+# bit 0: Wi-Fi 4
+# bit 1: Wi-Fi 5
+# bit 2: Wi-Fi 6
+# bit 3: Wi-Fi 7
+#wfa_gen_capa_supp=07
+#
+# wfa_gen_capa_cert: Certified Generations (hexdump of a bit field)
+# This has the same format as wfa_gen_capa_supp. This is an optional field, but
+# if included, shall have the same length as wfa_gen_capa_supp.
+#wfa_gen_capa_cert=07
+
# credential block
#
# Each credential used for automatic network selection is configured as a set
@@ -882,6 +954,8 @@
# NOTE: The protocol used for this mechanism is still subject to change and as
# such, this should not yet be enabled for production uses to avoid issues if
# something were to change.
+# A per-network block parameter with the same name can be used to override this
+# global parameter.
# 0 = Disabled (default)
# 1 = Enabled automatically if the driver indicates support
# 2 = Forced to be enabled even without driver capability indication
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 84b7bd5..d27ff1a 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -686,6 +686,18 @@
};
+enum local_hw_capab {
+ CAPAB_HT,
+ CAPAB_VHT,
+ CAPAB_HE,
+ CAPAB_EHT,
+};
+
+struct last_scan_ssid {
+ u8 ssid[SSID_MAX_LEN];
+ size_t ssid_len;
+};
+
/**
* struct wpa_supplicant - Internal data for wpa_supplicant interface
*
@@ -823,6 +835,8 @@
size_t last_scan_res_size;
struct os_reltime last_scan;
bool last_scan_external;
+ struct last_scan_ssid last_scan_ssids[WPAS_MAX_SCAN_SSIDS];
+ size_t last_scan_num_ssids;
const struct wpa_driver_ops *driver;
int interface_removed; /* whether the network interface has been
@@ -844,7 +858,7 @@
int eapol_received; /* number of EAPOL packets received after the
* previous association event */
- u8 rsnxe[20];
+ u8 rsnxe[257];
size_t rsnxe_len;
struct scard_data *scard;
@@ -941,6 +955,7 @@
unsigned int drv_key_mgmt;
unsigned int drv_rrm_flags;
unsigned int drv_max_acl_mac_addrs;
+ size_t drv_max_probe_req_ie_len;
/*
* A bitmap of supported protocols for probe response offload. See
@@ -1137,6 +1152,7 @@
u8 pending_join_dev_addr[ETH_ALEN];
u8 p2p_bootstrap_dev_addr[ETH_ALEN];
int pending_join_wps_method;
+ char pending_join_password[100];
u8 p2p_join_ssid[SSID_MAX_LEN];
size_t p2p_join_ssid_len;
int p2p_join_scan_count;
@@ -1193,6 +1209,7 @@
unsigned int p2p2:1;
u16 p2p_bootstrap;
enum hostapd_hw_mode p2p_go_acs_band;
+ enum wpa_p2p_mode p2p_mode;
int p2p_persistent_go_freq;
int p2p_persistent_id;
int p2p_go_intent;
@@ -1202,6 +1219,7 @@
struct wpa_radio_work *p2p_scan_work;
struct wpa_radio_work *p2p_listen_work;
struct wpa_radio_work *p2p_send_action_work;
+ bool p2p_removing_listen_work;
u16 p2p_oob_dev_pw_id; /* OOB Device Password Id for group formation */
struct wpabuf *p2p_oob_dev_pw; /* OOB Device Password for group
@@ -1274,12 +1292,7 @@
u16 num_modes;
u16 flags;
} hw;
- enum local_hw_capab {
- CAPAB_NO_HT_VHT,
- CAPAB_HT,
- CAPAB_HT40,
- CAPAB_VHT,
- } hw_capab;
+ unsigned int hw_capab; /* bitmap of enum local_hw_capab bits */
#ifdef CONFIG_MACSEC
struct ieee802_1x_kay *kay;
#endif /* CONFIG_MACSEC */
@@ -1400,6 +1413,7 @@
unsigned int oci_freq_override_fils_assoc;
unsigned int oci_freq_override_wnm_sleep;
unsigned int disable_eapol_g2_tx;
+ unsigned int eapol_2_key_info_set_mask;
int test_assoc_comeback_type;
#endif /* CONFIG_TESTING_OPTIONS */
@@ -1619,6 +1633,9 @@
struct wpa_radio_work *pasn_auth_work;
unsigned int pasn_count;
struct pasn_auth *pasn_params;
+#ifdef CONFIG_P2P
+ struct wpa_radio_work *p2p_pasn_auth_work;
+#endif /* CONFIG_P2P */
#endif /* CONFIG_PASN */
bool is_6ghz_enabled;
@@ -1760,7 +1777,7 @@
void fils_connection_failure(struct wpa_supplicant *wpa_s);
void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s);
-bool wpas_rsn_overriding(struct wpa_supplicant *wpa_s);
+bool wpas_rsn_overriding(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s);
void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
const u8 *bssid);
@@ -1773,6 +1790,9 @@
void wpas_request_disconnection(struct wpa_supplicant *wpa_s);
int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen,
struct wpa_bss *bss);
+int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ u8 *wpa_ie, size_t wpa_ie_len,
+ size_t max_wpa_ie_len);
int wpas_update_random_addr(struct wpa_supplicant *wpa_s,
enum wpas_mac_addr_style style,
struct wpa_ssid *ssid);
@@ -1908,7 +1928,8 @@
struct channel_list_changed *info);
int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s,
struct wpa_bss *current_bss,
- struct wpa_bss *seleceted);
+ struct wpa_bss *selected,
+ bool poll_current);
void wpas_reset_mlo_info(struct wpa_supplicant *wpa_s);
/* eap_register.c */
@@ -1944,8 +1965,10 @@
int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+enum sae_pwe wpas_get_ssid_sae_pwe(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr);
-void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid,
+void wpa_s_setup_sae_pt(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
bool force);
void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s);
@@ -2003,6 +2026,11 @@
struct wpa_ssid *group,
int only_first_ssid, int debug_print);
+struct wpa_bss * wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *group,
+ struct wpa_ssid **selected_ssid,
+ int only_first_ssid);
+
int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
enum wpa_driver_if_type if_type,
unsigned int *num,
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 741ac6c..0011274 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -355,7 +355,10 @@
"driver-based 4-way hs and FT");
res = eapol_sm_get_key(eapol, buf, 2 * PMK_LEN);
if (res == 0) {
- os_memcpy(pmk, buf + PMK_LEN, PMK_LEN);
+ if (wpa_key_mgmt_sha384(wpa_s->key_mgmt))
+ os_memcpy(pmk, buf, pmk_len);
+ else
+ os_memcpy(pmk, buf + PMK_LEN, PMK_LEN);
os_memset(buf, 0, sizeof(buf));
}
#else /* CONFIG_IEEE80211R */
@@ -1473,8 +1476,6 @@
ptk, NULL, NULL, 0);
}
-#endif /* CONFIG_NO_WPA */
-
#ifdef CONFIG_PASN
static int wpa_supplicant_set_ltf_keyseed(void *_wpa_s, const u8 *own_addr,
@@ -1509,6 +1510,8 @@
wpa_msg(wpa_s, MSG_INFO, "RSN: SSID matched expected value");
}
+#endif /* CONFIG_NO_WPA */
+
int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
{
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index f3a8c9c..d8f6198 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -1375,7 +1375,7 @@
wpa_printf(MSG_DEBUG, "WPS: Cancel operation - cancel scan");
wpa_supplicant_cancel_scan(wpa_s);
wpas_clear_wps(wpa_s);
- } else if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
+ } else if (wpa_s->wpa_state >= WPA_ASSOCIATING) {
wpa_printf(MSG_DEBUG, "WPS: Cancel operation - "
"deauthenticate");
wpa_s->own_disconnect_req = 1;