[wpa_supplicant] cumilative patch from commit a8655be0b
Bug: 369728263
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 (TBD)
BYPASS_INCLUSIVE_LANGUAGE_REASON=Merged from open source
a8655be0b Fix documentation for vendor interface command
a803fa9da Include the NAN header file into driver.h to avoid C++ constraints
2d92cae65 nl80211: Check nla_parse_nested() result
ba6b3dc78 AP MLD: Fix link_id validity check for own links
ffc9fa013 Pass CSA parameters by reference instead by value
1527a95ba Add QCA vendor subcommand to trigger Channel Usage Request
c0c877a1f QCA vendor test configuration to add random PMKIDs in RSNE
a6fd2467b PASN: Allow frequency to be set for responder
d5c07aaab P2P2: Parse new attributes
0f854cb35 P2P2: Add PMKSA caches for PASN initiator and responder
8426e5274 PASN: Use allocated memory for RSNXE and allow its contents to be set
d582f8ce9 PASN: PASN Encrypted Data element parsing
58cc67c72 P2P2: Export p2p_build_go_neg_req()
ff97a762b P2P: Debug print details on address mapping errors
27de11ca5 nl80211: Configure capability flag for NAN USD offload
5cb1929da Add QCA vendor feature flags to indicate NAN USD offload support
58f04221f nl80211: NAN USD commands for offloading
456c3a023 P2P2: Do not include WPS IE in GO Negotiation
839b52eaf P2P2: Fragment P2P IE if subelements are too long in GO Negotiation
c958a571a P2P2: GO Negotiation Action frame contents for wrapped case
64bfba98b P2P: Use enum p2p_status_code more consistently for PD
e633b471b P2P2: Refactor GO Negotiation and Invitation processing
b7de417c8 PASN: Define PMKSA helper functions for initiator and responder
cb9b1f8c5 PASN: Optional KEK derivation in PTK
17a891fd5 P2P2: Notify bootstrapping request and completed events
11a573f31 P2P2: Add a new method to P2P_CONNECT control interface command
bde17063d hostapd: Do not indicate a punctured secondary channel in HT operation
809d9d817 macsec_linux: Hardware offload requires Linux headers >= v5.7
0012c4433 DPP: Support for provisioning SAE password identifiers (Configurator)
782c89c35 DPP: Support for provisioning SAE password identifiers (Enrollee)
de40e08f7 nl80211: Pass "global" events to all interfaces
c3ee46bcb AP MLD: Check SAE message length without depending on pointer arithemetic
63df62c6c AP MLD: Work around delayed STA entry addition for SAE confirm
14cb3906a AP MLD: Introduce MLD level control interface socket
61dfd7ae3 AP MLD: Create link based hostapd control sockets
b7963348c Add QCA vendor attribute to disable channel switch initiation
2b7277d3f USD: Move control interface events to notify.c
97c6ef258 QCA vendor interface to set the P2P mode configuration
e33acc217 Add QCA vendor attribute to change P2P GO beacon interval
59299a8a7 P2P2: Add bootstrapping support with PD frames
6aa9ad8f8 P2P2: Refactor provision discovery request/response processing
b4f9742ee P2P2: Process Element container attribute from NAN SDFs
fa389f2a3 P2P2: Parse P2P2 IE
25c6598f3 NAN USD: Add publishChannelList option for Subscriber
bcab29a78 P2P2: Device Identity Key generation and storage in configuration
58ba550c5 FT: Fix writing of ft_prepend_pmkid configuration parameter
5b0112a18 P2P2: Add DIRA attributes to P2P2 IE of NAN SDFs
29f70292e P2P2: Add PCEA and PBMA attributes to P2P2 IE of NAN SDFs
a58b2ba2f P2P2: Allow P2P IE to be added into NAN SDFs
ae221945f P2P2: New element and attribute definitions
633e96931 NAN: Option to offload NAN DE for USD into the driver
d98417218 RSNO: Check that RSNOE/RSNO2E/RSNXOE fit into RSN Override Link KDE
c03edfd5b Allow IE overriding to use maximum element length
d9bb64914 PASN: Add a function to configure noauth variable
8f21cdf9d PASN: Add support to reject PASN auth 1 based on user input
882bd2edd DPP: Do not restrict SAE password length on Enrollee
503e22025 DPP: Do not restrict SAE password length on Configurator
df8c5e22d RSNO: Always enable SNonce cookie and RSN Override elements validation
bbb55af8c RSNO: Skip validating RSN Override elements with MLO when RSN overriding not used
66d8ac8cc RSNO: Do not enforce SNonce cookie and RSN Selection match if RSNO not used
70b8f64fa RSNO: Update RSN overriding capability indication to the driver
5fd3d05a4 More detailed documentation for QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES
fd72d395d QCA vendor interface for indicating supplicant support for RSN overriding
88150522c Use QCA_WLAN_VENDOR_FEATURE_RSN_OVERRIDE_STA only for indicating driver support
8c9b9ccb4 AP MLD: Fix PN/IPN/BIPN for group rekeying
7275b6514 AP MLD: Fix ML STA wpa_group update during rekey
19e12d5e2 Fix GKeyDoneStations tracking for VLAN
43943ea5b nl80211: Add AP_VLAN interface to bridge after interface is up
7e7e43d6b AP MLD: Add links to bridge FDB for FT roaming
015f6a5a0 nl80211: NULL pointer check for link before use
3e2758b19 hostapd: Avoid channel selection across underlying hardware index
15bf093b5 hostapd: Fetch multiple radios information from the driver
c43e1e5a5 Sync with wireless-next.git include/uapi/linux/nl80211.h
c3beaf6b8 nl80211: MLD: Fix is_shared_drv ops logic when num links is one
3e420372e nl80211: Remove unused function argument from is_drv_shared() ops
c6ff28cb6 AP MLD: Handle garbage pointer after MLD interface is deleted
e1bf37022 nl80211: MLO: Process stop AP event on link basis
f519f472e nl80211: Make nl80211_remove_link() non-static
2d290f196 AP MLD: Handle driver events for interface enable/disable
e9984e3db hostapd: Refactor interface enable/disable into separate helper functions
8324947a6 RSNO: Add debug prints for RSN override elements in EAPOL frames
abd7f4795 RSNO: Fix storing RSNE/RSNXE variants to wpa_sm from association event
72ac0ee02 WNM: Extend workaround for broken AP operating class behavior
e33a55d31 nl80211: Sanitize link ID in mlme_event_ch_switch() for AP interface
de2ee083e nl80211: Add ifname and link ID debug prints in mlme_event_ch_switch()
bd8a1f5ff hostapd: Enable HE when EHT is set for channel switch
c6faa8936 AP MLD: Use the cached per STA profile instead of forming a new one
74db2b744 AP MLD: Handle Vendor Specific element inheritance in per STA profile
023d70d6c AP MLD: Add non-inheritance support for per STA profile reporting
b5359d01e AP MLD: Intersect per STA profile with the reporting BSS
abe990afb AP MLD: Ignore elements which are not meant to be included in per STA profile
2042cae9b AP MLD: Generate and keep per STA profiles for each link
8f07e9699 Move mld_link_info structure to hostapd.h header file
5cb6747f9 Add support to switch channel when CAC is in progress
b7f08c28c WNM: Fix potential NULL pointer dereference during assoc response handling
c7e704bdf hostapd: Add Bandwidth Indication subelement support for channel switch
c9d0c6fd7 hostapd: Refactor Channel Switch Wrapper element generation
b592c1586 nl80211: Handle nl80211_cqm_event per BSS
89c31feb3 Relocate the declaration of the hostapd_find_by_sta() function to top
83c4adcda hostapd: Add Max Channel Switch Time element support
9f334fe68 Share usec-to/from-TU conversion macros in a general location
69deac87f AP MLD: Ensure successful addition of link item into list
ca58be3da SAE: Add group 20 in default groups when AP started with SAE-EXT-KEY
666d695bb nl80211: Fix simultaneous scanning failure in case of MLO
fd55dfe16 nl80211: Fix scan request and its related events handling with MLO
23456e480 Avoid sending DEAUTH or DISASSOC packet when using flag tx=0
619ff3d2e build: Add simple compile_commands.json generation
d42cfaa39 Move wpas_trigger_6ghz_scan() up in the file
a66cb0993 Trigger a 6 GHz scan if RNR contains matching short SSID
acd9332c3 Fix success check for triggering 6 GHz scan
d40788a5c P2P: Use specified frequency for group client in P2P_GROUP_ADD command
9c0a6d64d dbus: Emit ScanInProgress6GHz property
b53d7a6a8 Add non-PSC channels to 6 GHz scan request
9e50c12b3 WNM: Scan for BSSID if there are forbidden neighbors
54b25b7c1 WNM: Always parse candidate list
d9d862787 WNM: Consolidate the scanning paths for BTM requests
3b6abe358 WNM: Reject requests with an invalid dialog token
f4a9cb96d MBO: Always accept BTM request with disassociation imminent bit set
adc6ca34a WNM: Move neighbor report test into wnm_is_bss_excluded()
a83231280 WNM: Swap logic in wnm_is_bss_excluded() to allow more checks
582b5eff4 WNM: Remove unused age parameter for neighbor comparison
4bbe004e0 WNM: Split candidate list parsing into a separate function
b791d1f34 WNM: Use os_relatime_add_ms() helper
da1a86afc WNM: Rename wnm_dissoc_timer
ebd18f1ad WNM: Rename wnm_dissoc_addr
93eb3b83c WNM: Store whether disassociation address is an MLD MAC address
63ac001ed WNM: Only trigger selection logic for own scans
bb96540ef Add QCA vendor attribute to skip recently scanned channels
bc43e75b2 MLD STA: Fix destination address for EAPOL frames
69d18ab9f bgscan: Add OWE transition mode SSID to network scan
56e8f8bf3 OWE: Enable roaming between OWE APs
ddfed3f08 OWE: Reduce code duplication in OWE element parsing
1e5416051 hostapd: Fix BSS parameters change count on link removal
21c3a7494 Add Link ID attribute for external ACS vendor command
594296595 Add link ID attribute to ADD_STA_NODE QCA vendor command for AP MLD
e1ab680c9 Add QCA vendor subcommand to request audio transport switch
7e0e69cfe SAE: Send external auth status after sending Authentication frame
be6e4279f RSNO: Verify all RSNE/RSNXE variants in multi-link cases
521374b97 RSNO: Include all RSNE/RSNXE variants in EAPOL-Key message 3/4
6f522baa1 RSNO: Use SNonce cookie to indicate support for RSN overriding
62ca121f9 RSNO: Use the RSN Selection element to indicate which variant was used
524c45215 RSNO: Remove unused override element generation
13648dde9 FILS: Check for potential NULL return
376adfea8 RSNO: Protect wpa_ie_buf3 from reuse explicitly
4adf234cd RSNO: Remove override elements from EAPOL-Key msg 3/4
296104d35 Testing functionality to allow EAPOL-Key Reserved field to be set
2e4c612dd Allow RSNE/RSNXE/RSNOE/RSNO2E/RSNXOE to be replace for testing
bb61f6cb9 RSNO: Support over two octets of RSNXOE capabilities
8b2ddfdbb RSNO: Allow RSNXE to be omitted
Change-Id: Id01978ca4556c871937ebcee51493166a7d595ab
Signed-off-by: Sunil Ravi <sunilravi@google.com>
diff --git a/wpa_supplicant/aidl/aidl_manager.cpp b/wpa_supplicant/aidl/aidl_manager.cpp
index 707299d..4c50449 100644
--- a/wpa_supplicant/aidl/aidl_manager.cpp
+++ b/wpa_supplicant/aidl/aidl_manager.cpp
@@ -2060,7 +2060,7 @@
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
// number of tbtts to milliseconds
- duration_ms = wpa_s->wnm_dissoc_timer * beacon_int * 128 / 125;
+ duration_ms = wpa_s->wnm_disassoc_timer * beacon_int * 128 / 125;
}
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
//wnm_bss_termination_duration contains 12 bytes of BSS
diff --git a/wpa_supplicant/aidl/p2p_iface.cpp b/wpa_supplicant/aidl/p2p_iface.cpp
index 7afc8a1..2005af2 100644
--- a/wpa_supplicant/aidl/p2p_iface.cpp
+++ b/wpa_supplicant/aidl/p2p_iface.cpp
@@ -1061,7 +1061,8 @@
int new_pin = wpas_p2p_connect(
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));
+ vht, CONF_OPER_CHWIDTH_USE_HT, he, edmg, nullptr, 0, is6GhzAllowed(wpa_s),
+ false, 0, NULL);
if (new_pin < 0) {
return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
}
diff --git a/wpa_supplicant/bgscan_learn.c b/wpa_supplicant/bgscan_learn.c
index cab4ae2..bc9f324 100644
--- a/wpa_supplicant/bgscan_learn.c
+++ b/wpa_supplicant/bgscan_learn.c
@@ -280,6 +280,11 @@
params.num_ssids = 1;
params.ssids[0].ssid = data->ssid->ssid;
params.ssids[0].ssid_len = data->ssid->ssid_len;
+
+ /* Add OWE transition mode SSID of the current network */
+ wpa_add_owe_scan_ssid(wpa_s, ¶ms, data->ssid,
+ wpa_s->max_scan_ssids - params.num_ssids);
+
if (data->ssid->scan_freq)
params.freqs = data->ssid->scan_freq;
else {
diff --git a/wpa_supplicant/bgscan_simple.c b/wpa_supplicant/bgscan_simple.c
index a90cf86..d9aaa63 100644
--- a/wpa_supplicant/bgscan_simple.c
+++ b/wpa_supplicant/bgscan_simple.c
@@ -89,6 +89,10 @@
params.ssids[0].ssid_len = data->ssid->ssid_len;
params.freqs = data->ssid->scan_freq;
+ /* Add OWE transition mode SSID of the current network */
+ wpa_add_owe_scan_ssid(wpa_s, ¶ms, data->ssid,
+ wpa_s->max_scan_ssids - params.num_ssids);
+
/*
* A more advanced bgscan module would learn about most like channels
* over time and request scans only for some channels (probing others
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index cf94d4b..39de8ba 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -273,6 +273,57 @@
return NULL;
}
+/**
+ * wpa_bss_get_connection - Fetch a BSS table entry based on BSSID and SSID.
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: BSSID, or %NULL to match any BSSID
+ * @ssid: SSID
+ * @ssid_len: Length of @ssid
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ *
+ * This function is similar to wpa_bss_get() but it will also return OWE
+ * transition mode encrypted networks for which transition-element matches
+ * @ssid.
+ */
+struct wpa_bss * wpa_bss_get_connection(struct wpa_supplicant *wpa_s,
+ const u8 *bssid,
+ const u8 *ssid, size_t ssid_len)
+{
+ struct wpa_bss *bss;
+#ifdef CONFIG_OWE
+ const u8 *owe, *owe_bssid, *owe_ssid;
+ size_t owe_ssid_len;
+#endif /* CONFIG_OWE */
+
+ if (bssid && !wpa_supplicant_filter_bssid_match(wpa_s, bssid))
+ return NULL;
+ dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
+ if (bssid && !ether_addr_equal(bss->bssid, bssid))
+ continue;
+
+ if (bss->ssid_len == ssid_len &&
+ os_memcmp(bss->ssid, ssid, ssid_len) == 0)
+ return bss;
+
+#ifdef CONFIG_OWE
+ /* Check if OWE transition mode element is present and matches
+ * the SSID */
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+ if (!owe)
+ continue;
+
+ if (wpas_get_owe_trans_network(owe, &owe_bssid, &owe_ssid,
+ &owe_ssid_len))
+ continue;
+
+ if (owe_ssid_len == ssid_len &&
+ os_memcmp(owe_ssid, ssid, ssid_len) == 0)
+ return bss;
+#endif /* CONFIG_OWE */
+ }
+ return NULL;
+}
+
void calculate_update_time(const struct os_reltime *fetch_time,
unsigned int age_ms,
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index 508129c..31688fa 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -165,6 +165,9 @@
void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age);
struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
const u8 *ssid, size_t ssid_len);
+struct wpa_bss * wpa_bss_get_connection(struct wpa_supplicant *wpa_s,
+ const u8 *bssid,
+ const u8 *ssid, size_t ssid_len);
struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
const u8 *bssid);
struct wpa_bss * wpa_bss_get_bssid_latest(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 0f98f77..5b08478 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -3096,6 +3096,7 @@
os_free(config->dpp_mud_url);
os_free(config->dpp_extra_conf_req_name);
os_free(config->dpp_extra_conf_req_value);
+ wpabuf_free(config->dik);
os_free(config);
}
@@ -5496,6 +5497,8 @@
{ INT(p2p_interface_random_mac_addr), 0 },
{ INT(p2p_6ghz_disable), 0 },
{ INT(p2p_dfs_chan_enable), 0 },
+ { INT(dik_cipher), 0},
+ { BIN(dik), 0 },
#endif /* CONFIG_P2P */
{ FUNC(country), CFG_CHANGED_COUNTRY },
{ INT(bss_max_count), 0 },
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 7ea43a6..1281786 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -1843,6 +1843,12 @@
int mld_force_single_link;
#endif /* CONFIG_TESTING_OPTIONS */
+
+ /* Cipher version type */
+ int dik_cipher;
+
+ /* DevIK */
+ struct wpabuf *dik;
};
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index fa829eb..53614ae 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1634,7 +1634,11 @@
MAC2STR(config->mld_connect_bssid_pref));
#endif /* CONFIG_TESTING_OPTIONS */
if (config->ft_prepend_pmkid)
- fprintf(f, "ft_prepend_pmkid=%d", config->ft_prepend_pmkid);
+ fprintf(f, "ft_prepend_pmkid=%d\n", config->ft_prepend_pmkid);
+ if (config->dik) {
+ fprintf(f, "dik_cipher=%d\n", config->dik_cipher);
+ write_global_bin(f, "dik", config->dik);
+ }
}
#endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index d245531..6dba468 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -6035,7 +6035,7 @@
return -1;
}
- bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
+ bss = wpa_bss_get_connection(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
if (!bss) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
"from BSS table");
@@ -6376,6 +6376,10 @@
size_t group_ssid_len = 0;
int he;
bool allow_6ghz;
+ bool p2p2;
+ u16 bootstrap = 0;
+ const char *password = NULL;
+ char *token, *context = NULL;
if (!wpa_s->global->p2p_init_wpa_s)
return -1;
@@ -6385,10 +6389,12 @@
wpa_s = wpa_s->global->p2p_init_wpa_s;
}
- /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
+ /* <addr> <"pbc" | "pin" | "pair" | PIN> [label|display|keypad|p2ps]
* [persistent|persistent=<network id>]
* [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
- * [ht40] [vht] [he] [edmg] [auto] [ssid=<hexdump>] */
+ * [ht40] [vht] [he] [edmg] [auto] [ssid=<hexdump>]
+ * [p2p2] [bstrapmethod=<value>] [password=<string>]
+ */
if (hwaddr_aton(cmd, addr))
return -1;
@@ -6422,6 +6428,7 @@
vht;
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;
pos2 = os_strstr(pos, " go_intent=");
if (pos2) {
@@ -6477,6 +6484,8 @@
wps_method = WPS_PBC;
} else if (os_strstr(pos, "p2ps") != NULL) {
wps_method = WPS_P2PS;
+ } else if (os_strncmp(pos, "pair", 4) == 0 && p2p2) {
+ wps_method = WPS_NOT_READY;
} else {
pin = pos;
pos = os_strchr(pin, ' ');
@@ -6492,11 +6501,26 @@
}
}
+ pos2 = os_strstr(pos, "bstrapmethod=");
+ if (pos2) {
+ pos2 += 13;
+ bootstrap = atoi(pos2);
+ pd = true;
+ }
+
+ while ((token = str_token(pos, " ", &context))) {
+ if (os_strncmp(token, "password=", 9) == 0) {
+ password = token + 9;
+ continue;
+ }
+ }
+
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);
+ group_ssid, group_ssid_len, allow_6ghz, p2p2,
+ bootstrap, password);
if (new_pin == -2) {
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
return 25;
@@ -7172,7 +7196,7 @@
return -1;
}
- return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0,
+ return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, freq,
vht_center_freq2, ht40, vht,
vht_chwidth, he, edmg,
NULL, 0, 0, allow_6ghz, 0,
@@ -12202,6 +12226,7 @@
int ret = -1;
enum nan_service_protocol_type srv_proto_type = 0;
int *freq_list = NULL;
+ bool p2p = false;
os_memset(¶ms, 0, sizeof(params));
/* USD shall use both solicited and unsolicited transmissions */
@@ -12262,6 +12287,11 @@
continue;
}
+ if (os_strcmp(token, "p2p=1") == 0) {
+ p2p = true;
+ continue;
+ }
+
if (os_strcmp(token, "solicited=0") == 0) {
params.solicited = false;
continue;
@@ -12283,7 +12313,7 @@
}
publish_id = wpas_nan_usd_publish(wpa_s, service_name, srv_proto_type,
- ssi, ¶ms);
+ ssi, ¶ms, p2p);
if (publish_id > 0)
ret = os_snprintf(buf, buflen, "%d", publish_id);
fail:
@@ -12367,6 +12397,8 @@
struct wpabuf *ssi = NULL;
int ret = -1;
enum nan_service_protocol_type srv_proto_type = 0;
+ int *freq_list = NULL;
+ bool p2p = false;
os_memset(¶ms, 0, sizeof(params));
params.freq = NAN_USD_DEFAULT_FREQ;
@@ -12392,6 +12424,27 @@
continue;
}
+ if (os_strncmp(token, "freq_list=", 10) == 0) {
+ char *pos = token + 10;
+
+ if (os_strcmp(pos, "all") == 0) {
+ os_free(freq_list);
+ freq_list = wpas_nan_usd_all_freqs(wpa_s);
+ params.freq_list = freq_list;
+ continue;
+ }
+
+ while (pos && pos[0]) {
+ int_array_add_unique(&freq_list, atoi(pos));
+ pos = os_strchr(pos, ',');
+ if (pos)
+ pos++;
+ }
+
+ params.freq_list = freq_list;
+ continue;
+ }
+
if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
srv_proto_type = atoi(token + 15);
continue;
@@ -12406,6 +12459,11 @@
continue;
}
+ if (os_strcmp(token, "p2p=1") == 0) {
+ p2p = true;
+ continue;
+ }
+
wpa_printf(MSG_INFO,
"CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
token);
@@ -12414,11 +12472,12 @@
subscribe_id = wpas_nan_usd_subscribe(wpa_s, service_name,
srv_proto_type, ssi,
- ¶ms);
+ ¶ms, p2p);
if (subscribe_id > 0)
ret = os_snprintf(buf, buflen, "%d", subscribe_id);
fail:
wpabuf_free(ssi);
+ os_free(freq_list);
return ret;
}
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 76e42ff..5ad5bcd 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -2396,6 +2396,10 @@
case WPAS_DBUS_PROP_ROAM_COMPLETE:
prop = "RoamComplete";
break;
+ case WPAS_DBUS_PROP_SCAN_IN_PROGRESS_6GHZ:
+ prop = "ScanInProgress6GHz";
+ flush = TRUE;
+ break;
case WPAS_DBUS_PROP_SESSION_LENGTH:
prop = "SessionLength";
break;
@@ -3984,6 +3988,12 @@
NULL
},
{
+ "ScanInProgress6GHz", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
+ wpas_dbus_getter_scan_in_progress_6ghz,
+ NULL,
+ NULL
+ },
+ {
"SessionLength", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
wpas_dbus_getter_session_length,
NULL,
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index 952bb42..1db5fe8 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -36,6 +36,7 @@
WPAS_DBUS_PROP_ASSOC_STATUS_CODE,
WPAS_DBUS_PROP_ROAM_TIME,
WPAS_DBUS_PROP_ROAM_COMPLETE,
+ WPAS_DBUS_PROP_SCAN_IN_PROGRESS_6GHZ,
WPAS_DBUS_PROP_SESSION_LENGTH,
WPAS_DBUS_PROP_BSS_TM_STATUS,
WPAS_DBUS_PROP_MAC_ADDRESS,
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index 960b306..52e35a7 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -3836,6 +3836,29 @@
/**
+ * wpas_dbus_getter_scan_in_progress_6ghz - Get whether a 6 GHz scan is in
+ * progress
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter function for "ScanInProgress6GHz" property.
+ */
+dbus_bool_t wpas_dbus_getter_scan_in_progress_6ghz(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ dbus_bool_t scan_in_progress_6ghz = wpa_s->scan_in_progress_6ghz ?
+ TRUE : FALSE;
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
+ &scan_in_progress_6ghz, error);
+}
+
+
+/**
* wpas_dbus_getter_session_length - Get most recent BSS session length
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
index acd6af7..7faf70a 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -173,6 +173,7 @@
DECLARE_ACCESSOR(wpas_dbus_getter_assoc_status_code);
DECLARE_ACCESSOR(wpas_dbus_getter_roam_time);
DECLARE_ACCESSOR(wpas_dbus_getter_roam_complete);
+DECLARE_ACCESSOR(wpas_dbus_getter_scan_in_progress_6ghz);
DECLARE_ACCESSOR(wpas_dbus_getter_session_length);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_tm_status);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_expire_age);
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 418a8fd..65bd478 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -473,7 +473,7 @@
if (ssid == NULL || ssid->disabled != 2)
goto inv_args;
- if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0,
+ if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, freq,
freq2, ht40, vht,
max_oper_chwidth, he, edmg,
NULL, 0, 0, allow_6ghz,
@@ -706,7 +706,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);
+ NULL, 0, false, 0, 0, NULL);
if (new_pin >= 0) {
char npin[9];
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index 216224f..75a3d78 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -1433,6 +1433,17 @@
os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
ssid->ssid_len = conf->ssid_len;
+#ifdef CONFIG_DPP3
+ if (conf->akm == DPP_AKM_SAE && conf->password_id[0]) {
+ size_t len = os_strlen(conf->password_id);
+
+ ssid->sae_password_id = os_zalloc(len + 1);
+ if (!ssid->sae_password_id)
+ goto fail;
+ os_memcpy(ssid->sae_password_id, conf->password_id, len);
+ }
+#endif /* CONFIG_DPP3 */
+
if (conf->connector) {
if (dpp_akm_dpp(conf->akm)) {
ssid->key_mgmt = WPA_KEY_MGMT_DPP;
@@ -1490,12 +1501,17 @@
ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
else
ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
- if (conf->passphrase[0]) {
+ if (conf->passphrase[0] && dpp_akm_psk(conf->akm)) {
if (wpa_config_set_quoted(ssid, "psk",
conf->passphrase) < 0)
goto fail;
wpa_config_update_psk(ssid);
ssid->export_keys = 1;
+ } else if (conf->passphrase[0] && dpp_akm_sae(conf->akm)) {
+ if (wpa_config_set_quoted(ssid, "sae_password",
+ conf->passphrase) < 0)
+ goto fail;
+ ssid->export_keys = 1;
} else {
ssid->psk_set = conf->psk_set;
os_memcpy(ssid->psk, conf->psk, PMK_LEN);
@@ -1709,6 +1725,12 @@
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
hex);
}
+#ifdef CONFIG_DPP3
+ if (conf->password_id[0]) {
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_IDPASS "%s",
+ conf->password_id);
+ }
+#endif /* CONFIG_DPP3 */
if (conf->c_sign_key) {
char *hex;
size_t hexlen;
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index d01b52b..b6c7f50 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -9,6 +9,7 @@
#ifndef DRIVER_I_H
#define DRIVER_I_H
+#include "common/nan_de.h"
#include "drivers/driver.h"
/* driver_ops */
@@ -1175,4 +1176,75 @@
return wpa_s->driver->get_sta_mlo_info(wpa_s->drv_priv, mlo_info);
}
+static inline int
+wpas_drv_nan_flush(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s->driver->nan_flush)
+ return 0;
+
+ return wpa_s->driver->nan_flush(wpa_s->drv_priv);
+}
+
+static inline int
+wpas_drv_nan_publish(struct wpa_supplicant *wpa_s, const u8 *addr,
+ int publish_id, const char *service_name,
+ const u8 *service_id,
+ enum nan_service_protocol_type srv_proto_type,
+ const struct wpabuf *ssi, const struct wpabuf *elems,
+ struct nan_publish_params *params)
+{
+ if (!wpa_s->driver->nan_publish)
+ return 0;
+
+ return wpa_s->driver->nan_publish(wpa_s->drv_priv, addr, publish_id,
+ service_name, service_id,
+ srv_proto_type, ssi, elems, params);
+}
+
+static inline int
+wpas_drv_nan_cancel_publish(struct wpa_supplicant *wpa_s, int publish_id)
+{
+ if (!wpa_s->driver->nan_cancel_publish)
+ return 0;
+
+ return wpa_s->driver->nan_cancel_publish(wpa_s->drv_priv, publish_id);
+}
+
+static inline int
+wpas_drv_nan_update_publish(struct wpa_supplicant *wpa_s, int publish_id,
+ const struct wpabuf *ssi)
+{
+ if (!wpa_s->driver->nan_update_publish)
+ return 0;
+
+ return wpa_s->driver->nan_update_publish(wpa_s->drv_priv, publish_id,
+ ssi);
+}
+
+static inline int
+wpas_drv_nan_subscribe(struct wpa_supplicant *wpa_s, const u8 *addr,
+ int subscribe_id, const char *service_name,
+ const u8 *service_id,
+ enum nan_service_protocol_type srv_proto_type,
+ const struct wpabuf *ssi, const struct wpabuf *elems,
+ struct nan_subscribe_params *params)
+{
+ if (!wpa_s->driver->nan_subscribe)
+ return 0;
+
+ return wpa_s->driver->nan_subscribe(wpa_s->drv_priv, addr, subscribe_id,
+ service_name, service_id,
+ srv_proto_type, ssi, elems, params);
+}
+
+static inline int
+wpas_drv_nan_cancel_subscribe(struct wpa_supplicant *wpa_s, int subscribe_id)
+{
+ if (!wpa_s->driver->nan_cancel_subscribe)
+ return 0;
+
+ return wpa_s->driver->nan_cancel_subscribe(wpa_s->drv_priv,
+ subscribe_id);
+}
+
#endif /* DRIVER_I_H */
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 09a2bbb..006a4ea 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -9,6 +9,7 @@
#include "includes.h"
#include "common.h"
+#include "utils/crc32.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "rsn_supp/wpa.h"
#include "eloop.h"
@@ -1140,30 +1141,20 @@
const u8 **ret_ssid, size_t *ret_ssid_len)
{
#ifdef CONFIG_OWE
- const u8 *owe, *pos, *end, *bssid;
- u8 ssid_len;
+ const u8 *owe, *bssid;
owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
if (!owe || !wpa_bss_get_rsne(wpa_s, bss, NULL, false))
return;
- pos = owe + 6;
- end = owe + 2 + owe[1];
-
- if (end - pos < ETH_ALEN + 1)
- return;
- bssid = pos;
- pos += ETH_ALEN;
- ssid_len = *pos++;
- if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
+ if (wpas_get_owe_trans_network(owe, &bssid, ret_ssid, ret_ssid_len))
return;
/* Match the profile SSID against the OWE transition mode SSID on the
* open network. */
wpa_dbg(wpa_s, MSG_DEBUG, "OWE: transition mode BSSID: " MACSTR
- " SSID: %s", MAC2STR(bssid), wpa_ssid_txt(pos, ssid_len));
- *ret_ssid = pos;
- *ret_ssid_len = ssid_len;
+ " SSID: %s", MAC2STR(bssid),
+ wpa_ssid_txt(*ret_ssid, *ret_ssid_len));
if (!(bss->flags & WPA_BSS_OWE_TRANSITION)) {
struct wpa_ssid *ssid;
@@ -1171,8 +1162,8 @@
for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
if (wpas_network_disabled(wpa_s, ssid))
continue;
- if (ssid->ssid_len == ssid_len &&
- os_memcmp(ssid->ssid, pos, ssid_len) == 0) {
+ if (ssid->ssid_len == *ret_ssid_len &&
+ 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,
@@ -2411,6 +2402,78 @@
}
+static int wpas_trigger_6ghz_scan(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ struct wpa_driver_scan_params params;
+ unsigned int j;
+
+ wpa_dbg(wpa_s, MSG_INFO, "Triggering 6GHz-only scan");
+ os_memset(¶ms, 0, sizeof(params));
+ params.non_coloc_6ghz = wpa_s->last_scan_non_coloc_6ghz;
+ for (j = 0; j < data->scan_info.num_ssids; j++)
+ params.ssids[j] = data->scan_info.ssids[j];
+ params.num_ssids = data->scan_info.num_ssids;
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, ¶ms,
+ true, false, false);
+ if (!wpa_supplicant_trigger_scan(wpa_s, ¶ms, true, true)) {
+ wpa_s->scan_in_progress_6ghz = true;
+ wpas_notify_scan_in_progress_6ghz(wpa_s);
+ os_free(params.freqs);
+ return 1;
+ }
+ wpa_dbg(wpa_s, MSG_INFO, "Failed to trigger 6GHz-only scan");
+ os_free(params.freqs);
+ return 0;
+}
+
+
+static bool wpas_short_ssid_match(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *scan_res)
+{
+ size_t i;
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ u32 current_ssid_short = ieee80211_crc32(ssid->ssid, ssid->ssid_len);
+
+ for (i = 0; i < scan_res->num; i++) {
+ struct wpa_scan_res *res = scan_res->res[i];
+ const u8 *rnr_ie, *ie_end;
+ const struct ieee80211_neighbor_ap_info *info;
+ size_t left;
+
+ rnr_ie = wpa_scan_get_ie(res, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
+ if (!rnr_ie)
+ continue;
+
+ ie_end = rnr_ie + 2 + rnr_ie[1];
+ rnr_ie += 2;
+
+ left = ie_end - rnr_ie;
+ if (left < sizeof(struct ieee80211_neighbor_ap_info))
+ continue;
+
+ info = (const struct ieee80211_neighbor_ap_info *) rnr_ie;
+ if (info->tbtt_info_len < 11)
+ continue; /* short SSID not included */
+ left -= sizeof(struct ieee80211_neighbor_ap_info);
+ rnr_ie += sizeof(struct ieee80211_neighbor_ap_info);
+
+ while (left >= info->tbtt_info_len && rnr_ie + 11 <= ie_end) {
+ /* Skip TBTT offset and BSSID */
+ u32 short_ssid = WPA_GET_LE32(rnr_ie + 1 + ETH_ALEN);
+
+ if (short_ssid == current_ssid_short)
+ return true;
+
+ left -= info->tbtt_info_len;
+ rnr_ie += info->tbtt_info_len;
+ }
+ }
+
+ return false;
+}
+
+
/*
* Return a negative value if no scan results could be fetched or if scan
* results should not be shared with other virtual interfaces.
@@ -2428,6 +2491,7 @@
int ret = 0;
int ap = 0;
bool trigger_6ghz_scan;
+ bool short_ssid_match_found = false;
#ifndef CONFIG_NO_RANDOM_POOL
size_t i, num;
#endif /* CONFIG_NO_RANDOM_POOL */
@@ -2447,6 +2511,12 @@
scan_res = wpa_supplicant_get_scan_results(wpa_s,
data ? &data->scan_info :
NULL, 1, NULL);
+
+ if (wpa_s->scan_in_progress_6ghz) {
+ wpa_s->scan_in_progress_6ghz = false;
+ wpas_notify_scan_in_progress_6ghz(wpa_s);
+ }
+
if (scan_res == NULL) {
if (wpa_s->conf->ap_scan == 2 || ap ||
wpa_s->scan_res_handler == scan_only_handler)
@@ -2537,9 +2607,6 @@
return 0;
}
- if (wnm_scan_process(wpa_s, false) > 0)
- goto scan_work_done;
-
if (sme_proc_obss_scan(wpa_s) > 0)
goto scan_work_done;
@@ -2569,10 +2636,19 @@
wpas_wps_update_ap_info(wpa_s, scan_res);
+ if (wnm_scan_process(wpa_s, false) > 0)
+ goto scan_work_done;
+
if (wpa_s->wpa_state >= WPA_AUTHENTICATING &&
wpa_s->wpa_state < WPA_COMPLETED)
goto scan_work_done;
+ if (wpa_s->current_ssid && trigger_6ghz_scan && own_request && data &&
+ wpas_short_ssid_match(wpa_s, scan_res)) {
+ wpa_dbg(wpa_s, MSG_INFO, "Short SSID match in scan results");
+ short_ssid_match_found = true;
+ }
+
wpa_scan_results_free(scan_res);
if (own_request && wpa_s->scan_work) {
@@ -2599,6 +2675,9 @@
if (wpa_s->supp_pbc_active && !wpas_wps_partner_link_scan_done(wpa_s))
return ret;
+ if (short_ssid_match_found && wpas_trigger_6ghz_scan(wpa_s, data) > 0)
+ return 1;
+
return wpas_select_network_from_last_scan(wpa_s, 1, own_request,
trigger_6ghz_scan, data);
@@ -2613,30 +2692,6 @@
}
-static int wpas_trigger_6ghz_scan(struct wpa_supplicant *wpa_s,
- union wpa_event_data *data)
-{
- struct wpa_driver_scan_params params;
- unsigned int j;
-
- wpa_dbg(wpa_s, MSG_INFO, "Triggering 6GHz-only scan");
- os_memset(¶ms, 0, sizeof(params));
- params.non_coloc_6ghz = wpa_s->last_scan_non_coloc_6ghz;
- for (j = 0; j < data->scan_info.num_ssids; j++)
- params.ssids[j] = data->scan_info.ssids[j];
- params.num_ssids = data->scan_info.num_ssids;
- wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, ¶ms,
- true, !wpa_s->last_scan_non_coloc_6ghz, false);
- if (!wpa_supplicant_trigger_scan(wpa_s, ¶ms, true, true)) {
- os_free(params.freqs);
- return 1;
- }
- wpa_dbg(wpa_s, MSG_INFO, "Failed to trigger 6GHz-only scan");
- os_free(params.freqs);
- return 0;
-}
-
-
/**
* Select a network from the last scan
* @wpa_s: Pointer to wpa_supplicant data
@@ -2727,7 +2782,7 @@
wpa_supplicant_rsn_preauth_scan_results(wpa_s);
} else if (own_request) {
if (wpa_s->support_6ghz && trigger_6ghz_scan && data &&
- wpas_trigger_6ghz_scan(wpa_s, data) < 0)
+ wpas_trigger_6ghz_scan(wpa_s, data) > 0)
return 1;
/*
@@ -3376,12 +3431,13 @@
union wpa_event_data *data)
{
int l, len, found = 0, found_x = 0, wpa_found, rsn_found;
- const u8 *p;
+ const u8 *p, *ie;
u8 bssid[ETH_ALEN];
bool bssid_known;
#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
- struct wpa_ie_data ie;
+ struct wpa_ie_data wpa_ie;
#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
+ enum wpa_rsn_override rsn_override;
wpa_dbg(wpa_s, MSG_DEBUG, "Association info event");
wpa_s->ssid_verified = false;
@@ -3529,12 +3585,12 @@
* and pairwise suites from the assoc IE passed by the driver.
*/
if (wpas_driver_bss_selection(wpa_s)) {
- if (!(wpa_sm_parse_own_wpa_ie(wpa_s->wpa, &ie) < 0)) {
+ if (!(wpa_sm_parse_own_wpa_ie(wpa_s->wpa, &wpa_ie) < 0)) {
/* Check if firmware has roamed to a different security network */
- if(wpa_s->key_mgmt != ie.key_mgmt) {
+ if(wpa_s->key_mgmt != wpa_ie.key_mgmt) {
wpa_dbg(wpa_s, MSG_DEBUG, "Update to AKM suite 0x%x from Assoc IE",
- ie.key_mgmt);
- wpa_s->key_mgmt = ie.key_mgmt;
+ wpa_ie.key_mgmt);
+ wpa_s->key_mgmt = wpa_ie.key_mgmt;
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
if (wpa_key_mgmt_wpa_psk_no_sae(wpa_s->key_mgmt)) {
@@ -3557,10 +3613,10 @@
}
}
}
- if(wpa_s->pairwise_cipher != ie.pairwise_cipher) {
+ if(wpa_s->pairwise_cipher != wpa_ie.pairwise_cipher) {
wpa_dbg(wpa_s, MSG_DEBUG, "Update to pairwise cipher suite 0x%x "
- "from Assoc IE", ie.pairwise_cipher);
- wpa_s->pairwise_cipher = ie.pairwise_cipher;
+ "from Assoc IE", wpa_ie.pairwise_cipher);
+ wpa_s->pairwise_cipher = wpa_ie.pairwise_cipher;
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
wpa_s->pairwise_cipher);
}
@@ -3569,6 +3625,25 @@
}
#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
+ rsn_override = RSN_OVERRIDE_NOT_USED;
+ ie = get_vendor_ie(data->assoc_info.req_ies,
+ data->assoc_info.req_ies_len,
+ RSN_SELECTION_IE_VENDOR_TYPE);
+ if (ie && ie[1] >= 4 + 1) {
+ switch (ie[2 + 4]) {
+ case RSN_SELECTION_RSNE:
+ rsn_override = RSN_OVERRIDE_RSNE;
+ break;
+ case RSN_SELECTION_RSNE_OVERRIDE:
+ rsn_override = RSN_OVERRIDE_RSNE_OVERRIDE;
+ break;
+ case RSN_SELECTION_RSNE_OVERRIDE_2:
+ rsn_override = RSN_OVERRIDE_RSNE_OVERRIDE_2;
+ break;
+ }
+ }
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE, rsn_override);
+
#ifdef CONFIG_FILS
#ifdef CONFIG_SME
if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
@@ -3764,28 +3839,20 @@
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
}
- if (wpas_rsn_overriding(wpa_s) &&
- p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
- WPA_GET_BE32(&p[2]) == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
- rsn_found = 1;
- wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
- }
+ if (p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
+ WPA_GET_BE32(&p[2]) == RSNE_OVERRIDE_2_IE_VENDOR_TYPE)
+ wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, p, len);
- if (!rsn_found &&
- wpas_rsn_overriding(wpa_s) &&
- p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
- WPA_GET_BE32(&p[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
- rsn_found = 1;
- wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
- }
+ if (p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
+ WPA_GET_BE32(&p[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE)
+ wpa_sm_set_ap_rsne_override(wpa_s->wpa, p, len);
if (p[0] == WLAN_EID_RSNX && p[1] >= 1)
wpa_sm_set_ap_rsnxe(wpa_s->wpa, p, len);
- if (wpas_rsn_overriding(wpa_s) &&
- p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
+ if (p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
WPA_GET_BE32(&p[2]) == RSNXE_OVERRIDE_IE_VENDOR_TYPE)
- wpa_sm_set_ap_rsnxe(wpa_s->wpa, p, len);
+ wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, p, len);
l -= len;
p += len;
@@ -3796,6 +3863,9 @@
if (!rsn_found && data->assoc_info.beacon_ies) {
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_ap_rsne_override(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, NULL, 0);
}
if (wpa_found || rsn_found)
wpa_s->ap_ies_from_associnfo = 1;
@@ -3831,6 +3901,7 @@
static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
{
const u8 *bss_wpa = NULL, *bss_rsn = NULL, *bss_rsnx = NULL;
+ const u8 *rsnoe, *rsno2e, *rsnxoe;
if (!wpa_s->current_bss || !wpa_s->current_ssid)
return -1;
@@ -3840,17 +3911,27 @@
bss_wpa = wpa_bss_get_vendor_ie(wpa_s->current_bss,
WPA_IE_VENDOR_TYPE);
- bss_rsn = wpa_bss_get_rsne(wpa_s, wpa_s->current_bss, NULL,
- wpa_s->valid_links);
- bss_rsnx = wpa_bss_get_rsnxe(wpa_s, wpa_s->current_bss, NULL,
- wpa_s->valid_links);
+ bss_rsn = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSN);
+ bss_rsnx = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSNX);
+ rsnoe = wpa_bss_get_vendor_ie(wpa_s->current_bss,
+ RSNE_OVERRIDE_IE_VENDOR_TYPE);
+ rsno2e = wpa_bss_get_vendor_ie(wpa_s->current_bss,
+ RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
+ rsnxoe = wpa_bss_get_vendor_ie(wpa_s->current_bss,
+ RSNXE_OVERRIDE_IE_VENDOR_TYPE);
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
bss_wpa ? 2 + bss_wpa[1] : 0) ||
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
bss_rsn ? 2 + bss_rsn[1] : 0) ||
wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
- bss_rsnx ? 2 + bss_rsnx[1] : 0))
+ bss_rsnx ? 2 + bss_rsnx[1] : 0) ||
+ wpa_sm_set_ap_rsne_override(wpa_s->wpa, rsnoe,
+ rsnoe ? 2 + rsnoe[1] : 0) ||
+ wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, rsno2e,
+ rsno2e ? 2 + rsno2e[1] : 0) ||
+ wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, rsnxoe,
+ rsnxoe ? 2 + rsnxoe[1] : 0))
return -1;
return 0;
@@ -4203,7 +4284,6 @@
{
struct driver_sta_mlo_info drv_mlo;
struct wpa_sm_mlo wpa_mlo;
- const u8 *bss_rsn = NULL, *bss_rsnx = NULL;
int i;
os_memset(&drv_mlo, 0, sizeof(drv_mlo));
@@ -4223,6 +4303,7 @@
for_each_link(drv_mlo.req_links, i) {
struct wpa_bss *bss;
+ const u8 *rsne, *rsnxe, *rsnoe, *rsno2e, *rsnxoe;
bss = wpa_supplicant_get_new_bss(wpa_s, drv_mlo.links[i].bssid);
if (!bss) {
@@ -4231,13 +4312,25 @@
return -1;
}
- bss_rsn = wpa_bss_get_rsne(wpa_s, bss, NULL, true);
- bss_rsnx = wpa_bss_get_rsnxe(wpa_s, bss, NULL, true);
+ rsne = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+ rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
+ rsnoe = wpa_bss_get_vendor_ie(bss,
+ RSNE_OVERRIDE_IE_VENDOR_TYPE);
+ rsno2e = wpa_bss_get_vendor_ie(bss,
+ RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
+ rsnxoe = wpa_bss_get_vendor_ie(bss,
+ RSNXE_OVERRIDE_IE_VENDOR_TYPE);
- wpa_mlo.links[i].ap_rsne = bss_rsn ? (u8 *) bss_rsn : NULL;
- wpa_mlo.links[i].ap_rsne_len = bss_rsn ? 2 + bss_rsn[1] : 0;
- wpa_mlo.links[i].ap_rsnxe = bss_rsnx ? (u8 *) bss_rsnx : NULL;
- wpa_mlo.links[i].ap_rsnxe_len = bss_rsnx ? 2 + bss_rsnx[1] : 0;
+ wpa_mlo.links[i].ap_rsne = rsne ? (u8 *) rsne : NULL;
+ wpa_mlo.links[i].ap_rsne_len = rsne ? 2 + rsne[1] : 0;
+ wpa_mlo.links[i].ap_rsnxe = rsnxe ? (u8 *) rsnxe : NULL;
+ wpa_mlo.links[i].ap_rsnxe_len = rsnxe ? 2 + rsnxe[1] : 0;
+ wpa_mlo.links[i].ap_rsnoe = rsnoe ? (u8 *) rsnoe : NULL;
+ wpa_mlo.links[i].ap_rsnoe_len = rsnoe ? 2 + rsnoe[1] : 0;
+ wpa_mlo.links[i].ap_rsno2e = rsno2e ? (u8 *) rsno2e : NULL;
+ wpa_mlo.links[i].ap_rsno2e_len = rsno2e ? 2 + rsno2e[1] : 0;
+ wpa_mlo.links[i].ap_rsnxoe = rsnxoe ? (u8 *) rsnxoe : NULL;
+ wpa_mlo.links[i].ap_rsnxoe_len = rsnxoe ? 2 + rsnxoe[1] : 0;
os_memcpy(wpa_mlo.links[i].bssid, drv_mlo.links[i].bssid,
ETH_ALEN);
diff --git a/wpa_supplicant/nan_usd.c b/wpa_supplicant/nan_usd.c
index 657b302..1125f95 100644
--- a/wpa_supplicant/nan_usd.c
+++ b/wpa_supplicant/nan_usd.c
@@ -13,6 +13,8 @@
#include "wpa_supplicant_i.h"
#include "offchannel.h"
#include "driver_i.h"
+#include "notify.h"
+#include "p2p_supplicant.h"
#include "nan_usd.h"
@@ -241,19 +243,10 @@
const u8 *peer_addr, bool fsd, bool fsd_gas)
{
struct wpa_supplicant *wpa_s = ctx;
- char *ssi_hex;
- ssi_hex = os_zalloc(2 * ssi_len + 1);
- if (!ssi_hex)
- 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);
- os_free(ssi_hex);
+ wpas_notify_nan_discovery_result(wpa_s, srv_proto_type, subscribe_id,
+ peer_publish_id, peer_addr, fsd,
+ fsd_gas, ssi, ssi_len);
}
@@ -263,34 +256,9 @@
const u8 *ssi, size_t ssi_len)
{
struct wpa_supplicant *wpa_s = ctx;
- char *ssi_hex;
- ssi_hex = os_zalloc(2 * ssi_len + 1);
- if (!ssi_hex)
- 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);
- os_free(ssi_hex);
-}
-
-
-static const char * nan_reason_txt(enum nan_de_reason reason)
-{
- switch (reason) {
- case NAN_DE_REASON_TIMEOUT:
- return "timeout";
- case NAN_DE_REASON_USER_REQUEST:
- return "user-request";
- case NAN_DE_REASON_FAILURE:
- return "failure";
- }
-
- return "unknown";
+ wpas_notify_nan_replied(wpa_s, srv_proto_type, publish_id,
+ peer_subscribe_id, peer_addr, ssi, ssi_len);
}
@@ -299,9 +267,7 @@
{
struct wpa_supplicant *wpa_s = ctx;
- wpa_msg(wpa_s, MSG_INFO, NAN_PUBLISH_TERMINATED
- "publish_id=%d reason=%s",
- publish_id, nan_reason_txt(reason));
+ wpas_notify_nan_publish_terminated(wpa_s, publish_id, reason);
}
@@ -310,9 +276,7 @@
{
struct wpa_supplicant *wpa_s = ctx;
- wpa_msg(wpa_s, MSG_INFO, NAN_SUBSCRIBE_TERMINATED
- "subscribe_id=%d reason=%s",
- subscribe_id, nan_reason_txt(reason));
+ wpas_notify_nan_subscribe_terminated(wpa_s, subscribe_id, reason);
}
@@ -321,23 +285,28 @@
const u8 *peer_addr)
{
struct wpa_supplicant *wpa_s = ctx;
- char *ssi_hex;
- ssi_hex = os_zalloc(2 * ssi_len + 1);
- if (!ssi_hex)
- 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);
- os_free(ssi_hex);
+ wpas_notify_nan_receive(wpa_s, id, peer_instance_id, peer_addr,
+ ssi, ssi_len);
}
+#ifdef CONFIG_P2P
+static void wpas_nan_process_p2p_usd_elems(void *ctx, const u8 *buf,
+ u16 buf_len, const u8 *peer_addr,
+ unsigned int freq)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ wpas_p2p_process_usd_elems(wpa_s, buf, buf_len, peer_addr, freq);
+}
+#endif /* CONFIG_P2P */
+
+
int wpas_nan_usd_init(struct wpa_supplicant *wpa_s)
{
struct nan_callbacks cb;
+ bool offload = wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD;
os_memset(&cb, 0, sizeof(cb));
cb.ctx = wpa_s;
@@ -348,8 +317,11 @@
cb.publish_terminated = wpas_nan_de_publish_terminated;
cb.subscribe_terminated = wpas_nan_de_subscribe_terminated;
cb.receive = wpas_nan_de_receive;
+#ifdef CONFIG_P2P
+ 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, false, &cb);
+ wpa_s->nan_de = nan_de_init(wpa_s->own_addr, offload, false, &cb);
if (!wpa_s->nan_de)
return -1;
return 0;
@@ -377,22 +349,42 @@
if (!wpa_s->nan_de)
return;
nan_de_flush(wpa_s->nan_de);
+ if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD)
+ wpas_drv_nan_flush(wpa_s);
}
int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
- struct nan_publish_params *params)
+ struct nan_publish_params *params, bool p2p)
{
int publish_id;
struct wpabuf *elems = NULL;
+ const u8 *addr;
if (!wpa_s->nan_de)
return -1;
+ if (p2p) {
+ elems = wpas_p2p_usd_elems(wpa_s);
+ addr = wpa_s->global->p2p_dev_addr;
+ } else {
+ addr = wpa_s->own_addr;
+ }
+
publish_id = nan_de_publish(wpa_s->nan_de, service_name, srv_proto_type,
- ssi, elems, params);
+ ssi, elems, params, p2p);
+ if (publish_id >= 1 &&
+ (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
+ wpas_drv_nan_publish(wpa_s, addr, publish_id, service_name,
+ nan_de_get_service_id(wpa_s->nan_de,
+ publish_id),
+ srv_proto_type, ssi, elems, params) < 0) {
+ nan_de_cancel_publish(wpa_s->nan_de, publish_id);
+ publish_id = -1;
+ }
+
wpabuf_free(elems);
return publish_id;
}
@@ -403,15 +395,23 @@
if (!wpa_s->nan_de)
return;
nan_de_cancel_publish(wpa_s->nan_de, publish_id);
+ if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD)
+ wpas_drv_nan_cancel_publish(wpa_s, publish_id);
}
int wpas_nan_usd_update_publish(struct wpa_supplicant *wpa_s, int publish_id,
const struct wpabuf *ssi)
{
+ int ret;
+
if (!wpa_s->nan_de)
return -1;
- return nan_de_update_publish(wpa_s->nan_de, publish_id, ssi);
+ 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)
+ return -1;
+ return ret;
}
@@ -419,16 +419,35 @@
const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
- struct nan_subscribe_params *params)
+ struct nan_subscribe_params *params, bool p2p)
{
int subscribe_id;
struct wpabuf *elems = NULL;
+ const u8 *addr;
if (!wpa_s->nan_de)
return -1;
+ if (p2p) {
+ elems = wpas_p2p_usd_elems(wpa_s);
+ addr = wpa_s->global->p2p_dev_addr;
+ } else {
+ addr = wpa_s->own_addr;
+ }
+
subscribe_id = nan_de_subscribe(wpa_s->nan_de, service_name,
- srv_proto_type, ssi, elems, params);
+ srv_proto_type, ssi, elems, params,
+ p2p);
+ if (subscribe_id >= 1 &&
+ (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
+ wpas_drv_nan_subscribe(wpa_s, addr, subscribe_id, service_name,
+ nan_de_get_service_id(wpa_s->nan_de,
+ subscribe_id),
+ srv_proto_type, ssi, elems, params) < 0) {
+ nan_de_cancel_subscribe(wpa_s->nan_de, subscribe_id);
+ subscribe_id = -1;
+ }
+
wpabuf_free(elems);
return subscribe_id;
}
@@ -440,6 +459,8 @@
if (!wpa_s->nan_de)
return;
nan_de_cancel_subscribe(wpa_s->nan_de, subscribe_id);
+ if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD)
+ wpas_drv_nan_cancel_subscribe(wpa_s, subscribe_id);
}
diff --git a/wpa_supplicant/nan_usd.h b/wpa_supplicant/nan_usd.h
index 149ac9e..ecb4973 100644
--- a/wpa_supplicant/nan_usd.h
+++ b/wpa_supplicant/nan_usd.h
@@ -21,7 +21,7 @@
int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
- struct nan_publish_params *params);
+ struct nan_publish_params *params, bool p2p);
void wpas_nan_usd_cancel_publish(struct wpa_supplicant *wpa_s, int publish_id);
int wpas_nan_usd_update_publish(struct wpa_supplicant *wpa_s, int publish_id,
const struct wpabuf *ssi);
@@ -29,7 +29,7 @@
const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
- struct nan_subscribe_params *params);
+ struct nan_subscribe_params *params, bool p2p);
void wpas_nan_usd_cancel_subscribe(struct wpa_supplicant *wpa_s,
int subscribe_id);
int wpas_nan_usd_transmit(struct wpa_supplicant *wpa_s, int handle,
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index d53ae56..b8fdf29 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -10,6 +10,7 @@
#include "utils/common.h"
#include "common/wpa_ctrl.h"
+#include "common/nan_de.h"
#include "config.h"
#include "wpa_supplicant_i.h"
#include "wps_supplicant.h"
@@ -210,6 +211,16 @@
}
+void wpas_notify_scan_in_progress_6ghz(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_prop_changed(wpa_s,
+ WPAS_DBUS_PROP_SCAN_IN_PROGRESS_6GHZ);
+}
+
+
void wpas_notify_session_length(struct wpa_supplicant *wpa_s)
{
if (wpa_s->p2p_mgmt)
@@ -1457,3 +1468,105 @@
wpas_dbus_signal_hs20_t_c_acceptance(wpa_s, url);
#endif /* CONFIG_HS20 */
}
+
+#ifdef CONFIG_NAN_USD
+
+void wpas_notify_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)
+{
+ char *ssi_hex;
+
+ ssi_hex = os_zalloc(2 * ssi_len + 1);
+ if (!ssi_hex)
+ 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);
+ os_free(ssi_hex);
+}
+
+
+void wpas_notify_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)
+{
+ char *ssi_hex;
+
+ ssi_hex = os_zalloc(2 * ssi_len + 1);
+ if (!ssi_hex)
+ 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);
+ os_free(ssi_hex);
+}
+
+
+void wpas_notify_nan_receive(struct wpa_supplicant *wpa_s, int id,
+ int peer_instance_id, const u8 *peer_addr,
+ const u8 *ssi, size_t ssi_len)
+{
+ char *ssi_hex;
+
+ ssi_hex = os_zalloc(2 * ssi_len + 1);
+ if (!ssi_hex)
+ 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);
+ os_free(ssi_hex);
+}
+
+
+static const char * nan_reason_txt(enum nan_de_reason reason)
+{
+ switch (reason) {
+ case NAN_DE_REASON_TIMEOUT:
+ return "timeout";
+ case NAN_DE_REASON_USER_REQUEST:
+ return "user-request";
+ case NAN_DE_REASON_FAILURE:
+ return "failure";
+ }
+
+ return "unknown";
+}
+
+
+void wpas_notify_nan_publish_terminated(struct wpa_supplicant *wpa_s,
+ 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));
+}
+
+
+void wpas_notify_nan_subscribe_terminated(struct wpa_supplicant *wpa_s,
+ 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));
+}
+
+#endif /* CONFIG_NAN_USD */
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index a584884..85326da 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -20,6 +20,8 @@
struct tls_cert_data;
struct wpa_cred;
struct rsn_pmksa_cache_entry;
+enum nan_de_reason;
+enum nan_service_protocol_type;
int wpas_notify_supplicant_initialized(struct wpa_global *global);
void wpas_notify_supplicant_deinitialized(struct wpa_global *global);
@@ -35,6 +37,7 @@
void wpas_notify_auth_timeout(struct wpa_supplicant *wpa_s);
void wpas_notify_roam_time(struct wpa_supplicant *wpa_s);
void wpas_notify_roam_complete(struct wpa_supplicant *wpa_s);
+void wpas_notify_scan_in_progress_6ghz(struct wpa_supplicant *wpa_s);
void wpas_notify_session_length(struct wpa_supplicant *wpa_s);
void wpas_notify_bss_tm_status(struct wpa_supplicant *wpa_s);
void wpas_notify_network_changed(struct wpa_supplicant *wpa_s);
@@ -234,5 +237,26 @@
enum mlo_info_change_reason reason);
void wpas_notify_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
const char *url);
+void wpas_notify_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_notify_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_notify_nan_receive(struct wpa_supplicant *wpa_s, int id,
+ int peer_instance_id, const u8 *peer_addr,
+ const u8 *ssi, size_t ssi_len);
+void wpas_notify_nan_publish_terminated(struct wpa_supplicant *wpa_s,
+ int publish_id,
+ enum nan_de_reason reason);
+void wpas_notify_nan_subscribe_terminated(struct wpa_supplicant *wpa_s,
+ int subscribe_id,
+ enum nan_de_reason reason);
#endif /* NOTIFY_H */
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 9c20ee5..768b917 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -4501,7 +4501,8 @@
}
-static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
+static void wpas_p2ps_prov_complete(void *ctx, enum p2p_status_code status,
+ const u8 *dev,
const u8 *adv_mac, const u8 *ses_mac,
const u8 *grp_mac, u32 adv_id, u32 ses_id,
u8 conncap, int passwd_id,
@@ -4858,6 +4859,70 @@
WPA_IF_P2P_CLIENT, len, freq_list);
}
+
+static void wpas_p2p_send_bootstrap_comeback(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+
+ wpa_printf(MSG_DEBUG, "P2P2: Send bootstrapping comeback PD Request");
+ wpas_p2p_connect(wpa_s, wpa_s->p2p_bootstrap_dev_addr, wpa_s->p2p_pin,
+ wpa_s->p2p_wps_method, wpa_s->p2p_persistent_group, 0,
+ 0, 0, wpa_s->p2p_go_intent, wpa_s->p2p_connect_freq,
+ wpa_s->p2p_go_vht_center_freq2,
+ wpa_s->p2p_persistent_id,
+ wpa_s->p2p_pd_before_go_neg,
+ wpa_s->p2p_go_ht40,
+ wpa_s->p2p_go_vht,
+ wpa_s->p2p_go_max_oper_chwidth,
+ 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);
+}
+
+
+static void wpas_p2p_register_bootstrap_comeback(void *ctx, const u8 *addr,
+ u16 comeback_after)
+{
+ unsigned int timeout_us;
+ struct wpa_supplicant *wpa_s = ctx;
+
+ timeout_us = comeback_after * 1024;
+ os_memcpy(wpa_s->p2p_bootstrap_dev_addr, addr, ETH_ALEN);
+
+ eloop_cancel_timeout(wpas_p2p_send_bootstrap_comeback, wpa_s, NULL);
+ eloop_register_timeout(0, timeout_us, wpas_p2p_send_bootstrap_comeback,
+ wpa_s, NULL);
+}
+
+
+static void wpas_bootstrap_req_rx(void *ctx, const u8 *addr,
+ u16 bootstrap_method)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_BOOTSTRAP_REQUEST MACSTR
+ " bootstrap_method=%u", MAC2STR(addr), bootstrap_method);
+}
+
+
+static void wpas_bootstrap_completed(void *ctx, const u8 *addr,
+ enum p2p_status_code status, int freq)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ 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);
+ }
+}
+
+
int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s)
{
int ret = 0;
@@ -4982,6 +5047,9 @@
p2p.get_pref_freq_list = wpas_p2p_get_pref_freq_list;
p2p.p2p_6ghz_disable = wpa_s->conf->p2p_6ghz_disable;
p2p.p2p_dfs_chan_enable = wpa_s->conf->p2p_dfs_chan_enable;
+ p2p.register_bootstrap_comeback = wpas_p2p_register_bootstrap_comeback;
+ p2p.bootstrap_req_rx = wpas_bootstrap_req_rx;
+ p2p.bootstrap_completed = wpas_bootstrap_completed;
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);
@@ -5097,6 +5165,34 @@
else
p2p.passphrase_len = 8;
+ if (wpa_s->conf->dik &&
+ wpabuf_len(wpa_s->conf->dik) <= DEVICE_IDENTITY_KEY_MAX_LEN) {
+ p2p.pairing_config.dik_cipher = wpa_s->conf->dik_cipher;
+ p2p.pairing_config.dik_len = wpabuf_len(wpa_s->conf->dik);
+ os_memcpy(p2p.pairing_config.dik_data,
+ wpabuf_head(wpa_s->conf->dik),
+ p2p.pairing_config.dik_len);
+ } else {
+ p2p.pairing_config.dik_cipher = DIRA_CIPHER_VERSION_128;
+ p2p.pairing_config.dik_len = DEVICE_IDENTITY_KEY_LEN;
+ if (os_get_random(p2p.pairing_config.dik_data,
+ p2p.pairing_config.dik_len) < 0)
+ return -1;
+
+ wpa_s->conf->dik =
+ wpabuf_alloc_copy(p2p.pairing_config.dik_data,
+ p2p.pairing_config.dik_len);
+ if (!wpa_s->conf->dik)
+ return -1;
+
+ wpa_s->conf->dik_cipher = p2p.pairing_config.dik_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");
+ }
+
global->p2p = p2p_init(&p2p);
if (global->p2p == NULL)
return -1;
@@ -5151,6 +5247,7 @@
wpa_s->p2p_send_action_work = NULL;
}
eloop_cancel_timeout(wpas_p2p_send_action_work_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_p2p_send_bootstrap_comeback, wpa_s, NULL);
wpabuf_free(wpa_s->p2p_oob_dev_pw);
wpa_s->p2p_oob_dev_pw = NULL;
@@ -5233,7 +5330,8 @@
enum p2p_wps_method wps_method,
int go_intent, const u8 *own_interface_addr,
unsigned int force_freq, int persistent_group,
- struct wpa_ssid *ssid, unsigned int pref_freq)
+ struct wpa_ssid *ssid, unsigned int pref_freq,
+ bool p2p2, u16 bootstrap, const char *password)
{
if (persistent_group && wpa_s->conf->persistent_reconnect)
persistent_group = 2;
@@ -5251,7 +5349,7 @@
ssid ? ssid->ssid_len : 0,
wpa_s->p2p_pd_before_go_neg, pref_freq,
wps_method == WPS_NFC ? wpa_s->p2p_oob_dev_pw_id :
- 0);
+ 0, p2p2, bootstrap, password);
}
@@ -5260,7 +5358,8 @@
enum p2p_wps_method wps_method,
int go_intent, const u8 *own_interface_addr,
unsigned int force_freq, int persistent_group,
- struct wpa_ssid *ssid, unsigned int pref_freq)
+ struct wpa_ssid *ssid, unsigned int pref_freq,
+ u16 bootstrap, const char *password)
{
if (persistent_group && wpa_s->conf->persistent_reconnect)
persistent_group = 2;
@@ -5270,7 +5369,7 @@
persistent_group, ssid ? ssid->ssid : NULL,
ssid ? ssid->ssid_len : 0, pref_freq,
wps_method == WPS_NFC ? wpa_s->p2p_oob_dev_pw_id :
- 0);
+ 0, bootstrap, password);
}
@@ -5454,7 +5553,9 @@
wpa_s->p2p_go_he,
wpa_s->p2p_go_edmg,
NULL, 0,
- is_p2p_allow_6ghz(wpa_s->global->p2p));
+ is_p2p_allow_6ghz(wpa_s->global->p2p),
+ wpa_s->p2p2, wpa_s->p2p_bootstrap,
+ NULL);
return;
}
@@ -5970,6 +6071,9 @@
HOSTAPD_MODE_IEEE80211A, true))
return false;
+ if (wpa_s->p2p2)
+ return true;
+
if (!p2p_wfd_enabled(wpa_s->global->p2p))
return false;
if (peer_addr && !p2p_peer_wfd_enabled(wpa_s->global->p2p, peer_addr))
@@ -6021,6 +6125,10 @@
* @group_ssid: Specific Group SSID for join or %NULL if not set
* @group_ssid_len: Length of @group_ssid in octets
* @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
+ * in P2P2
* 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
@@ -6032,7 +6140,8 @@
int persistent_id, int pd, int ht40, int vht,
unsigned int vht_chwidth, int he, int edmg,
const u8 *group_ssid, size_t group_ssid_len,
- bool allow_6ghz)
+ bool allow_6ghz, bool p2p2, u16 bootstrap,
+ const char *password)
{
int force_freq = 0, pref_freq = 0;
int ret = 0, res;
@@ -6052,6 +6161,8 @@
return -1;
}
+ wpa_s->p2p2 = p2p2;
+
if (wpas_p2p_check_6ghz(wpa_s, peer_addr, allow_6ghz, freq))
return -2;
@@ -6082,6 +6193,7 @@
wpa_s->p2p_go_max_oper_chwidth = vht_chwidth;
wpa_s->p2p_go_he = !!he;
wpa_s->p2p_go_edmg = !!edmg;
+ wpa_s->p2p_bootstrap = bootstrap;
if (pin)
os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
@@ -6167,14 +6279,15 @@
if (wpas_p2p_auth_go_neg(wpa_s, peer_addr, wps_method,
go_intent, if_addr,
force_freq, persistent_group, ssid,
- pref_freq) < 0)
+ pref_freq, bootstrap, password) < 0)
return -1;
return ret;
}
if (wpas_p2p_start_go_neg(wpa_s, peer_addr, wps_method,
go_intent, if_addr, force_freq,
- persistent_group, ssid, pref_freq) < 0) {
+ persistent_group, ssid, pref_freq, p2p2,
+ bootstrap, password) < 0) {
if (wpa_s->create_p2p_iface)
wpas_p2p_remove_pending_group_interface(wpa_s);
return -1;
@@ -8828,7 +8941,8 @@
wpa_s->p2p_go_max_oper_chwidth,
wpa_s->p2p_go_he,
wpa_s->p2p_go_edmg,
- NULL, 0, is_p2p_allow_6ghz(wpa_s->global->p2p));
+ NULL, 0, is_p2p_allow_6ghz(wpa_s->global->p2p),
+ wpa_s->p2p2, wpa_s->p2p_bootstrap, NULL);
return ret;
}
@@ -9366,7 +9480,8 @@
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
params->go_ssid_len ? params->go_ssid : NULL,
- params->go_ssid_len, false);
+ params->go_ssid_len, false, wpa_s->p2p2,
+ wpa_s->p2p_bootstrap, NULL);
}
@@ -9445,7 +9560,8 @@
forced_freq, wpa_s->p2p_go_vht_center_freq2,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
- NULL, 0, false);
+ NULL, 0, false, wpa_s->p2p2,
+ wpa_s->p2p_bootstrap, NULL);
}
@@ -9462,7 +9578,8 @@
forced_freq, wpa_s->p2p_go_vht_center_freq2,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
- NULL, 0, false);
+ NULL, 0, false, wpa_s->p2p2,
+ wpa_s->p2p_bootstrap, NULL);
if (res)
return res;
@@ -10330,3 +10447,25 @@
wpa_s->p2p_lo_started = 0;
return ret;
}
+
+
+struct wpabuf * wpas_p2p_usd_elems(struct wpa_supplicant *wpa_s)
+{
+ struct p2p_data *p2p = wpa_s->global->p2p;
+
+ if (wpa_s->global->p2p_disabled || !p2p)
+ return NULL;
+ return p2p_usd_elems(p2p);
+}
+
+
+void wpas_p2p_process_usd_elems(struct wpa_supplicant *wpa_s, const u8 *buf,
+ u16 buf_len, const u8 *peer_addr,
+ unsigned int freq)
+{
+ struct p2p_data *p2p = wpa_s->global->p2p;
+
+ if (wpa_s->global->p2p_disabled || !p2p)
+ return;
+ p2p_process_usd_elems(p2p, buf, buf_len, peer_addr, freq);
+}
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index d71f770..a0fbddc 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -39,7 +39,8 @@
int persistent_id, int pd, int ht40, int vht,
unsigned int vht_chwidth, int he, int edmg,
const u8 *group_ssid, size_t group_ssid_len,
- bool allow_6ghz);
+ bool allow_6ghz, bool p2p2, u16 bootstrap,
+ const char *password);
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,
@@ -178,6 +179,9 @@
void wpas_p2p_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx);
int wpas_p2p_try_edmg_channel(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *params);
+void wpas_p2p_process_usd_elems(struct wpa_supplicant *wpa_s, const u8 *buf,
+ u16 buf_len, const u8 *peer_addr,
+ unsigned int freq);
#ifdef CONFIG_P2P
@@ -225,6 +229,7 @@
unsigned int count);
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);
#else /* CONFIG_P2P */
@@ -351,6 +356,11 @@
return 0;
}
+static inline struct wpabuf * wpas_p2p_usd_elems(struct wpa_supplicant *wpa_s)
+{
+ return NULL;
+}
+
#endif /* CONFIG_P2P */
#endif /* P2P_SUPPLICANT_H */
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 8b59e40..f0ab122 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -940,9 +940,9 @@
}
-static void wpa_add_owe_scan_ssid(struct wpa_supplicant *wpa_s,
- struct wpa_driver_scan_params *params,
- struct wpa_ssid *ssid, size_t max_ssids)
+void wpa_add_owe_scan_ssid(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params,
+ const struct wpa_ssid *ssid, size_t max_ssids)
{
#ifdef CONFIG_OWE
struct wpa_bss *bss;
@@ -954,8 +954,7 @@
wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
- const u8 *owe, *pos, *end;
- const u8 *owe_ssid;
+ const u8 *owe, *owe_bssid, *owe_ssid;
size_t owe_ssid_len;
if (bss->ssid_len != ssid->ssid_len ||
@@ -966,21 +965,9 @@
if (!owe || owe[1] < 4)
continue;
- pos = owe + 6;
- end = owe + 2 + owe[1];
-
- /* Must include BSSID and ssid_len */
- if (end - pos < ETH_ALEN + 1)
- return;
-
- /* Skip BSSID */
- pos += ETH_ALEN;
- owe_ssid_len = *pos++;
- owe_ssid = pos;
-
- if ((size_t) (end - pos) < owe_ssid_len ||
- owe_ssid_len > SSID_MAX_LEN)
- return;
+ if (wpas_get_owe_trans_network(owe, &owe_bssid, &owe_ssid,
+ &owe_ssid_len))
+ continue;
wpa_printf(MSG_DEBUG,
"OWE: scan_ssids: transition mode OWE ssid=%s",
diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h
index d4c06c1..7ea9992 100644
--- a/wpa_supplicant/scan.h
+++ b/wpa_supplicant/scan.h
@@ -104,5 +104,8 @@
enum chan_width cw);
int wpas_adjust_snr_by_chanwidth(const u8 *ies, size_t ies_len,
enum chan_width max_cw, int snr);
+void wpa_add_owe_scan_ssid(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params,
+ const struct wpa_ssid *ssid, size_t max_ssids);
#endif /* SCAN_H */
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 57c9b38..e4be388 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -2471,26 +2471,46 @@
wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
}
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE_SUPPORT,
+ wpas_rsn_overriding(wpa_s));
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
+ RSN_OVERRIDE_NOT_USED);
if (wpas_rsn_overriding(wpa_s) &&
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)) {
u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
- u32 type = 0;
const u8 *ie;
+ enum rsn_selection_variant variant = RSN_SELECTION_RSNE;
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
+ RSN_OVERRIDE_RSNE);
ie = wpa_bss_get_rsne(wpa_s, wpa_s->current_bss, ssid,
wpa_s->valid_links);
- if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4)
- type = WPA_GET_BE32(&ie[2]);
+ if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4) {
+ u32 type;
- if (type) {
- /* Indicate support for RSN overriding */
- *pos++ = WLAN_EID_VENDOR_SPECIFIC;
- *pos++ = 4;
- WPA_PUT_BE32(pos, type);
- wpa_s->sme.assoc_req_ie_len += 2 + 4;
+ type = WPA_GET_BE32(&ie[2]);
+ if (type == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
+ variant = RSN_SELECTION_RSNE_OVERRIDE;
+ wpa_sm_set_param(wpa_s->wpa,
+ WPA_PARAM_RSN_OVERRIDE,
+ RSN_OVERRIDE_RSNE_OVERRIDE);
+ } else if (type == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
+ variant = RSN_SELECTION_RSNE_OVERRIDE_2;
+ wpa_sm_set_param(wpa_s->wpa,
+ WPA_PARAM_RSN_OVERRIDE,
+ RSN_OVERRIDE_RSNE_OVERRIDE_2);
+ }
}
+
+ /* Indicate which RSNE variant was used */
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+ *pos++ = 4 + 1;
+ WPA_PUT_BE32(pos, RSN_SELECTION_IE_VENDOR_TYPE);
+ pos += 4;
+ *pos = variant;
+ wpa_s->sme.assoc_req_ie_len += 2 + 4 + 1;
}
params.bssid = bssid;
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index ea79ae6..3bb621d 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -27,7 +27,6 @@
#define MAX_TFS_IE_LEN 1024
#define WNM_MAX_NEIGHBOR_REPORT 10
-#define WNM_SCAN_RESULT_AGE 2 /* 2 seconds */
/* get the TFS IE from driver */
static int ieee80211_11_get_tfs_ie(struct wpa_supplicant *wpa_s, u8 *buf,
@@ -556,7 +555,7 @@
}
freq = ieee80211_chan_to_freq(country, op_class, chan);
- if (freq <= 0 && op_class == 0) {
+ if (freq <= 0 && (op_class == 0 || op_class == 255)) {
/*
* Some APs do not advertise correct operating class
* information. Try to determine the most likely operating
@@ -740,7 +739,7 @@
}
static struct wpa_bss *
-compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs,
+compare_scan_neighbor_results(struct wpa_supplicant *wpa_s,
enum mbo_transition_reject_reason *reason)
{
u8 i;
@@ -761,11 +760,6 @@
struct neighbor_report *nei;
nei = &wpa_s->wnm_neighbor_report_elements[i];
- if (nei->preference_present && nei->preference == 0) {
- wpa_printf(MSG_DEBUG, "Skip excluded BSS " MACSTR,
- MAC2STR(nei->bssid));
- continue;
- }
target = wpa_bss_get_bssid(wpa_s, nei->bssid);
if (!target) {
@@ -777,19 +771,6 @@
continue;
}
- if (age_secs) {
- struct os_reltime now;
-
- if (os_get_reltime(&now) == 0 &&
- os_reltime_expired(&now, &target->last_update,
- age_secs)) {
- wpa_printf(MSG_DEBUG,
- "Candidate BSS is more than %ld seconds old",
- age_secs);
- continue;
- }
- }
-
/*
* TODO: Could consider allowing transition to another ESS if
* PMF was enabled for the association.
@@ -1192,8 +1173,13 @@
goto send_bss_resp_fail;
}
+ if (!pre_scan_check && !wpa_s->wnm_transition_scan)
+ return 0;
+
+ wpa_s->wnm_transition_scan = false;
+
/* Compare the Neighbor Report and scan results */
- bss = compare_scan_neighbor_results(wpa_s, 0, &reason);
+ bss = compare_scan_neighbor_results(wpa_s, &reason);
/*
* If this is a pre-scan check, returning 0 will trigger a scan and
@@ -1235,11 +1221,19 @@
return 1;
send_bss_resp_fail:
- /* Send reject response for all the failures */
+ if (wpa_s->wnm_reply) {
+ /* If disassoc imminent is set, we must not reject */
+ if (wpa_s->wnm_mode &
+ (WNM_BSS_TM_REQ_DISASSOC_IMMINENT |
+ WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT)) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Accept BTM request because disassociation imminent bit is set");
+ status = WNM_BSS_TM_ACCEPT;
+ }
- if (wpa_s->wnm_reply)
wnm_send_bss_transition_mgmt_resp(wpa_s, status, reason,
0, NULL);
+ }
wnm_btm_reset(wpa_s);
@@ -1376,6 +1370,63 @@
}
+static int wnm_parse_candidate_list(struct wpa_supplicant *wpa_s,
+ const u8 *pos, const u8 *end,
+ int *num_valid_candidates)
+{
+ *num_valid_candidates = 0;
+
+ while (end - pos >= 2 &&
+ wpa_s->wnm_num_neighbor_report < WNM_MAX_NEIGHBOR_REPORT) {
+ u8 tag = *pos++;
+ u8 len = *pos++;
+
+ wpa_printf(MSG_DEBUG, "WNM: Neighbor report tag %u", tag);
+ if (len > end - pos) {
+ wpa_printf(MSG_DEBUG, "WNM: Truncated request");
+ return -1;
+ }
+ if (tag == WLAN_EID_NEIGHBOR_REPORT) {
+ struct neighbor_report *rep;
+
+ if (!wpa_s->wnm_num_neighbor_report) {
+ wpa_s->wnm_neighbor_report_elements = os_calloc(
+ WNM_MAX_NEIGHBOR_REPORT,
+ sizeof(struct neighbor_report));
+ if (!wpa_s->wnm_neighbor_report_elements)
+ return -1;
+ }
+
+ rep = &wpa_s->wnm_neighbor_report_elements[
+ wpa_s->wnm_num_neighbor_report];
+ wnm_parse_neighbor_report(wpa_s, pos, len, rep);
+ if ((wpa_s->wnm_mode &
+ WNM_BSS_TM_REQ_DISASSOC_IMMINENT) &&
+ ether_addr_equal(rep->bssid, wpa_s->bssid))
+ rep->disassoc_imminent = 1;
+
+ if (rep->preference_present && rep->preference)
+ *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;
+ }
+
+ return 0;
+}
+
+
static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
const u8 *pos, const u8 *end,
int reply)
@@ -1386,6 +1437,7 @@
const u8 *vendor;
#endif /* CONFIG_MBO */
bool disassoc_imminent;
+ int num_valid_candidates;
if (wpa_s->disable_mbo_oce || wpa_s->conf->disable_btm)
return;
@@ -1409,7 +1461,7 @@
wpa_s->wnm_dialog_token = pos[0];
wpa_s->wnm_mode = pos[1];
- wpa_s->wnm_dissoc_timer = WPA_GET_LE16(pos + 2);
+ wpa_s->wnm_disassoc_timer = WPA_GET_LE16(pos + 2);
wpa_s->wnm_link_removal = false;
valid_int = pos[4];
wpa_s->wnm_reply = reply;
@@ -1418,7 +1470,12 @@
"dialog_token=%u request_mode=0x%x "
"disassoc_timer=%u validity_interval=%u",
wpa_s->wnm_dialog_token, wpa_s->wnm_mode,
- wpa_s->wnm_dissoc_timer, valid_int);
+ wpa_s->wnm_disassoc_timer, valid_int);
+
+ if (!wpa_s->wnm_dialog_token) {
+ wpa_printf(MSG_DEBUG, "WNM: Invalid dialog token");
+ goto reset;
+ }
#if defined(CONFIG_MBO) && defined(CONFIG_TESTING_OPTIONS)
if (wpa_s->reject_btm_req_reason) {
@@ -1428,7 +1485,7 @@
wnm_send_bss_transition_mgmt_resp(
wpa_s, wpa_s->reject_btm_req_reason,
MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0, NULL);
- return;
+ goto reset;
}
#endif /* CONFIG_MBO && CONFIG_TESTING_OPTIONS */
@@ -1437,7 +1494,7 @@
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
if (end - pos < 12) {
wpa_printf(MSG_DEBUG, "WNM: Too short BSS TM Request");
- return;
+ goto reset;
}
os_memcpy(wpa_s->wnm_bss_termination_duration, pos, 12);
pos += 12; /* BSS Termination Duration */
@@ -1450,13 +1507,13 @@
if (end - pos < 1) {
wpa_printf(MSG_DEBUG, "WNM: Invalid BSS Transition "
"Management Request (URL)");
- return;
+ goto reset;
}
url_len = *pos++;
if (url_len > end - pos) {
wpa_printf(MSG_DEBUG,
"WNM: Invalid BSS Transition Management Request (URL truncated)");
- return;
+ goto reset;
}
os_memcpy(url, pos, url_len);
url[url_len] = '\0';
@@ -1464,7 +1521,8 @@
wpa_msg(wpa_s, MSG_INFO, ESS_DISASSOC_IMMINENT "%d %u %s",
wpa_sm_pmf_enabled(wpa_s->wpa),
- wpa_s->wnm_dissoc_timer * beacon_int * 128 / 125, url);
+ wpa_s->wnm_disassoc_timer * beacon_int * 128 / 125,
+ url);
}
#ifdef CONFIG_MBO
@@ -1505,77 +1563,34 @@
wnm_send_bss_transition_mgmt_resp(
wpa_s, WNM_BSS_TM_ACCEPT, 0, 0, NULL);
- return;
+ goto reset;
}
/* The last link is being removed (which must be the assoc link)
*/
wpa_s->wnm_link_removal = true;
- os_memcpy(wpa_s->wnm_dissoc_addr,
+ wpa_s->wnm_disassoc_mld = false;
+ os_memcpy(wpa_s->wnm_disassoc_addr,
wpa_s->links[wpa_s->mlo_assoc_link_id].bssid,
ETH_ALEN);
+ } else if (wpa_s->valid_links) {
+ wpa_s->wnm_disassoc_mld = true;
+ os_memcpy(wpa_s->wnm_disassoc_addr, wpa_s->ap_mld_addr,
+ ETH_ALEN);
} else {
- os_memcpy(wpa_s->wnm_dissoc_addr, wpa_s->valid_links ?
- wpa_s->ap_mld_addr : wpa_s->bssid, ETH_ALEN);
+ wpa_s->wnm_disassoc_mld = false;
+ os_memcpy(wpa_s->wnm_disassoc_addr, wpa_s->bssid, ETH_ALEN);
}
- if (disassoc_imminent) {
+ if (disassoc_imminent)
wpa_msg(wpa_s, MSG_INFO, "WNM: Disassociation Imminent - "
- "Disassociation Timer %u", wpa_s->wnm_dissoc_timer);
- if (wpa_s->wnm_dissoc_timer && !wpa_s->scanning &&
- (!wpa_s->current_ssid || !wpa_s->current_ssid->bssid_set)) {
- wpa_printf(MSG_DEBUG, "Trying to find another BSS");
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- }
- }
+ "Disassociation Timer %u", wpa_s->wnm_disassoc_timer);
+
+ if (wnm_parse_candidate_list(wpa_s, pos, end,
+ &num_valid_candidates) < 0)
+ goto reset;
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED) {
- unsigned int valid_ms;
-
- wpa_msg(wpa_s, MSG_INFO, "WNM: Preferred List Available");
- wpa_s->wnm_neighbor_report_elements = os_calloc(
- WNM_MAX_NEIGHBOR_REPORT,
- sizeof(struct neighbor_report));
- if (wpa_s->wnm_neighbor_report_elements == NULL)
- return;
-
- while (end - pos >= 2 &&
- wpa_s->wnm_num_neighbor_report < WNM_MAX_NEIGHBOR_REPORT)
- {
- u8 tag = *pos++;
- u8 len = *pos++;
-
- wpa_printf(MSG_DEBUG, "WNM: Neighbor report tag %u",
- tag);
- if (len > end - pos) {
- wpa_printf(MSG_DEBUG, "WNM: Truncated request");
- return;
- }
- if (tag == WLAN_EID_NEIGHBOR_REPORT) {
- struct neighbor_report *rep;
- rep = &wpa_s->wnm_neighbor_report_elements[
- wpa_s->wnm_num_neighbor_report];
- wnm_parse_neighbor_report(wpa_s, pos, len, rep);
- if ((wpa_s->wnm_mode &
- WNM_BSS_TM_REQ_DISASSOC_IMMINENT) &&
- ether_addr_equal(rep->bssid, wpa_s->bssid))
- rep->disassoc_imminent = 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;
- }
-
if (!wpa_s->wnm_num_neighbor_report) {
wpa_printf(MSG_DEBUG,
"WNM: Candidate list included bit is set, but no candidates found");
@@ -1583,18 +1598,13 @@
wpa_s, WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES,
MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0,
NULL);
- return;
+ goto reset;
}
+ wpa_msg(wpa_s, MSG_INFO, "WNM: Preferred List Available");
+ }
- if (wpa_s->current_ssid && wpa_s->current_ssid->bssid_set) {
- wpa_printf(MSG_DEBUG,
- "WNM: Configuration prevents roaming (BSSID set)");
- wnm_send_bss_transition_mgmt_resp(
- wpa_s, WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES,
- MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0,
- NULL);
- return;
- }
+ if (wpa_s->wnm_num_neighbor_report) {
+ unsigned int valid_ms;
wnm_sort_cand_list(wpa_s);
wnm_dump_cand_list(wpa_s);
@@ -1602,40 +1612,12 @@
wpa_printf(MSG_DEBUG, "WNM: Candidate list valid for %u ms",
valid_ms);
os_get_reltime(&wpa_s->wnm_cand_valid_until);
- wpa_s->wnm_cand_valid_until.sec += valid_ms / 1000;
- wpa_s->wnm_cand_valid_until.usec += (valid_ms % 1000) * 1000;
- wpa_s->wnm_cand_valid_until.sec +=
- wpa_s->wnm_cand_valid_until.usec / 1000000;
- wpa_s->wnm_cand_valid_until.usec %= 1000000;
-
- /*
- * Try fetching the latest scan results from the kernel.
- * This can help in finding more up-to-date information should
- * the driver have done some internal scanning operations after
- * the last scan result update in wpa_supplicant.
- *
- * It is not a new scan, this does not update the last_scan
- * timestamp nor will it expire old BSSs.
- */
- wpa_supplicant_update_scan_results(wpa_s, NULL);
- if (wnm_scan_process(wpa_s, true) > 0)
- return;
- wpa_printf(MSG_DEBUG,
- "WNM: No valid match in previous scan results - try a new scan");
-
- wnm_set_scan_freqs(wpa_s);
- if (wpa_s->wnm_num_neighbor_report == 1) {
- os_memcpy(wpa_s->next_scan_bssid,
- wpa_s->wnm_neighbor_report_elements[0].bssid,
- ETH_ALEN);
- wpa_printf(MSG_DEBUG,
- "WNM: Scan only for a specific BSSID since there is only a single candidate "
- MACSTR, MAC2STR(wpa_s->next_scan_bssid));
- }
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- } else if (reply) {
+ os_reltime_add_ms(&wpa_s->wnm_cand_valid_until, valid_ms);
+ } else if (!disassoc_imminent) {
enum bss_trans_mgmt_status_code status;
+ /* No candidate list and disassociation is not imminent */
+
if ((wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT) ||
wpa_s->wnm_link_removal)
status = WNM_BSS_TM_ACCEPT;
@@ -1643,10 +1625,66 @@
wpa_msg(wpa_s, MSG_INFO, "WNM: BSS Transition Management Request did not include candidates");
status = WNM_BSS_TM_REJECT_UNSPECIFIED;
}
- wnm_send_bss_transition_mgmt_resp(
- wpa_s, status,
- MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0, NULL);
+
+ if (reply)
+ wnm_send_bss_transition_mgmt_resp(
+ wpa_s, status,
+ MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0,
+ NULL);
+
+ goto reset;
}
+
+ /*
+ * Try fetching the latest scan results from the kernel.
+ * This can help in finding more up-to-date information should
+ * the driver have done some internal scanning operations after
+ * the last scan result update in wpa_supplicant.
+ *
+ * It is not a new scan, this does not update the last_scan
+ * timestamp nor will it expire old BSSs.
+ */
+ wpa_supplicant_update_scan_results(wpa_s, NULL);
+ if (wnm_scan_process(wpa_s, true) > 0)
+ return;
+ wpa_printf(MSG_DEBUG,
+ "WNM: No valid match in previous scan results - try a new scan");
+
+ /*
+ * If we have a fixed BSSID configured, just reject at this point.
+ * NOTE: We could actually check if we are allowed to stay (and we do
+ * above if we have scan results available).
+ */
+ if (wpa_s->current_ssid && wpa_s->current_ssid->bssid_set) {
+ wpa_printf(MSG_DEBUG, "WNM: Fixed BSSID, rejecting request");
+
+ if (reply)
+ wnm_send_bss_transition_mgmt_resp(
+ wpa_s, WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES,
+ MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0,
+ NULL);
+
+ goto reset;
+ }
+
+ wnm_set_scan_freqs(wpa_s);
+ if (num_valid_candidates == 1) {
+ /* Any invalid candidate was sorted to the end */
+ os_memcpy(wpa_s->next_scan_bssid,
+ wpa_s->wnm_neighbor_report_elements[0].bssid,
+ ETH_ALEN);
+ wpa_printf(MSG_DEBUG,
+ "WNM: Scan only for a specific BSSID since there is only a single candidate "
+ MACSTR, MAC2STR(wpa_s->next_scan_bssid));
+ }
+ wpa_s->wnm_transition_scan = true;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+
+ /* Continue from scan handler */
+ return;
+
+reset:
+ wnm_btm_reset(wpa_s);
}
@@ -2067,22 +2105,41 @@
bool wnm_is_bss_excluded(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
{
- if (!(wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))
- return false;
+ int i;
/*
* In case disassociation imminent is set, do no try to use a BSS to
* which we are connected.
*/
- if (wpa_s->wnm_link_removal ||
- !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) ||
- is_zero_ether_addr(bss->mld_addr)) {
- if (ether_addr_equal(bss->bssid, wpa_s->wnm_dissoc_addr))
- return true;
- } else {
- if (ether_addr_equal(bss->mld_addr, wpa_s->wnm_dissoc_addr))
- return true;
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
+ if (!wpa_s->wnm_disassoc_mld) {
+ if (ether_addr_equal(bss->bssid,
+ wpa_s->wnm_disassoc_addr))
+ return true;
+ } else {
+ if (ether_addr_equal(bss->mld_addr,
+ wpa_s->wnm_disassoc_addr))
+ return true;
+ }
}
+ for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
+ struct neighbor_report *nei;
+
+ nei = &wpa_s->wnm_neighbor_report_elements[i];
+ if (!ether_addr_equal(nei->bssid, bss->bssid))
+ continue;
+
+ if (nei->preference_present && nei->preference == 0)
+ return true;
+
+ break;
+ }
+
+ /* If the abridged bit is set, the BSS must be a known neighbor. */
+ if ((wpa_s->wnm_mode & WNM_BSS_TM_REQ_ABRIDGED) &&
+ wpa_s->wnm_num_neighbor_report == i)
+ return true;
+
return false;
}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 15a859f..6df886f 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -418,6 +418,9 @@
wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_ap_rsne_override(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, NULL, 0);
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
wpa_s->rsnxe_len = 0;
@@ -1838,12 +1841,31 @@
!!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
if (bss || !wpa_s->ap_ies_from_associnfo) {
+ const u8 *rsnoe = NULL, *rsno2e = NULL, *rsnxoe = NULL;
+
+ if (bss) {
+ bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+ bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
+ rsnoe = wpa_bss_get_vendor_ie(
+ bss, RSNE_OVERRIDE_IE_VENDOR_TYPE);
+ rsno2e = wpa_bss_get_vendor_ie(
+ bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
+ rsnxoe = wpa_bss_get_vendor_ie(
+ bss, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
+ }
+
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
bss_wpa ? 2 + bss_wpa[1] : 0) ||
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
bss_rsn ? 2 + bss_rsn[1] : 0) ||
wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
- bss_rsnx ? 2 + bss_rsnx[1] : 0))
+ bss_rsnx ? 2 + bss_rsnx[1] : 0) ||
+ wpa_sm_set_ap_rsne_override(wpa_s->wpa, rsnoe,
+ rsnoe ? 2 + rsnoe[1] : 0) ||
+ wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, rsno2e,
+ rsno2e ? 2 + rsno2e[1] : 0) ||
+ wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, rsnxoe,
+ rsnxoe ? 2 + rsnxoe[1] : 0))
return -1;
}
@@ -3968,57 +3990,48 @@
wpa_ie_len += multi_ap_ie_len;
}
- if (!wpas_driver_bss_selection(wpa_s) &&
- wpas_rsn_overriding(wpa_s) &&
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE_SUPPORT,
+ wpas_rsn_overriding(wpa_s));
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
+ RSN_OVERRIDE_NOT_USED);
+ if (wpas_rsn_overriding(wpa_s) &&
wpas_ap_supports_rsn_overriding(wpa_s, bss) &&
- wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
- u8 *pos = wpa_ie + wpa_ie_len;
- u32 type = 0;
+ wpa_ie_len + 2 + 4 + 1 <= max_wpa_ie_len) {
+ u8 *pos = wpa_ie + wpa_ie_len, *start = pos;
const u8 *ie;
+ enum rsn_selection_variant variant = RSN_SELECTION_RSNE;
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
+ RSN_OVERRIDE_RSNE);
ie = wpa_bss_get_rsne(wpa_s, bss, ssid, wpa_s->valid_links);
- if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4)
+ if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4) {
+ u32 type;
+
type = WPA_GET_BE32(&ie[2]);
-
- if (type) {
- /* Indicate support for RSN overriding */
- *pos++ = WLAN_EID_VENDOR_SPECIFIC;
- *pos++ = 4;
- WPA_PUT_BE32(pos, type);
- pos += 4;
- wpa_hexdump(MSG_MSGDUMP, "RSNE Override", wpa_ie,
- pos - wpa_ie);
- wpa_ie_len += 2 + 4;
+ if (type == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
+ variant = RSN_SELECTION_RSNE_OVERRIDE;
+ wpa_sm_set_param(wpa_s->wpa,
+ WPA_PARAM_RSN_OVERRIDE,
+ RSN_OVERRIDE_RSNE_OVERRIDE);
+ } else if (type == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
+ variant = RSN_SELECTION_RSNE_OVERRIDE_2;
+ wpa_sm_set_param(wpa_s->wpa,
+ WPA_PARAM_RSN_OVERRIDE,
+ RSN_OVERRIDE_RSNE_OVERRIDE_2);
+ }
}
+
+ /* Indicate which RSNE variant was used */
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+ *pos++ = 4 + 1;
+ WPA_PUT_BE32(pos, RSN_SELECTION_IE_VENDOR_TYPE);
+ pos += 4;
+ *pos++ = variant;
+ wpa_hexdump(MSG_MSGDUMP, "RSN Selection", start, pos - start);
+ wpa_ie_len += pos - start;
}
- if (wpas_driver_bss_selection(wpa_s) &&
- wpas_rsn_overriding(wpa_s)) {
- if (wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
- u8 *pos = wpa_ie + wpa_ie_len;
-
- *pos++ = WLAN_EID_VENDOR_SPECIFIC;
- *pos++ = 4;
- WPA_PUT_BE32(pos, RSNE_OVERRIDE_IE_VENDOR_TYPE);
- pos += 4;
- wpa_hexdump(MSG_MSGDUMP, "RSNE Override", wpa_ie,
- pos - wpa_ie);
- wpa_ie_len += 2 + 4;
- }
-
- if (wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
- u8 *pos = wpa_ie + wpa_ie_len;
-
- *pos++ = WLAN_EID_VENDOR_SPECIFIC;
- *pos++ = 4;
- WPA_PUT_BE32(pos, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
- pos += 4;
- wpa_hexdump(MSG_MSGDUMP, "RSNE Override 2",
- wpa_ie, pos - wpa_ie);
- wpa_ie_len += 2 + 4;
- }
- }
-
+ params->rsn_overriding = wpas_rsn_overriding(wpa_s);
params->wpa_ie = wpa_ie;
params->wpa_ie_len = wpa_ie_len;
params->auth_alg = algs;
@@ -5511,8 +5524,8 @@
static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
const u8 *entry_ssid, size_t entry_ssid_len)
{
- const u8 *owe, *pos, *end;
- u8 ssid_len;
+ const u8 *owe, *owe_bssid, *owe_ssid;
+ size_t owe_ssid_len;
struct wpa_bss *bss;
/* Check network profile SSID aganst the SSID in the
@@ -5526,18 +5539,12 @@
if (!owe)
return 0;
- pos = owe + 6;
- end = owe + 2 + owe[1];
-
- if (end - pos < ETH_ALEN + 1)
- return 0;
- pos += ETH_ALEN;
- ssid_len = *pos++;
- if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
+ if (wpas_get_owe_trans_network(owe, &owe_bssid, &owe_ssid,
+ &owe_ssid_len))
return 0;
- return entry_ssid_len == ssid_len &&
- os_memcmp(pos, entry_ssid, ssid_len) == 0;
+ return entry_ssid_len == owe_ssid_len &&
+ os_memcmp(owe_ssid, entry_ssid, owe_ssid_len) == 0;
}
#endif /* CONFIG_OWE */
@@ -9787,3 +9794,34 @@
return false;
}
+
+
+int wpas_get_owe_trans_network(const u8 *owe_ie, const u8 **bssid,
+ const u8 **ssid, size_t *ssid_len)
+{
+#ifdef CONFIG_OWE
+ const u8 *pos, *end;
+ u8 ssid_len_tmp;
+
+ if (!owe_ie)
+ return -1;
+
+ pos = owe_ie + 6;
+ end = owe_ie + 2 + owe_ie[1];
+
+ if (end - pos < ETH_ALEN + 1)
+ return -1;
+ *bssid = pos;
+ pos += ETH_ALEN;
+ ssid_len_tmp = *pos++;
+ if (end - pos < ssid_len_tmp || ssid_len_tmp > SSID_MAX_LEN)
+ return -1;
+
+ *ssid = pos;
+ *ssid_len = ssid_len_tmp;
+
+ return 0;
+#else /* CONFIG_OWE */
+ return -1;
+#endif /* CONFIG_OWE */
+}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 245ac93..84b7bd5 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1135,6 +1135,7 @@
int pending_pd_before_join;
u8 pending_join_iface_addr[ETH_ALEN];
u8 pending_join_dev_addr[ETH_ALEN];
+ u8 p2p_bootstrap_dev_addr[ETH_ALEN];
int pending_join_wps_method;
u8 p2p_join_ssid[SSID_MAX_LEN];
size_t p2p_join_ssid_len;
@@ -1189,6 +1190,8 @@
unsigned int p2ps_method_config_any:1;
unsigned int p2p_cli_probe:1;
unsigned int p2p_go_allow_dfs:1;
+ unsigned int p2p2:1;
+ u16 p2p_bootstrap;
enum hostapd_hw_mode p2p_go_acs_band;
int p2p_persistent_go_freq;
int p2p_persistent_id;
@@ -1324,13 +1327,15 @@
u8 *mac_addr_pno;
#ifdef CONFIG_WNM
+ bool wnm_transition_scan;
u8 wnm_dialog_token;
u8 wnm_reply;
u8 wnm_num_neighbor_report;
u8 wnm_mode;
bool wnm_link_removal;
- u8 wnm_dissoc_addr[ETH_ALEN];
- u16 wnm_dissoc_timer;
+ bool wnm_disassoc_mld;
+ u8 wnm_disassoc_addr[ETH_ALEN];
+ u16 wnm_disassoc_timer;
u8 wnm_bss_termination_duration[12];
struct neighbor_report *wnm_neighbor_report_elements;
struct os_reltime wnm_cand_valid_until;
@@ -1607,6 +1612,7 @@
bool wps_scan_done; /* Set upon receiving scan results event */
bool supp_pbc_active; /* Set for interface when PBC is triggered */
bool wps_overlap;
+ bool scan_in_progress_6ghz; /* Set upon a 6 GHz scan being triggered */
#ifdef CONFIG_PASN
struct pasn_data pasn;
@@ -2057,5 +2063,7 @@
struct wpa_bss *bss);
bool wpas_ap_supports_rsn_overriding_2(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss);
+int wpas_get_owe_trans_network(const u8 *owe_ie, const u8 **bssid,
+ const u8 **ssid, size_t *ssid_len);
#endif /* WPA_SUPPLICANT_I_H */
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index de216d2..741ac6c 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -148,6 +148,7 @@
{
struct wpa_supplicant *wpa_s = ctx;
u8 *msg, *dst, bssid[ETH_ALEN];
+ struct driver_sta_mlo_info drv_mlo;
size_t msglen;
int res;
@@ -197,11 +198,16 @@
if (is_zero_ether_addr(wpa_s->bssid)) {
wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an "
"EAPOL frame");
+ os_memset(&drv_mlo, 0, sizeof(drv_mlo));
if (wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
+ (!wpa_s->valid_links ||
+ wpas_drv_get_sta_mlo_info(wpa_s, &drv_mlo) == 0) &&
!is_zero_ether_addr(bssid)) {
- dst = bssid;
- wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR
+ dst = drv_mlo.valid_links ? drv_mlo.ap_mld_addr : bssid;
+ wpa_printf(MSG_DEBUG, "Using current %s " MACSTR
" from the driver as the EAPOL destination",
+ drv_mlo.valid_links ? "AP MLD MAC address" :
+ "BSSID",
MAC2STR(dst));
} else {
dst = wpa_s->last_eapol_src;
@@ -211,9 +217,10 @@
MAC2STR(dst));
}
} else {
- /* BSSID was already set (from (Re)Assoc event, so use it as
- * the EAPOL destination. */
- dst = wpa_s->bssid;
+ /* BSSID was already set (from (Re)Assoc event, so use BSSID or
+ * AP MLD MAC address (in the case of MLO connection) as the
+ * EAPOL destination. */
+ dst = wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid;
}
msg = wpa_alloc_eapol(wpa_s, type, buf, len, &msglen, NULL);
@@ -441,13 +448,29 @@
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
ret = -1;
- ie = wpa_bss_get_rsne(wpa_s, curr, ssid, false);
+ ie = wpa_bss_get_ie(curr, WLAN_EID_RSN);
if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
ret = -1;
- ie = wpa_bss_get_rsnxe(wpa_s, curr, ssid, false);
+ ie = wpa_bss_get_ie(curr, WLAN_EID_RSNX);
if (wpa_sm_set_ap_rsnxe(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
ret = -1;
+
+ ie = wpa_bss_get_vendor_ie(curr, RSNE_OVERRIDE_IE_VENDOR_TYPE);
+ if (wpa_sm_set_ap_rsne_override(wpa_s->wpa, ie,
+ ie ? 2 + ie[1] : 0))
+ ret = -1;
+
+ ie = wpa_bss_get_vendor_ie(curr,
+ RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
+ if (wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, ie,
+ ie ? 2 + ie[1] : 0))
+ ret = -1;
+
+ ie = wpa_bss_get_vendor_ie(curr, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
+ if (wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, ie,
+ ie ? 2 + ie[1] : 0))
+ ret = -1;
} else {
ret = -1;
}