Compare commits

...

534 commits

Author SHA1 Message Date
Michael-CY Lee
bde17063d5 hostapd: Do not indicate a punctured secondary channel in HT operation
If the secondary channel is punctured, the HT operation in the Beacon
frames should not indicate a secondary channel offset.

Co-developed-by: Money Wang <money.wang@mediatek.com>
Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
2024-09-01 16:39:57 +03:00
Sergey Matyukevich
809d9d8172 macsec_linux: Hardware offload requires Linux headers >= v5.7
Hardware offload in Linux macsec driver is enabled in compile time if
libnl version is >= v3.6. This is not sufficient for successful build
since enum 'macsec_offload' has been added to Linux header if_link.h
in kernels v5.6 and v5.7, see commits:
- 21114b7fee
- 76564261a7

New libnl with older Linux headers is a valid combination. This is how
hostapd build failure has been detected by Buildroot autobuilder, see:
- http://autobuild.buildroot.net/results/b59d5bc5bd17683a3a1e3577c40c802e81911f84/

Extend compile time condition for the enablement of the macsec hardware
offload adding Linux headers version check.

Fixes: 40c1396644 ("macsec_linux: Add support for MACsec hardware offload")
Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com>
2024-09-01 16:36:11 +03:00
Jouni Malinen
3ab781fb29 tests: DPP and SAE password identifier
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-09-01 16:33:26 +03:00
Jouni Malinen
0012c4433c DPP: Support for provisioning SAE password identifiers (Configurator)
Allow SAE password identifiers to be provisioned to Enrollees that
indicate support for this capability.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-09-01 16:32:39 +03:00
Dan Harkins
782c89c359 DPP: Support for provisioning SAE password identifiers (Enrollee)
DPP supports provisioning of SAE password identifiers to uniquely
identify a password if the enrollee indicates support for them. Indicate
Enrollee support for that and add the received value into the network
profile.

I put everything under defines for CONFIG_DPP3 as this is a bleeding
edge feature in DPP.

This was tested against my DPP reference implementation acting as the
Configurator.

Signed-off-by: Dan Harkins <dharkins@lounge.org>
2024-09-01 16:06:18 +03:00
Cermak Dominik
de40e08f70 nl80211: Pass "global" events to all interfaces
We got connection failures because of outdated channel information.
That's because the NL80211_CMD_REG_CHANGE event is important for all
interfaces.

Commit f136837202 ("nl80211: Pass wiphy events to all affected
interfaces") skips the early termination for events directed to a wiphy,
but that doesn't cover the regulatory change event because it doesn't
have a wiphy set either. Therefore the early termination still kicks in
and from three interfaces, only one got the updated channel list.

Fix this by changing the early termination logic to only apply to events
directed either to a specific interface index for wdev.

Signed-off-by: Dominik Cermak <dominik.cermak@joynext.com>
2024-09-01 15:39:36 +03:00
Jouni Malinen
c3ee46bcbe AP MLD: Check SAE message length without depending on pointer arithemetic
The way this was checked previously used pointer arithmetic could result
in undefined behavior due to the pointer ending up pointing more than
one byte beyond the end of the buffer. Avoid this by checking the buffer
length before incrementing the pointer.

Fixes: bcbe80a66a ("AP: MLO: Handle Multi-Link element during authentication")
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-09-01 13:24:29 +03:00
Jouni Malinen
63df62c6c0 AP MLD: Work around delayed STA entry addition for SAE confirm
The driver is expected to have an STA entry for a non-AP MLD ready to
translate the address fields for SAE confirm messages. However, there is
at least a theoretical race condition in a case where the peer sends the
SAE confirm message quickly enough for the driver translation mechanism
to not be available to update the SAE confirm message addresses. Work
around that by searching for the STA entry using the link address of the
non-AP MLD if no match is found based on the MLD MAC address.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-09-01 13:14:12 +03:00
Aditya Kumar Singh
f3fd2f699f tests: AP MLD control socket connectivity test case
Add a simple test case to bring up a two link AP MLD and get the status
of each link via the MLD level control socket.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-09-01 12:09:46 +03:00
Aditya Kumar Singh
14cb3906af AP MLD: Introduce MLD level control interface socket
With MLO, each link have socket created with "<ifname>_link<link id>"
under the control interface directory.

Introduce a MLD level socket "<ifname>" as well under the same control
interface directory. This socket can be used to pass the command to its
partner links directly instead of using the link level socket. Link ID
needs to be passed with the command in a prefix way. If no Link ID is
provided the first link ID is selected.

The structure of the command is -
 "LINKID <link id> <COMMAND APPLICABALE FOR THE LINK>"

Directory looks something like this -
  $ ls /var/run/hostapd/
    wlan0
    wlan0_link0
    wlan0_link1

wlan0 here is the MLD level socket. Rest are each link level sockets.

This also helps to maintain backwards compatibility with applications
which looks for <ifname> under the control interface directory.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-09-01 11:49:00 +03:00
Aditya Kumar Singh
757d8d9aac tests: MLO: Use link ID to access control sockets
With MLO, each BSS will create sockets under the given ctrl_iface
directory with the socket name being '<ifname>_link<link_ID>'.

Make necessary changes in MLO related test cases so that it can access
the new socket and proceed further as expected.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-09-01 11:17:11 +03:00
Karthikeyan Kathirvel
61dfd7ae35 AP MLD: Create link based hostapd control sockets
Create link based control sockets to access the link based commands
through hostapd_cli. This will create the link interfaces in the name of
<ifname>_link<X>

Example:
To fetch link 0 status from wlan0, below command can be used -
    $ hostapd_cli -i wlan0 -l 0 status

On failure of link/interface selection, below error will be observed
    $ hostapd_cli -i wlan0 -l 2 status
    Failed to connect to hostapd - wpa_ctrl_open: No such file or directory

Signed-off-by: Karthikeyan Kathirvel <quic_kathirve@quicinc.com>
Co-developed-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-09-01 11:17:03 +03:00
Jouni Malinen
8625001ce5 tests: Clear scan cache in wifi_display_parsing
This is needed to avoid false failures if an old BSS entry is still
present for dev[0]. This could happen, e.g., with the following test
case sequence: wpas_mesh_max_peering wifi_display_parsing

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-29 20:21:31 +03:00
Shivani Baranwal
b7963348cd Add QCA vendor attribute to disable channel switch initiation
Add a test config u8 attribute to disable the channel switch
initiation in P2P GO mode.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2024-08-29 20:11:06 +03:00
Jouni Malinen
d15403aefb tests: Make rsn_override_mld_too_long_elems more robust
Wait longer for the disconnection event since the previous wait was
exactly the same length as the authentication timeout in wpa_supplicant
and as such, subject to race conditions.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-29 20:10:22 +03:00
Jouni Malinen
3935d78e7b tests: More robust error handling for wifi_display_parsing
Check explicitly that wfd_subelems is present in the dict instead of
failing on a key error when trying to fetch it.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-29 20:10:22 +03:00
Lo,Chin-Ran
2b7277d3f0 USD: Move control interface events to notify.c
This separates the control interface specific generation of a text event
message away from the main implementation of USD and makes it more
convenient to add support for other control interface mechanisms like
dbus.

Signed-off-by: Lo,Chin-Ran <chin-ran.lo@nxp.com>
2024-08-28 11:24:11 +03:00
Vinay Gannevaram
97c6ef2588 QCA vendor interface to set the P2P mode configuration
Add the QCA_NL80211_VENDOR_SUBCMD_SET_P2P_MODE for setting the P2P mode
in which the P2P Group Owner (GO) should be brought up. These modes
include Wi-Fi Direct R1 only, Wi-Fi Direct R2 only, and P2P Connection
Compatibility Mode, which supports both R1 and R2. These modes are
defined in the enum qca_wlan_vendor_p2p_mode.

Signed-off-by: Vinay Gannevaram <quic_vganneva@quicinc.com>
2024-08-28 00:11:42 +03:00
Kiran Kumar Lokere
e33acc2178 Add QCA vendor attribute to change P2P GO beacon interval
Add new QCA vendor attribute to configure the P2P GO beacon interval
dynamically while the BSS continues operating.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-28 00:05:12 +03:00
Shivani Baranwal
59299a8a7d P2P2: Add bootstrapping support with PD frames
Add support for P2P2 bootstrapping with comeback mechanism using
Provision Discovery frames. Extend the control interface command
P2P_CONNECT to allow P2P2 bootstrapping handshake.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2024-08-27 23:50:20 +03:00
Shivani Baranwal
6aa9ad8f8f P2P2: Refactor provision discovery request/response processing
Parse the P2P IEs in functions that handle provision discovery request
and response. Process the frames based on the IEs received in the PD
frames. This makes it easier to extend PD for P2P2 cases.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2024-08-27 10:51:56 +03:00
Shivani Baranwal
b4f9742ee2 P2P2: Process Element container attribute from NAN SDFs
Process the Element Container attribute from NAN SDF frames and check if
P2P attributes are present. Add a P2P peer device entry if the NAN SDF
frame has matching service and P2P capabilities.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2024-08-27 10:51:56 +03:00
Shivani Baranwal
fa389f2a3b P2P2: Parse P2P2 IE
Add parsing of the P2P2 IE similarly to the way the P2P IE is parsed.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2024-08-27 10:51:56 +03:00
Shivani Baranwal
25c6598f30 NAN USD: Add publishChannelList option for Subscriber
Add frequency list to active NAN USD Subscriber to search for a
Publisher on multiple channels. This is the publish channel list used by
the Subscriber to periodically search for a service on these channels.
publishChannelList was already supported in the Publisher and this
commit extends that to the Subscriber.

This is needed for a P2P2 seeker that is an active subscriber looking
for an advertiser on a list of publish channels.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2024-08-27 10:51:56 +03:00
Shivani Baranwal
bcab29a78c P2P2: Device Identity Key generation and storage in configuration
Generate a random device identity key and save it to the config file.
Use the same identity key from config to derive DIRA for NAN SDF frames.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2024-08-27 10:51:56 +03:00
Shivani Baranwal
58ba550c53 FT: Fix writing of ft_prepend_pmkid configuration parameter
This was missing a newline at the end of the line.

Fixes: 8fa52a7974 ("FT: Allow wpa_supplicant to be configured to prepend PMKR1Name")
Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2024-08-27 10:51:56 +03:00
Shivani Baranwal
5b0112a185 P2P2: Add DIRA attributes to P2P2 IE of NAN SDFs
Add DIRA attribute in P2P2 IE of NAN Subscribe and Publish frames
to enable support for device identity of paired peers.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2024-08-27 10:51:56 +03:00
Shivani Baranwal
29f70292e5 P2P2: Add PCEA and PBMA attributes to P2P2 IE of NAN SDFs
Add PCEA and PBMA attribute in P2P2 IE of NAN Subscribe and Publish frames
to include the P2P2 capabilities and bootstrapping methods.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2024-08-27 10:51:56 +03:00
Shivani Baranwal
a58b2ba2fc P2P2: Allow P2P IE to be added into NAN SDFs
Extend the NAN Subscribe and Publish methods to allow p2p=1 to be
specified to include P2P attributes in a P2P IE to be added into the NAN
Element Container attribute. In addition, use the P2P Device Address for
the NAN SDFs for the P2P cases.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2024-08-27 10:51:56 +03:00
Shivani Baranwal
ae221945f6 P2P2: New element and attribute definitions
Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2024-08-27 10:51:53 +03:00
Shivani Baranwal
633e969311 NAN: Option to offload NAN DE for USD into the driver
Support implementation architecture where the NAN discovery engine is
located in the driver/firmware instead of wpa_supplicant.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
2024-08-27 00:26:46 +03:00
Jouni Malinen
87c6b322ee tests: AP MLD and RSN overriding with too long elements
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-23 18:42:55 +03:00
Jouni Malinen
d984172189 RSNO: Check that RSNOE/RSNO2E/RSNXOE fit into RSN Override Link KDE
While these elements fit without issue in production use cases, it is
possible to override the elements for testing purposes and if such
overridden elements are overly long, they would nto fit into the maximum
length RSN Override Link KDE. This could result in difficult to debug
failure cases, so check for this explicitly and instead of sending out
the invalid M3, report the internal issue in the debug log and do not
send M3.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-23 18:40:53 +03:00
Jouni Malinen
c6a8db47c3 tests: RSNXE extensibility
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-23 10:09:10 +03:00
Jouni Malinen
c03edfd5bd Allow IE overriding to use maximum element length
Elements can actually be 257 octets long (2 octets of header followed by
255 octets of payload). The maximum length for various IE override
testing parameters had somehow ended up being one octet too short to
cover the maximum. Increase this to allow the maximum element length to
be reached for testing purposes.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-23 10:07:19 +03:00
Jouni Malinen
7683ce1cff tests: Fix EHT 320 MHz tests to clear sae_groups
These test cases could fail if they happened to be executed after a test
case that set a specific SAE group.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-22 12:09:20 +03:00
Shivam Rai
d9bb64914a PASN: Add a function to configure noauth variable
When the PASN implementation is used as a library for Wi-Fi Aware
applications there is need to allow the Responder to set the noauth
parameter to support opportunistic pairing method using PASN AKMP. Add
pasn_set_noauth() to address this.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-22 11:36:02 +03:00
Shivam Rai
8f21cdf9d7 PASN: Add support to reject PASN auth 1 based on user input
When the PASN implementation is used as a library for Wi-Fi Aware
applications there is need to reject the PASN auth 1 frame based on the
user input. Add support to send PASN auth 2 with failure status for
auth 1 frame received to address this need.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-22 11:28:19 +03:00
Jouni Malinen
18116e38a2 tests: DPP and SAE with short password
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-22 11:27:00 +03:00
Jouni Malinen
882bd2edd5 DPP: Do not restrict SAE password length on Enrollee
The restriction of the passphrase length to 8..63 characters is only
applicable for WPA2-Personal (PSK). Remove this constraint when
processing a configuration object that includes SAE without PSK.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-22 11:26:53 +03:00
Jouni Malinen
503e22025b DPP: Do not restrict SAE password length on Configurator
The restriction of the passphrase length to 8..63 characters is only
applicable for WPA2-Personal (PSK). Remove this constraint when
provisioning a configuration object that includes SAE without PSK.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-22 11:20:20 +03:00
Jouni Malinen
064a46b478 tests: RSN overriding and WPA3-Personal Compatibility Mode
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-20 19:31:00 +03:00
Jouni Malinen
9da9e41612 tests: RSN overriding enabled only on the STA
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-15 20:45:55 +03:00
Veerendranath Jakkam
df8c5e22d7 RSNO: Always enable SNonce cookie and RSN Override elements validation
Always set SNonce cookie and enable RSN Override elements validation
irrespective of the RSN Selection element usage in (Re)Association
Request frame when RSN overriding supported.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-08-15 20:45:55 +03:00
Veerendranath Jakkam
bbb55af8c3 RSNO: Skip validating RSN Override elements with MLO when RSN overriding not used
STA needs to skip validating RSN Override elements when RSN overriding
is not used since AP will not send RSN Override elements in EAPOL-Key
message 3/4. This is handled correctly in non-MLO case but in MLO case
wpa_supplicant always validates RSN Override link KDEs. Fix validating
RSN Override elements in MLO case as well.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-08-15 20:45:55 +03:00
Jouni Malinen
66d8ac8ccc RSNO: Do not enforce SNonce cookie and RSN Selection match if RSNO not used
A STA that supports RSN overriding will always use the SNonce cookie. An
AP that does not advertise RSN overriding elements must not enforce that
SNonce cookie is used with RSN Selection element since a STA includes
the latter only when it sees the AP advertising RSN overriding elements.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-15 20:45:55 +03:00
Veerendranath Jakkam
70b8f64faf RSNO: Update RSN overriding capability indication to the driver
Modify wpa_supplicant code based on the updated driver interface for RSN
overriding capability indication.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-08-14 00:47:31 +03:00
Jouni Malinen
5fd3d05a40 More detailed documentation for QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES
Be more specific on how the QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS attribute
is used in the response.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-14 00:47:31 +03:00
Veerendranath Jakkam
fd72d395db QCA vendor interface for indicating supplicant support for RSN overriding
Add QCA_NL80211_VENDOR_SUBCMD_CONNECT_EXT to send additional information
such as RSN overriding support of the supplicant for the (re)association
attempts with NL80211_CMD_CONNECT.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-08-14 00:47:31 +03:00
Veerendranath Jakkam
88150522ce Use QCA_WLAN_VENDOR_FEATURE_RSN_OVERRIDE_STA only for indicating driver support
Use separate interfaces for indicating driver and supplicant RSN
overriding support. Modifying this interface is fine since this feature
is still under development.

Subsequent commit will define the interface for indicating supplicant
RSN overriding support to the driver.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-08-14 00:47:28 +03:00
Aditya Kumar Singh
bc5d3bf623 tests: Enable MLD GTK rekey test
Now that MLO GTK rekey support is added, enable the test case fully.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-13 19:24:12 +03:00
Aditya Kumar Singh
8c9b9ccb49 AP MLD: Fix PN/IPN/BIPN for group rekeying
wpa_auth_get_seqnum() for ML group rekeying needs to be skipped in the
same way as it is done for non-ML cases to avoid indicating old values
and resulting in group frames being dropped as replays. The simple check
for gsm->wpa_group_state != WPA_GROUP_SETKEYS (as is done for non-ML) is
not sufficient for this since the per-link Authenticator states are not
strictly synchronized and the state change happens in the middle of this
step.

Fixes: 137b855092 ("MLO: Mechanism for fetching group key information for the links")
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-13 19:24:12 +03:00
Rameshkumar Sundaram
7275b65149 AP MLD: Fix ML STA wpa_group update during rekey
At present, group key update is not confined only on the association
link as originally intended. Hence, ensure now that the group key update
is only performed on the association link for non-AP MLDs.

This was missed during adding support for group rekeying for MLO.

Fixes: 12acda633b ("AP MLD: Support group rekeying for MLO")
Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-13 12:59:40 +03:00
Jouni Malinen
5dbbca24ea tests: Group rekeying with VLANs
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-13 12:58:45 +03:00
Jouni Malinen
19e12d5e2d Fix GKeyDoneStations tracking for VLAN
The AP MLD change to use a helper function for this broke the design
that depends on the value for sm->group (i.e., the currently assigned
VLAN) being used instead of the sm->wpa_auth->group. Restore previous
behavior to fix GKeyDoneStations tracking when VLANs are used.

Fixes: 78adbf2c08 ("AP MLD: Mark GKeyDone completed for STAs in a helper function")
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-13 12:58:45 +03:00
Jouni Malinen
189972d129 tests: Fix duplicate test case name
The new test case for an AP MLD in a bridge was supposed to use a unique
test name to avoid hiding an existing test case.

Fixes: c4f9279267 ("tests: AP MLD with two links in a bridge")
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-13 11:44:09 +03:00
Radha Krishna Simha Jiguru
43943ea5b3 nl80211: Add AP_VLAN interface to bridge after interface is up
In the current hostapd flow, AP_VLAN net device is added to a bridge
before the interface is brought up.

Interface up event is used in mac80211 layer for setting device context
in the driver. Vendor specific datapath offload configurations for net
device might also be set up in interface up event context. Adding
AP_VLAN interface to a bridge before the UP event could cause
inconsistent state for datapath offload context setup in a vendor
driver.

Change the sequence to add AP_VLAN interface to a bridge after the
interface is set up. This makes the interface up and bridge add sequence
for AP_VLAN to be consistent with that of a regular AP interface.

Signed-off-by: Radha Krishna Simha Jiguru <quic_rjiguru@quicinc.com>
2024-08-12 12:40:03 +03:00
Jouni Malinen
c4f9279267 tests: AP MLD with two links in a bridge
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-12 12:11:39 +03:00
Karthikeyan Kathirvel
7e7e43d6b3 AP MLD: Add links to bridge FDB for FT roaming
During FT, RRB messages are getting dropped at bridge on an AP MLD since
bridge doesn't know all the link address, so roaming gets failed.

Add AP MLD's each link address to the bridge FDB, so that RRB frames
get forwarded through bridge to hostapd.

Co-developed-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Signed-off-by: Karthikeyan Kathirvel <quic_kathirve@quicinc.com>
2024-08-12 12:02:00 +03:00
Jouni Malinen
1282787878 tests: hostapd error path on driver interface initialization failure
Signed-off-by: Jouni Malinen <j@w1.fi>
2024-08-10 11:12:07 +03:00
Jintao Lin
015f6a5a0c nl80211: NULL pointer check for link before use
bss->flink could be NULL when wpa_driver_nl80211_del_beacon() is called
if wpa_driver_nl80211_drv_init() fails early through the 'failed' label
and jumps to wpa_driver_nl80211_deinit() with bss->flink unset.

Fixes: 47269be36e ("nl80211: Refactor i802_bss to support multiple links")
Signed-off-by: Jintao Lin <jintaolin@chromium.org>
2024-08-10 11:11:53 +03:00
Aditya Kumar Singh
3e2758b19a hostapd: Avoid channel selection across underlying hardware index
Currently, channel is selected from the current hw_mode. However, not
all channels under current hw_mode might be available for the current
operating underlying hardware.

Add logic to check if the selected channel falls under the current
operating hardware index and only if so, continue with the selected
channel.

Co-developed-by: Harshitha Prem <quic_hprem@quicinc.com>
Signed-off-by: Harshitha Prem <quic_hprem@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-09 22:25:02 +03:00
Aditya Kumar Singh
15bf093b5b hostapd: Fetch multiple radios information from the driver
When a driver consolidates several hardware components under a single
radio, it provides details about these components via the
NL80211_CMD_GET_WIPHY command.

Parse this information and store it. A subsequent change will use this
information for validation in certain scenarios.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-09 22:20:24 +03:00
Jouni Malinen
c43e1e5a5f Sync with wireless-next.git include/uapi/linux/nl80211.h
This brings in nl80211 definitions as of 2024-07-09.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-08-09 21:58:05 +03:00
Ganesh Kariganuru Mahabalesh
c3beaf6b86 nl80211: MLD: Fix is_shared_drv ops logic when num links is one
Whenever there is only one BSS left and if the number of links is one,
is_shared_drv() returns false assuming no one else is sharing the driver
interface. However, when the number of links is one, this does not
guarantee that the caller's link ID is the only active link ID. If this
is not the case and false is returned, the caller calls hapd_deinit()
which will free the driver interface. However, when the actual active
link_id reaches deinit path, this leads to dereferencing a NULL pointer
ultimately leading to segmentation fault.

To prevent this, pass the link ID into the is_drv_shared() ops and match
it with only with active link IDs. Only return false if they are same.

Signed-off-by: Ganesh Kariganuru Mahabalesh <quic_gkarigan@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-09 10:05:39 +03:00
Aditya Kumar Singh
3e420372e7 nl80211: Remove unused function argument from is_drv_shared() ops
The bss_ctx argument was never used and can be removed.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-09 09:56:51 +03:00
Naveen S
c6ff28cb63 AP MLD: Handle garbage pointer after MLD interface is deleted
In function driver_nl80211_link_remove(), when there is no active links,
interface is removed. This will free the BSS pointer. A copy of the BSS
pointer is also stored in each of the affiliated links' hapd->drv_priv
member.

driver_nl80211_link_remove() is called via multiple paths, e.g., via
NL80211_CMD_STOP_AP and via driver_nl80211_ops. When called when
handling an nl80211 event, links will be removed and when count reaches
zero, the interface will be removed. However, core hostapd will be
unaware of this removal. Hence, if it tries to access its drv_priv
pointer, this can lead to segmentation fault at times since the pointer
is now pointing to freed memory.

Prevent this by adding a new notification event
(EVENT_MLD_INTERFACE_FREED). Whenever the interface is freed, this
notification will be sent. hostapd will process this notification and
will set all affliated links' hapd->drv_priv to NULL.

Signed-off-by: Naveen S <quic_naves@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-09 09:56:22 +03:00
Aditya Kumar Singh
e1bf37022e nl80211: MLO: Process stop AP event on link basis
Currently, a stop AP event is processed always on the first BSS in the
drv. However, with multi-link operation, it can come on any interface
and there is need to process it for the intended BSS. Also, the event
has a link ID attribute during MLO which is not used and still the event
is passed to the first link BSS.

Process the event for the intended BSS and for the intended link BSS
during MLO.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-09 09:49:04 +03:00
Aditya Kumar Singh
f519f472e6 nl80211: Make nl80211_remove_link() non-static
No functionality changes.

This is needed to support STOP_AP events for MLD interface in a
subsequent change.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-09 09:44:18 +03:00
Aditya Kumar Singh
2d290f1966 AP MLD: Handle driver events for interface enable/disable
When an interface is enabled, keys are reconfigured, if required, and
beaconing is started again. With MLO, this needs to be done for each of
the affiliated links. Before starting the beaconing, the link needs to
be added back first.

Similarly, when the interface is disabled, hostapd removes the keys and
set the BSS state to disabled. However, for an AP MLD interface, this
needs to be done for each of the affiliated link BSS.

Handle the interface enable/disable driver event for AP MLD.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-09 09:42:59 +03:00
Aditya Kumar Singh
e9984e3db2 hostapd: Refactor interface enable/disable into separate helper functions
Driver events for interface enable/disable are currently handled on
interface level with one hostapd_data instance under consideration. In
order to extend it for MLO, this needs to be done for each of the
affiliated links. Hence, refactor the code into a helper function which
can be used later.

No functionality change. Support for MLO will be added in a subsequent
change.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-09 09:36:02 +03:00
Veerendranath Jakkam
8324947a67 RSNO: Add debug prints for RSN override elements in EAPOL frames
Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-08-08 22:39:39 +03:00
Veerendranath Jakkam
abd7f47958 RSNO: Fix storing RSNE/RSNXE variants to wpa_sm from association event
Store the full set of AP's RSNE/RSNXE variants to wpa_sm while
processing association event. Commit 521374b978 did this for the cases
that were needed for SME-in-wpa_supplicant cases, but forgot to update
the cases needed for SME-in-driver. Convert those to the updated
protocol design as well.

Fixes: 521374b978 ("RSNO: Include all RSNE/RSNXE variants in EAPOL-Key message 3/4")
Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-08-08 22:34:03 +03:00
Yu Zhang(Yuriy)
72ac0ee026 WNM: Extend workaround for broken AP operating class behavior
Some APs do not advertise operating classes correctly for BSS Transition
Management. Try to determine the most likely operating frequency based
on the channel number (1..14 --> 2.4 GHz; 36..177 --> 5 GHz) if invalid
op_class == 255 is received in a BSS Transition Management Request. This
speeds up the following operating by avoiding a full scan due to an
unknown channel.

This extends the workaround that was added in commit 80ce804e88 ("WNM:
Workaround for broken AP operating class behavior") for invalid
operating class 0 to cover another observed case with invalid operating
class 255.

Signed-off-by: Yu Zhang(Yuriy) <quic_yuzha@quicinc.com>
2024-08-08 22:26:53 +03:00
Aditya Kumar Singh
e900bcb149 tests: Add CSA support on non-first link of AP MLD
Currently MLO CSA test case supports CSA only on the first link.
However, now it can be extended to other links as well.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-08 22:18:49 +03:00
Aditya Kumar Singh
e33a55d31d nl80211: Sanitize link ID in mlme_event_ch_switch() for AP interface
During channel switch handling for AP MLD, if link ID is incorrect,
there is no point in proceeding till end and failing or returning from
there. Hence sanitize it in the initial time itself and return if it is
incorrect. Throw a warning print if it is not correct as well.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-08 22:18:49 +03:00
Aditya Kumar Singh
de2ee083e7 nl80211: Add ifname and link ID debug prints in mlme_event_ch_switch()
This makes it easier to debug AP MLD behavior.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-08 22:18:49 +03:00
Aloka Dixit
bd8a1f5ff5 hostapd: Enable HE when EHT is set for channel switch
Channel switch operation fails if 'eht' option is given without 'he'
as hostapd_config_check() returns following error:
"Cannot set ieee80211be without ieee80211ax"

The issue is seen only when switching within/to DFS channels because
hostapd_switch_channel_fallback() does not set 'ieee80211ax' in
hostapd configuration unless 'he_enabled' is set for the new channel.

Set 'he_enabled' in struct hostapd_freq_params for channel switch
when EHT is enabled.

Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
2024-08-08 22:18:47 +03:00
Aditya Kumar Singh
c6faa89366 AP MLD: Use the cached per STA profile instead of forming a new one
Now that per STA profile is cached already, there is no need to form it
dynamically on every Probe Request frame.

Use the cached one instead.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-07 18:58:47 +03:00
Arunpandi Kannan
74db2b7449 AP MLD: Handle Vendor Specific element inheritance in per STA profile
As per IEEE P802.11be/D7.0, 35.3.3.5.1 (Inheritance in the Per-STA
Profile subelement of Basic Multi-Link element), Note 1, if there exists
one or more Vendor Specific elements carried in a Management frame that
includes the Basic Multi-Link element containing a per-STA profile for a
reported STA, and the contents of the Information field for at least one
of the Vendor Specific elements is not the same as that of at least one
Vendor Specific element that applies to the reported STA, then each
Vendor Specific element that applies to the reported STA is included in
its Per-STA Profile subelement.

Handle this.

Signed-off-by: Arunpandi Kannan <quic_arunpand@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-07 18:58:32 +03:00
Sriram R
023d70d6ca AP MLD: Add non-inheritance support for per STA profile reporting
There can be an element in the reporting BSS which is not there in the
reported BSS. This element should not be inherited in the per STA
profile. Hence to indicate this, the corresponding per STA profile
should include a Non-Inheritance element in the per STA profile.

Include Non-Inheritance element in the per STA profiles when needed.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-07 18:58:08 +03:00
Sriram R
b5359d01ed AP MLD: Intersect per STA profile with the reporting BSS
If an element is present in the reporting BSS and it is also present in
the reported BSS and the contents are same, ideally, the reported BSS
need not carry such element in its per STA profile. Such elements are
assumed to be inherited from the reporting BSS.

Intersect the reported BSS profile with the reporting BSS and avoid such
element inclusion.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-07 18:57:42 +03:00
Sriram R
abe990afb9 AP MLD: Ignore elements which are not meant to be included in per STA profile
There are certain elements which should not be included in a per STA
profile.

Ignore such elements.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-07 18:57:35 +03:00
Sriram R
2042cae9b3 AP MLD: Generate and keep per STA profiles for each link
Currently, upon receiving a Probe Request frame, per STA profile is
generated and added to the Probe Response frame. However, the per STA
profile remains unchanged unless there’s a property change in one of the
affliated link of the AP MLD. This approach introduces unnecessary delay
in forming and sending out the Probe Response frame.

To optimize this process, generate the per STA profile for each link at
the start and store it. When needed, it can be simply copied into the
Probe Response frame. Additionally, whenever there’s a change in the
link’s properties, re-generate the per STA profiles for all affiliated
links of the AP MLD.

As an initial step, copy the complete per STA profile and store it
within the links. The intersection with reporting BSS and inheritance
will be addressed in a subsequent change. Then finally, this will be
used to generate the Probe Response frame. As of this commit, no change
in adding per STA profiles in the Probe Response frame.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Co-developed-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-07 18:57:09 +03:00
Sriram R
8f07e9699b Move mld_link_info structure to hostapd.h header file
At present, the mld_link_info structure is nested within the mld_info
structure. However, a future modification will require mld_link_info to
be outside of mld_info. To address this, move the mld_link_info
structure to hostapd.h so that it can be accessed both in the current
context and in the location needed for the upcoming change.

No functional changes.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-07 18:57:04 +03:00
Amith A
5cb6747f97 Add support to switch channel when CAC is in progress
Prior to initiating communication on a DFS channel, channel availability
check needs to be performed. During this period, the AP does not beacon.
Hence, no channel switch was allowed during this period. However, if a
user wishes to switch to a non-DFS channel during the potentially long
CAC period and start transmission immediately, there is no provision to
do that currently.

Extend the existing CHAN_SWITCH control interface command to allow
channel switch even when the AP is in CAC state. To do this, first
disable the interface to abort the CAC in progress and then configure
the interface with the new parameters and finally re-enable the
interface.

Signed-off-by: Amith A <quic_amitajit@quicinc.com>
2024-08-07 11:37:00 +03:00
Rameshkumar Sundaram
b7f08c28cd WNM: Fix potential NULL pointer dereference during assoc response handling
In the send_assoc_resp() function, there’s a chance that the sta
argument could be NULL. Therefore, it’s crucial not to directly
dereference sta without first checking whether it’s a valid pointer.
However, commit 58ac46baf7 (“WNM: AP configuration to allow BSS max
idle period requests”) introduces direct dereferencing of max idle
period from sta, which might lead to a NULL pointer dereference. Fix
this now.

Fixes: 58ac46baf7 ("WNM: AP configuration to allow BSS max idle period requests")
Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-07 11:34:07 +03:00
Karthik M
c7e704bdf9 hostapd: Add Bandwidth Indication subelement support for channel switch
The Bandwidth Indication subelement contains channel bandwidth, channel
center frequency, and optionally punctured subchannels.

As per IEEE P802.11be/D7.0, 35.15.3 (Channel switching methods for an
EHT BSS), if a Channel Switch Announcement element or an Extended
Channel Switch Announcement element is used to announce a switch to an
EHT BSS operating channel width wider than 160 MHz or to an EHT BSS
operating channel width including at least one punctured 20 MHz
subchannel, the Bandwidth Indication subelement in the Channel Switch
Wrapper element shall be present in the same frame.

Hence, add it into the Beacon and Probe Response frames under the above
mentioned conditions.

Signed-off-by: Karthik M <quic_karm@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-06 23:15:58 +03:00
Karthik M
c9d0c6fd7e hostapd: Refactor Channel Switch Wrapper element generation
The Wide Bandwidth Channel Switch subelement was directly appended in
the Channel Switch Wrapper element function
hostapd_eid_wb_chsw_wrapper(). However, a subsequent change would add
Bandwidth Indication subelement in the Channel Switch Wrapper element.
Hence using the same function name would be confusing.

Hence, refactor the current code into two functions. The first function
hostapd_eid_chsw_wrapper() forms the channel switch wrapper element.
This calls hostapd_eid_wb_channel_switch() to add a Wide Bandwidth
Channel Switch subelement inside it.

No functionality change.

Signed-off-by: Karthik M <quic_karm@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-06 22:52:19 +03:00
Manish Dharanenthiran
b592c1586e nl80211: Handle nl80211_cqm_event per BSS
During MLO, an nl80211_cqm_event may be received by any BSS. Directing
this event to the first BSS may not be suitable as it might not
correspond to the link the event is meant for. Hence, there is a need to
handle this on per-BSS basis.

Therefore, handle nl80211_cqm_event per BSS. The event handler further
uses the address information present in the event to fetch the intended
link BSS if no matching STA entry was found based on the initial
ap_get_sta() call.

Signed-off-by: Manish Dharanenthiran <quic_mdharane@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-06 20:17:47 +03:00
Manish Dharanenthiran
89c31feb31 Relocate the declaration of the hostapd_find_by_sta() function to top
The hostapd_find_by_sta() function may be utilized by multiple driver
events. Therefore, it should be declared at the outset to ensure
accessibility by all event handlers.

No functional changes.

Signed-off-by: Manish Dharanenthiran <quic_mdharane@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-06 20:17:47 +03:00
Aditya Kumar Singh
83c4adcdac hostapd: Add Max Channel Switch Time element support
The Max Channel Switch Time element indicates the time delta between the
time the last beacon is transmitted by the AP in the current channel and
the expected time of the first Beacon frame transmitted by the AP in the
new channel.

IEEE P802.11be/D7.0, 35.3.11 (ML procedures for (extended) channel
switching and channel quieting) indicates that if an AP affiliated with
an AP MLD is switching channel, Max Channel Switch Time element shall be
included in every Beacon and Probe Response frame it transmits.

Add support to include the Max Channel Switch Time element in Beacon and
Probe Response frames during channel switch announcement for an AP
affiliated with an AP MLD.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-06 18:34:34 +03:00
Aditya Kumar Singh
9f334fe683 Share usec-to/from-TU conversion macros in a general location
These can be used outside the context of FST and hostapd.c, so move the
macro definitions into a shared header file. In addition, fix the
currently unused US_TO_TU() definition and rename "US" to "USEC".

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-06 18:05:18 +03:00
Sidhanta Sahu
69deac87fb AP MLD: Ensure successful addition of link item into list
Currently, hapd->link is added to the MLD links list during driver
initialization and setup BSS operation. However, a call trace has been
observed where a BSS link item is not present in the list and an attempt
is made to delete it from the list. This scenario occurs during the
deinitialization operation, which calls hostapd_bss_link_deinit() and
tries to remove the hapd->link which is not present in the list.

Ensures that the link item is added to the list only after the
successful operation of link addition. Also ensure that mld->num_links
increments only when the addition is successful. Therefore, return from
hostapd_bss_link_deinit(), if mld->num_links is zero. Since the mld
object is shared among all the links, num_links has to be incremented
only when the addition is successful.

Call trace:
        dl_list_del.lto_priv.9.lto_priv ()
        hostapd_bss_link_deinit.lto_priv ()
        hostapd_bss_deinit ()
        hostapd_interface_deinit ()
        hostapd_interface_deinit_free ()
        hostapd_main ()

Signed-off-by: Sidhanta Sahu <quic_sidhanta@quicinc.com>
2024-08-06 00:29:00 +03:00
Veerendranath Jakkam
ca58be3da4 SAE: Add group 20 in default groups when AP started with SAE-EXT-KEY
hostapd used to always enable only the group 19 when SAE groups were not
configured explicitly in hostapd.conf. This may cause undesired
connection delay with STAs which use group 20 as the primary group with
SAE-EXT-KEY AKM during SAE authentication attempt.

To avoid this, enable group 20 in default groups when AP supports
SAE-EXT-KEY and SAE groups have not been configured explicitly in
hostapd.conf.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-08-06 00:06:22 +03:00
Aditya Kumar Singh
666d695bbd nl80211: Fix simultaneous scanning failure in case of MLO
Currently only one scan can be performed on per phy level at a time in
the driver. Due to this, if another scan request is sent via anoother
underlying phy, the kernel returns -EBUSY. This would result in hostapd
trying to set the interface into station mode if it was originally in AP
mode and retry sending a scan request. However, this behavior is
expected in case of multi link operation and hence there is no need to
switch the mode as such.

Hence, add logic to not change the NL mode if the kernel returns -EBUSY
during multi link AP operation. The caller can accordingly decide and,
if needed, it can re-schedule a scan request after some time.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-05 20:34:12 +03:00
Aditya Kumar Singh
fd55dfe16e nl80211: Fix scan request and its related events handling with MLO
Currently, whenever a scan is started, it uses drv's first BSS only
whether it is AP or STA interface. However, with AP MLD related changes,
the same drv could be used by other BSSs as well which needs scanning.
Hence, the current logic will not work since scan needs to be handled on
a non-first BSS as well.

Move the logic of always using drv's first BSS during scan events to
using BSS on which the event arrived.

Also, for AP MLD operation, even though the BSS is same, the link BSS
also needs to be identified. Hence, add a back pointer in the BSS struct
which would be used to point to the link BSS which requested the scan on
that BSS. This will help in routing the scan events to an appropriate
BSS ctx.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-08-05 20:34:12 +03:00
Gal Savion
23456e480e Avoid sending DEAUTH or DISASSOC packet when using flag tx=0
hostapd would send DISASSOC packet (after quiet DEAUTH) or DEAUTH packet
(after quiet DISASSOC) to the station after some inactivity timeout,
even though the command has tx=0 parameter. Fix this so that tx=0 cleans
the STA info without sending any DISASSOC or DEAUTH packets.

Signed-off-by: Gal Savion <gsavion@maxlinear.com>
2024-08-03 20:25:20 +03:00
Benjamin Berg
619ff3d2e8 build: Add simple compile_commands.json generation
This can be used with a clangd server to get code completion and cross
references in editor. To simplify the generation, create .cmd files for
most object files while building that contains the base directory and
command that was used when compiling it.

A very simple gen_compile_commands.py is provided which will read one or
more build directories and generate the compile_commands.json file for
it.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-03 20:16:18 +03:00
Jouni Malinen
733069fd4c tests: Use newer hostapd.add_ap() argument style
Convert the easy cases of old hostapd.add_ap() uses to the new one.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-08-03 19:02:29 +03:00
Janusz Dziedzic
222d443950 tests: Use remote_cli in remote testing
This allows to use remote wpa_cli/hostapd_cli for:
 - hwsim wrapper
 - example test case

For example,
 modprobe mac80211_hwsim radios=8
 ./run-tests.py -d hwsim0 -d hwsim1 -d hwsim2 -r hwsim3 -r hwsim4 -h ap_wpa2_psk -v

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@gmail.com>
2024-08-03 18:35:10 +03:00
Janusz Dziedzic
205dbb0fef tests: Allow user name to be skipped in ssh connection with remotehost
Allow to skip user name when we run ssh user@hostname.

We can specify user name in .ssh/config and simplify using network name
spaces mapped per user.

An example .ssh/config:

 Host localhost
    HostName localhost
    User root

 Host test1
    HostName testpc
    User wlan1

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@gmail.com>
2024-08-03 18:35:10 +03:00
Janusz Dziedzic
9ff4fd30ff tests: Allow to use remote hostapd_cli in Hostapd classes
Signed-off-by: Janusz Dziedzic <janusz.dziedzic@gmail.com>
2024-08-03 18:35:10 +03:00
Janusz Dziedzic
871bfdcdf6 tests: Allow to use remote wpa_cli in WpaSupplicant class
Signed-off-by: Janusz Dziedzic <janusz.dziedzic@gmail.com>
2024-08-03 18:35:02 +03:00
Janusz Dziedzic
d3f340c869 tests: Add RemoteCtrl class
Signed-off-by: Janusz Dziedzic <janusz.dziedzic@gmail.com>
2024-08-03 18:17:37 +03:00
Matthew Wang
d42cfaa397 Move wpas_trigger_6ghz_scan() up in the file
This avoids an unnecessary forward declaration for the static function.

Signed-off-by: Matthew Wang <matthewmwang@chromium.org>
2024-08-03 12:27:39 +03:00
Matthew Wang
a66cb09930 Trigger a 6 GHz scan if RNR contains matching short SSID
If a scan triggers a regdom update into a 6 GHz-allowed regdom, and an
RNR element in one of the legacy band scan results points to a 6 GHz
scan result with a short SSID matching the current_ssid, delay
connection in favor of a 6 GHz-only scan. This will optimize the case in
which we first connect to a 5 GHz AP, then later roam to a 6 GHz one by
directly connecting to the 6 GHz one.

Signed-off-by: Matthew Wang <matthewmwang@chromium.org>
2024-08-03 12:25:47 +03:00
Matthew Wang
acd9332c3b Fix success check for triggering 6 GHz scan
wpas_trigger_6ghz_scan() returns 1 on success and 0 on failure to
trigger the scan. Checking the return value to be less than zero is not
correct. This was supposed to check for success, i.e., greater than
zero.

Fixes: 42add3c27b ("Scan 6 GHz channels after change to 6 GHz-allowed regdom")
Signed-off-by: Matthew Wang <matthewmwang@chromium.org>
2024-08-03 12:17:10 +03:00
Jintao Lin
d40788a5cb P2P: Use specified frequency for group client in P2P_GROUP_ADD command
In P2P_GROUP_ADD command and GroupAdd dbus method, frequency is passed
in as a parameter when restarting a persistent group. This is the group
operating frequency determined out of band. Use this pre-determined
frequency in P2P client as well to expedite the P2P scan.

Signed-off-by: Jintao Lin <jintaolin@chromium.org>
2024-08-03 11:49:24 +03:00
Ruth Mekonnen
9c0a6d64d0 dbus: Emit ScanInProgress6GHz property
Expose whether a 6 GHz scan is in progress with the ScanInProgress6GHz
property and flush properties as soon as the property is updated, so
that platforms can choose not to disconnect while a 6 GHz scan is in
progress. Once the 6 GHz scan has completed and scan results have been
received, the ScanInProgress6GHz property is reset to false.

Signed-off-by: Ruth Mekonnen <rmekonnen@chromium.org>
2024-08-03 11:43:57 +03:00
Ruth Mekonnen
b53d7a6a86 Add non-PSC channels to 6 GHz scan request
When non_coloc_6ghz = false, the STA is expected to scan for colocated
APs. However, if the colocated AP is on a non-PSC channel, it will not
be detected during the 6 GHz-only scan because the frequency list is
limited to PSC channels. Even when the NL80211_SCAN_FLAG_COLOCATED_6GHZ
is set, the cfg80211 only scans a subset of the channels in the original
6 GHz scan request. Therefore, this patch adds non-PSC channels to the
original 6 GHz scan request.

Signed-off-by: Ruth Mekonnen <rmekonnen@chromium.org>
2024-08-03 11:36:35 +03:00
Benjamin Berg
9e50c12b31 WNM: Scan for BSSID if there are forbidden neighbors
The test to scan for a single BSSID assumed that there is only a single
neighbor in the candidate list. Also do this optimization if there are
multiple neighbors but only one of them is valid.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 13:49:32 +03:00
Benjamin Berg
3cf4b4ad88 tests: Add a WNM tests to check candidate list is used if not required
This tests that the candidate list is used even if it is not required
because the abridged and preferred candidate list included bits are not
set.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 13:49:32 +03:00
Benjamin Berg
54b25b7c1d WNM: Always parse candidate list
The preferred candidate list included bit just makes parsing the list
mandatory. The AP may still include a candidate list which we should use
to be able to optimize scanning. As such, always parse out the list but
still verify that if the list is not empty if the bit is set.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 13:49:19 +03:00
Benjamin Berg
d9d8627873 WNM: Consolidate the scanning paths for BTM requests
There was an ancient code path to trigger a scan that was apparently
forgotten when the code was extended over time. It does not make any
sense to trigger a scan twice, so remove the earlier scan.

The earlier scan call was avoiding to trigger a new scan if a fixed
BSSID is configured. This seems like a reasonable restriction to do, so
add this check before starting a scan.

Consolidate everything so that scanning happens at the end of the
functions unless we bail out before. Add a "reset" label for all other
cases to ensure that we don't leave things in the a bad state.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 13:40:37 +03:00
Benjamin Berg
3b6abe3580 WNM: Reject requests with an invalid dialog token
The dialog token must be non-zero. We are using this fact internally to
track the state in some cases, so ensure that the assumption is valid.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 13:22:34 +03:00
Avraham Stern
f4a9cb96d6 MBO: Always accept BTM request with disassociation imminent bit set
According to Multiband Operation specification (r17, section 3.5.2),
a BSS Transition Management Request with the disassociation imminent
bit set should always be accepted.

This is enforced in case the request did not include a candidate list.
However, in case a candidate list was included but none of the APs in
the candidate list was found in the scan results, the request is
rejected.

Fix that by always accepting a request with the disassociation imminent
bit set even if no roaming candidate was found.

Signed-off-by: Avraham Stern <avraham.stern@intel.com>
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 13:20:53 +03:00
Benjamin Berg
020f20a222 tests: Set the abridged bit in BTM tests
Many of the WNM tests assume that the supplicant will only select a
neighbor that was included in the candidate list. However, without the
abridged bit being set, the supplicant is allowed to also select any BSS
that is not explicitly included in the list.

Prepare for the supplicant handling the abridged bit by setting it in
the tests where relevant.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 13:16:10 +03:00
Benjamin Berg
adc6ca34a0 WNM: Move neighbor report test into wnm_is_bss_excluded()
Having it in wnm_is_bss_excluded() is more generic as it works for other
locations (e.g., MLD link selection). So move the test and add a check
for the abridged bit while at it. Note that without the abridged bit
check another check would be needed (e.g., checking wnm_dialog_token) to
ensure that there isn't a rejection unless a BTM is in progress.

compare_scan_neighbor_results() calls wpa_scan_res_match() which calls
wnm_is_bss_excluded() so the previous behavior is maintained for WNM
scan result processing.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 13:06:59 +03:00
Benjamin Berg
a832312806 WNM: Swap logic in wnm_is_bss_excluded() to allow more checks
Following commits will move more checks into wnm_is_bss_excluded().
Prepare for that by changing the logical flow so that further checks can
be inserted.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 12:58:27 +03:00
Benjamin Berg
582b5eff40 WNM: Remove unused age parameter for neighbor comparison
compare_scan_neighbor_results() was taking an age parameter to check
whether the BSS has been seen recently. This was used historically in a
codepath when no new scan was done. However, the logic was changed in
commit 20ed289a78 ("WNM: Clean up old scan data processing") and the
parameter is not used at all anymore as it is replaced by a different
logic. Remove it.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 12:57:34 +03:00
Benjamin Berg
4bbe004e06 WNM: Split candidate list parsing into a separate function
ieee802_11_rx_bss_trans_mgmt_req() is already dealing with a lot of
things including the decisions on how to act on the frame. Split out
candidate list parsing to make it easier to work with the function.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 12:53:07 +03:00
Benjamin Berg
b791d1f342 WNM: Use os_relatime_add_ms() helper
Just simplify the code a little bit by using the helper instead of doing
the math inline.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 12:48:42 +03:00
Jouni Malinen
da1a86afc6 WNM: Rename wnm_dissoc_timer
Use "disassoc" instead of "dissoc" when referring to disassociation.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-08-02 12:48:25 +03:00
Benjamin Berg
ebd18f1ade WNM: Rename wnm_dissoc_addr
Use "disassoc" instead of "dissoc" when referring to disassociation.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 12:48:25 +03:00
Benjamin Berg
93eb3b83c6 WNM: Store whether disassociation address is an MLD MAC address
Commit 17a2aa822c ("WNM: Follow BTM procedure if the last link is
dropped") added code to store either the MLD MAC address or BSSID when
being disassociated. However, it did not save which one was stored
making the tests later on awkward.

Store whether it was an MLD MAC address or not and then do the test
accordingly.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 12:48:25 +03:00
Benjamin Berg
63ac001ed2 WNM: Only trigger selection logic for own scans
Commit e508c070c4 ("WNM: Keep BTM information until connection
completes") changed the logic so that much of the information about a
transition management request will be kept around for longer. However,
doing this also implies that the scan logic can be called multiple times
with wnm_dialog_token being set.

Add a guard to bail out if the scan was not done for a BTM request. But,
add it after the transition candidate validity check so that we reset
the state when a new scan invalidated it.

However, invalidation does not make sense for any scan, primarily an ML
probe request during a connection attempt should not trigger
invalidation. So move the call to wnm_scan_process() further down in the
list to avoid issues.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-08-02 12:48:18 +03:00
Purushottam Kushwaha
bb96540ef5 Add QCA vendor attribute to skip recently scanned channels
Add a new vendor attribute
QCA_WLAN_VENDOR_ATTR_SCAN_SKIP_CHANNEL_RECENCY_PERIOD for sub command
QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN to skip the recently scanned
channels within specified time (in ms), thus reducing the number of
channels for requested scan.

Signed-off-by: Purushottam Kushwaha <quic_pkushwah@quicinc.com>
2024-08-01 20:16:50 +03:00
Veerendranath Jakkam
bc43e75b2b MLD STA: Fix destination address for EAPOL frames
For MLO association, specify the destination address as the AP MLD MAC
address for sending EAPOL frames. Previously, this was set to the BSSID
in all cases (and hoped for the driver to map it to MLD MAC address when
needed).

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-08-01 20:15:07 +03:00
David Bauer
69d18ab9f2 bgscan: Add OWE transition mode SSID to network scan
Add transition mode SSIDs to the SSID scan-list for bgscan. This is
currently missing and bgscan fails to scan for SSIDs on the OWE
transition network if one is currently used.

Signed-off-by: David Bauer <mail@david-bauer.net>
2024-08-01 18:16:34 +03:00
David Bauer
56e8f8bf34 OWE: Enable roaming between OWE APs
This allows to use the ROAM control interface command to force roaming
on a transition network. Previously, this was not possible, as the open
SSID is stored for the connection profile. Add a new function to also
return OWE transition networks if the profile SSID is set as the
transition-ssid for the OWE RSN network.

Signed-off-by: David Bauer <mail@david-bauer.net>
2024-08-01 18:06:54 +03:00
David Bauer
ddfed3f084 OWE: Reduce code duplication in OWE element parsing
Reduce the code-duplication for methods handling the OWE transition
mode.

Signed-off-by: David Bauer <mail@david-bauer.net>
2024-08-01 18:01:07 +03:00
Johannes Berg
1e54160515 hostapd: Fix BSS parameters change count on link removal
The value currently is simply incremented, but it must not
reach 255 and rather wrap around from 254 to 0, since in
the Reduced Neighbor Report 255 means unknown. Fix that.

Fixes: d95838b793 ("AP: Add support for testing ML link removal")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-08-01 17:30:12 +03:00
Diya Sati
21c3a7494c Add Link ID attribute for external ACS vendor command
The Link Id attribute is required for
qca_wlan_vendor_attr_external_acs_event to identify the link on which
the command is received for an AP MLD.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-01 10:38:24 +03:00
Shiva Sankar Gajula
5942965955 Add link ID attribute to ADD_STA_NODE QCA vendor command for AP MLD
Add QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_LINKID attribute to the
ADD_STA_NODE command to identify a specific link affiliated to an AP
MLD.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-08-01 10:37:10 +03:00
Purushottam Kushwaha
e1ab680c98 Add QCA vendor subcommand to request audio transport switch
Add a new sub command QCA_NL80211_VENDOR_SUBCMD_AUDIO_TRANSPORT_SWITCH
to request the audio data transport switch in both the command and event
path. This is used when two or more audio data transports are available
between peers.

Signed-off-by: Purushottam Kushwaha <quic_pkushwah@quicinc.com>
2024-08-01 10:32:00 +03:00
Vinay Gannevaram
7e0e69cfea SAE: Send external auth status after sending Authentication frame
The driver might delete the STA node details on receiving external auth
status. In SAE authentication failure case on the AP, an Authentication
frame with a failure status is sent to the driver after sending the
external auth status. Authentication frame transmission didn't have a
dependency with STA node details earlier, but with MLO, Authentication
frames should be transmitted using the link address for a given MLD MAC
address by the supplicant. Since MLD to link address translation is done
by the driver, the STA node details are required to transmit the
Authentication frame. Hence, send external auth status to the driver
after sending the Authentication frame.

SAE external auth was introduced in commit 4ffb0fefe4 ("hostapd:
Support external authentication offload in AP mode"), which requires the
change in order of sending Authentication frame and auth status in case
of failure when using MLO.

Signed-off-by: Vinay Gannevaram <quic_vganneva@quicinc.com>
2024-07-31 18:28:39 +03:00
Jouni Malinen
be6e4279fa RSNO: Verify all RSNE/RSNXE variants in multi-link cases
Use the RSN Override Link KDE to include the override variants of the
RSNE/RSNXE for each link so that all variants are verifies when
processing the protected EAPOL-Key message 3/4.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-30 19:56:00 +03:00
Jouni Malinen
4d110b4f87 tests: More detailed error logging for RSN overriding with MLD
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-30 18:52:15 +03:00
Jouni Malinen
521374b978 RSNO: Include all RSNE/RSNXE variants in EAPOL-Key message 3/4
This allows all variants to be verified based on a protected frame to
achieve robust downgrade protection.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-30 18:52:15 +03:00
Jouni Malinen
6f522baa1b RSNO: Use SNonce cookie to indicate support for RSN overriding
This provides an implicitly protected (SNonce is used as an input to PTK
derivation) mechanism for a STA to indicate support for RSN overriding
in a manner that does not cause interopability issues with deployed APs.

In addition, update sm->SNonce on the Authenticator only based on
message 2/4 since that is the only EAPOL-Key message that is defined to
provide the actual SNonce value. While clearing of this internal buffer
on message 4/4 might not cause issues, it is better to keep the actual
SNonce value here since the SNonce cookie can be used at a later point
in the sequence.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-30 12:16:05 +03:00
Jouni Malinen
62ca121f96 RSNO: Use the RSN Selection element to indicate which variant was used
This replaces the use of the RSNE Override and RSNE Override 2 elements
with empty payload to indicate which RSNE variant was used.

In addition, this adds stricter validation of the RSNE in
(Re)Association Request frame to allow only the pairwise cipher suites
and AKMs listed in the indicated RSNE variant to be used.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-30 12:16:05 +03:00
Jouni Malinen
524c452153 RSNO: Remove unused override element generation
The separate RSNOE/RSNO2E/RSNXOE buffers were not actually used on the
Authenticator, so remove them.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-30 12:16:05 +03:00
Chenming Huang
13648dde91 FILS: Check for potential NULL return
hostapd_eid_assoc_fils_session() might return NULL if memory allocation
fails. This NULL value then will be used for invalid calculation and
cause unspecified behavior or be dereferenced unexpectedly. Avoid this
with an explicit check of the returned pointer.

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-07-25 21:03:59 +00:00
Adil Saeed Musthafa
376adfea8d RSNO: Protect wpa_ie_buf3 from reuse explicitly
Use else-if check for better clarity regarding usage of wpa_ie_buf3 to
make it explicit that memory is allocated for this pointer only once.

Signed-off-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
2024-07-25 21:03:51 +00:00
Jouni Malinen
4adf234cd3 RSNO: Remove override elements from EAPOL-Key msg 3/4
This was not done in case the STA did not use RSN overriding.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-25 19:22:00 +00:00
Jouni Malinen
9732c8b85c wlantest: Remove unused QoS handling from GCMP nonce generation
This was copied from CCMP, but is not needed (and can trigger compiler
warnings) with GCMP.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-25 00:39:30 +00:00
Jouni Malinen
e0053bf9d0 tests: Long extra KDE in EAPOL-Key msg 3/4
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-24 20:35:11 +00:00
Jouni Malinen
296104d35c Testing functionality to allow EAPOL-Key Reserved field to be set
The new hostapd configuration parameter eapol_key_reserved_random=1 can
be used for testing STA/Supplicant functionality to accept a random
value in the Reserved field within EAPOL-Key frames.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-24 17:22:42 +00:00
Jouni Malinen
2e4c612dd2 Allow RSNE/RSNXE/RSNOE/RSNO2E/RSNXOE to be replace for testing
This is convenient for testing STA behavior with various RSN element
combinations and special cases.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-24 01:01:29 +00:00
Jouni Malinen
bb61f6cb95 RSNO: Support over two octets of RSNXOE capabilities
The RSNXE generation function was extended to support this earlier, but
that update was missed from the RSNXOE variant.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-23 21:36:46 +00:00
Jouni Malinen
8b2ddfdbb6 RSNO: Allow RSNXE to be omitted
Add an explicit rsn_override_omit_rsnxe=1 configuration parameter to
allow the RSNXE to be omitted when using the RSNXOE and wanting to
minimize interoperability issues with STAs that might recognize the
RSNXE, but not handle it correctly, e.g., when multiple octets of
payload is included.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-23 21:20:45 +00:00
Hu Wang
92374d59d4 Enhance select_network() to trigger new scans in some cases
wpa_supplicant select_network() relies on fast_associate to reuse old
scan results. However, this approach does not apply in some cases in
Android:

1 - If the selected network is hidden, and the SSID is in Chinese,
Android switches between fallback SSIDs, necessitating a new scan for
switching between different hidden SSIDs.

2 - Similarly, if the selected SSID is OWE (Opportunistic Wireless
Encryption), and the OWE SSID bands have been changed, select_network()
requires a fresh scan to discover hidden OWE SSIDs.

To address these, enhance select_network() to trigger new scans instead
of relying on fast_associate. This improves network selection behavior
in Android.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-22 19:01:18 +00:00
Veerendranath Jakkam
ff99012d84 RSNO: Use correct MLO capability while fetching RSNE/RSNXE
Use current connection MLO capability to fetch the appropriate
RSNE/RSNXE variant while processing association event.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-07-22 18:50:24 +00:00
Veerendranath Jakkam
526ea193c8 Fallback to RSNXE when AP is not using valid RSN Overrding
wpa_supplicant was ignoring RSNXE also if the AP is not using valid
RSN overriding combination when the STA supports RSN overriding. Fix
this fallback to the RSNXE when AP is not using valid RSN overriding.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-07-22 18:48:20 +00:00
Vinay Gannevaram
4417b5ba86 Add QCA vendor interface to support Unsynchronized Service Discovery
Add a new QCA command QCA_NL80211_VENDOR_SUBCMD_USD and related
attributes to support Unsynchronized Service Discovery (USD).

Device in active subscriber role sends SDF frames with service
information to find devices that advertise or publish the required
services. Device address, operation type, instance id, service_id,
channel info, service specific info, element container attribute, and
timeout are sent to the driver to initiate USD publish or USD subscribe
operation. The driver sends QCA_NL80211_VENDOR_SUBCMD_USD event with
instance_id and the USD operation status. QCA_NL80211_VENDOR_SUBCMD_USD
is also used to update publish operation and to cancel the publish or
subscribe operation for a service. It also allows all the operations to
be terminated using the USD flush command.

Signed-off-by: Vinay Gannevaram <quic_vganneva@quicinc.com>
2024-07-20 21:00:21 +00:00
Jouni Malinen
8d54863550 tests: RSNE/RSNXE overriding
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-20 21:28:28 +03:00
Jouni Malinen
765c48d5ad RSNE/RSNXE overriding for STA
Add support for RSNE/RSNXE Override elements. Use these elements to
determine AP's extended RSN parameters.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-20 21:28:28 +03:00
Jouni Malinen
d0b55eb360 Make driver capabilities for AKM suites available within wpa_supplicant
In addition, add some of the previously missed AKM suites from the
default capabilities.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-20 21:28:28 +03:00
Jouni Malinen
5488e120d3 Use helper functions to access RSNE/RSNXE from BSS entries
This is a step towards allowing the contents of RSNE/RSNXE to be
overridden.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-20 21:28:28 +03:00
Veerendranath Jakkam
341bcb2b5c nl80211: Add a capability flag for RSN overriding
Add a new capability flag based on the nl80211 feature advertisement for
RSN overriding support.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-07-20 21:28:28 +03:00
Veerendranath Jakkam
6fad7224be Add QCA vendor feature flags to indicate RSN override elements support
Add a separate feature flag for STA mode to indicate support for RSN
override elements.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-07-20 21:28:28 +03:00
Jouni Malinen
157b016383 RSNE/RSNXE overriding for AP
Allow hostapd to be configured to advertised two separate sets of
RSNE/RSNXE parameters so that RSNE/RSNXE can use a reduced set of
capabilities (e.g., WPA2-Personal only) for supporting deployed STAs
that have issues with transition modes while the new override elements
can use a newer security option (e.g., WPA3-Personal only) for STAs that
support the new mechanism.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-20 21:28:28 +03:00
Jouni Malinen
b8a2d11ae0 Allow RSNXE Override element to override RSNXE contents during parsing
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-20 21:28:28 +03:00
Jouni Malinen
48ca68f6f8 Allow RSNE Override element to override RSNE contents during parsing
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-20 21:28:28 +03:00
Jouni Malinen
c16ac89be2 Add RSN overriding elements into IE parsing
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-20 21:28:28 +03:00
Jouni Malinen
6b0ce29d25 Define WFA vendor specific element types for RSNE/RSNXE overriding
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-20 21:28:28 +03:00
Jouni Malinen
e99cdfae41 The main branch is now used for v2.12 development
Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-20 21:16:55 +03:00
Jouni Malinen
d945ddd368 Preparations for v2.11 release
Update the version number for the build and also add the ChangeLog
entries for both hostapd and wpa_supplicant to describe main changes
between v2.10 and v2.11. Update the copyright years for the main
programs.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-20 21:04:37 +03:00
Davide Caratti
aa2dfae5eb dbus: Fix memory leak with Bonjour params for a P2P UPnP service
Using D-Bus, it is possible to add a valid UPnP service where 'query'
and 'response' are specified. In this case, memory for 'query' and
'response' is allocated but not used nor freed. Valgrind complains as
follows:

 42 bytes in 1 blocks are definitely lost in loss record 32 of 75
    at 0x484C214: calloc (vg_replace_malloc.c:1675)
    by 0x41C673: wpabuf_alloc (wpabuf.c:124)
    by 0x41C673: wpabuf_alloc_copy (wpabuf.c:162)
    by 0x54F41A: wpas_dbus_handler_p2p_add_service (dbus_new_handlers_p2p.c:2762)
    by 0x53B9A2: msg_method_handler (dbus_new_helpers.c:356)
    by 0x53B9A2: message_handler (dbus_new_helpers.c:412)
    by 0x4EAB4B8: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.19.13)
    by 0x5495DF: dispatch_data (dbus_common.c:37)
    by 0x5495DF: process_watch (dbus_common.c:73)
    by 0x5495DF: process_watch_read (dbus_common.c:89)
    by 0x41EE8E: eloop_sock_table_dispatch.part.0 (eloop.c:603)
    by 0x41FA46: eloop_sock_table_dispatch (eloop.c:597)
    by 0x41FA46: eloop_run (eloop.c:1233)
    by 0x56A3CE: wpa_supplicant_run (wpa_supplicant.c:8074)
    by 0x40DB06: main (main.c:393)

 49 bytes in 1 blocks are definitely lost in loss record 37 of 75
    at 0x484C214: calloc (vg_replace_malloc.c:1675)
    by 0x41C673: wpabuf_alloc (wpabuf.c:124)
    by 0x41C673: wpabuf_alloc_copy (wpabuf.c:162)
    by 0x54F348: wpas_dbus_handler_p2p_add_service (dbus_new_handlers_p2p.c:2755)
    by 0x53B9A2: msg_method_handler (dbus_new_helpers.c:356)
    by 0x53B9A2: message_handler (dbus_new_helpers.c:412)
    by 0x4EAB4B8: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.19.13)
    by 0x5495DF: dispatch_data (dbus_common.c:37)
    by 0x5495DF: process_watch (dbus_common.c:73)
    by 0x5495DF: process_watch_read (dbus_common.c:89)
    by 0x41EE8E: eloop_sock_table_dispatch.part.0 (eloop.c:603)
    by 0x41FA46: eloop_sock_table_dispatch (eloop.c:597)
    by 0x41FA46: eloop_run (eloop.c:1233)
    by 0x56A3CE: wpa_supplicant_run (wpa_supplicant.c:8074)
    by 0x40DB06: main (main.c:393)

Fix this ensuring that query and resp are freed both in the error and
non-error path of wpas_dbus_handler_p2p_add_service(). Also, add a test
in test_dbus.py to verify the correct behavior.

Signed-off-by: Davide Caratti <davide.caratti@gmail.com>
2024-07-20 20:28:40 +03:00
David Ruth
70e5bad563 dbus: Fix SignalChange property
SignalChange should be defined as a property of an interface.
Previously, it was incorrectly defined as a property of P2P peers.

Fixes: 7a7ce95746 ("dbus: Emit more information over D-Bus")
Signed-off-by: David Ruth <druth@chromium.org>
2024-07-20 20:20:38 +03:00
Sunil Ravi
ed5887a8c9 Move NULL check for driver private data (drv_priv)
In the hostapd_cleanup_driver() function, the NULL check for the driver
private data (drv_priv) is located within the CONFIG_IEEE80211BE feature
flag. As a result, on platforms where CONFIG_IEEE80211BE is not defined,
driver->hapd_deinit(drv_priv) is called with drv_priv set to NULL. This
leads to a null pointer exception in wpa_driver_nl80211_deinit().

To address this issue, move the NULL check for drv_priv outside the
CONFIG_IEEE80211BE build flag. This ensures that the check is performed
regardless of the value of CONFIG_IEEE80211BE, preventing the NULL
pointer exception.

Fixes: df34c2ced3 ("AP MLD: De-initialize/disable link BSS properly")
Signed-off-by: Sunil Ravi <sunilravi@google.com>
2024-07-20 20:14:08 +03:00
Veerendranath Jakkam
c3d305d939 FT: Fix FTE MIC calculation with fragmented FTE
Currently wpa_ft_parse_ies() is setting FTE information to wpa_buf
pointer data which is generated after defragmentation. This data will
not contain FTE and Fragment element(s) headers.

IEEE P802.11be/D5.0 describes the MIC to be calculated on the
concatenation of FTE and corresponding Fragment element(s) which
implies the element headers are included for each element in the
fragmented case.

Fix this by correctly populating FTE information when FTE is
fragmented.

Fixes: 43b5f11d9 ("Defragmentation of FTE")
Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-07-15 10:51:44 -04:00
Michael-CY Lee
e7172e26d3 MLD STA: Find partner links by BSSID and SSID
Non-AP MLD finds AP MLD's partner links by BSSID from the scan results.
However, if the scan results contain BSSs with the same BSSID but
different BSS information, the non-AP MLD might assign a wrong BSS to
one of the AP MLD's partner links.

Avoids the problem by using both BSSID and SSID to find the AP MLD's
partner links.

Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
2024-07-13 18:09:32 +03:00
marek@mazekey.pl
6809f2b955 tests: Check CSA between non DFS and DFS chan
Add test to validate CSA between non DFS channel
and DFS channel with different operating class.

Signed-off-by: Marek Kwaczynski <marek@mazekey.pl>
2024-07-13 18:09:32 +03:00
marek@mazekey.pl
816e22bba1 hostapd: Fix opclass during CSA with DFS channels
During CSA with DFS channels, disable, enable interface is a part of the
algorithm. When interface was enabled old operating class before switch
and new channel were used causing mismatch in
configured_fixed_chan_to_freq() function.

Example of log when switch from channel 157 to 108 was triggered:
"Could not convert op_class 124 channel 108 to operating frequency"

Fixes: bb781c763 ("AP: Populate iface->freq before starting AP")
Signed-off-by: Marek Kwaczynski <marek@mazekey.pl>
2024-07-13 18:09:32 +03:00
gasmibal@gmail.com
93a3c59ad9 Multi-AP: Honor wds_sta even with multi_ap
When multi_ap is active, hostapd creates an AP-VLAN interface for 4addr
stations, even though wds_sta is not configured.

A check should be added to determine if wds_sta is active before
re-enabling the WDS mode by creating an AP-VLAN for 4addr stations.

Signed-off-by: Baligh Gasmi <gasmibal@gmail.com>
2024-07-13 18:09:32 +03:00
Jouni Malinen
90344c323e tests: Set sta_wds in multi_ap_backhaul_shared_bss
This is needed to add the WDS interface for a STA with stricter
implementation checks.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-13 18:09:32 +03:00
Jouni Malinen
49fe24e6f5 tests: wpa_supplicant secure mesh and injected SAE messages
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-13 16:38:48 +03:00
Jouni Malinen
7d51bf2abd SAE: Drop default dot11RSNASAESync value from 5 to 3
Going through five extra rounds of SAE commit messages in cases where
SAE peers are somehow unsynchronized feels unnecessary much to do by
default, so drop the default value to 3.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-13 16:37:15 +03:00
Jouni Malinen
5da59ff1cd SAE: Disable protocol instance temporarily on sync error in mesh
Reduce the number of unwanted SAE commit retries in synchronization
error cases when Sync > dot11RSNASAESync in mesh cases by discarding
received SAE commit messages for 10 seconds after a sync error has been
detected.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-13 16:35:12 +03:00
Nicolas Escande
7b8517d197 nl80211: Fix AP scan with STA fallback error path
I've run into a case where I can bring a 2.4 GHz AP up without it being
in a bridge while I used the 'bridge=' config option. This happens when
the HT scan needed for 40 MHz operation failed to start from the get go
because another dev on the same phy was already in a scan. At the end
the AP is up and running but not added into any bridge.

Upon looking at the code, it seems that some hardware fails to issue a
scan while in AP and thus we have a fallback that switches the interface
from AP to STA before retrying another scan (it will change it back to
AP later on when finished). As we cannot have a (non-WDS) STA in a
bridge, during that procedure, we also remove/add the AP/STA from/to the
bridge as needed.

However, in wpa_driver_nl80211_scan() we do not set
drv->ap_scan_as_station until the end of the switch-to-sta &
retry-scan-start block. This means that when the recursive call to
wpa_driver_nl80211_scan() fails (the hardware is busy in my case) we
restore the interface to AP with wpa_driver_nl80211_set_mode() but that
will not add it back to the bridge. Problem.

To fix this lets always set drv->ap_scan_as_station before calling
wpa_driver_nl80211_set_mode(). In case wpa_driver_nl80211_set_mode() or
wpa_driver_nl80211_scan() fails lets call nl80211_restore_ap_mode() that
will set the mode back to AP but also handle the bridge thing as needed.

Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
2024-07-12 16:44:30 +03:00
Chien Wong
6ad59779c2 nl80211: NAN: Register multicast action frames if possible
The USD passive subscriber and solicited transmission only publisher
require receiving multicast NAN action frames in order to work.
Currently, we are not requesting to receive multicast when
registering NAN action frames. As a result, USD passive subscribe or
solicited only publish may not work.

The NL80211_ATTR_RECEIVE_MULTICAST attribute corresponds to wiphy
ext feature NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS, which
requires driver support and only a few drivers in the kernel tree
support it. Namely ath9k, ath9k_htc, ath10k and hwsim. We should
fall back to register non multicast action frames if the driver
has no support.

It was confirmed that ath9k_htc starts to work after the changes.

Note that even without requesting to receive multicast Action
frames, some drivers would still upload them. For example, rtl8192cu
and hwsim. This is why test cases like test_nan_usd_match would not
fail.

Tested-on: TP-LINK TL-WN821N v3(AR7010+AR9287, ath9k_htc)
Signed-off-by: Chien Wong <m@xv97.com>
2024-07-12 16:40:48 +03:00
Chien Wong
f250c34d10 tests: NAN: Check USD publish type
Signed-off-by: Chien Wong <m@xv97.com>
2024-07-12 16:37:15 +03:00
Chien Wong
92829d8bee NAN: Reject undefined publish type
The Wi-Fi Aware Specification v4.0 only defines unsolicited
transmissions only, solicited transmissions only and both unsolicited
and solicited transmissions publish. The other possibility is undefined
so we should reject it.

Signed-off-by: Chien Wong <m@xv97.com>
2024-07-12 16:37:01 +03:00
Chien Wong
44f20382cc NAN: Fix a typo in USD doc
The 'req_instance' parameter in transmit command should be
'req_instance_id'.

Fixes: e3f9ab3c3a ("NAN: USD in wpa_supplicant")
Signed-off-by: Chien Wong <m@xv97.com>
2024-07-12 16:34:56 +03:00
Michael-CY Lee
7c935eef36 nl80211: AP MLD: Reassign drv->ctx correctly to prevent hostapd crash
When the first link is deleted and there are still remaining links,
drv->ctx should be updated to the new default link on the bss.
Otherwise, drv->ctx points to the address that has already been freed
and makes hostapd crash.

Fixes: d2b62b3fe5 ("AP MLD: Support link removal before removing interface")
Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
2024-07-12 15:20:44 +03:00
Jouni Malinen
3137a41247 tests: Make SSID verification through beacon protection more robust
Clear scan results at the beginning of the test case to avoid incorrect
behavior if there are multiple entries for the same BSS. In addition,
use a bit longer wait for receiving an updated Beacon frame in scan
results.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-12 13:15:57 +03:00
Jouni Malinen
1023654532 Make Beacon frame checks less frequent for SSID verification
Instead of checking the latest scan results every second indefinitely,
add more latency between the checks in case the driver does not update
the time stamp value (i.e., does not report new Beacon frames during an
association).

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-12 13:13:09 +03:00
Ilan Peer
b946a800f0 tests: Fix run_eht_mld_sae_two_links()
In the case that the AP MLD is disabled and enabled again, flush
the wpa_supplicant BSS table before reconnecting as otherwise
the previous AP MLD BSSs would be in the BSS table and the wpa_supplicant
would try to connect to them.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
2024-07-12 13:00:46 +03:00
Johannes Berg
b7aecfe5f9 wlantest: ICMP: Use sta_find_mlo()
Using just sta_find() won't work for any link addresses
but the assoc link, use sta_find_mlo() instead.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-07-12 13:00:10 +03:00
Andrei Otcheretianski
c3b3c506b6 tests: Use different groups in test_sae_no_ffc_by_default
The test assumes that STA will try to reconnect with the same SAE group
after the first authentication attempt is rejected due to unsupported
group. Since this behaviour is fixed in the previous patch, configure
two different groups to trigger the second authentication attempt.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
2024-07-12 12:59:26 +03:00
Andrei Otcheretianski
fcf799c0dd wpa_supplicant: Do not select a rejected SAE group
Make sure that sme_set_sae_group() doesn't select a group that was
previously rejected during this instance of SAE authentication.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
2024-07-12 12:58:38 +03:00
Andrei Otcheretianski
5f83f4db0b Add int_array_includes()
This is a convenient helper function for using int_array instances.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
2024-07-12 12:58:05 +03:00
Andrei Otcheretianski
094e188f84 wpa_supplicant: Always clear SAE rejected groups on roaming to another BSS
SAE rejected groups were not cleared in case of re-association to the
same ESS. Since new BSS can support different groups, keeping rejected
groups doesn't make sense and may result in AP rejecting the
authentication. Fix it.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
2024-07-12 12:54:20 +03:00
Hari Naraayana Desikan Kannan
627b67f29b ACS: Fix primary channel puncturing in ACS
Currently, when the ACS is updating the puncturing bitmap, the function
acs_update_puncturing_bitmap() sets the primary channel bitmap to 0.
This leads to a potential issue where the primary channel could be
punctured if ACS selects a different best channel within the same
segment.

To fix this issue, ensure that the primary channel bitmap is correctly
set by calculating the index of the primary channel based on the
frequency difference between the current channel and the best channel in
the segment, and is then passed to acs_update_puncturing_bitmap().

Fixes: af0f60e7dd ("EHT: Calculate puncturing bitmap for ACS")
Signed-off-by: Hari Naraayana Desikan Kannan <quic_hnaraaya@quicinc.com>
2024-07-12 12:42:08 +03:00
Hari Naraayana Desikan Kannan
be2ac92918 ACS: Fix ACS behavior for channel selection
The current ACS algorithm incorrectly returns success even when there is
no survey list, leading to improper interference factor calculation.
This leads to treating 0 as a valid interference factor, which affects
channel selection judgment.

Fix the issue by ensuring success is only returned when the survey list
is not empty, thereby ignoring non-zero values in the interference
factor calculation.

Signed-off-by: Hari Naraayana Desikan Kannan <quic_hnaraaya@quicinc.com>
2024-07-12 12:40:00 +03:00
Hari Naraayana Desikan Kannan
83cfeb8903 ACS: Update ACS documentation
Update the documentation to reflect the ACS algorithm used in the code.
No functionality change.

Signed-off-by: Hari Naraayana Desikan Kannan <quic_hnaraaya@quicinc.com>
2024-07-12 12:38:10 +03:00
Hu Wang
cb91ef2566 MLO: Swap Tx/Rx keys for GTK TKIP Michael MIC in MLO GTK KDE
While TKIP should not really be used at all anymore and is not allowed
for WPA3 (which is required for Wi-Fi 7), there are some deployed APs
that allow WPA2 PSK to be used with MLO and even allowing WPA+WPA2 mode
with TKIP as the group cipher). IEEE P802.11be/D5.0 does not seem to
explicitly disallow this combination, so handle the MLO GTK KDE key
processing similarly to the way GTK KDE is processed, i.e., including
swapping of Michael MIC Tx and Rx keys for TKIP.

This fixes issues with Michael MIC failures if TKIP is used as a group
cipher for a multi-link association.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-12 12:36:50 +03:00
Pradeep Kumar Chitrapu
7d314d6bdf Fix channel switch without 'ht' for HE and EHT modes in 2.4 GHz band
hostapd_cli chan_switch command fails in 2.4 GHz band for HE and EHT
modes if the user does not explicitly specify 'ht' option in the
command.

For example:
"hostapd_cli -i wlan2 chan_switch 10 2412 sec_channel_offset=0 \
 center_freq1=2412 bandwidth=20 blocktx he"

Fix this by enabling HT by default if HE is enabled in the 2.4 GHz and 5
GHz bands. Similarly, enable VHT by default when HE is enabled in the 5
GHz band.

Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
2024-07-12 12:25:55 +03:00
Harshitha Prem
99e82880e8 Fix mesh 6 GHz incorrect channel bandwidth
When the wiphy supports multiple bands and reports different capability
values between 5 GHz and 6 GHz channels, the 6 GHz mesh interface is
unable to correctly map the channel width in function
ibss_mesh_setup_freq(). This issue arises because the modes of 5 GHz and
6 GHz interfaces are the same (HOSTAPD_MODE_IEEE80211A) in supported
modes.

To address this, use function get_mode() to determine the appropriate
mode during mesh setup. This will iterates through all the hw_features
sets and ensures compatibility with the band of the channel supported in
hw_features set.

Signed-off-by: Harshitha Prem <quic_hprem@quicinc.com>
2024-07-12 12:17:04 +03:00
Jouni Malinen
454a22daba tests: SSID verification using beacon protection
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-11 23:55:14 +03:00
Jouni Malinen
5452a4a302 SSID verification based on beacon protection
If SSID was not verified during the initial setup of an association, but
beacon protection was negotiated, try verify the SSID based on Beacon
frames that have been received after the first BIGTK has been
configured.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-11 23:55:05 +03:00
Jouni Malinen
89b164138c BSS: Add wpa_bss_get_ie_beacon()
This is a variant of wpa_bss_get_ie() to allow IEs to be checked from
only Beacon frames similarly to how wpa_bss_get_vendor_ie_beacon()
behaves for vendor specific elements.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-11 23:50:55 +03:00
Jouni Malinen
d5d0012bfb tests: Verify bigtk_set=1 indication
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-11 23:16:05 +03:00
Jouni Malinen
7436b5b012 Indicate if BIGTK has been set in STATUS output
The new "bigtk_set=1" entry in the control interface STATUS command
output indicates that a BIGTK has been successfully configured. This
shows that beacon protection has been enabled for the current
association.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-11 23:14:02 +03:00
Jouni Malinen
42c1a512d9 tests: Verify that ssid_verified=1 is set appropriately
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-11 23:04:07 +03:00
Jouni Malinen
c6f394b888 Indicate if SSID has been verified in STATUS output
Add a new "ssid_verified=1" entry into the control interface STATUS
command output if the SSID has been verified for the current
association. This verification may have been done implicitly (e.g., with
SAE H2E and FT protocol binding in the SSID into key derivation or with
FILS protecting the SSID element in the (Re)Association Request frame)
or explicitly with the recently added SSID protection mechanism during
the 4-way handshake.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-11 22:58:12 +03:00
Sai Pratyusha Magam
b745cd33ef PASN: Derive KDK on AP only when both ends support SecureLTF
On the AP responder side, KDK was derived if the driver advertises
WPA_DRIVER_FLAGS2_SEC_LTF_AP. That is not correct, i.e., this needs to
also depend on the initiator indicating support for this in the RSNXE of
PASN authentication frame 1.

Signed-off-by: Sai Pratyusha Magam <quic_smagam@quicinc.com>
2024-07-11 22:14:50 +03:00
Ilan Peer
e5f76b9153 dbus: Fix error path in scan request handling
In case the scan request handling fails, exit cleanly, i.e., without
setting internal state such as the 'scan_res_handler' pointer.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
2024-07-11 19:56:08 +03:00
Benjamin Berg
7f3fe956d8 tests: Ignore large memory blocks when searching for keys
wpa_supplicant will generally never allocate a memory block of that
size. We can therefore assume that it belongs to ASAN and we need to
ignore it.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-07-11 19:55:48 +03:00
Benjamin Berg
58b2759551 trace: Only permit explicit prefix matching for functions
The matching code currently only tests whether the prefix of a function
matches. Make this more strict by ensuring that the function name is not
longer.

However, as this breaks some tests (due to inlining), add the ability to
do an explicit prefix match by appending a '*' to the function name. Use
this to change the eap_eke_prf match to eap_eke_prf_* in order to match
one of the actual implementations.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-07-11 19:54:50 +03:00
Benjamin Berg
49344db095 trace: Use strncmp() to match function names
The functions specified by the user might be longer than the function in
the backtrace, potentially overflowing the memcmp(). In practice, it
should not be a relevant out-of-memory read. However, we can use
strncmp() instead.

Note that, as before, this is only a prefix match. If a function name is
longer in the backtrace it will still match.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-07-11 19:52:34 +03:00
Benjamin Berg
918da644e1 tests: Use sha256_prf_bits for failure stack matching
It seems that sha256_prf may not always be in the stack trace for
failure checking, possibly due to tail call optimization as it simply
calls sha256_prf_bits with updated parameters. Simply match against
sha256_prf_bits directly to avoid issues due to optimizations.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-07-11 19:51:29 +03:00
Benjamin Berg
9ba372a23d tests: Remove duplicate fail test check
The wpas_p2p_nfc_handover failure test and the more specific
wps_build_nfc_handover_req_p2p were effectively the same as the matching
currently does a prefix match. The code-path tested in these two cases
only hit a single TEST_FAIL macro in openssl_digest_vector.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-07-11 19:51:06 +03:00
Benjamin Berg
f6ba44d6f9 tests: Use more specific alloc_fail location
The test here is triggering the allocation failure in the static
wpa_config_parse_password() helper. Use this and decrease the count
instead of matching both wpa_config_set_quoted() and wpa_config_set()
and counting down based on that.

This is in preparation to fix the failure function matching to not do a
prefix match.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-07-11 19:50:42 +03:00
Benjamin Berg
050bd6e2b1 tests: Specify correct function name for failure
The test expects rsn_pmkid_suite_b_192() to fail but specified only
rsn_pmkid_suite_b without the _192 postfix. Add the postfix so that the
function matching can be fixed later.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-07-11 19:49:46 +03:00
Benjamin Berg
ac15b79fe5 PMKSA: Guard against NULL KCK for memcpy()
If the kck_len is 0 then the pointer may be NULL. If that happens UBSAN
complains about the NULL pointer as memcpy() has the arguments declared
to never be NULL even if the copied number of bytes were zero.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-07-11 19:48:11 +03:00
Benjamin Berg
7bcede06e0 MLD: Ensure link_bssid array has space for sentinel
The consumer of the link_bssid array assumes it is a NULL terminated
array of BSSIDs. As such, add one to the maximum number of links to
ensure that there is always a sentinel value.

Fixes: 5af986c75a ("MLD: Also mark links as failed after association failure")
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-07-11 18:53:59 +03:00
Benjamin Berg
cf3883f3d1 MLD: Ensure link BSSIDs remain on stack for ignore
When ignoring a link BSSID the multi-link information was parsed out
into a struct ml_sta_link_info on the stack. However, this stack
variable went out of scope before it was used by passing the link_bssids
pointer array to another function.

Fixes: 5af986c75a ("MLD: Also mark links as failed after association failure")
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-07-11 18:53:59 +03:00
Jouni Malinen
9f0429c9e1 dbus: Make sure ServiceDiscoveryRequest/Result does not override pointers
Explicitly free the previously allocated copy if ServiceDiscoveryRequest
or Service DiscvoveryResponse parsing loop finds multiple instances of
the same dict entry.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-11 18:47:12 +03:00
Davide Caratti
d22401d895 dbus: Fix memory leak in case dbus provides 'tlvs' in invalid P2P SD response
Using D-Bus it is possible to request an invalid SD response where
"tlvs" is specified and there is an unknown key (e.g. "bar": "foo"). In
this case, "tlv" is allocated and then never used nor freed. Valgrind
complains as follows:

 36 bytes in 1 blocks are definitely lost in loss record 20 of 74
    at 0x484C214: calloc (vg_replace_malloc.c:1675)
    by 0x41C673: wpabuf_alloc (wpabuf.c:124)
    by 0x41C673: wpabuf_alloc_copy (wpabuf.c:162)
    by 0x54FB94: wpas_dbus_handler_p2p_service_sd_res (dbus_new_handlers_p2p.c:3016)
    by 0x53B9A2: msg_method_handler (dbus_new_helpers.c:356)
    by 0x53B9A2: message_handler (dbus_new_helpers.c:412)
    by 0x4EAB4B8: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.19.13)
    by 0x5495DF: dispatch_data (dbus_common.c:37)
    by 0x5495DF: process_watch (dbus_common.c:73)
    by 0x5495DF: process_watch_read (dbus_common.c:89)
    by 0x41EE8E: eloop_sock_table_dispatch.part.0 (eloop.c:603)
    by 0x41FA46: eloop_sock_table_dispatch (eloop.c:597)
    by 0x41FA46: eloop_run (eloop.c:1233)
    by 0x56A3EE: wpa_supplicant_run (wpa_supplicant.c:8074)
    by 0x40DB06: main (main.c:393)

Fix it ensuring that "tlv" is freed both in the error and non-error path
of wpas_dbus_handler_p2p_service_sd_res(). Also, add a test case in
test_dbus.py to verify correct behavior.

Signed-off-by: Davide Caratti <davide.caratti@gmail.com>
2024-07-11 18:39:39 +03:00
Davide Caratti
0c2d8417c6 dbus: Fix memory leak in case dbus provides tlv in P2P UPnP SD request
Using D-Bus it is possible to trigger a valid UPnP SD request where
"tlv" is specified: in this case "tlv" is allocated, and then not used
nor freed. Valgrind complains as follows:

 72 bytes in 2 blocks are definitely lost in loss record 46 of 68
    at 0x484C214: calloc (vg_replace_malloc.c:1675)
    by 0x41C673: wpabuf_alloc (wpabuf.c:124)
    by 0x41C673: wpabuf_alloc_copy (wpabuf.c:162)
    by 0x54F8B5: wpas_dbus_handler_p2p_service_sd_req (dbus_new_handlers_p2p.c:2928)
    by 0x53B9A2: msg_method_handler (dbus_new_helpers.c:356)
    by 0x53B9A2: message_handler (dbus_new_helpers.c:412)
    by 0x4EAB4B8: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.19.13)
    by 0x5495DF: dispatch_data (dbus_common.c:37)
    by 0x5495DF: process_watch (dbus_common.c:73)
    by 0x5495DF: process_watch_read (dbus_common.c:89)
    by 0x41EE8E: eloop_sock_table_dispatch.part.0 (eloop.c:603)
    by 0x41FA46: eloop_sock_table_dispatch (eloop.c:597)
    by 0x41FA46: eloop_run (eloop.c:1233)
    by 0x56A3CE: wpa_supplicant_run (wpa_supplicant.c:8074)
    by 0x40DB06: main (main.c:393)

Fix it ensuring that "tlv" is freed, both in the error and non-error
path of wpas_dbus_handler_p2p_service_sd_req(). Also, add a test case in
test_dbus.py to verify correct behavior.

Signed-off-by: Davide Caratti <davide.caratti@gmail.com>
2024-07-11 18:37:14 +03:00
Sascha Hauer
3b4f127084 nl80211: Use actual number of supported AKMs for AP setup
Since 0ce1545dcb ("nl80211: Determine maximum number of supported
AKMs") we get the maximum number of supported AKMs from the kernel.
Let's use that instead of the legacy NL80211_MAX_NR_AKM_SUITES when
setting up AP mode operation.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
2024-07-11 18:30:21 +03:00
Sai Pratyusha Magam
8f69e538a9 SecureLTF: Work around misbehaving STAs for PTK derivation without KDK
Some deployed STAs that advertise SecureLTF support in the RSNXE in
(Re)Association Request frames, do not derive KDK during PTK generation.
Since the correct key calculations in the AP includes an additional KDK
generation in such cases, this causes different PTK-KCK being derived
and the AP ultimately discarding EAPOL-Key message 2/4 due to MIC
validation failure.

Try to derive a PTK without KDK as a workaround in such cases and allow
the 4-way handshake to continue if this results in a matching MIC.

Signed-off-by: Sai Pratyusha Magam <quic_smagam@quicinc.com>
2024-07-11 18:23:49 +03:00
Hu Wang
438a27b369 Do not derive SAE PT if the network profile does not include SAE
wpa_s_setup_sae_pt() derived SAE PT even when the configured key
management options did not include SAE if the global sae_pwe
configuration parameter had been changed to enable H2E. This adds
unnecessary extra delay, so derive PT only if SAE is actually enabled in
the network profile.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-11 17:39:19 +03:00
Aditya Kumar Singh
b7c6aa3ac6 tests: Extend color change test for a non-first link of an AP MLD
Currently color change test is supported only on the first link of the
AP MLD. Extend the support to test on non-first link as well.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-07-11 17:25:25 +03:00
Aditya Kumar Singh
61eb89d5fd nl80211: AP MLD: Parse link ID to determine the BSS for color event
When an HE BSS color event is received from the driver, the event was
delevered to the first link BSS ctx. To support HE BSS color with MLO,
there is a need to identify the correct link for which the event is
intended.

Add link ID parsing support in the event handler and pass the link ID
(if included) down to the event handler so that appropriate link can be
selected.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-07-11 17:23:47 +03:00
Aditya Kumar Singh
5d16ad9ab0 nl80211: Refactor color collision related nl80211 commands handling
Almost same logic is there in handling four different commands related
to color collision. Later when link ID needs to be parsed, it would be
more duplicate logic at four different places. Hence refactor and bring
it in a single function.

No functionality changes.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-07-11 17:21:03 +03:00
Aditya Kumar Singh
22a592d119 hostapd: Fix updating Beacon frames during association handling
In function handle_assoc(), ieee802_11_update_beacons() was used to
update the Beacon frames. However, with commit a5d0bb42a2 ("Reduce
delay between Association Request and Association Response"), it was
changed to ieee802_11_set_beacons() which basically overturned what
commit e59d2a31cf ("hostapd: Fix premature beacon set during
association handling") did which is not correct.

Fix this and use ieee802_11_update_beacons() instead of
ieee802_11_set_beacons().

Fixes: a5d0bb42a2 ("Reduce delay between Association Request and Association Response")
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-07-11 17:13:45 +03:00
Jouni Malinen
9716bf1160 SAE: Reject invalid Rejected Groups element in the parser
There is no need to depend on all uses (i.e., both hostapd and
wpa_supplicant) to verify that the length of the Rejected Groups field
in the Rejected Groups element is valid (i.e., a multiple of two octets)
since the common parser can reject the message when detecting this.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-09 23:37:45 +03:00
Jouni Malinen
593a7c2f8c SAE: Check for invalid Rejected Groups element length explicitly on STA
Instead of practically ignoring an odd octet at the end of the element,
check for such invalid case explicitly. This is needed to avoid a
potential group downgrade attack.

Fixes: 444d76f74f ("SAE: Check that peer's rejected groups are not enabled")
Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-09 23:34:21 +03:00
Aleti Nageshwar Reddy
5f98c853e4 nl80211: Send link ID with NL80211_CMD_TDLS_MGMT to enable TDLS with MLO
The latest Linux kernel is mandating link ID with NL80211_CMD_TDLS_MGMT
for MLO connections. This resulted in not being able to perform TDLS
operations during a multi-link association.

Fix this by sending link ID in NL80211_CMD_TDLS_MGMT when available. If
link ID info is not available, send the link ID of the association link.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-07-09 23:20:50 +03:00
Jouni Malinen
f302d9f964 RADIUS: Check Message-Authenticator if it is present even if not required
Always check the Message-Authenticator attribute in a received RADIUS
message if it is present. Previously, this would have been skipped if
the attribute was not required to be present.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-09 14:58:39 +03:00
Jouni Malinen
58097123ec RADIUS: Require Message-Authenticator attribute in MAC ACL cases
hostapd required Message-Authenticator attribute to be included in EAP
authentication cases, but that requirement was not in place for MAC ACL
cases. Start requiring Message-Authenticator attribute for MAC ACL by
default. Unlike the EAP case, this can still be disabled with
radius_require_message_authenticator=1 to maintain compatibility with
some RADIUS servers when used in a network where the connection to such
a server is secure.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-09 14:58:39 +03:00
Jouni Malinen
934b0c3a45 Require Message-Authenticator in Access-Reject even without EAP-Message
Do not allow the exception for missing Message-Authenticator in
Access-Reject without EAP-Message. While such exception is allowed in
RADIUS definition, there is no strong reason to maintain this since
Access-Reject is supposed to include EAP-Message and even if it doesn't,
discarding Access-Reject will result in the connection not completing.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-09 14:58:39 +03:00
Jouni Malinen
f54157077f RADIUS DAS: Move Message-Authenticator attribute to be the first one
Even if this might not be strictly speaking necessary for mitigating
certain RADIUS protocol attacks, be consistent with the RADIUS server
behavior and move the Message-Authenticator attribute to be the first
attribute in the RADIUS DAS responses from hostapd.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-09 14:58:39 +03:00
Jouni Malinen
37fe8e48ab hostapd: Move Message-Authenticator attribute to be the first one in req
Even if this is not strictly speaking necessary for mitigating certain
RADIUS protocol attacks, be consistent with the RADIUS server behavior
and move the Message-Authenticator attribute to be the first attribute
in the message from RADIUS client in hostapd.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-09 14:58:39 +03:00
Jouni Malinen
689a248260 eapol_test: Move Message-Authenticator attribute to be the first one
Even if this is not strictly speaking necessary for mitigating certain
RADIUS protocol attacks, be consistent with the RADIUS server behavior
and move the Message-Authenticator attribute to be the first attribute
in the message from RADIUS client.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-09 14:58:39 +03:00
Jouni Malinen
54abb0d3cf RADIUS server: Place Message-Authenticator attribute as the first one
Move the Message-Authenticator attribute to be the first attribute in
the RADIUS messages. This mitigates certain MD5 attacks against
RADIUS/UDP.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-09 14:58:39 +03:00
Jouni Malinen
adac846bd0 RADIUS: Allow Message-Authenticator attribute as the first attribute
If a Message-Authenticator attribute was already added to a RADIUS
message, use that attribute instead of adding a new one when finishing
message building. This allows the Message-Authenticator attribute to be
placed as the first attribute in the message.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-09 14:58:39 +03:00
Jouni Malinen
566dc139a0 tests: Include Message-Authenticator attribute in RADIUS tests
This is in preparation for hostapd requiring this attribute for all
cases.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-09 14:58:39 +03:00
Jouni Malinen
2846b74f14 tests: SAE H2E and rejected groups with different APs and different config
Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-07 12:14:34 +03:00
Jouni Malinen
d944ef1c01 SAE: Clear rejected groups list on completing authentication
The rejected groups list is valid only during each individual SAE
authentication instance and it should not be maintained between separate
instances. In particular, it should not be maintained when roaming to
another AP since the APs might use different configuration for the
allowed SAE groups.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-07 12:14:34 +03:00
Jouni Malinen
368aa0230b tests: SAE protocol testing - Invalid Rejected Groups element
Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-07 12:14:33 +03:00
Jouni Malinen
0ab009db3c SAE: Clear rejected groups list on continuous failures
wpa_supplicant used to maintain the list of rejected groups for SAE over
multiple failed attempts. This could have some DoS issues, so clear this
list if SAE authentication attempts fails continuously.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-07 11:58:18 +03:00
Jouni Malinen
21fe042815 SAE: Clear peer_rejected_groups when no element is included
When parsing a SAE Commit message, the temporary peer_rejected_groups
parameter was left to its old value in cases where the new SAE Commit
message did not include the Rejected Groups element. This could result
in unexpected behavior if a previously processed SAE Commit message
included a Rejected Groups element that claimed one of the enabled
groups to be rejected.

Explicitly clear the peer_rejected_groups value when parsing an SAE
Commit message without a Rejected Groups element to avoid rejecting the
new message based on some previously received incorrect information.
This avoids some potential denial-of-service issues during the lifetime
of the SAE temporary data.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-07 11:48:35 +03:00
Jouni Malinen
364c2da874 SAE: Check for invalid Rejected Groups element length explicitly
Instead of practically ignoring an odd octet at the end of the element,
check for such invalid case explicitly. This is needed to avoid a
potential group downgrade attack.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-07-07 11:46:49 +03:00
Gururaj Pandurangi
c9db4925f6 Vendor attribute to configure STA to follow AP preference for candidates
Add a vendor attribute to configure a STA to follow AP advertised
preference values to select roam candidates with BTM.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-06-20 18:59:00 +03:00
Purushottam Kushwaha
0cb42655fb Vendor command extension for Responder PM Mode bit in TWT SET Request
Use the existing QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE
attribute for TWT setup request to configure the Responder PM Mode bit
in the control field of the TWT element or broadcast TWT schedule.

Signed-off-by: Purushottam Kushwaha <quic_pkushwah@quicinc.com>
2024-06-20 18:54:51 +03:00
Purushottam Kushwaha
9832f13242 Add vendor flag to indicate unavailability mode in TWT responder mode
Add a flag attribute
QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_UNAVAILABILITY_MODE into enum
qca_wlan_vendor_attr_twt_set_param to configure the TWT responder
unavailability outside of the SPs of its broadcast TWT schedule.

Signed-off-by: Purushottam Kushwaha <quic_pkushwah@quicinc.com>
2024-06-20 18:52:53 +03:00
Jouni Malinen
7cf0021267 tests: SAE protocol testing and a valid commit after a failed one
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-06-20 18:24:10 +03:00
Chenming Huang
761041b18a SAE: Free password identifier if SAE commit is rejected due to it
Authentication rejection was found when doing fuzz testing even with a
valid SAE commit message when it was sent after a SAE commit message
that included an incorrect password identifier. The test steps for this
are as below:

1. Peer sends an abnormal commit message with incorrect password
   identifier
2. APUT rejects as expected
3. Peer sends a valid commit message
4. APUT rejects again, which is not expected

In step 2, as the abnormal data fakes an empty password identifier
element, it passes sae_is_password_id_elem() checking. Memory is then
allocated for sae->tmp->pw_id. The authentication process then fails
due to no available password with this invalid password identifier.

In step 4, though the peer sends a valid commit message, APUT rejects
this SAE commit again due to no password identifier element (due to that
sae->tmp->pw_id being set), which is not expected.

Free the sae->tmp->pw_id field and set it to NULL when SAE commit
message processing fails due to an unknown password identifier so that
the bogus value is not used as a requirement for any consecutive SAE
commit from the same STA before the STA entry gets cleared.

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-06-20 18:19:26 +03:00
Nidhi Jain
d97b5c6492 Define Link Id attribute for secure ranging context vendor command
The Link Id attribute is required for secure ranging context to identify
the link on which the command is received for an MLD.

Signed-off-by: Nidhi Jain <quic_nidhjain@quicinc.com>
2024-06-19 22:33:52 +03:00
Nidhi Jain
2097de2a6a Define Link Id attribute for QCA_NL80211_VENDOR_SUBCMD_PASN
The Link Id attribute is required for QCA_NL80211_VENDOR_SUBCMD_PASN to
identify the link on which the command is received for an MLD.

Signed-off-by: Nidhi Jain <quic_nidhjain@quicinc.com>
2024-06-19 22:31:59 +03:00
Diya Sati
c6e55fb96b Add Link ID for External ACS vendor command
The Link Id attribute is required for external ACS context to identify
the link on which the command is received for an AP MLD.

Signed-off-by: Diya Sati <quic_dsati@quicinc.com>
2024-06-19 22:28:50 +03:00
Jouni Malinen
b54ccd4129 tests: SAE with SSID protection in 4-way handshake
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-06-19 12:38:14 +03:00
Jouni Malinen
37a289f8bc SSID protection in 4-way handshake on AP
Add support for SSID protection in 4-way handshake based on the
mechanism added in IEEE 802.11REVme/D6.0. This is a mitigation against
CVE-2023-52424 (a.k.a. the SSID Confusion Attack).

This functionality is disabled by default and can be enabled with
ssid_protection=1. Once there has been more testing of this to confirm
there is no significant interoperability issues, the goal is to be able
to change this to be enabled by default.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-06-19 12:38:14 +03:00
Jouni Malinen
dab7549d68 SSID protection in 4-way handshake on STA
Add support for SSID protection in 4-way handshake based on the
mechanism added in IEEE 802.11REVme/D6.0. This is a mitigation against
CVE-2023-52424 (a.k.a. the SSID Confusion Attack).

This functionality is disabled by default and can be enabled with
ssid_protection=1 in the network profile. Once there has been more
testing of this to confirm there is no significant interoperability
issues, the goal is to be able to change this to be enabled by default.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-06-19 12:31:04 +03:00
Veerendranath Jakkam
9a022cdc70 STA: Update scan results when BSS entry with current SSID is not found
wpa_supplicant might use a wrong BSS entry with the SSID different from
the current SSID of the current BSS while processing a roam event from
the driver when wpa_supplicant has a stale BSS entry with the old SSID
and the driver roams to the same BSS after it is restarted with a new
SSID.

To avoid this, update scan results from the driver when a BSS entry is
not found with the current SSID and try to fetch the BSS entry again
with the current SSID after this.

Also, with this change wpa_supplicant_get_new_bss() itself will update
the BSS table and search for the current BSS entry if it is not found in
the BSS table. So, remove the BSS table update and search logic from the
callers of wpa_supplicant_get_new_bss().

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-06-13 18:36:08 +03:00
Aditya Kumar Singh
cb5c4e49c7 tests: Add color change test for an AP MLD
Add the eht_mlo_color_change test case to perform color change on the
first link of an AP MLD. Performing on non-first link will be done
later.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-06-12 12:42:33 +03:00
Aditya Kumar Singh
72203b8fe3 tests: Add HE BSS color change test
Add the he_bss_color_change test case which brings up an HE AP and
performs color change operations and validates the result.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-06-12 12:38:32 +03:00
Aditya Kumar Singh
320c4c8f8d AP MLD: Send link id to the driver during color change
Send the link ID in the nl80211 command to switch color if the AP is
affiliated with an AP MLD.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-06-12 12:31:45 +03:00
Aditya Kumar Singh
ecfe2aa61b Update Beacon frames after color change
Once CCA is finished, Beacon frames need to be updated. The BCCA element
needs to be removed and the new color value shall be advertised in the
BSS Color Information field of the HE Operation element.

Update the Beacon frames accordingly.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-06-12 12:25:26 +03:00
Aditya Kumar Singh
5913d1a187 Remove double "on" from debug prints in CCA event callbacks
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-06-12 12:22:34 +03:00
Aditya Kumar Singh
d8e1a353a6 hostapd: Add support to change BSS color from the control interface
Add hostapd_cli command "color_change <color>" to change BSS color at
run time. hostapd_cli status can be used to check the updated color.

Usage: hostapd_cli -i <interface> color_change <color>

If 0 value is given, HE BSS color would be disabled. Same or a non-zero
value between [1-63] can be given to enable color again.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-06-12 12:21:09 +03:00
Harshitha Prem
3e52a90d34 ACS: Handle scan start request failure with error code -EBUSY
Currently, if ACS scan request fails, states are cleared and returned.
However, in case of MLO, there is a possibilty of getting return value
of -EBUSY. In this case, ACS can retry the scan request after some time
similary to the HT40 scan.

Hence, retry the scan after 5 seconds if -EBUSY is returned. Maximum of
15 re-attempts are made before giving up.

Signed-off-by: Harshitha Prem <quic_hprem@quicinc.com>
Co-developed-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-06-12 00:25:17 +03:00
Aditya Kumar Singh
3cf7bf68f4 AP MLD: Fix deferred first link BSS's authentication server init
Currently, RADIUS client, auth server, and 802.1X are copied from the
first link's BSS into the non-first link during its setup. However,
there could be a case where the first link is not initialized fully
because of ACS/HT40 SCAN/DFS. Hence, in such cases, NULL is getting
copied and later it leads to segmentation fault.

Initialize those on behalf of the first link in such case and update it
so that the next time other non-first link can use it.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-06-11 23:41:03 +03:00
Jouni Malinen
2829f1c439 wlantest: Initial support for Multiple BSSID procedure
Parse the Multiple BSSID element in Beacon frames and create and update
all the nontransmitted BSSs.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-06-10 21:27:00 +03:00
Balamurugan Mahalingam
1b96745f1d Add a new QCA vendor attribute to set interface offload type
Userspace tools can use QCA_WLAN_VENDOR_ATTR_CONFIG_IF_OFFLOAD_TYPE to
configure the different below acceleration features (hardware, software)
on a per interface basis.

0 - No acceleration Packets are processed through the Linux kernel
networking stack.

1 - Software based acceleration: Packets are processed through the
shortcut forwarding engine (SFE) to bypass the Linux networking stack
for improved throughput performance. This option is applicable for AP,
STA, and Mesh mode and available for all radio designs. From the
performance aspect, this option consumes more CPU compared to the other
two options. Linux traffic control can be further applied with this
option to have more control on the traffic flows.

2 - Hybrid acceleration (software and hardware acceleration combined):
Packets are processed through both hardware and software in this case.
Packet classification is done by the hardware and then the packets are
delivered to software along with classification results as meta data.
Software can choose to do more classification/QoS based on use cases.
This is applicable for AP, STA, and Mesh modes and is available for all
radio designs. From the performance aspect, this option consumes
relatively less CPU compared to the SFE option above. Linux traffic
control rules cannot be applied with this option.

3 - Hardware based acceleration : Packets are processed through special
hardware (Direct Switch) rings which can directly forward the packets
between ethernet hardware and Wi-Fi hardware with very less software
involvement. This is applicable only for AP and STA modes; not
applicable for Mesh mode. From the performance aspect, this option
consumes very much less CPU compared to the other options. Linux traffic
control rules cannot be applied when this option is used. This option is
applicable only for specific radio designs. When this option is not
available, the default option (SFE) would be configured.

Signed-off-by: Balamurugan Mahalingam <quic_bmahalin@quicinc.com>
2024-06-07 16:21:54 +03:00
Jianmin Zhu
ffcb7392f0 Add vendor attributes to detect data stall for consecutive TX no ack
Add following vendor attributes to dynamically configure parameters to
detect data stall for consecutive TX no ack.
 - QCA_WLAN_VENDOR_ATTR_CONFIG_CONSECUTIVE_TX_NO_ACK_DURATION
 - QCA_WLAN_VENDOR_ATTR_CONFIG_CONSECUTIVE_TX_NO_ACK_THRESHOLD

Signed-off-by: Jianmin Zhu <quic_jianminz@quicinc.com>
2024-06-07 15:51:17 +03:00
Kiran Kumar Lokere
a5ee11e025 Add new traffic type values for flow report vendor attribute
Define new traffic type values for
QCA_WLAN_VENDOR_ATTR_FLOW_STATS_TRAFFIC_TYPE attribute.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-06-07 15:46:36 +03:00
Jouni Malinen
e4e91f5320 tests: WNM BSS max idle period management
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-05-29 23:46:02 +03:00
Jouni Malinen
2c89b56d64 WNM: Include BSS max idle period in STATUS command output
This makes it a bit easier to test BSS max idle period management.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-05-29 23:40:22 +03:00
Jouni Malinen
58ac46baf7 WNM: AP configuration to allow BSS max idle period requests
Add a new hostapd configuration parameter max_acceptable_idle_period to
allow the AP to accept per-STA requested BSS max idle periods.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-05-29 23:40:22 +03:00
Jouni Malinen
6594ea9ef1 WNM: Allow a specific BSS max idle period to be requested
Add a new wpa_supplicant network profile parameter max_idle that can be
used to specify a specific maximum idle period in units of 1000 TUs
(1.024 s) for associations.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-05-29 22:12:48 +03:00
Jouni Malinen
829ab90d27 tests: Use consistent indentation level for clear_regdom_state()
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-05-29 13:21:02 +03:00
Jouni Malinen
fdf23679f8 tests: More coverage for WNM BSS max idle period management
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-05-29 13:20:02 +03:00
Jouni Malinen
6cd0231112 WNM: Group rekeying skipping with BSS max idle period management
Allow hostapd to be configured to not disconnect a STA if the STA fails
to reply to a group key handshake when BSS max idle period management is
used. This might be needed for some STAs that use aggressive power
saving (e.g., battery powered IoT devices).

This is disabled by default since this can delayed group rekeying
slightly and also to maintain the previous behavior. The more relaxed
operation can be enabled with the new configuration parameter
no_disconnect_on_group_keyerror=1.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-05-29 12:57:08 +03:00
Jouni Malinen
846b1d618c WNM: Configurable BSS Max Idle Period management on AP
Allow AP's behavior for BSS Max Idle Period management to be configured.
Previously, this was automatically enabled for all CONFIG_WNM_AP=y
builds. This can now be changed with the new hostapd configuration
parameter bss_max_idle:
0 = BSS Max Idle Period management disabled
1 = BSS Max Idle Period management enabled
    (default and the previous behavior)
2 = BSS Max Idle Period management enabled with requirement for
    protected keep-alive frames

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-05-29 12:45:02 +03:00
Aleti Nageshwar Reddy
7566370a96 Add QCA vendor attribute to get number of TX/RX packets for each NSS
Add support to get the number of TX/RX packets for each NSS value from
the driver.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-05-10 19:57:55 +03:00
Aditya Kodukula
4c0ea82700 Add vendor attributes to configure TX/RX NSS and chains per band
Add attributes to QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
vendor command to configure asymmetric TX/RX NSS and chains per band.
Also document driver's response when existing attributes to configure
TX/RX NSS and chains for all the bands 2.4 GHz and 5/6 GHz are used in
the same command.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-05-10 19:30:23 +03:00
Aditya Kodukula
c484a0fca4 Add kernel documentation for nss and chain configuration vendor command
Add kernel documentation to the attributes used in the vendor command
QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION to configure the NSS
and chains values used for transmitting and receiving the data.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-05-10 19:21:54 +03:00
Veerendranath Jakkam
cb40986a7e Add QCA vendor attribute for uplink delay jitter
Add uplink delay jitter attribute in responses of
QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor command.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-05-10 12:17:29 +03:00
mtk30479
ed56dfc339 P2P: Fix fast IP address allocation for invitation of a persistent group
Allocate static IPv4 address in EAPOL frames during 4-way handshake
instead of DHCP when using P2P invitation. wpa_s->current_bss needs to
be set for the P2P specific IP address assignment mechanism to be used
in wpa_supplicant_rsn_supp_set_config(). This worked for the initial P2P
connection, but not for some cases reinvoking a persistent group.

Since there is only one AP (P2P GO) in the P2P client case, the
conditions added in commit 4d3be9cdd1 ("Postpone updating of
wpa_s->current_bss till association event") are not needed and the
easiest approach for this is to allow current_bss to be set for
p2p_in_invitation cases. If the GO P2P Interface Address (BSSID) could
be determined for all the related cases, this could be addressed a bit
more cleanly by setting the go_bssid argument for
wpas_start_p2p_client(), but that can be left as a possible future step.

Signed-off-by: tzu-meng wang <tzu-meng.wang@mediatek.com>
2024-05-08 00:32:46 +03:00
Mukul Sharma
0ae087994c Add a new QCA vendor attribute to set reduced power scan mode
Userspace can use QCA_WLAN_VENDOR_ATTR_CONFIG_REDUCED_POWER_SCAN_MODE to
configure reduce power scan mode to the driver/firmware.

Signed-off-by: Mukul Sharma <quic_mukul@quicinc.com>
2024-05-08 00:17:43 +03:00
Jouni Malinen
bd36dc90f1 AP MLD: Remove unused get_ml_rsn_info callback definition
This is not used anymore after the previous AP MLD cleanup.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-25 11:56:23 +03:00
Aditya Kumar Singh
1dda619ed2 tests: Cohosted MLDs connectivity testing
Add a test case 'eht_mld_cohosted_connectivity' which creates two 2 link
AP MLDs and connect a 2 link MLD client to each one of them and test
data traffic.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-24 21:58:49 +03:00
Aditya Kumar Singh
a1e585fb63 tests: Basic cohosted MLDs functionality testing
Add test cases to test basic cohosted MLDs functionality. Add helper
functions to create the configuration file, start hostapd instance.

Client connectivity test case will be added via a subsequent commit.

eht_mld_cohosted_discovery: 2 co-hosted MLDs without non-MLD RNR. Basic
bring up and beacon, MLD RNR, scan validation.

eht_mld_cohosted_discovery_with_rnr: Same like eht_mld_cohosted_discovery
but additionally non-MLD RNR (rnr=1) is also enabled. Validate the non-MLD
RNR as well.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-24 21:58:49 +03:00
Rathees Kumar R Chinannan
51b5b9512f Update Probe Response template on BSS color change
When AP is beaconing only on the 6 GHz band and unsol_bcast_presp
interval is set, AP sends unsolicited broadcast Probe Response frames
for in-band discovery. hostapd sent the Probe Response template for this
frame only when setting a new Beacon frame template.

Extend this to update the Probe Response template during BSS color
change.

Signed-off-by: Rathees Kumar R Chinannan <quic_rrchinan@quicinc.com>
2024-04-24 21:58:49 +03:00
Rathees Kumar R Chinannan
6f1fbebeb6 Update Probe Response template on channel switch
When AP is beaconing only on the 6 GHz band and unsol_bcast_presp
interval is set, AP sends unsolicited broadcast Probe Response frames
for in-band discovery. hostapd sent the Probe Response template for this
frame only when setting a new Beacon frame template.

Extend this to update the Probe Response template during channel switch.

Signed-off-by: Rathees Kumar R Chinannan <quic_rrchinan@quicinc.com>
2024-04-24 21:58:49 +03:00
Rathees Kumar R Chinannan
7d0c08910b More generic unsolicited broadcast Probe Response template setup
When AP is beaconing only on the 6 GHz band and unsol_bcast_presp
interval is set, AP sends unsolicited broadcast Probe Response frames
for in-band discovery. hostapd sent the Probe Response template for this
frame only when setting a new beacon.

As a preparation for extending this functionality to other cases, move
the generation of the unsolicited broadcast Probe Response template into
a more generic function and data structure.

Signed-off-by: Rathees Kumar R Chinannan <quic_rrchinan@quicinc.com>
2024-04-24 21:58:49 +03:00
Jouni Malinen
b38f14e13d tests: Update opclass 124 test to use opclass 125
This is needed to match the implementation change to map the 5 GHz
channels 149-175 to the global operating class 125 instead of 124.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-24 21:58:49 +03:00
Jouni Malinen
ef5d2f9e8f tests: Fix a typo in opclass test descriptions
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-24 21:58:49 +03:00
Amith A
195cc3d919 Make selection of current opclass more generic for 20 MHz UNI-III channels
According to IEEE Std 802.11-2020, Operating classes Table E-2 (Europe)
and Table E-6 (China) map channels in the range 149 to 161 to the global
operating class 125, while Table E-1 (United States) maps these channels
to global operating classes 125 and 124 as well. The global operating
class 125 contains all channels from the global operating class 124 and
some additional channels.

Hence, to make the selection of the current operating class generic, use
operating class 125 for all 20 MHz channels in the range 149 to 161.

Signed-off-by: Amith A <quic_amitajit@quicinc.com>
2024-04-24 00:19:05 +03:00
Sriram R
b9113105ad FILS: Add Operating Class and Primary Channel in FD for non-PSC chan
If a non-PSC 6 GHz channel with bandwidth higher than 20 MHz is
configured, duplicate beacons/FD/UBPR will be transmitted in other 20
MHz channels of the current configured bandwidth to aid in faster scan.
In such cases the duplicate FD needs to carry the Operating Class and
Primary Channel subfields for non-AP STAs to identify the primary
non-PSC.

IEEE Std 802.11-2020, 9.6.7.36 (FILS Discovery frame format):
"The Operating Class subfield specifies the operating class of the
Primary Channel of the transmitting AP (see 9.4.1.36).

The Primary Channel subfield is set to the channel number of the primary
channel (see 11.15.2) if the FILS Discovery frame is transmitted as a
non-HT duplicate PPDU; otherwise, the subfield is not present."

Hence, add the Operating Class and Primary Channel subfields if the
current channel is non-PSC and the channel bandwidth is 40 MHz or
higher.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Karthikeyan Kathirvel <quic_kathirve@quicinc.com>
2024-04-24 00:17:15 +03:00
Rakesh Pillai
5929b4eb1d Define QCA vendor commands for flow stats/classification
Add nl80211 vendor commands and attributes for the collection of flow
stats and classification.

- QCA_NL80211_VENDOR_SUBCMD_FLOW_STATS
- QCA_NL80211_VENDOR_SUBCMD_FLOW_CLASSIFY_RESULT
- QCA_NL80211_VENDOR_SUBCMD_ASYNC_STATS_POLICY
- QCA_NL80211_VENDOR_SUBCMD_CLASSIFIED_FLOW_REPORT

Signed-off-by: Rakesh Pillai <quic_pillair@quicinc.com>
2024-04-23 15:49:38 +03:00
Chenming Huang
5308029f86 nl80211: Update link bandwidth when receiving channel switch event
There is a chance that the driver has switched the channel width so we
should update the bandwidth, too, when receiving a channel switch event.
Otherwise, this may cause out of sync for bandwidth between i802_link
and hostapd_config.

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-04-22 23:39:20 +03:00
Chenming Huang
11dfdf64c0 AP MLD: Set link_id field in hostapd_freq_params when setting up AP
If not set, 0 is set by default and this could fail in the following
code path when link ID is not matching:
hostapd_drv_set_ap -> wpa_driver_nl80211_set_ap -> nl80211_set_channel

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-04-22 23:33:15 +03:00
Purushottam Kushwaha
df14f1e2bd Add QCA vendor subcommand to suspend/resume AP interface
Add a new QCA vendor subcommand QCA_NL80211_VENDOR_SUBCMD_AP_SUSPEND to
allow suspend and resume the AP interface. When an AP is suspended, it
disconnects all connected clients and stops all TX/RX operations on the
AP interface. The driver retains the AP configuration and on resume, all
AP operations are resumed with the same configuration.

This subcommand is also used in the event path to notify userspace about
AP suspended or resumed state changes.

This uses attributes defined in enum qca_wlan_vendor_attr_ap_suspend.

Signed-off-by: Purushottam Kushwaha <quic_pkushwah@quicinc.com>
2024-04-22 23:19:49 +03:00
Jouni Malinen
e141b33a66 tests: Fix a race condition in mesh_link_probe
Wait for both peers to be connected before checking MESH_LINK_PROBE
behavior. Without this, it was possible for a MESH_LINK_PROBE command to
be issues before the specific peer had been added and that would result
in the nl80211 command failing.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-22 23:14:08 +03:00
Jouni Malinen
97da087c0c tests: Fix autogo_chan_switch to not drop HT capability
This test case ended up dropping HT capability on channel switch which
is now resulting in mac80211 disconnecting. Avoid this by leaving HT
enabled. In addition, check the P2P Client events explicitly.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-22 16:17:39 +03:00
Jouni Malinen
42080798b5 tests: AP MLD with two links when only one of the links is negotiated
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-22 14:38:59 +03:00
Jouni Malinen
df59880042 AP MLD: Add MLO Link KDE for each affiliated link in EAPOL-Key 3/4
Previously, MLO Link KDE was added only for each link that was
negotiated for the ML association. However, IEEE Std 802.11be/D5.0,
12.7.6.1 defines the MLO Link KDE to be included "for each affiliated
AP" which is not constrained by what the non-AP MLD might have requested
or what the negotiation outcome for this particular ML association is.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-22 14:38:59 +03:00
Jouni Malinen
b26971774c AP MLD: Do not store per-supplicant AP RSNE/RSNXE information
There is no need to store the AP MLD's RSNE/RSNXE within per-supplicant
data structure in struct wpa_state_machine since those elements are
available from the generic authenticator data in struct
wpa_authenticator.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-22 14:38:59 +03:00
Jouni Malinen
20872d5256 AP MLD: Do not store per-supplicant AP link MAC address information
There is no need to store the AP MLD's link MAC addresses within
per-supplicant data structure in struct wpa_state_machine since those
MAC addresses are available from the generic authenticator data in
struct wpa_authenticator.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-22 14:38:59 +03:00
Jouni Malinen
3b68eef7d7 AP MLD: Do not store per-supplicant AP MLD MAC address information
There is no need to store the AP MLD MAC address within per-supplicant
data structure in struct wpa_state_machine since that MLD MAC address is
available from the generic authenticator data in struct
wpa_authenticator.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-22 14:38:59 +03:00
Aleti Nageshwar Reddy
ed78f56dce Add a vendor attribute value to set aggressive roaming mode
Add QCA_ROAMING_MODE_AGGRESSIVE in enum qca_roaming_policy to set
aggressive roaming mode. In addition, document the existing enum values.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-22 12:48:25 +03:00
Jouni Malinen
8f83b7d7d1 tests: WPA2-PSK from RADIUS during 4-way handshake with Session-Timeout
Signed-off-by: Jouni Malinen <j@w1.fi>
2024-04-21 11:55:53 +03:00
Lee Harding
e6ec62aa2d Allow Session-Timeout with PSK RADIUS during 4-way handshake
When the RADIUS response included a Session-Timeout attribute, but is
otherwise valid (an Access-Accept with a valid Tunnel-Password), the
association still failed due to the strict comparison of the accepted
value with HOSTAPD_ACL_ACCEPT. Apparently this combination wasn't
previously tested.

Extend this to allow a packet containing a valid Session-Timeout
attribute to be accepted by extending the "success" comparison to
include HOSTAPD_ACL_ACCEPT_TIMEOUT.

Fixes: 1c3438fec4 ("RADIUS ACL/PSK check during 4-way handshake")
Signed-off-by: Lee Harding <somerandomstring@gmail.com>
2024-04-21 11:55:53 +03:00
arun.jose
f44a07d5c4 wpa_cli: Make WPA_EVENT_CHANNEL_SWITCH events accessible to action scripts
Make the channel switch complete event, WPA_EVENT_CHANNEL_SWITCH,
accessible to the action script.

Signed-off-by: arun.jose <arun.jose.wg@bp.renesas.com>
2024-04-21 11:55:53 +03:00
Jurijs Soloveckis
2e1f7d091c Fix center segment indexes in channel switch fallback to non-5 GHz cases
Hardcoded conversion for 5 GHz band was used, but this won't work for
other cases. Set the correct center segment indexes in channel switch
fallback for non-5GHz band.

Signed-off-by: Jurijs Soloveckis <jsoloveckis@maxlinear.com>
2024-04-21 11:55:53 +03:00
Benjamin Berg
7cf3ceadaa P2P: Call normal SD query callback on RX/TX race
If the TX success response races with the RX frame then the state
machine was simply move to P2P_SD_DURING_FIND to continue the operation.
However, this does not take into account broadcast queries where the
callback handler updates the peer's sd_pending_bcast_queries.

Fix this by exporting the callback and calling it directly. This is
fine, as the operation is cancelled immediately afterwards, ensuring
that the callback is not called a second time.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-04-21 11:55:53 +03:00
Andrei Otcheretianski
9b1e0ab4e8 dbus: Use correct values for persistent group
D-Bus expects "persistent" to be a bool (0/1) and crashes otherwise.
Since persistent may also be 2 convert it to boolean.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-04-21 11:55:53 +03:00
Ilan Peer
cf36ffd43c wpa_supplicant: Do not allow fast associate before scanning 6 GHz
In case the channel map was updated to include the 6 GHz but these channels
were not scanned yet, do not allow fast associate.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
2024-04-21 11:55:53 +03:00
Benjamin Berg
ff798fbb83 ctrl_iface: Allow sending ML probe without AP MLD ID
If one sends a Probe Request frame to a non-TX BSSID, no AP MLD ID
should be included in the request. Permit mld_id to be -1 so that it is
not a required argument and can be left out.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-04-21 11:55:53 +03:00
Ilan Peer
4d2f76fabf MLD: Use AP MLD MAC address with deauthenticate
When the authentication is an MLD authentication need to use the AP MLD
MAC address when requesting the driver to deauthenticate.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
2024-04-21 11:55:53 +03:00
Ilan Peer
5d9b4a1a14 SME: MLD: Clear MLD state only after the deauthentication
In case of failure handling an Authentication frame from the AP MLD,
clear the MLD state only after the deauthentication is done. This allows
deauthentication process to use the AP MLD MAC address.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
2024-04-21 11:55:53 +03:00
Ilan Peer
39fefeada6 SME: MLD: Deauthenticate when failing to parse ML element
If parsing the basic ML element in the Authenticate frame fails,
instead of only disassociating, completely deauthenticate so all
state machines would be in a consistent state.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
2024-04-21 11:01:28 +03:00
Ilan Peer
6f3e7c5d3e wpa_supplicant: Do not roam to an associated link
When considering to roam to a different BSS and the connection
is an MLD connection, do not roam to a BSS which is already
included in the MLD connection.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
2024-04-21 11:00:13 +03:00
Ilan Peer
0df2c72c54 tests: Wait after removing a BSS
When a BSS is removed, the flow continues without actually
waiting for the AP to be stopped. This is racy in flows that
actually expect the AP to be stopped, e.g., test_ap_bss_add_remove().

Try to mitigate such cases by adding a short sleep after the
AP is removed.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
2024-04-21 10:53:39 +03:00
Jouni Malinen
2bbe4822a6 Clear connect_without_scan on network profile removal
wpa_s->connect_without_scan could have been left pointing to invalid
network when a network profile was removed. It seems to be possible for
this to happen in some hwsim test case scenarios under specific timing,
but the exact reason for this is not clear. In any case, this pointer
needs to be cleared.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-04-20 18:42:26 +03:00
Jouni Malinen
42517eb3b0 tests: Clear scan cache in ap_hs20_anqp_invalid_gas_response
This is needed to avoid unexpected behavior if a previously executed
test case has left a BSS entry with Interworking emabled into the case.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-04-20 18:31:11 +03:00
Jouni Malinen
b3ad54e460 Check whether to skip a BSS in RNR with a shared helper
The functions that determine the length of the RNR information and that
build the actual RNR need to use the same conditions for skipping BSSs.
Use a shared helper function for this to avoid having to maintain two
copies of the same implementation and the risking those getting out of
sync.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-20 18:31:11 +03:00
Aditya Kumar Singh
de1bfda64e Fix RNR building for co-location and MLO
RNR formation for co-location or MLO did not work as expected. Fix this.

For example, during co-location, if the BSS is also its ML partner
there is no need to include a separate TBTT for it.

Also, during co-location, if the BSS is not its partner but it is ML
capable, the TBTT length should be 16 bytes and it should include the
MLD Parameters for it in the RNR.

During co-location, for a given Neighbor AP (operating on a given
channel and op-class) if it has BSSs which are ML capable as well as
BSSs which are not, there should be two Neighbor AP Info present: one
indicating TBTT length as 13 bytes and one indicating TBTT info length
as 16 bytes.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Harshitha Prem
8d434bf65c AP MLD: Add link details in STATUS command
Include link ID and partner link details in the STATUS command output
for AP MLDs.

The details would be seen as below for an AP MLD interface:

$ hostapd_cli -i wlan0 status | grep link
num_links=1
link_id=0
link_addr=AA:BB:CC:DD:EE:FF

$ hostapd_cli -i wlan1 status | grep link
num_links=2
link_id=0
link_addr=AA:BB:CC:DD:EE:FF
partner_link[1]=AA:BB:CC:DD:EE:AA

Signed-off-by: Harshitha Prem <quic_hprem@quicinc.com>
Co-developed-by: Manish Dharanenthiran <quic_mdharane@quicinc.com>
Signed-off-by: Manish Dharanenthiran <quic_mdharane@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Aditya Kumar Singh
b1e463374e AP MLD: Link-specific flushing of stations
Whenever a BSS was set up,hostapd flushed all stations via the flush()
driver operation which maps to NL80211_CMD_DEL_STATION in the nl80211
interface. However, in case of MLO, a station could have been connected
to other links by the time this link is coming up. Since link ID was not
passed to flush(), all those stations entries were also removed in the
driver which is wrong.

Include the link ID along with the command in AP MLD so that the driver
can use this link ID and flush only the stations that use the passed
link ID as one of their links.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Rameshkumar Sundaram
5e3c2b489c AP MLD: Run authenticator state machine for all links
This is needed for MLO group rekeying.

Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Co-developed-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
Signed-off-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Rameshkumar Sundaram
12acda633b AP MLD: Support group rekeying for MLO
Group rekeying was not supported for ML stations when non-association
link initiates a group rekey. Support this by arming the group key rekey
timer on one of the affiliated links and whenever this timer fires,
rekey group keys on all the affiliated links.

Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Co-developed-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
Signed-off-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Rameshkumar Sundaram
62a8f96e5b AP MLD: Calculate ML KDE length separately for each link
Calculate links specific MLO GTK/IGTK/BIGTK KDE lengths based on
corresponding cipher and key instead of taking length of one link and
multiplying it by no of associated links. This is needed since the group
ciphers might be different between the affiliated links.

Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Co-developed-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
Signed-off-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Rameshkumar Sundaram
78adbf2c08 AP MLD: Mark GKeyDone completed for STAs in a helper function
This makes it easier to extend the design for MLO group rekeying.

Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Co-developed-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
Signed-off-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Rameshkumar Sundaram
e5b49876a8 AP MLD: Debug print of MLO KDE lengths
Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Co-developed-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
Signed-off-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Rameshkumar Sundaram
84d2a36da0 AP MLD: Require same AKM and pairwise cipher for all links
Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Co-developed-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
Signed-off-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Jouni Malinen
8891ebdc1d Use defined values for RSN PN length
Make the code more readable by using a define for the PN length to avoid
potential confusion of this 6 octet length with the MAC address length.
In addition, Use ETH_ALEN more consistently for the latter.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-20 18:31:11 +03:00
Rameshkumar Sundaram
3ea7cf11db AP MLD: Enhance authenticator state machine
Add required ML specific members in struct wpa_authenticator and struct
wpa_state_machine to maintain self and partner link information.

Maintain state machine object in all associated link stations and
destroy/remove references from the same whenever link stations are
getting removed.

Increase the wpa_group object reference count for all links in which ML
station is getting associated and release the same whenever link
stations are getting removed.

Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Aditya Kumar Singh
19fdcf511b AP MLD: Skip association link processing in ML info
All links were iterated over during processing ML info in Association
Request frame. However, the association link info will not be present in
the ML info and hence the following debug print is observed during ML
association (assoc link is 1):

MLD: No link match for link_id=1

Skip processing for the association link to avoid this.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Sriram R
4a1197acde AP MLD: Update all partner links' beacons
Whenever there is a beacon update for any one of the affiliated link,
all the other partner links' beacon should be refreshed.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Sriram R
a518810322 AP MLD: Handle link_id in EAPOL RX handler
Add link ID support into EAPOL RX handler so that the events can
be routed to the appropriate link BSSs.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Sriram R
eea52c4b51 AP MLD: Handle link_id in EAPOL TX status handler
Add link ID support into EAPOL TX status handler so that the events can
be routed to the appropriate link BSSs.

Check each BSS's other partner link BSS STA list as well in
hostapd_find_by_sta() to support this.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:11 +03:00
Sriram R
636530bc26 hostapd: Make hostapd_eapol_tx_status() function static
hostapd_eapol_tx_status() function is used only in drv_callbacks.c.
However, it is defined in ieee802_11.c which is not really the correct
place for it.

Hence, move the function into drv_callbacks.c and make it static.

No functionality changes.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 18:31:09 +03:00
Sriram R
93d204b1ee nl80211: Move control port TX status to per BSS handling
Control port TX status events were handled on drv's first BSS
only. However, to support multiple MLDs there is requirement to handle
this on a given BSS.

Use the passed BSS instead of always going with drv's first BSS.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 15:58:48 +03:00
Sriram R
efb484bbce nl80211: Move Management frame TX status to per BSS handling
Management frame TX status events were handled on drv's first BSS
only. However, to support multiple MLDs there is requirement to handle
this on a given BSS.

Use the passed BSS instead of always going with drv's first BSS.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 15:58:48 +03:00
Sriram R
80864d0116 AP MLD/nl80211: Pass ctx in mlme_event_mgmt()
Pass ctx in mlme_event_mgmt(). This will help in routing the event
properly to the link BSS.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 15:58:48 +03:00
Sriram R
c36ad11500 AP MLD: Use link_id in the get_hapd_bssid() helper function
The get_hapd_bssid() function matched the given BSSID in all BSSs of its
own interface. However with MLO, there is requirement to check its own
partner BSS at least.

Compare the BSS's link partners as well and if the specified link ID
matches the link ID of the partner, return the BSS.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 15:58:48 +03:00
Sriram R
d9c5d601f1 AP NLD: Extend support for cohosted ML BSS
Modify necessary helper functions to support multiple BSS support for
MLO to make the changes scalable.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 15:58:48 +03:00
Sriram R
3d0cc612fc AP MLD: Support cohosted ML BSS
AP MLD was added with an assumption of only a single BSS per link in the
hostapd configuration. This needs to be extended when a cohosted ML BSS
exist in the same configuration.

Extend the support for cohosted BSSs. This is required for MBSSID MLO
support as well.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 15:58:48 +03:00
Aditya Kumar Singh
9098535ef1 AP MLD: Reset authenticator state machine's ML info
Authenticator state machine ML info was set only when it was created.
However, if the association is tried again, the state machine will
already exist and hence the ML info will not be refreshed. This leads to
an issue where if in the subsequent association request, the MLD info is
different than the old info, validation of it will fail.

Fix this issue by refreshing the authenticator state machine's ML info
every time association request is handled.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 15:58:48 +03:00
Jouni Malinen
866ed63243 Remove the bssid argument from send_auth_reply()
This became unused, so remove the argument from this function, all its
callers, and from places that became unused with these changes.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-20 15:58:48 +03:00
Sriram R
fd1a35e14a AP MLD: Handle authentication and association on link address
The nl80211 driver interface function mlme_event_mgmt_tx_status(),
filled in link_id only if the frame was the last transmitted on the
whole drv (driver) level. With co-hosted MLDs, there could be cases
where multiple frames are sent out by various interfaces (BSS) under the
same drv. Now while handling the TX status, only one interface will get
the proper link_id. Rest will get -1 and the event will be routed to the
first BSS always. If the frame was not sent from the first BSS this
leads to possibility of the frame getting dropped.

Hence to make the underlying link identification easier, modify
authentication and association frames to be always sent with the link
address as A1 and A3 for ease of TX status handling.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-20 15:58:48 +03:00
Jouni Malinen
e4e7724560 AP MLD: Use if/else/endif comments more consistently
Include the condition in #else similarly to #endif.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-20 15:58:12 +03:00
Jouni Malinen
9e3988fc64 tests: Enable TLSv1.3 test cases with OpenSSL 3.3
Signed-off-by: Jouni Malinen <j@w1.fi>
2024-04-20 11:08:50 +03:00
Jouni Malinen
9fcc636daf nl80211: Restore libnl3-route inclusion for full VLAN support with netlink
The changes in nl80211 to get rid of the libnl3-route dependency are not
sufficient to fully remove the depency from other parts of the code.
Revert the makefile related changes from that commit to avoid build
issues for cases where CONFIG_FULL_DYNAMIC_VLAN=y and
CONFIG_VLAN_NETLINK=y are used without CONFIG_DRIVER_MACSEC_LINUX=y
pulling in the needed library.

Fixes: a210fdb1c7 ("nl80211: Rewrite neigh code to not depend on libnl3-route")
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-19 19:04:14 +03:00
Aleti Nageshwar Reddy
61c8cc94fa Add a vendor attribute to configure custom keep-alive interval for STA
Introduce an attribute QCA_WLAN_VENDOR_ATTR_CONFIG_KEEP_ALIVE_INTERVAL
in QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION to configure
station's keep-alive interval to the driver/firmware. This can be used
to resolve kickout issues from APs which kick out STAs before the BSS
maximum idle period expires.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-19 18:54:13 +03:00
Veerendranath Jakkam
47d1307d2c Add QCA vendor interface for reporting station info in unicast event
Add a QCA vendor command for registering NL80211_CMD_GET_STATION
response as a unicast event when there is a NL80211_CMD_GET_STATION
request from any userspace module.

The driver will send the unicast events with the same netlink port ID
which is used by userspace application for sending the registration
command. If multiple registration commands are received with different
netlink port IDs, the driver will send unicast event with each netlink
port ID separately.

Userspace application can deregister the unicast events with disable
configuration. The registrations will be removed automatically by the
driver when the corresponding netlink socket is closed.

This will help avoid multiple NL80211_CMD_GET_STATION requests from
different userspace applications in short span. The userspace
application which registers for the unicast event can avoid sending
NL80211_CMD_GET_STATION request again if the response is available with
a recently received unicast event.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
2024-04-19 18:48:24 +03:00
Manaswini Paluri
3c79173c32 Add TWT responder support for AP in HT and VHT modes
Add support for TWT responder for AP operating in HT and VHT modes by
introducing a new configuration parameter ht_vht_twt_responder. When
this is enabled, TWT responder mode support in HT and VHT modes is
enabled if the driver supports this and is disabled otherwise.

Signed-off-by: Manaswini Paluri<quic_mpaluri@quicinc.com>
2024-04-19 18:38:37 +03:00
Manaswini Paluri
54b1df85c6 Add QCA vendor feature flag for TWT responder support in HT and VHT modes
Add a feature flag to indicate driver support for TWT responder for AP
operating in HT and VHT modes.

Signed-off-by: Manaswini Paluri<quic_mpaluri@quicinc.com>
2024-04-19 18:32:11 +03:00
Jouni Malinen
25e465d5b7 tests: Update RSA 3k certificates (2024)
These have not yet expired, but it is easier to get in sync with all
certificate updates.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-04-17 21:26:36 +03:00
Jouni Malinen
9e59cb8392 tests: Update server and user certificates (2024)
At least some of the previous versions have expired, so need to re-sign
these to avoid EAP test case failures. This contains updates from
running tests/hwsim/auth_server/update.sh.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-04-17 21:25:56 +03:00
Jouni Malinen
ea2c5fe4d1 tests: Fix sigma_dut_dpp_pb_ap to clear sae_groups
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-16 11:22:41 +03:00
Aditya Kumar Singh
85ea5f3496 nl80211: Send link_id on sta_deauth()
i802_sta_deauth() already has the link_id passed to it in its arguments.
Use that to pass it down to send MLME handler as well.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-16 10:56:05 +03:00
Aditya Kumar Singh
62e0c10193 nl80211: Print the interface name in debug during link add
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-16 10:54:45 +03:00
Aditya Kumar Singh
e8764518bd nl80211: Generate link add command on per-BSS basis for AP MLD
Function nl80211_link_add() created the link add netlink message on drv
basis which in turn always uses the drv's first BSS. To support link add
for various other interfaces, use the per-BSS function to create the
netlink message.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-16 10:53:23 +03:00
Aditya Kumar Singh
16aea07e50 AP MLD: Simplify for_each_mld_link() macro
for_each_mld_link() macro used three nested for loops. Since now the
affliated links are linked together via a linked list, the logic can be
improved by using dl_list_for_each() macro instead which uses one for
loop.

Modify for_each_mld_link() macro to use dl_list_for_each() instead.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-04-16 10:51:24 +03:00
Johannes Berg
ae1a9909e0 tests: Add test with stuck ECSA in Probe Response frames
Add a test behaving like an Asus RT-AC53 with firmware
3.0.0.4.380_10760-g21a5898, which (in some cases?) can have an ECSA
element stuck in the probe response, when the channel switch is long
finished.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-04-16 10:46:15 +03:00
Johannes Berg
41fd49958d tests: Add connecting-while-CSA tests
Add a few tests to validate what happens with connections
while an AP is doing CSA:
 - quiet to diff channel (shouldn't connect)
 - quiet to same channel (shouldn't connect)
 - non-quiet to diff channel (shouldn't connect)
 - non-quiet to same channel (should connect)

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-04-16 10:46:13 +03:00
Johannes Berg
d43eb71da7 hostapd: Add support for testing Probe Response frame elements
Add support for additional (vendor) elements to be added
to only Probe Response frames, for testing.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-04-16 10:38:00 +03:00
Jouni Malinen
a6062568ab tests: Fix he_6ghz_reg to clear sae_groups
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-15 23:35:29 +03:00
Felix Fietkau
4b755c9672 build: De-duplicate _DIRS before calling mkdir
If the build path is long, the contents of the _DIRS variable can be
very long, since it repeats the same directories very often. In some
cases, this has triggered an "Argument list too long" build error.

Reported-by: Robert Marko <robimarko@gmail.com>
Suggested-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2024-04-15 23:19:42 +03:00
Felix Fietkau
9a44236452 hostapd: Only attempt to set QoS map if supported by the driver
This fixes issues with full-MAC drivers like brcmfmac.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2024-04-15 23:19:05 +03:00
Felix Fietkau
dec6fccf17 Support qos_map_set without CONFIG_INTERWORKING
This feature is useful on its own even without full interworking
support.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2024-04-15 23:18:24 +03:00
Felix Fietkau
8634e7343d mesh: Allow processing authentication frames in blocked state
If authentication fails repeatedly, e.g., because of a weak signal, the
link can end up in blocked state. If one of the nodes tries to establish
a link again before it is unblocked on the other side, it will block the
link to that other side. The same happens on the other side when it
unblocks the link. In that scenario, the link never recovers on its own.

To fix this, allow restarting authentication even if the link is in
blocked state, but don't initiate the attempt until the blocked period
is over. This reverts commit 09d96de09e ("mesh: Drop Authentication
frames from BLOCKED STA").

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2024-04-15 23:14:33 +03:00
Felix Fietkau
a210fdb1c7 nl80211: Rewrite neigh code to not depend on libnl3-route
This removes an unnecessary dependency and also makes the code smaller.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2024-04-15 23:12:51 +03:00
Felix Fietkau
3ef0579013 ndisc_snoop: Call dl_list_del() before freeing IPv6 addresses
This fixes a segmentation fault on STA disconnect in case IPv6 addresses
where learned for the STA based on snooped neighbor solicication.

Fixes: bd00c4311c ("AP: Add Neighbor Discovery snooping mechanism for Proxy ARP")
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2024-04-15 23:05:00 +03:00
Felix Fietkau
e1cd3fe3cd Cancel channel_list_update_timeout() in hostapd_cleanup_iface_partial()
This fixes a crash when disabling an interface during channel list
update.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2024-04-15 23:02:03 +03:00
Felix Fietkau
47d7f31693 nl80211: Update drv->ifindex on removing the first BSS
Otherwise it will point at the ifindex of the just removed BSS.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2024-04-15 23:00:58 +03:00
Raj Kumar Bhagat
1be706e862 hostapd: Add RRM link measurement request support
RRM link measurement request/report management frames are used to get
the radio link information between the connected stations.

Add new hostapd_cli command req_link_measurement to send an RRM link
measurement request to an associated station. Add support to handle the
link measurement report in hostapd.

RRM link measurement support can be enabled with the following new
configuration parameter:
rrm_link_measurement_report=1

Signed-off-by: Raj Kumar Bhagat <quic_rajkbhag@quicinc.com>
Signed-off-by: Yuvarani V <quic_yuvarani@quicinc.com>
2024-04-15 22:28:55 +03:00
Karthikeyan Kathirvel
92fdb49b2e AP MLD: Set DTIM information properly in per-STA profile
The DTIM information in the per-STA profile is set incorrectly. The DTIM
period is set in the LSB octet of the DTIM Info subfield (2 octets),
which is intended for the DTIM count.

Fix this by setting the DTIM period and DTIM count information properly
to the MSB and LSB octets of the DTIM Info subfield, respectively.

Signed-off-by: Karthikeyan Kathirvel <quic_kathirve@quicinc.com>
Signed-off-by: Govindaraj Saminathan <quic_gsaminat@quicinc.com>
2024-04-15 12:04:01 +03:00
Rajat Soni
36bd75dfd2 hostapd: Fix channel switch to a DFS channel
When we are configuring automatic channel selection, we are not able to
switch to a given DFS channel because when we are trying to move to a
DFS channel, the interface is disabled and enabled again. When the
interface is disabled and enabled we are setting iface's freq and
channel to 0 in setup_interface2() in case ACS is enabled, and now we
don't know to which channel we were trying to move. Now ACS will run and
the interface will be up in the channel that is suitable.

To fix this issue add a flag named is_ch_switch_dfs to check if the
channel switch request is for a DFS channel and we can use this in
setup_interface2() to decide whther we have to set iface's freq and
channel to 0 or not. This way iface's freq and channel will retain the
values while channel switching to a DFS channel when ACS is enabled.

Signed-off-by: Rajat Soni <quic_rajson@quicinc.com>
2024-04-15 11:56:41 +03:00
Chenming Huang
f4b84ecaf7 AP MLD: Track radar detection in offloaded DFS case
Add a new flag radar_detected which is used in the following cases
when setting up a link on a DFS channel while the interface is not yet
enabled:
    1. DFS link received CAC start event
    2. If no radar detected, link setup succeeeds after CAC end
       event is received. Else go to 3.
    3. Radar detected on this link -> set radar_detected bit
    4. CAC end received for the current freq -> Do not setup interface
       as radar already detected. Clear radar_detected bit.
    5. The driver sends channel switch event to switch to another channel
        a. Switch to another DFS channel -> go to 1
        b. Switch to non-DFS channel -> proceed to set up interface

Or when receiving a CAC start event when the interface is already set up:
    1. DFS link already set up successfully
    2. Radar detected on this link -> set radar_detected bit
       a. Switch to DFS channel
           a.1. CAC start -> clear radar_detected bit and partner RNR
           a.2. If radar detected, go to 2.
           a.3. CAC end -> clear radar_detected bit
           a.4. Link enabled successfully
       b. Switch to non-DFS channel
           b.1  No op and the driver handles this

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-04-15 11:38:56 +03:00
Chenming Huang
aaf879ef20 AP MLD: Do not update other links' RNR element if not enabled yet
When one link is still under CAC or disabled, peer links should not
carry the information of this link in the RNR elements.

With this change, the RNR element will be included only if a peer link
is in HAPD_IFACE_ENABLED state.

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-04-15 11:38:49 +03:00
Chenming Huang
32261721e1 nl80211: AP MLD: Parse link ID to determine the BSS for radar event
Link ID is more accurate to specify the BSS for a radar event in some
corner cases, e.g., when there is a radar detection event and the driver
then switches to another DFS channel. There will then be two events
coming from the driver (CAC start and channel switch complete). In case
the CAC-start event comes first, hostapd still stores the previous
frequency and cannot find the correct link by calling
nl80211_get_mld_link_by_freq() with the new frequency.

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-04-15 11:38:42 +03:00
Chenming Huang
216cfd708d AP MLD: Fix missing check for legacy client case
The AP MLD case missed the "else" branch which handles legacy STA's
disassociation. So this STA's sta_info will not be cleared ever.

Add the "else" check to make sure the sta_info gets cleared.

Fixes: 7ceafb6e9f ("AP MLD: Handle disassociation notification with SME offload to driver")
Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-04-15 11:38:42 +03:00
Chenming Huang
d5e6f79988 AP MLD: Request Handle OBSS scan for a specific link
OBSS scan can be required in different links if operating as an AP MLD.
When triggering scan, specify the link ID for the driver to find the
correct link to scan.

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-04-12 10:52:19 +03:00
Chenming Huang
c9ad16870b AP MLD: Allow scan processing link to match the request
If the driver provides an identifying cookie value for scan operations,
use that to select which link processes the scan result. This is needed
for OBSS scans that can be required in different links if operating as
an AP MLD.  Distinguish the scans using scan_cookie for QCA vendor scan
events.

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-04-12 10:52:19 +03:00
Chenming Huang
9b682e72d9 AP MLD: Find the link that is waiting for scan events
In AP MLD case, HT scan results need to be handled in the link that
triggered this scan. So find the link that has a valid scan_cb to handle
EVENT_SCAN_RESULTS.

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-04-12 10:23:27 +03:00
Vinay Gannevaram
147f836924 PASN: Add set and get API for PASN data context
Modules that use libpasn for PASN authentication need the context of
PASN data. PASN data is a common context for the library and the modules
using it. Hence, initialize the context through init and deinit
functions. Also use set and get functions to update the parameters.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-06 00:12:54 +03:00
Vinay Gannevaram
ab37a57314 Replace PMKSA cache inline stubs with wrapper function stubs
PMKSA cache API is included in libpasn.so used by external modules,
e.g., Wi-Fi Aware. To avoid dependency on IEEE8021X_EAPOL define for the
external modules at compile time, remove PMKSA cache static inline
functions from the header file and add wrapper function stubs.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-06 00:12:52 +03:00
Vinay Gannevaram
ba55088a73 Replace PTKSA cache inline stubs with wrapper function stubs
PTKSA cache API is included in libpasn.so used by external modules,
e.g., Wi-Fi Aware. To avoid dependency on CONFIG_PTKSA_CACHE define for
the external modules at compile time, remove PTKSA cache static inline
functions from the header file and add wrapper function stubs.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-05 20:07:32 +03:00
Jouni Malinen
e2ae53e1db tests: MBSSID and beacon protection disabled/enabled
Verify that the Extended Capabilities element for the TX BSS shows
beacon protection disabled and the Extended Capabilities element for the
non-TX BSS (within the Multiple BSSID element) shows it enabled.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-04 20:44:22 +03:00
Jouni Malinen
1f230a497a MBSSID: Include Extended Capabilities element in non-TX BSSID profile
Add the Extended Capabilities element for a non-TX BSS into the non-TX
BSSID profile subelement in the Multiple BSSID element if the non-TX BSS
has different extended capabilities than the TX BSS.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-04-04 20:42:59 +03:00
Chenming Huang
37c00c3c5d AP MLD: Provide link addresses for non-AP MLDs in control interface
Add affiliated link addresses for non-AP MLDs in the STA* control
interface commands.

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-04-04 18:54:42 +03:00
Purushottam Kushwaha
b818a1be14 Add a QCA vendor attribute to set avoid frequencies per netdev
Add a new attribute QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFINDEX
for QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT subcommand to
apply rules for avoid frequencies on a specific netdev. This is a
32-bit unsigned optional attribute.

Signed-off-by: Purushottam Kushwaha <quic_pkushwah@quicinc.com>
2024-04-04 18:39:18 +03:00
Jouni Malinen
07c9f183ea tests: Avoid control interface throttling in various test cases
These can cause unexpected test failures, so dump the pending monitor
socket events more frequently in some cases where event throttling is
seen.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-27 23:48:39 +02:00
Hu Wang
9ac0e785c3 Revert "nl80211: Skip interface down/up when setting MAC address"
This reverts commit bffd2b3994.

Revert this commit to fix a regression when setting up P2P Group Owner
on some old device.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-27 23:01:14 +02:00
Jouni Malinen
94506e8ed8 Use the latest updated BSS entry for sending ANQP requests
Try to find the BSS entry that contains the most likely current
information for the target BSS. This is mainly needed to avoid some
unusual behavior with APs changing their Beacon frame information in a
manner that shows up in automated testing, but this might help with some
more dynamic real world uses as well, so better do the BSS entry search
for the newest entry.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-27 22:37:18 +02:00
Jouni Malinen
0e4bff095b tests: Flush scan cache to make dbus_anqp_get more reliable
This test could have failed if scan results from a previously executed
test case were still the in the driver cache.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-27 22:33:38 +02:00
Jouni Malinen
a9bc6e89df OpenSSL: Fix a memory leak in CMAC
The OpenSSL 3.0 (or newer) version of omac1_aes_vector() did not free
the EVP_MAC. This resulted in a memory leak that shows up in a bit
strange way in valgrind reports and because of that, was not caught
during automated testing.

Fixes: 0c61f6234f ("OpenSSL: Implement CMAC using the EVP_MAC API")
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-27 20:35:25 +02:00
Aditya Kumar Singh
4bc61b6577 AP MLD: Remove restriction of having to disable the first link BSS last
The first link BSS was always disabled last. However, now the first BSS
can be dynamically adjusted. Hence, remove such restriction.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
a6d92da9aa AP MLD: Support removal of link station from AP
Whenever ap_free_sta() was called, it deleted the whole station entry
from the kernel as well. However, with MLD stations, there is a
requirement to delete only the link station.

Add support to remove the link station alone from an MLD station. If the
link going to be removed is the association link, the whole station
entry will be removed.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
1f88b3daf0 nl80211: Add callback function for removing link STAs
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
19e50f8627 Export hostapd_sta_is_link_sta()
This functionality can be shared with other files as well.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
df34c2ced3 AP MLD: De-initialize/disable link BSS properly
When the first link BSS of an interface was de-initialized/disabled, the
whole MLD was brought down. All other links were stopped beaconing and
links were removed. And if the non-first link BSS was
de-initialized/disabled, nothing happened. Even beaconing was not
stopped which is wrong.

Fix this by properly bringing down the intended link alone from the
interface.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
63982fd094 nl80211: Print the MLD capabilities in debug
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
9fdbaf2ed6 AP MLD: Fix advertisement of MLD capabilities
Previously, hostapd directly advertised the MLD capabilities received
from the driver. Since this information is exchanged during
initialization time only, the driver will advertise the maximum
supported values. hostapd should parse it and then based on the current
situation fill the values accordingly.

For example, the maximum number of simultaneous links is supposed to be
a value between 0 and 14, which is the number of affiliated APs minus 1.
The driver advertises this value as 5 and hostapd, irrespective of the
current active links, puts 5 in the frames.

Fix this by parsing the value from the driver capabilities and then
using the values as per the current situation of the links. The
advertised values will be used as the upper limit.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
7a0501d20d AP MLD: Refresh beacons for other links when one gets disabled/enabled
If one or more BSS from the interface is partnering with BSSs from
another interface and if this interface gets disabled, the Beacon frames
need to be refreshed for other interfaces. Similar thing should happen
when it gets enabled.

Add logic to refresh other interface Beacon frames when one of the
interfaces is disabled or enabled.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
d2b62b3fe5 AP MLD: Support link removal before removing interface
Previously, whenever if_remove() was called, the whole interface was
deleted. In an AP MLD, all partner BSS use the same driver private
context and hence removing the interface when only one of the links goes
down should be avoided.

Add a helper function to remove a link first whenever if_remove() is
called. Later while handling it, if the number of active links goes to
0, if_remove() would be called to clean up the interface.

This helper function will be used later when co-hosted AP MLD support is
added and as well later during ML reconfiguration support.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
55c30e8aba nl80211: Remove AP MLD links while removing the interface
When the interface was removed, the added links were not removed. While
removing the interface, kernel has removed the stale links but hostapd
has not. This is wrong since hostapd should remove and do the clean ups
properly while removing the interface.

Hence, remove the links when interface is removed.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
a576180cd8 nl80211: Use per-BSS command for remove link
Construct the nl80211 remove link command using the per-BSS approach
instead of per-driver (drv->first_bss).

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
b162886fd0 nl80211: Re-factor nl80211_remove_links() function
nl80211_remove_links() iterated over all active links in the given BSS
and removed all of them. However, at times it is required to remove only
one link and not all links.

Add a helper function nl80211_remove_link() which will remove just the
given link_id from the passed BSS. nl80211_remove_links() will use this
and will call this for each of the active links to be removed.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
b810426eaa nl80211: Remove redundant put_freq call in set_ap() for AP MLD
wpa_driver_nl80211_set_ap() called nl80211_put_freq_params() twice if AP
is an AP MLD. It called once while putting the MLO link ID and the other
time in the normal flow if frequency info is present. Doing this twice
is not required.

Call put_freq once during the normal flow only and separately of that,
add the link ID for AP MLD.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Jouni Malinen
4200657338 nl80211: Fix set_ap() to add frequency without CONFIG_IEEE80211AX
This call was added within a conditional CONFIG_IEEE80211AX block even
though this can apply without that build option. Move this outside that
conditional block.

Fixes: b3921db426 ("nl80211: Add frequency info in start AP command")
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
f2f0dd354f nl80211: Cache hostapd_data context in per link BSS struct for AP MLD
Cache the corresponding hostapd_data struct context into the link entry
within the driver wrapper. This will be useful for driver events
callback processing.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:39 +02:00
Aditya Kumar Singh
60e1dca1ef AP MLD: Clean up MLD when not required any further
Currently, whenever a new BSS is created, if it is an EHT BSS it is tied
to a corresponding MLD structure. If the structure does not exist
already, a new one is created and tied to it. Accordingly, the link ID
is assigned as well. However, when the BSS is deleted, the MLD structure
is not freed and when it is again created the next time, the link ID is
incremented further and the BSS gets a wrong link ID.

For example, 2.4 GHz single link AP MLD case: First ADD, link ID 0 would
be assigned and MLD interface wlan0 would be created. When REMOVE is
issued, the BSS would be deleted but MLD wlan0 will not. When ADD is
issued again, the BSS will tie back to MLD wlan0 but this time the link
ID will be incremented again and 1 would be assigned. Hence, at
subsequent REMOVE/ADD, the link ID keeps on incrementing.

Since the link ID remains same for the full lifetime of the BSS and MLD,
the next link ID counter cannot be just reset back to 0 when a BSS is
deleted. Otherwise, in interleaved link enable/disable case, the link ID
would be changed.

To overcome this situation, whenever a BSS is deleted, if the MLD is not
referenced by any other existing BSS, delete the MLD structure itself.

To know how many BSSs are referring a given MLD, introduce a new member
refcount in MLD. If the value is 0 it is safe to delete the MLD.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 18:12:36 +02:00
Aditya Kumar Singh
fac34688ad AP MLD: Assign link ID during BSS creation
Link ID was assigned when BSS is going through setup and the driver
interface init. Later if interface is disabled and enabled again, setup
BSS is called which will give a new link ID to it. However, Link ID
should be same for a BSS affliated to an AP MLD for the full lifetime of
the BSS.

Hence, assign the link ID during BSS creation itself. And it will remain
until BSS entry is completely freed. Hence, link ID will not change as
part of disable/enable.

Also, since link ID would be decided now, it will help in creating link
level control sockets in a subsequent patch.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 11:15:33 +02:00
Aditya Kumar Singh
b19aa9c422 AP MLD: Use MLD struct for MLD level information
MLD level structure is present to store the MLD level information.

Add changes to use the MLD structure instead of link specific struct
hostapd_data to get/set the MLD level information.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 11:15:19 +02:00
Aditya Kumar Singh
2f0e5303e8 AP MLD: Add a separate MLD level structure
MLD level information like MLD MAC address, next link ID, etc. was
stored in each BSS. However, only the first link BSS assigns values to
these members and the other link BSSs store references to the first BSS.
However, if the first BSS is disabled, the first BSS reference in all
BSS should be updated which is an overhead. Also, this does not seem to
scale.

Instead, a separate MLD level structure can be maintained which can
store all this ML related information. All affiliated link BSSs can keep
reference to this MLD structure.

This commit adds that MLD level structure. However, assigning values to
it and using that instead of BSS level members will be done in
subsequent commits.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-27 11:15:10 +02:00
Aditya Kumar Singh
e51f1109b0 tests: AP MLD: Remove mld_id config
mld_id config is not used anymore. Remove its use from test cases.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-26 20:20:55 +02:00
Sriram R
259b43a31a hostapd: MLO: Avoid use of mld_id as user configuration
mld_id was provided as a user configuration to identify partner BSS
belonging to the same AP MLD. The same id is used at the protocol level
also to indicate the AP MLD ID of the MLD.

But, in general mld_id is a relative reference of the MLD where 0 is
used as the mld_id to represent the self MLD and in case of MLO MBSSID
mld_id of a non transmitted BSS affiliated to an AP MLD is based on the
relative BSS index of the non transmitted BSS from the transmitted BSS.
Hence mld_id need not be fetched from users, rather it can be identified
wherever required.

To verify if the partners belong to the same AP MLD the interface name
can be checked, since all link BSS partners of the same AP MLD belong to
the same interface.

Hence, remove use of mld_id user config and instead introduce two
functions hostapd_is_ml_partner() and hostapd_get_mld_id(). The former
is used to verify whether partners belong to the same AP MLD and the
latter is used to get the MLD ID of the BSS.

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-26 20:16:59 +02:00
Jouni Malinen
272c253dc9 tests: Clear sae_groups in eht_mld_legacy_stas
This is needed to avoid failures due to previous test cases having left
sae_groups set to something else than the default.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-26 19:14:48 +02:00
Karthikeyan Kathirvel
69d53b8b6b nl80211: Fix potential NULL pointer dereference in set_ap()
In the code review, it was found that param->freq is accessed without
NULL check in wpa_driver_nl80211_set_ap(), while in other sections of
the code, freq is accessed only after NULL validation. This situation
could result in a segmentation fault at least in theory.

Add a NULL check for freq before accessing it to be consistent with the
other uses.

Fixes: 0c6c948047 ("nl80211: Support setting up an AP on a specified link")
Signed-off-by: Karthikeyan Kathirvel <quic_kathirve@quicinc.com>
2024-03-26 19:14:48 +02:00
Jouni Malinen
666e954ca2 Remove unused wpa_drv_set_ap()
This wrapper function was not used at all, so remove it to make it
clearer that the set_ap() driver op is called only from hostapd code.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-26 19:14:43 +02:00
Chenming Huang
9be122d2e0 nl80211: Fix AP MLD frequency update on channel switch
mlme_event() calls nl80211_get_link_id_by_freq() to determine the link
to handle reported events. However, in channel switch event it is always
setting freq to the default link that leads to the issue that all other
events that go to mlme_event() will be handled in the default link.

Fix this by setting freq to the correct link specified by the link ID
when processing the event for a completed channel switch.

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-03-26 17:46:33 +02:00
Jouni Malinen
bd52684498 tests: Convert sigma_dut control to a context manager class
This cleans up the implementation and makes stopping of sigma_dut (and
cleanup after some parameters it might leave behind) more robust.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-24 00:24:07 +02:00
Jouni Malinen
64c3c58080 tests: Make rrm_reassociation more robust
It was possible for this test case to fail if a previously executed test
case left another BSS entry for the BSSID used by the second AP here.
That could have skipped the needed scan with scan_for_bss(bssid2). Force
this command to run a new scan to discover the second AP correctly.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-23 22:22:07 +02:00
Nikita Chernikov
9144f876a5 nl80211: Fix sending NL80211_CMD_DEL_BEACON command to wrong interface
The NL80211_CMD_DEL_BEACON command was always sent to the main interface
of the radio instead of the desired BSS interface, e.g., when sending a
STOP_AP control interface command from upper layer.

Signed-off-by: Nikita Chernikov <nchernikov@maxlinear.com>
2024-03-23 22:08:15 +02:00
Janusz Dziedzic
ec4b755b06 wpa_cli: Don't select interface when using global socket
In case we run command like:
wpa_cli -g <global_ctrl_path> command

don't print
"Selected interface " message.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@gmail.com>
2024-03-23 22:03:54 +02:00
Janusz Dziedzic
2342d95821 tests: remotehost: Extend proc API
Signed-off-by: Janusz Dziedzic <janusz.dziedzic@gmail.com>
2024-03-23 21:58:59 +02:00
Shailendra Singh
c24453dd93 Add a vendor attribute per MLO link ratemask bitmap configuration
Define attribute QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LINK_ID in
enum qca_wlan_vendor_attr_ratemask_params to configure ratemask
per MLO link. If the attribute is not provided, ratemask will be
applied for setup link.

Signed-off-by: Shailendra Singh <quic_shasing@quicinc.com>
2024-03-20 23:41:03 +02:00
Shailendra Singh
77f39ed23b Document vendor command ratemask bitmap for EHT case
In addition, update the comment on the number of bits used with HE to
match the defined bits.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-20 23:37:38 +02:00
Nagasai Bharat Gatkeshwar Sainoji
58017de69d Add QCA vendor sub-command and attribute for spectral scan completion
Add a new QCA vendor sub-command
QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_COMPLETE which will be used as a
netlink event to indicate the completion of a spectral scan request.
This event can also be sent incase of the spectral scan request timeout.

To be able to configure the timeout the value, add a new vendor
attribute QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COMPLETION_TIMEOUT in
enum qca_wlan_vendor_attr_spectral_scan.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-20 23:36:46 +02:00
Nagasai Bharat Gatkeshwar Sainoji
8f9da72d2e Add QCA vendor attribute indicating the spectral transport mode
Add a vendor attribute QCA_WLAN_VENDOR_ATTR_SPECTRAL_DATA_TRANSPORT_MODE
to indicate the current spectral data transport mechanism to be used to
get spectral scan samples from the driver to userspace.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-20 23:35:33 +02:00
Jouni Malinen
b83797a3eb tests: Clear scan cache for SAE-EXT-KEY tests
These test cases check the BSS entry information and if the kernel scan
cache maintains an old BSS entry for a previous test case for the same
BSSID this can result in a false failure.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-20 18:13:08 +02:00
Jouni Malinen
5b4a78b1f9 Optimize internal BSS table updates based on a specific BSSID
When wpa_supplicant needed to update the internal BSS table with the
latest scan results from the driver, it fetched all BSSs and processed
them all. This is unnecessary for cases where an update is needed only
for a specific BSS. Optimize this by filtering out the unnecessary
entries from the results.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-20 12:00:46 +02:00
Jouni Malinen
8d0bd7f9c8 Update BSS entry on roaming only for actual BSS frequency change
Commit 117e812d06 ("Update BSS table entry if roaming event indicates
frequency change") added wpa_supplicant BSS table update based on the
latest driver scan results whenever processing an association event that
results in the current operating channel changing. While that is needed
to cover the case where an AP changes its own operating channel (and
that is noticed as a roam or new connection instead of a channel switch
event), this should not really be needed for cases where the
wpa_supplicant entry for the new BSS is already up to date.

Skip the full BSS table update on association event if the event is for
a roaming case to a different BSS and the BSS entry for the target is
already available and for the current operating channel. This avoids
undesired latency when processing the association event.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-20 11:08:16 +02:00
Manoj Sekar
024d4bca13 Multi-AP: WPS support for different Multi-AP profiles
Update EAP-WSC parameters to include Multi-AP profile info to pass the
profile information through the provisioning steps. This is needed for
provisioning the STA configuration when different profiles are used.

Signed-off-by: Manoj Sekar <quic_sekar@quicinc.com>
2024-03-19 19:24:29 +02:00
Manoj Sekar
69d0862989 Multi-AP: Add support for VLAN related information
Add support to fill "multi_ap_vlanid" info to the hostapd config file.
Add the Multi-AP Default 802.1Q Setting subelement into Multi-AP element
generating and parsing.

Signed-off-by: Manoj Sekar <quic_sekar@quicinc.com>
2024-03-19 19:20:51 +02:00
Manoj Sekar
210c2b4bd7 Multi-AP: Add hostapd config option to disallow certain profiles
Add a new config option "multi_ap_client_disallow" to control allowing
backhaul STA with certain profiles alone to associate. This is done to
adhere to Wi-Fi EasyMesh specification which defined rules to
allow/disallow association of backhaul STA of certain profiles.

Signed-off-by: Manoj Sekar <quic_sekar@quicinc.com>
2024-03-19 19:11:27 +02:00
Manoj Sekar
9a1512532e Multi-AP: Reject non-Multi-AP STA association on backhaul-only BSS
Do not allow non-Multi-AP STAs to associate with a BSS that is
configured as a backhaul-only.

Signed-off-by: Manoj Sekar <quic_sekar@quicinc.com>
2024-03-19 18:57:38 +02:00
Manoj Sekar
420afbdbdf Multi-AP: Allow supported profile to be configured
Allow both hostapd and wpa_supplicant to be configured with the
supported Multi-AP profile. The configured value will be advertised in
the Multi-AP element.

Signed-off-by: Manoj Sekar <quic_sekar@quicinc.com>
2024-03-19 18:57:35 +02:00
Manoj Sekar
c3e5286537 Multi-AP: Parse Profile subelement
Parse the indicate profile support for the Multi-AP Profile subelement.

Signed-off-by: Manoj Sekar <quic_sekar@quicinc.com>
2024-03-19 18:55:14 +02:00
Manoj Sekar
0034112429 Multi-AP: Generation of Multi-AP Profile subelement
Add support for including the Multi-AP Profile subelement into the
Multi-AP element.

Signed-off-by: Manoj Sekar <quic_sekar@quicinc.com>
2024-03-19 18:53:45 +02:00
Manoj Sekar
364cb7c943 Multi-AP: Parse the Multi-AP element using a shared helper function
This makes it more convenient to handle extensions to the element and
allows code to be shared between hostapd and wpa_supplicant.

Signed-off-by: Manoj Sekar <quic_sekar@quicinc.com>
2024-03-19 18:53:42 +02:00
Jouni Malinen
0e2ca2e4e2 Multi-AP: Use proper length for remaining buffer for the element
Replace the hardcoded buffer length with the actually number of
remaining bytes on the buffer. This is needed to be able to do real
buffer size validation within add_multi_ap_ie().

Furthermore, make hostapd_eid_multi_ap() static since it is not used
outside this file.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-19 16:45:41 +02:00
Manoj Sekar
61e46f860c Multi-AP: Move IE parameters into a struct for extensibility
This makes it easier to extend the information that is encoded in the
Multi-AP element.

Signed-off-by: Manoj Sekar <quic_sekar@quicinc.com>
2024-03-19 16:40:13 +02:00
Jouni Malinen
91b9786ced tests: cfg80211_tx_frame: filter frames based on SA
This makes the test care less likely to fail due to another STA
happening to be listening for Public Action frames and replying to the
P2P GO Negotiation Request.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-17 19:55:11 +02:00
Jouni Malinen
ab719621b7 tests: Allow WlantestCapture to be used with context managers
In addition, convert many of the uses to do so.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-17 17:10:33 +02:00
Jouni Malinen
91282e29ff tests: Clean up test case importing
Move this to a helper function and return a set of test names instead of
a list.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-17 15:39:54 +02:00
Jouni Malinen
3054112254 tests: Add missed test case __doc__ strings
Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-17 15:21:11 +02:00
Jouni Malinen
caf0cda761 tests: Verify test case function documentation
Check that each test case function includes a title in __doc__ and also
verify that the same test case is not added multiple times from
different files.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-17 15:20:26 +02:00
Jouni Malinen
695277a5b3 tests: Use CS more carefully in p2p_device_autogo_chan_switch
Do not disable HT support on the GO and wait for the channel switch
event on the P2P Client before proceeding with connectivity test.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-09 18:08:52 +02:00
Jouni Malinen
541fa25246 tests: Use triple double quotes around docstrings more consistently
Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-09 17:59:25 +02:00
Damien Dejean
2ae1e6f18b DBus: Add ANQP fields to BSS properties
Add ANQP fields to the BSS properties to allow DBus clients to be
notified and obtain the values when it changes.

Signed-off-by: Damien Dejean <damiendejean@chromium.org>
2024-03-09 17:59:22 +02:00
Damien Dejean
2ea04435ec DBus: Signal ANQP query done
Add a D-Bus signal "ANQPQueryDone" to notify of the result of an ANQP
request.

Signed-off-by: Damien Dejean <damiendejean@chromium.org>
2024-03-09 17:20:52 +02:00
Damien Dejean
d71c838519 DBus: Add a method to get ANQP fields
Add a D-Bus method to perform ANQP get requests. The new method is
equivalent to the "anqp_get" command available in wpa_cli.

Signed-off-by: Damien Dejean <damiendejean@chromium.org>
2024-03-09 17:16:27 +02:00
Damien Dejean
5eb409c4bc DBus: Add dict helper for uint16 arrays
Extend dict helper to support uint16 arrays.

Signed-off-by: Damien Dejean <damiendejean@chromium.org>
2024-03-09 17:05:29 +02:00
Chien Wong
a438e52933 OpenSSL: Fix a memory leak on hpke_labeled_expand() error path
Fixes: 786ea402bc ("HPKE base mode with single-shot API")
Signed-off-by: Chien Wong <m@xv97.com>
2024-03-08 10:43:52 +02:00
Chien Wong
b35b1036fe OpenSSL: Fix a memory leak on openssl_evp_pkey_ec_prime_len() error path
Fixes: b700a56e14 ("OpenSSL 3.0: Determine the prime length for an EC key group using EVP_PKEY")
Signed-off-by: Chien Wong <m@xv97.com>
2024-03-08 10:43:39 +02:00
Evan Benn
35df7ee09e DPP: Emit a DPP PB_STATUS event when push button starts
To implement an action script that listens for DPP push button events
and for example blinks a LED it is useful to know when push button has
started. Emit an event when push button starts.

Signed-off-by: Evan Benn <evan.benn@morsemicro.com>
2024-03-08 10:37:28 +02:00
Jouni Malinen
d8dca78a3a tests: Wait for a specific DPP-PB-STATUS event
This wait for a specific event is needed to allow a new DPP-PB-STATUS
event to be added at the start of the PB operation.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-08 10:37:28 +02:00
Aditya Kumar Singh
2986146d9c tests: Add basic MLO CSA test case
Verify that CSA can be performed on the first link of an AP MLD and
further check that traffic still continues even after channel switch.

Finally, check again that a subsequent CSA can be performed without
affecting the data traffic.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
2024-03-08 10:26:34 +02:00
Johannes Berg
da833a7520 tests: Set valid configuration for EHT puncturing tests
When puncturing is used on EHT, the HT/VHT/HE channel configuration must
not encompass the punctured subchannel, so must use a lower bandwidth.
Change the puncturing tests accordingly.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2024-03-08 10:20:51 +02:00
Jouni Malinen
e625b46a9d Revert "tests: Remove eht_5ghz_80mhz_puncturing_override_1 for now"
This reverts commit eecaceed8f. This test
case can now be restored since hostapd is modified to allow test cases
changes to be done to cover the special impact from EHT puncturing to
available HT/VHT/HE channel bandwidth in this particular case.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-08 10:20:51 +02:00
Jouni Malinen
69dd408fb8 EHT: More accurate no-second-channel-offset checks when puncturing
This is needed to allow some cases where puncturing prevents HT/VHT/HE
from using the full channel bandwidth.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-08 10:20:28 +02:00
Jouni Malinen
131ee59266 EHT: Support punct_bitmap overriding in HE element generation
This was already added for VHT, but a similar change is needed for HE as
well.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-08 10:13:12 +02:00
Jouni Malinen
c96c3adc36 Move punct_update_legacy_bw() into src/common
This function is needed for more common operations so move it to a more
suitable location.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-08 10:13:12 +02:00
Jouni Malinen
9f43c1e26b Provide punct_bitmap to hostapd_set_freq_params()
This is needed to be able to check validity of the channel parameters
for cases where EHT puncturing impacts what can be enabled for
HT/VHT/HE.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-08 10:01:30 +02:00
Jouni Malinen
47dad1ed16 EHT: Move puncturing bitmap determination into a helper function
Avoid duplicated implementation for this by using a shared helper
function.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-08 10:00:35 +02:00
Jouni Malinen
eecaceed8f tests: Remove eht_5ghz_80mhz_puncturing_override_1 for now
mac80211 has been modified to reject the configuration that is used in
this test case. For now, remove this until the puncturing of the second
20 MHz segment can be handled in a manner that allows mac80211 STA to
use EHT.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-06 22:38:09 +02:00
Jouni Malinen
010d8d10ed EHT: Use eht_oper_puncturing_override when constructing VHT elements
The testing functionality for overriding EHT puncturing bitmap was
applied only for the EHT elements. The mac80211 has been updated to
enforce compartibility between EHT and HT/VHT information and that made
the related test cases fail. Apply the override value for VHT element
generation to avoid some of those issues.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-06 22:34:57 +02:00
Jouni Malinen
0eb67e43bb tests: Do not drop HT capability on CS to avoid test failures
Leave the HT capability of the AP as-is when running channel switch test
cases that started failing with a recent kernel change that disconnects
on such "unexpected" change in AP capabilities.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-06 19:32:16 +02:00
Jouni Malinen
0a321d1733 tests: Fix fuzzing tester for WNM
Processing of WNM frames can results in a lookup of the current BSS
table. As such, the testing tool needs to initialize the BSS table to
avoid NULL pointer dereferences. This is not an issue that would show up
with real production uses with wpa_supplicant since wpa_bss_init() is
called there.

Credit to OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=67244
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-06 17:38:08 +02:00
Jouni Malinen
40d5fecac2 Fix fuzzing test build
The commit that renamed the WNM BTM deallocation function forgot to
update the fuzz tester tool.

Fixes: e508c070c4 ("WNM: Keep BTM information until connection completes")
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-05 17:24:50 +02:00
Jouni Malinen
27dac87b7c tests: Update Supported Operating Classes element validation
The wpa_supplicant implementation for building the Supported Operating
Classes element was modified to add support for 80 MHz and wider
bandwidth on the 6 GHz band, 2-octet operating classes, and freq_list on
the 6 GHz band. Update the test cases that verify exact encoding of this
information to match the implementation changes.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-05 17:24:50 +02:00
Jouni Malinen
c00abc69f2 Handle 6 GHz channels in Supported Operating Classes with freq_list
Only the 2.4 and 5 GHz channels were handled previously when removing
operating classes from the Supported Operating Classes element based on
the freq_list parameter. Extend this to include the 6 GHz band as well.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-05 17:01:30 +02:00
Jouni Malinen
9e90486bce 2-octet operating classes in Support Operating Classes element
A previous workaround was used to move the special operating class 130
to the end of the Supported Operating Classes element to avoid getting
any following entry being ignored or misunderstood. That is not really
the correct way of encoding the special cases, i.e., 80+80 MHz channels
that use two nonadjacent frequency segments.

Add support for encoding the 80+80 MHz channel with the 2-octet
operating class design using the Operating Class Duple sequence field of
the Supported Operating Classes element instead of listing the operating
classes that have the 80+ behavior limit set indication in Table E-4
(i.e., opclass 130 and 135) as 1-octet operating classes in the
Operating Classes field.

Fixes: a92660a00e ("Work around Supported Operating Classes element issues for 6 GHz")
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-05 16:24:35 +02:00
Jouni Malinen
460df51ed8 tests: Verify supported operating classes indication for 6 GHz
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-03-04 19:20:03 +02:00
Ainy Kumari
5dabc10185 Extend support for the 6 GHz operating class 137 (320 MHz)
Commit 085a3fc76e ("EHT: Add 320 channel width support") added this in
various places, but it did not cover everything. Extend this support to
be more complete. In particular, this allows wpa_supplicant to report
the operating class 137 in the Supported Operating Classes element and
to use it when processing beacon requests.

Signed-off-by: Ainy Kumari <quic_ainykuma@quicinc.com>
2024-03-04 19:20:03 +02:00
Ainy Kumari
e74d95e0aa nl80211: Process 6 GHz regulatory rules to accurate channel flags
This is needed to be able to indicate all supported operating classes.

Signed-off-by: Ainy Kumari <quic_ainykuma@quicinc.com>
2024-03-04 19:20:03 +02:00
Jouni Malinen
59951ebf09 Use a helper function to free neighbor DB entries
There is no need to duplicate this code in multiple locations.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-03 21:33:46 +02:00
Jouni Malinen
96f0af07e6 Clear all neighbor entry items explicitly
Do not leave some of the variables to their previously used values when
a neighbor entry is cleared.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-03 21:33:46 +02:00
Nikita Chernikov
6f285fbafc Update own report in nr_db if SSID is changed
short_ssid in the own neighbor report might get out of sync, causing
advertising RNR element based on the old SSID, when SSID is changed
either with control interface command SET or with SIGHUP. Therefore,
sync the own report entry by removing the old entry and setting own
report again if the short SSID value has changed.

Signed-off-by: Nikita Chernikov <nchernikov@maxlinear.com>
2024-03-03 21:33:46 +02:00
Michael-CY Lee
b653420a23 AP MLD: Set link address only when non-AP MLD is not added to driver
Once the non-AP MLD is added to the driver, the driver handles the
address translation so that hostapd receives Management frames with
SA/DA being translated into MLD MAC addresses.

If the Authentication frmae is retransmitted with transaction being 1,
SA of the retransmitted Authentication frame is translated into the MLD
MAC address by the driver, and then in the function handle_auth(),
sta->mld_info.links[].peer_addr would be replaced by the MLD MAC address
even though it is supposed to be the link address.

Therefore, update the MLD information only when the STA has not yet been
added into the driver to avoid replacing the previously determined link
address with the MLD MAC address.

Fixes: bcbe80a66 ("AP: MLO: Handle Multi-Link element during authentication")
Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
2024-03-03 21:33:46 +02:00
Mujibur Rahiman K
16abdac809 Fix INTERFACES command buffer size to allow more data
reply_size instead sizeof(buffer) should be provided to
hostapd_global_ctrl_iface_interfaces() when processing INTERFACES
commands. The previous use of sizeof(buffer) used a significantly
shorter limit (256 vs. 4096 bytes) for the output and this could have
resulted in unnecessary truncation of the output.

Fixes: 618f5d01b0 ("hostapd: Add INTERFACES ctrl_iface command")
Signed-Off-By : Mujibur Rahiman K mujiburrahimank@maxlinear.com
2024-03-03 20:10:13 +02:00
Janusz Dziedzic
b483ceafc4 hostapd: Dump VHT/HE/EHT full capabilities in STA command output
Show full VHT/HE/EHT capabilities for connected stations.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@gmail.com>
2024-03-03 20:07:41 +02:00
Jouni Malinen
040ba112aa Use os_snprintf_error() more consistently in STA output generation
In theory, os_snprintf() could return a negative value and as such,
os_snprintf_error() should be used in all cases where the buffer might
not be large enough.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-03 20:01:27 +02:00
Jouni Malinen
31bbc9391e Do not change out-of-range configuration parameters
The INT_RANGE() cases for wpa_supplicant global and network profile
parameters ended up changing the configured value to the minimum value
if the provided value was too small or to the maximum value if the
provided value was too large. This does not seem most logical. Change
this to not change the configured value at all if the provided value is
outside the valid range.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-03 19:55:45 +02:00
Jouni Malinen
16f7072888 tests: More debug info for eht_mld_sae_legacy_client
It looks like this test case can fail in some cases. Add more debug info
and event wait that might help with a race condition.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-03 19:25:27 +02:00
Jouni Malinen
6889380177 tests: Use even larger timeout of concurrent P2P operations
It looks like the 30 second timeout, i.e., 25 second to discover and
receive GO Negotiation Request, was not sufficient for all cases.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-03 19:09:10 +02:00
Jouni Malinen
0e399ced32 tests: wpa_supplicant configuration parser range checking
Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-03 18:47:16 +02:00
Jouni Malinen
fd24ed9490 Fix valid range for disable_ht40
This network parameter uses values 0 and 1, so -1 should not have been
accepted.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-03 18:37:21 +02:00
Jouni Malinen
b1a880f38f Enforce valid range check for SET mbo_cell_capa and oce
These parameters have both a separate SET command handler and a global
configuration parameter handler. Only the global configuration parameter
handler for enforcing valid range checking. Do that for the SET command
as well.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-03 18:21:07 +02:00
Chien Wong
e5b7e5b900 wpa_supplicant: Fix ignoring boundary 0 in config parser
The following config file contains invalid items:
----
filter_rssi=1234 # should be rejected

network={
 mode=-1 # should be rejected
 ssid="ssid"
 psk="password"
}
----
But it is accepted by the config parser. The issue is due to using NULL
to represent no limit. If a boundary is set to 0, it's disregarded.
Fix this.
Note that string parser is not affected as length cannot be negative and
we are not limiting any string to be always empty.

Signed-off-by: Chien Wong <m@xv97.com>
2024-03-03 18:21:01 +02:00
Jouni Malinen
10122e951d P2P: Fix pri/sec channel switch skipping for GO
Use of wpa_s->p2p_go_no_pri_sec_switch needs to be conditional on
CONFIG_P2P being defined for the build to avoid a compilation error and
ssid->p2p_group to avoid using this for non-P2P AP mode case in
wpa_supplicant. Furthermore, it is better to clear this flag when
stopping a P2P GO to reduce risk of this getting used for a separate
instance of starting a GO.

Fixes: b18d957593 ("P2P: Disable pri/sec channel switch for GO with forced frequency")
Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-02 21:04:30 +02:00
Benjamin Berg
e508c070c4 WNM: Keep BTM information until connection completes
In the MLD case, the information from the transition management request
is relevant during the association process in order to filter out links
that were disallowed by the BTM request. Also, the information remains
useful should a connection attempt fail.

To enable these scenarios, keep the information around until the
connection has completed. As this might make it impossible to establish
a connection, also clear this information at the same time that a normal
BSS ignore is cleared to avoid getting stuck in case the transition
fails unexpectedly.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 20:52:50 +02:00
Benjamin Berg
17a2aa822c WNM: Follow BTM procedure if the last link is dropped
If the last link is dropped, it makes sense to follow the BTM procedure.
However, in that case we need to prevent reconnection to this link
specifically, while if the AP MLD is terminating we need to forbid
connecting to the AP MLD.

As such, add a new variable to track the BSSID or AP MLD MAC address.
Which one it refers to depends on whether wnm_link_removal is set.

This also simplifies the check in wnm_is_bss_excluded() and untangles it
from wpa_s->current_bss.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 20:52:17 +02:00
Benjamin Berg
770f3cb30b WNM: Remove dialog_token parameter
All callers of wnm_send_bss_transition_mgmt_resp() are explicitly
passing wpa_s->wnm_dialog_token. As such, we might as well not pass it
and use the variable directly.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 20:52:17 +02:00
Benjamin Berg
c7cafef8a1 WNM: Set wnm_reply to 0 when sending it
There is no point in the caller to set it to zero. Just do so within
wnm_send_bss_transition_mgmt_resp().

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 20:52:17 +02:00
Benjamin Berg
261f7f9e51 WNM: Do not store coloc_intf_elems
The elements are (currently) not used except for sending an immediate
response similar to COLOC_INTF_REPORT with the main difference being
that the dialog token is included.

Do not store the elements. It easy enough to re-add this should the
implementation improve. And this fixes the fact that the variable is
cleared at odd times as wnm_deallocate_memory() is used specifically to
clear the neighbor report list of a BTM request.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 20:52:17 +02:00
Benjamin Berg
033adbf833 WNM: Drop explicit wpa_is_bss_tmp_disallowed() check
There is no need for this check as wpa_scan_res_match() already calls
the function through wpa_scan_res_ok() before accepting a match.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 20:52:17 +02:00
Benjamin Berg
8b51310f4e WNM: Drop explicit SSID check
The call to wpa_scan_res_match already checks that the SSID matches
current_ssid. Therefore there is no need to do any further checking.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 20:52:17 +02:00
Benjamin Berg
939cd294b2 WNM: Drop check for current_ssid
It should never be NULL. In the unlikely event that it is NULL, the
logic changes slightly to reject all candidates.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 20:52:17 +02:00
Benjamin Berg
436f07d02b WNM: Define a stub wnm_is_bss_excluded if WNM is disabled
This removes the need to check for CONFIG_WNM.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 20:52:17 +02:00
Avraham Stern
e164943f43 WNM: Wait for BTM response TX status before roaming
When accepting a BSS transition request there is a race between
sending the response and roaming to the target AP. As a result,
the response may not be sent because the station deauthenticated
from the AP before the response was actually sent.

To make sure the BSS transition response is sent, start roaming only
after the TX status is received for the BSS transition response.

Signed-off-by: Avraham Stern <avraham.stern@intel.com>
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 20:52:17 +02:00
Benjamin Berg
40ef706e55 WNM: Don't scan frequencies of neighbors that should be ignored
It does not make sense to scan for neighbors that we are not supposed to
use anyway. As such, skip them.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 20:52:17 +02:00
Benjamin Berg
20ed289a78 WNM: Clean up old scan data processing
When receiving a BTM request, wpa_supplicant would try to fetch new
results from the driver, and, independently of that, would also process
the latest scan results that were partially updated by the previous
fetch.

Simplify the logic by using wpa_supplicant_get_scan_results() directly
and then process the old scan data as usual. However, this data may be
outdated, so add a new heuristic to avoid roaming to a BSS if it is
either outdated or bad.

Doing this moves all scan data processing into wnm_scan_process() and
removes duplicated functionality for scan result processing in scan.c.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 20:52:14 +02:00
Jouni Malinen
4750a4f62a DPP: Wait for TX wait expiration on moving to neg_freq for Auth Resp
Avoid potential race conditions with the driver operations between
stopping an ongoing wait for responses for an offchannel TX that was
used to send Authentication Request with a request to use a different
channel for Authentication Response and the start of a new ROC on the
other channel by waiting for the TX expiration event before issuing the
ROC request.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-02 19:39:49 +02:00
Jouni Malinen
963dbad7dc nl80211: Indicate EVENT_TX_WAIT_EXPIRE on match-saved
The event indicating expiration of an offchannel TX is useful for cases
where the wait is for a frame that was explicitly requested to have the
pending cookie to be saved.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-02 19:39:49 +02:00
Jouni Malinen
451d299528 DPP: Wait for ROC cancelled event on Auth Resp TX on another channel
Avoid potential race conditions with the driver operations between
cancelling an ongoing ROC that was used to receive Authentication
Request that requested a different channel to be used for the
negotiation by waiting for the ROC cancelled event before issuing the
offchannel TX command for the Authentication Response.

In addition, speed up the retry on Authentication Response in this type
of a case if the first attempt on the other channel is not AKC'ed since
it might take the peer device a bit more time to be ready to listen
there.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-02 19:39:49 +02:00
Benjamin Berg
45fffac0fe BSS: Switch struct wpa_bss to use valid_links bitmask
This aligns both the wpa_supplicant and bss structures to use the same
pattern of a valid_links bitmask plus per-link entries.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 12:24:15 +02:00
Benjamin Berg
e90f6678f1 nl80211: Remnove unused struct i802_link ctx
This was never used.

Fixes: 47269be36e ("nl80211: Refactor i802_bss to support multiple links")
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 12:01:33 +02:00
Benjamin Berg
0d4288a005 nl80211: Use valid_links bitmask for bss->links array
Most places in the codebase use a valid_links bitmask with an array.
Switch the bss->links array to use the same design with the Link ID
being used as the array index instead of having a link_id inside.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 11:59:16 +02:00
Jouni Malinen
9ed51186e8 Use a single define MAX_NUM_MLD_LINKS for the maximum number of links
There is no need to maintain a separate MAX_NUM_MLO_LINKS define for
practically the same thing.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-03-02 11:25:20 +02:00
Benjamin Berg
11f26fed64 Use for_each_link() where possible
This takes care of the places that the spatch did not catch already.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 11:12:13 +02:00
Benjamin Berg
dbdf7ef679 Use for_each_link() in most cases
This was done using the below semantic patch. There are a few more
places that were missed due to variable declarations or additional
checks in the for loop.

@@
iterator name for_each_link;
identifier max_links =~ "MAX_NUM_MLD_LINKS|MAX_NUM_MLO_LINKS";
expression links;
expression further_tests;
identifier i;
statement stmt;
@@
-for (i = 0; i < max_links; i++)
+for_each_link(links, i)
 {
(
-  if (!(links & BIT(i)))
-    continue;
   ...
|
-  if (!(links & BIT(i)) || further_tests)
+  if (further_tests)
     continue;
   ...
|
-  if (further_tests || !(links & BIT(i)))
+  if (further_tests)
     continue;
   ...
|
-  if (links & BIT(i))
     stmt
|
-  if (further_tests && (links & BIT(i)))
+  if (further_tests)
     stmt
|
-  if ((links & BIT(i)) && further_tests)
+  if (further_tests)
     stmt
)
 }

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 11:11:12 +02:00
Benjamin Berg
c9f8fe0664 common: Introduce for_each_link() macro
This is a simple macro iterating the given bitmask using the given
variable. Having the macro avoids the for loop-continuation making it
more readable overall.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 11:02:54 +02:00
Benjamin Berg
6cb421c1fa nl80211: Fix link indexing in nl80211_connect_common()
In some places the wrong index variable was used to access the link
configuration. Fix this by simply using link_id instead of i.

With this, the i loop variable is not needed anymore. We can simply
always pass 0 to nla_nest_start(). Also, the kernel does not care about
the order that the links are provides, so just remove the special
handling for the association link.

Fixes: a2c4c0b1b6 ("nl80211: Support MLD association request")
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 10:59:02 +02:00
Ilan Peer
408a399aa4 nl80211: Explicitly differentiate between 5 GHz and 6 GHz modes
When a device supports both the 5 GHz band and the 6 GHz band,
these are reported as two separate modes, both with mode set to
HOSTAPD_MODE_IEEE80211A. However, as these are different modes,
each with its own characteristics, e.g., rates, capabilities etc.,
specifically differentiate between them by adding a flag to indicate
whether the mode describes a 6 GHz band capabilities or not.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 10:53:19 +02:00
Benjamin Berg
b532201034 tests: Add missing scan cache flush
Otherwise a BSS from a previous test may still be in the cache.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
2024-03-02 10:46:55 +02:00
Sunil Ravi
dbcf9ff156 P2P: Notify the IP address of the connected P2P Client
When wpa_supplicant assigns the IP address (WFA EAPOL IP address
allocation feature), the assigned IP address of the P2P Client on the GO
side is notified in the AP-STA-CONNECTED event. So to obtain the IP info
to external programs, modify the STA authorized event to include the the
assigned IP address of the P2P Client.

Test: Establish P2P connection and verified from the logs that
      the P2P Client IP address is notified.
Signed-off-by: Sunil Ravi <sunilravi@google.com>
2024-03-01 20:36:41 +02:00
Sunil Ravi
b18d957593 P2P: Disable pri/sec channel switch for GO with forced frequency
When wpa_supplicant receives a request to start a P2P group owner on a
fixed frequency with bandwidth wider than 20 MHz, wpa_supplicant scans
for neighboring BSSs prior to starting the GO. This is done to switch
the primary/secondary channels if there are any other networks which are
operating on the same secondary channel. Though this logic is defined
for 20/40 MHz coexistence and might improve throughput, there are P2P
use cases where this logic causes problem:

1. The file transfer use case takes time to start the file transfer or
   even fails when the 20/40 coex scan repeatedly fails due to an
   ongoing externally triggered scan happening in the system.
2. wpa_supplicant overrides the channel which is selected by the
   application based on the best channel it derived by looking into
   the channel conditions. This degrades the expected throughput.
3. Latency sensitive applications experience long time to
   start the group owner which gives a bad user experience.

So do not allow 40 MHz co-ex PRI/SEC switch to force a change to
Autonomous GO PRI channel when the P2P group add is called with a forced
frequency.

Test: Tested autonomous GO and confirmed from the logs that
P2P GO is not triggering 20/40 coex scan.

Signed-off-by: Sunil Ravi <sunilravi@google.com>
2024-03-01 20:04:13 +02:00
Jouni Malinen
88a0ab87a2 tests: Make ap_wpa2_gtk_rekey_fail_1_sta more robust
Slight differences in timing might make the final data connectivity
check fail, so disable the incorrect behavior first and wait for a
successfully completed GTK rekeying at the end before the final test.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-02-29 11:55:31 +02:00
Jouni Malinen
0e4aa28daf hostapd_cli: Indentation cleanup
Fix indentation level for some function parameters.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-02-28 22:35:04 +02:00
Chenming Huang
a01972a065 Add "stop_ap" command for hostapd_cli
Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-02-28 22:34:08 +02:00
Chenming Huang
8cdb0d3f24 AP MLD: Stop AP per link
For AP MLD cases, the link id is required to determine the correct link
to stop in the stop_ap() driver op.

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-02-28 22:32:09 +02:00
Jouni Malinen
d084ef36b3 AP MLD: Clean up disassoc handling for non-AP MLD link validity check
The check for the non-AP MLD link being valid can be done one level
outside the loop that tries to find a matching AP link.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-02-28 22:17:57 +02:00
Chenming Huang
7ceafb6e9f AP MLD: Handle disassociation notification with SME offload to driver
For non-AP MLDs, clear STA entry from all affiliated links.

For legacy non-MLO case, find association link to clear the STA entry.

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
2024-02-28 22:17:52 +02:00
Jouni Malinen
8aff823649 tests: RADIUS/TLS with FreeRADIUS
Signed-off-by: Jouni Malinen <j@w1.fi>
2024-02-25 20:54:14 +02:00
Jouni Malinen
95a825bc43 RADIUS: Preliminary support RADIUS/TLS as an alternative to RADIUS/UDP
This adds initial parts for RADIUS/TLS support in the RADIUS client.
This can be used with eapol_test and hostapd. This functionality is not
included by default and CONFIG_RADIUS_TLS=y in .config can be used to
enable it.

This version does not yet include all the needed functionality for TLS
validation and the rules for dropping a TCP connection based on invalid
RADIUS attributes.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-02-25 20:54:14 +02:00
Jouni Malinen
87f33c26b9 RADIUS: Simplify IPv4/IPv6 socket handling in client
There is only one connection in use in parallel to a RADIUS
authentication server (and similarly to a RADIUS accounting server). As
such, there is not really any need to maintain separate open IPv4 and
IPv6 sockets. Instead, open the socket for the appropriate IP version
only when actually connecting to a specific server.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-02-25 18:10:05 +02:00
Jouni Malinen
971b781479 RADIUS: Simplify radius_change_server() parameters
There is no need for passing the sock and sock6 parameters separately
since they were always the same values for auth == 0 or auth == 1 cases.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-02-25 17:25:15 +02:00
Jouni Malinen
3386e1327e l2_packet_freebsd: Fix macOS build
ETHER_VLAN_ENCAP_LEN does not seem to be defined in macOS
net/ethernet.h, so define that, if needed, to avoid build issues.

Fixes: 5b21f4861c ("l2_packet_freebsd: Enable receiving priority tagged (VID=0) frames")
Signed-off-by: Jouni Malinen <j@w1.fi>
2024-02-24 18:29:57 +02:00
Kiran Kumar Lokere
86c2421711 TDLS: Defer the start request until the discovery response RX for MLO
When the station (non-AP MLD) is associated with an AP MLD the link ID
for TDLS setup is derived from the discovery response frame and the link
ID is used in TDLS setup operation when acting as initiator. The driver
sends the received discovery response frame followed by the TDLS setup
request event. But the discovery response frame is received after the
setup request event leading to use incorrect link ID value for TDLS
setup operation causing the setup failure. Process the TDLS setup
request if the discovery response frame is received, else defer the
process until the discovery response frame is received and process the
setup request after discovery response frame is processed.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
2024-02-18 11:24:29 +02:00
Haribabu Krishnasamy
352ad5f1a2 Apply CHAN_SWITCH in all BSS for MBSSID case
When the CHAN_SWITCH command is executed during multi BSSID case (say
BSS1, BSS2, and BSS3), if one of the BSS is disabled (say BSS2), the
CHAN_SWITCH command returns an error in BSS2 and does not proceed to the
next BSS (BSS3).

The CHAN_SWITCH command handler iterates over all configured BSSs and
attempts to send the switch_channel to each one. However, if any one of
the BSSs fails, the entire command is aborted and returns a failure.

Continue the iteration even if one BSS is failing to make sure the
configuration is applied to other BSSs.

Signed-off-by: Haribabu Krishnasamy <quic_hkr@quicinc.com>
2024-02-18 11:09:40 +02:00
Jouni Malinen
39da3c7c63 test: Clear country config param at the end of kernel_reg_disconnect
This is needed to avoid causing issues for following test cases.

Signed-off-by: Jouni Malinen <j@w1.fi>
2024-02-18 11:03:55 +02:00
264 changed files with 21309 additions and 6931 deletions

3
.gitignore vendored
View file

@ -6,3 +6,6 @@ wpaspy/build
**/parallel-vm.log
tags
build/
# clangd commands and cache
compile_commands.json
.cache

2
README
View file

@ -1,7 +1,7 @@
wpa_supplicant and hostapd
--------------------------
Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> and contributors
Copyright (c) 2002-2024, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
These programs are licensed under the BSD license (the one with

View file

@ -583,6 +583,24 @@ fi.w1.wpa_supplicant1.CreateInterface.
<h3>InterworkingSelect ( ) --> nothing</h3>
<p>Perform Interworking (Hotspot 2.0) network selection.</p>
</li>
<li>
<h3>ANQPGet ( a{sv} : args) --> nothing</h3>
<p>Send an ANQP request.</p>
<h4>Arguments</h4>
<dl>
<dt>a{sv} : args</dt>
<dd>
<table>
<tr><th>Key</th><th>Value type</th><th>Description</th><th>Required</th>
<tr><td>addr</td><td>s</td><td>Address of the BSS</td><td>Yes</td>
<tr><td>freq</td><td>u</td><td>Frequency of the BSS</td><td>No</td>
<tr><td>ids</td><td>aq</td><td>List of ANQP information IDs to query</td><td>No</td>
<tr><td>hs20_ids</td><td>ay</td><td>List of Hotspot 2.0 ANQP information IDs to query</td><td>No</td>
<tr><td>mbo_ids</td><td>ay</td><td>List of MBO ANQP information IDs to query</td><td>No</td>
</table>
</dd>
</dl>
</li>
<li>
<h3>EAPLogoff ( ) --> nothing</h3>
<p>IEEE 802.1X EAPOL state machine logoff.</p>
@ -865,6 +883,11 @@ fi.w1.wpa_supplicant1.CreateInterface.
<p>The most recent roam success or failure.</p>
</li>
<li>
<h3>ScanInProgress6GHz - b - (read)</h3>
<p>Whether a 6GHz scan is currently in progress.</p>
</li>
<li>
<h3>SessionLength - u - (read)</h3>
<p>The most recent BSS session length in milliseconds.</p>
@ -1129,6 +1152,12 @@ fi.w1.wpa_supplicant1.CreateInterface.
<li>
<h3>MACAddress - ay - (read)</h3>
<p>MAC address of the interface</p>
</li>
<li>
<h3>SignalChange - "a{sv}" - (read)</h3>
<p>Signal and quality properties of the interface</p>
</li>
</ul>
\subsection dbus_interface_signals Signals
@ -1345,6 +1374,17 @@ fi.w1.wpa_supplicant1.CreateInterface.
<dd>URL of the terms and conditions page.</dd>
</dl>
</li>
<li>
<h3>ANQPQueryDone ( s : addr, s : result )</h3>
<p>Result of an ANQP query.</p>
<dl>
<dt>s : addr</dt>
<dd>Address of the BSS targeted by the query.</dd>
<dt>s : result</dt>
<dd>Determine if the request was successful. If so fields are available in BSS.</dd>
</dl>
</li>
</ul>
@ -2185,6 +2225,30 @@ scan results.
<h3>Age - u - (read)</h3>
<p>Number of seconds since the BSS was last seen.</p>
</li>
<li>
<h3>ANQP - a{sv} - (read)</h3>
<p>ANQP information of the BSS. Empty dictionary indicates no ANQP field. Named dictionary entries are:</p>
<table>
<tr><td>CapabilityList</td><td>ay</td></tr>
<tr><td>VenueName</td><td>ay</td></tr>
<tr><td>NetworkAuthType</td><td>ay</td></tr>
<tr><td>RoamingConsortium</td><td>ay</td></tr>
<tr><td>IPAddrTypeAvailability</td><td>ay</td></tr>
<tr><td>NAIRealm</td><td>ay</td></tr>
<tr><td>3GPP</td><td>ay</td></tr>
<tr><td>DomainName</td><td>ay</td></tr>
<tr><td>FilsRealmInfo</td><td>ay</td></tr>
<tr><td>HS20CapabilityList</td><td>ay</td></tr>
<tr><td>HS20OperatorFriendlyName</td><td>ay</td></tr>
<tr><td>HS20WanMetrics</td><td>ay</td></tr>
<tr><td>HS20ConnectionCapability</td><td>ay</td></tr>
<tr><td>HS20OperatingClass</td><td>ay</td></tr>
<tr><td>HS20OSUProvidersList</td><td>ay</td></tr>
<tr><td>HS20OperatorIconMetadata</td><td>ay</td></tr>
<tr><td>HS20OSUProvidersNAIList</td><td>ay</td></tr>
</table>
<p>Unnamed ANQP elements have a generic entry name 'anqp[id]' where 'id' is the InfoID of the ANQP element as described in IEEE Std 802.11-2020, Table 9-331 (ANQP-element definitions).</p>
</li>
</ul>
\subsection dbus_bss_signals Signals

View file

@ -31,7 +31,7 @@ PROJECT_NAME = "wpa_supplicant / hostapd"
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 2.10
PROJECT_NUMBER = 2.11
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.

54
gen_compile_commands.py Executable file
View file

@ -0,0 +1,54 @@
#!/usr/bin/env python3
# compile_commands.json generator
# Copyright (C) 2024 Intel Corporation
#
# This software may be distributed under the terms of the BSD license.
# See README for more details.
import os
import sys
import glob
import json
import argparse
parser = argparse.ArgumentParser(description='Read each of the build directories that are given and generate '
'a compile_commands.json file. If a source file is found multiple times, '
'then the compile flags from the last build directory will be used.')
parser.add_argument('-o', '--output', default='compile_commands.json', type=str,
help="Output file to generate")
parser.add_argument('builddirs', nargs='+', type=str, metavar="builddir",
help='Build directories to search')
args = parser.parse_args()
files = {}
for builddir in args.builddirs:
for cmd_file in glob.glob('**/*.o.cmd', root_dir=builddir, recursive=True):
with open(os.path.join(builddir, cmd_file), encoding='ascii') as f:
base_dir, cmd = f.readline().split(':', 1)
src_file = cmd.rsplit(maxsplit=1)[1]
src_file = os.path.abspath(os.path.join(base_dir, src_file))
files[src_file] = {
'command': cmd.strip(),
'directory': base_dir,
'file': src_file,
}
flist = json.dumps(sorted(list(files.values()), key=lambda k: k['file']), indent=2, sort_keys=True)
try:
# Avoid writing the file if it did not change, first read original
with open(args.output, 'rt', encoding='UTF-8') as f:
orig = []
while data := f.read():
orig.append(data)
orig = ''.join(orig)
except OSError:
orig = ''
# And only write if something changed
if orig != flist:
with open(args.output, 'wt', encoding='UTF-8') as f:
f.write(flist)

View file

@ -154,6 +154,7 @@ OBJS += src/utils/crc32.c
OBJS += src/common/ieee802_11_common.c
OBJS += src/common/wpa_common.c
OBJS += src/common/hw_features_common.c
OBJS += src/common/ptksa_cache.c
OBJS += src/eapol_auth/eapol_auth_sm.c
@ -594,7 +595,6 @@ NEED_HMAC_SHA256_KDF=y
NEED_HMAC_SHA384_KDF=y
NEED_SHA256=y
NEED_SHA384=y
OBJS += src/common/ptksa_cache.c
endif
ifdef CONFIG_EAP_IKEV2
@ -647,6 +647,11 @@ ifdef CHAP
OBJS += src/eap_common/chap.c
endif
ifdef CONFIG_RADIUS_TLS
TLS_FUNCS=y
L_CFLAGS += -DCONFIG_RADIUS_TLS
endif
ifdef TLS_FUNCS
NEED_DES=y
# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
@ -1046,6 +1051,7 @@ OBJS += src/ap/wmm.c
OBJS += src/ap/ap_list.c
OBJS += src/ap/comeback_token.c
OBJS += src/pasn/pasn_responder.c
OBJS += src/pasn/pasn_common.c
OBJS += src/ap/ieee802_11.c
OBJS += src/ap/hw_features.c
OBJS += src/ap/dfs.c

View file

@ -1,5 +1,42 @@
ChangeLog for hostapd
2024-07-20 - v2.11
* Wi-Fi Easy Connect
- add support for DPP release 3
- allow Configurator parameters to be provided during config exchange
* HE/IEEE 802.11ax/Wi-Fi 6
- various fixes
* EHT/IEEE 802.11be/Wi-Fi 7
- add preliminary support
* SAE: add support for fetching the password from a RADIUS server
* support OpenSSL 3.0 API changes
* support background radar detection and CAC with some additional
drivers
* support RADIUS ACL/PSK check during 4-way handshake (wpa_psk_radius=3)
* EAP-SIM/AKA: support IMSI privacy
* improve 4-way handshake operations
- use Secure=1 in message 3 during PTK rekeying
* OCV: do not check Frequency Segment 1 Channel Number for 160 MHz cases
to avoid interoperability issues
* support new SAE AKM suites with variable length keys
* support new AKM for 802.1X/EAP with SHA384
* extend PASN support for secure ranging
* FT: Use SHA256 to derive PMKID for AKM 00-0F-AC:3 (FT-EAP)
- this is based on additional details being added in the IEEE 802.11
standard
- the new implementation is not backwards compatible
* improved ACS to cover additional channel types/bandwidths
* extended Multiple BSSID support
* fix beacon protection with FT protocol (incorrect BIGTK was provided)
* support unsynchronized service discovery (USD)
* add preliminary support for RADIUS/TLS
* add support for explicit SSID protection in 4-way handshake
(a mitigation for CVE-2023-52424; disabled by default for now, can be
enabled with ssid_protection=1)
* fix SAE H2E rejected groups validation to avoid downgrade attacks
* use stricter validation for some RADIUS messages
* a large number of other fixes, cleanup, and extensions
2022-01-16 - v2.10
* SAE changes
- improved protection against side channel attacks

View file

@ -84,6 +84,7 @@ OBJS += ../src/ap/beacon.o
OBJS += ../src/ap/bss_load.o
OBJS += ../src/ap/neighbor_db.o
OBJS += ../src/ap/rrm.o
OBJS += ../src/common/ptksa_cache.o
OBJS_c = hostapd_cli.o
OBJS_c += ../src/common/wpa_ctrl.o
@ -620,7 +621,6 @@ NEED_HMAC_SHA256_KDF=y
NEED_HMAC_SHA384_KDF=y
NEED_SHA256=y
NEED_SHA384=y
OBJS += ../src/common/ptksa_cache.o
endif
ifdef CONFIG_EAP_IKEV2
@ -682,6 +682,11 @@ ifdef CHAP
OBJS += ../src/eap_common/chap.o
endif
ifdef CONFIG_RADIUS_TLS
TLS_FUNCS=y
CFLAGS += -DCONFIG_RADIUS_TLS
endif
ifdef TLS_FUNCS
NEED_DES=y
# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
@ -1192,6 +1197,7 @@ OBJS += ../src/ap/wmm.o
OBJS += ../src/ap/ap_list.o
OBJS += ../src/ap/comeback_token.o
OBJS += ../src/pasn/pasn_responder.o
OBJS += ../src/pasn/pasn_common.o
OBJS += ../src/ap/ieee802_11.o
OBJS += ../src/ap/hw_features.o
OBJS += ../src/ap/dfs.o

View file

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

View file

@ -121,6 +121,9 @@ CONFIG_PKCS12=y
# Build IPv6 support for RADIUS operations
CONFIG_IPV6=y
# Include support fo RADIUS/TLS into the RADIUS client
#CONFIG_RADIUS_TLS=y
# IEEE Std 802.11r-2008 (Fast BSS Transition)
#CONFIG_IEEE80211R=y

View file

@ -1678,6 +1678,8 @@ static int parse_anqp_elem(struct hostapd_bss_config *bss, char *buf, int line)
return 0;
}
#endif /* CONFIG_INTERWORKING */
static int parse_qos_map_set(struct hostapd_bss_config *bss,
char *buf, int line)
@ -1719,8 +1721,6 @@ static int parse_qos_map_set(struct hostapd_bss_config *bss,
return 0;
}
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
@ -2436,6 +2436,31 @@ static int get_u16(const char *pos, int line, u16 *ret_val)
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_TESTING_OPTIONS
static bool get_hexstream(const char *val, struct wpabuf **var,
const char *name, int line)
{
struct wpabuf *tmp;
size_t len = os_strlen(val) / 2;
tmp = wpabuf_alloc(len);
if (!tmp)
return false;
if (hexstr2bin(val, wpabuf_put(tmp, len), len)) {
wpabuf_free(tmp);
wpa_printf(MSG_ERROR, "Line %d: Invalid %s '%s'",
line, name, val);
return false;
}
wpabuf_free(*var);
*var = tmp;
return true;
}
#endif /* CONFIG_TESTING_OPTIONS */
static int hostapd_config_fill(struct hostapd_config *conf,
struct hostapd_bss_config *bss,
const char *buf, char *pos, int line)
@ -2549,6 +2574,27 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->ap_max_inactivity = atoi(pos);
} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
bss->skip_inactivity_poll = atoi(pos);
} else if (os_strcmp(buf, "bss_max_idle") == 0) {
int val = atoi(pos);
if (val < 0 || val > 2) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid bss_max_idle value", line);
return 1;
}
bss->bss_max_idle = val;
} else if (os_strcmp(buf, "max_acceptable_idle_period") == 0) {
bss->max_acceptable_idle_period = atoi(pos);
} else if (os_strcmp(buf, "no_disconnect_on_group_keyerror") == 0) {
int val = atoi(pos);
if (val < 0 || val > 1) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid no_disconnect_on_group_keyerror",
line);
return 1;
}
bss->no_disconnect_on_group_keyerror = val;
} else if (os_strcmp(buf, "config_id") == 0) {
os_free(bss->config_id);
bss->config_id = os_strdup(pos);
@ -2869,6 +2915,37 @@ static int hostapd_config_fill(struct hostapd_config *conf,
os_free(bss->radius->auth_server->shared_secret);
bss->radius->auth_server->shared_secret = (u8 *) os_strdup(pos);
bss->radius->auth_server->shared_secret_len = len;
} else if (bss->radius->auth_server &&
os_strcmp(buf, "auth_server_type") == 0) {
if (os_strcmp(pos, "UDP") == 0) {
bss->radius->auth_server->tls = false;
#ifdef CONFIG_RADIUS_TLS
} else if (os_strcmp(pos, "TLS") == 0) {
bss->radius->auth_server->tls = true;
#endif /* CONFIG_RADIUS_TLS */
} else {
wpa_printf(MSG_ERROR, "Line %d: unsupported RADIUS type '%s'",
line, pos);
return 1;
}
#ifdef CONFIG_RADIUS_TLS
} else if (bss->radius->auth_server &&
os_strcmp(buf, "auth_server_ca_cert") == 0) {
os_free(bss->radius->auth_server->ca_cert);
bss->radius->auth_server->ca_cert = os_strdup(pos);
} else if (bss->radius->auth_server &&
os_strcmp(buf, "auth_server_client_cert") == 0) {
os_free(bss->radius->auth_server->client_cert);
bss->radius->auth_server->client_cert = os_strdup(pos);
} else if (bss->radius->auth_server &&
os_strcmp(buf, "auth_server_private_key") == 0) {
os_free(bss->radius->auth_server->private_key);
bss->radius->auth_server->private_key = os_strdup(pos);
} else if (bss->radius->auth_server &&
os_strcmp(buf, "auth_server_private_key_passwd") == 0) {
os_free(bss->radius->auth_server->private_key_passwd);
bss->radius->auth_server->private_key_passwd = os_strdup(pos);
#endif /* CONFIG_RADIUS_TLS */
} else if (os_strcmp(buf, "acct_server_addr") == 0) {
if (hostapd_config_read_radius_addr(
&bss->radius->acct_servers,
@ -2903,8 +2980,42 @@ static int hostapd_config_fill(struct hostapd_config *conf,
os_free(bss->radius->acct_server->shared_secret);
bss->radius->acct_server->shared_secret = (u8 *) os_strdup(pos);
bss->radius->acct_server->shared_secret_len = len;
} else if (bss->radius->acct_server &&
os_strcmp(buf, "acct_server_type") == 0) {
if (os_strcmp(pos, "UDP") == 0) {
bss->radius->acct_server->tls = false;
#ifdef CONFIG_RADIUS_TLS
} else if (os_strcmp(pos, "TLS") == 0) {
bss->radius->acct_server->tls = true;
#endif /* CONFIG_RADIUS_TLS */
} else {
wpa_printf(MSG_ERROR, "Line %d: unsupported RADIUS type '%s'",
line, pos);
return 1;
}
#ifdef CONFIG_RADIUS_TLS
} else if (bss->radius->acct_server &&
os_strcmp(buf, "acct_server_ca_cert") == 0) {
os_free(bss->radius->acct_server->ca_cert);
bss->radius->acct_server->ca_cert = os_strdup(pos);
} else if (bss->radius->acct_server &&
os_strcmp(buf, "acct_server_client_cert") == 0) {
os_free(bss->radius->acct_server->client_cert);
bss->radius->acct_server->client_cert = os_strdup(pos);
} else if (bss->radius->acct_server &&
os_strcmp(buf, "acct_server_private_key") == 0) {
os_free(bss->radius->acct_server->private_key);
bss->radius->acct_server->private_key = os_strdup(pos);
} else if (bss->radius->acct_server &&
os_strcmp(buf, "acct_server_private_key_passwd") == 0) {
os_free(bss->radius->acct_server->private_key_passwd);
bss->radius->acct_server->private_key_passwd = os_strdup(pos);
#endif /* CONFIG_RADIUS_TLS */
} else if (os_strcmp(buf, "radius_retry_primary_interval") == 0) {
bss->radius->retry_primary_interval = atoi(pos);
} else if (os_strcmp(buf,
"radius_require_message_authenticator") == 0) {
bss->radius_require_message_authenticator = atoi(pos);
} else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) {
bss->acct_interim_interval = atoi(pos);
} else if (os_strcmp(buf, "radius_request_cui") == 0) {
@ -3070,6 +3181,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos);
if (bss->wpa_key_mgmt == -1)
return 1;
} else if (os_strcmp(buf, "rsn_override_key_mgmt") == 0) {
bss->rsn_override_key_mgmt =
hostapd_config_parse_key_mgmt(line, pos);
if (bss->rsn_override_key_mgmt == -1)
return 1;
} else if (os_strcmp(buf, "rsn_override_key_mgmt_2") == 0) {
bss->rsn_override_key_mgmt_2 =
hostapd_config_parse_key_mgmt(line, pos);
if (bss->rsn_override_key_mgmt_2 == -1)
return 1;
} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
bss->wpa_psk_radius = atoi(pos);
if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
@ -3101,6 +3222,32 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, pos);
return 1;
}
} else if (os_strcmp(buf, "rsn_override_pairwise") == 0) {
bss->rsn_override_pairwise =
hostapd_config_parse_cipher(line, pos);
if (bss->rsn_override_pairwise == -1 ||
bss->rsn_override_pairwise == 0)
return 1;
if (bss->rsn_override_pairwise &
(WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
wpa_printf(MSG_ERROR,
"Line %d: unsupported pairwise cipher suite '%s'",
line, pos);
return 1;
}
} else if (os_strcmp(buf, "rsn_override_pairwise_2") == 0) {
bss->rsn_override_pairwise_2 =
hostapd_config_parse_cipher(line, pos);
if (bss->rsn_override_pairwise_2 == -1 ||
bss->rsn_override_pairwise_2 == 0)
return 1;
if (bss->rsn_override_pairwise_2 &
(WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
wpa_printf(MSG_ERROR,
"Line %d: unsupported pairwise cipher suite '%s'",
line, pos);
return 1;
}
} else if (os_strcmp(buf, "group_cipher") == 0) {
bss->group_cipher = hostapd_config_parse_cipher(line, pos);
if (bss->group_cipher == -1 || bss->group_cipher == 0)
@ -3122,6 +3269,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
os_free(bss->rsn_preauth_interfaces);
bss->rsn_preauth_interfaces = os_strdup(pos);
#endif /* CONFIG_RSN_PREAUTH */
} else if (os_strcmp(buf, "rsn_override_omit_rsnxe") == 0) {
bss->rsn_override_omit_rsnxe = atoi(pos);
} else if (os_strcmp(buf, "peerkey") == 0) {
wpa_printf(MSG_INFO,
"Line %d: Obsolete peerkey parameter ignored", line);
@ -3556,6 +3705,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
conf->use_driver_iface_addr = atoi(pos);
} else if (os_strcmp(buf, "ieee80211w") == 0) {
bss->ieee80211w = atoi(pos);
} else if (os_strcmp(buf, "rsn_override_mfp") == 0) {
bss->rsn_override_mfp = atoi(pos);
} else if (os_strcmp(buf, "rsn_override_mfp_2") == 0) {
bss->rsn_override_mfp_2 = atoi(pos);
} else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
if (os_strcmp(pos, "AES-128-CMAC") == 0) {
bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
@ -3602,6 +3755,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
}
} else if (os_strcmp(buf, "require_ht") == 0) {
conf->require_ht = atoi(pos);
} else if (os_strcmp(buf, "ht_vht_twt_responder") == 0) {
conf->ht_vht_twt_responder = atoi(pos);
} else if (os_strcmp(buf, "obss_interval") == 0) {
conf->obss_interval = atoi(pos);
#ifdef CONFIG_IEEE80211AC
@ -4196,10 +4351,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->gas_frag_limit = val;
} else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
bss->gas_comeback_delay = atoi(pos);
#endif /* CONFIG_INTERWORKING */
} else if (os_strcmp(buf, "qos_map_set") == 0) {
if (parse_qos_map_set(bss, pos, line) < 0)
return 1;
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_RADIUS_TEST
} else if (os_strcmp(buf, "dump_msk_file") == 0) {
os_free(bss->dump_msk_file);
@ -4374,23 +4529,29 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->radio_measurements[0] |=
WLAN_RRM_CAPS_NEIGHBOR_REPORT;
} else if (os_strcmp(buf, "own_ie_override") == 0) {
struct wpabuf *tmp;
size_t len = os_strlen(pos) / 2;
tmp = wpabuf_alloc(len);
if (!tmp)
if (!get_hexstream(pos, &bss->own_ie_override,
"own_ie_override", line))
return 1;
if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) {
wpabuf_free(tmp);
wpa_printf(MSG_ERROR,
"Line %d: Invalid own_ie_override '%s'",
line, pos);
} else if (os_strcmp(buf, "rsne_override") == 0) {
if (!get_hexstream(pos, &bss->rsne_override,
"rsne_override", line))
return 1;
} else if (os_strcmp(buf, "rsnoe_override") == 0) {
if (!get_hexstream(pos, &bss->rsnoe_override,
"rsnoe_override", line))
return 1;
} else if (os_strcmp(buf, "rsno2e_override") == 0) {
if (!get_hexstream(pos, &bss->rsno2e_override,
"rsno2e_override", line))
return 1;
} else if (os_strcmp(buf, "rsnxe_override") == 0) {
if (!get_hexstream(pos, &bss->rsnxe_override,
"rsnxe_override", line))
return 1;
} else if (os_strcmp(buf, "rsnxoe_override") == 0) {
if (!get_hexstream(pos, &bss->rsnxoe_override,
"rsnxoe_override", line))
return 1;
}
wpabuf_free(bss->own_ie_override);
bss->own_ie_override = tmp;
} else if (os_strcmp(buf, "sae_reflection_attack") == 0) {
bss->sae_reflection_attack = atoi(pos);
} else if (os_strcmp(buf, "sae_commit_status") == 0) {
@ -4452,8 +4613,13 @@ static int hostapd_config_fill(struct hostapd_config *conf,
return 1;
} else if (os_strcmp(buf, "eapol_m3_no_encrypt") == 0) {
bss->eapol_m3_no_encrypt = atoi(pos);
} else if (os_strcmp(buf, "eapol_key_reserved_random") == 0) {
bss->eapol_key_reserved_random = atoi(pos);
} else if (os_strcmp(buf, "test_assoc_comeback_type") == 0) {
bss->test_assoc_comeback_type = atoi(pos);
} else if (os_strcmp(buf, "presp_elements") == 0) {
if (parse_wpabuf_hex(line, buf, &bss->presp_elements, pos))
return 1;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_SAE
} else if (os_strcmp(buf, "sae_password") == 0) {
@ -4600,6 +4766,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
} else if (os_strcmp(buf, "rrm_link_measurement_report") == 0) {
if (atoi(pos))
bss->radio_measurements[0] |=
WLAN_RRM_CAPS_LINK_MEASUREMENT;
} else if (os_strcmp(buf, "gas_address3") == 0) {
bss->gas_address3 = atoi(pos);
} else if (os_strcmp(buf, "stationary_ap") == 0) {
@ -4740,6 +4910,36 @@ static int hostapd_config_fill(struct hostapd_config *conf,
}
bss->multi_ap = val;
} else if (os_strcmp(buf, "multi_ap_profile") == 0) {
int val = atoi(pos);
if (val < MULTI_AP_PROFILE_1 || val > MULTI_AP_PROFILE_MAX) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid multi_ap_profile '%s'",
line, buf);
return -1;
}
bss->multi_ap_profile = val;
} else if (os_strcmp(buf, "multi_ap_client_disallow") == 0) {
int val = atoi(pos);
if (val < 0 || val > 3) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid multi_ap_client_allow '%s'",
line, buf);
return -1;
}
bss->multi_ap_client_disallow = val;
} else if (os_strcmp(buf, "multi_ap_vlanid") == 0) {
int val = atoi(pos);
if (val < 0 || val > MAX_VLAN_ID) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid multi_ap_vlan_id '%s'",
line, buf);
return -1;
}
bss->multi_ap_vlanid = val;
} else if (os_strcmp(buf, "rssi_reject_assoc_rssi") == 0) {
conf->rssi_reject_assoc_rssi = atoi(pos);
} else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) {
@ -4922,6 +5122,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
return 1;
} else if (os_strcmp(buf, "rnr") == 0) {
bss->rnr = atoi(pos);
} else if (os_strcmp(buf, "ssid_protection") == 0) {
int val = atoi(pos);
if (val < 0 || val > 1)
return 1;
bss->ssid_protection = val;
#ifdef CONFIG_IEEE80211BE
} else if (os_strcmp(buf, "ieee80211be") == 0) {
conf->ieee80211be = atoi(pos);
@ -4952,8 +5158,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
conf->punct_acs_threshold = val;
} else if (os_strcmp(buf, "mld_ap") == 0) {
bss->mld_ap = !!atoi(pos);
} else if (os_strcmp(buf, "mld_id") == 0) {
bss->mld_id = atoi(pos);
} else if (os_strcmp(buf, "mld_addr") == 0) {
if (hwaddr_aton(pos, bss->mld_addr)) {
wpa_printf(MSG_ERROR, "Line %d: Invalid mld_addr",

View file

@ -1309,6 +1309,8 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
hostapd_disassoc_deny_mac(hapd);
} else if (os_strcasecmp(cmd, "accept_mac_file") == 0) {
hostapd_disassoc_accept_mac(hapd);
} else if (os_strcasecmp(cmd, "ssid") == 0) {
hostapd_neighbor_sync_own_report(hapd);
} else if (os_strncmp(cmd, "wme_ac_", 7) == 0 ||
os_strncmp(cmd, "wmm_ac_", 7) == 0) {
hapd->parameter_set_count++;
@ -1942,7 +1944,7 @@ static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap)
addr = hapd->mld_addr;
addr = hapd->mld->mld_addr;
#endif /* CONFIG_IEEE80211BE */
hapd->l2_test = l2_packet_init(ifname, addr,
ETHERTYPE_IP, hostapd_data_test_rx,
@ -2452,6 +2454,31 @@ static int hostapd_ctrl_register_frame(struct hostapd_data *hapd,
#ifdef NEED_AP_MLME
static bool
hostapd_ctrl_is_freq_in_cmode(struct hostapd_hw_modes *mode,
struct hostapd_multi_hw_info *current_hw_info,
int freq)
{
struct hostapd_channel_data *chan;
int i;
for (i = 0; i < mode->num_channels; i++) {
chan = &mode->channels[i];
if (chan->flag & HOSTAPD_CHAN_DISABLED)
continue;
if (!chan_in_current_hw_info(current_hw_info, chan))
continue;
if (chan->freq == freq)
return true;
}
return false;
}
static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params,
u16 punct_bitmap)
{
@ -2475,6 +2502,21 @@ static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params,
bw_idx[bw] != params->bandwidth)
return -1;
}
} else { /* Non-6 GHz channel */
/* An EHT STA is also an HE STA as defined in
* IEEE P802.11be/D5.0, 4.3.16a. */
if (params->he_enabled || params->eht_enabled) {
params->he_enabled = 1;
/* An HE STA is also a VHT STA if operating in the 5 GHz
* band and an HE STA is also an HT STA in the 2.4 GHz
* band as defined in IEEE Std 802.11ax-2021, 4.3.15a.
* A VHT STA is an HT STA as defined in IEEE
* Std 802.11, 4.3.15. */
if (IS_5GHZ(params->freq))
params->vht_enabled = 1;
params->ht_enabled = 1;
}
}
switch (params->bandwidth) {
@ -2638,6 +2680,8 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
unsigned int i;
int bandwidth;
u8 chan;
unsigned int num_err = 0;
int err = 0;
ret = hostapd_parse_csa_settings(pos, &settings);
if (ret)
@ -2649,6 +2693,15 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
settings.link_id = iface->bss[0]->mld_link_id;
#endif /* CONFIG_IEEE80211BE */
if (iface->num_hw_features > 1 &&
!hostapd_ctrl_is_freq_in_cmode(iface->current_mode,
iface->current_hw_info,
settings.freq_params.freq)) {
wpa_printf(MSG_INFO,
"chanswitch: Invalid frequency settings provided for multi band phy");
return -1;
}
ret = hostapd_ctrl_check_freq_params(&settings.freq_params,
settings.punct_bitmap);
if (ret) {
@ -2711,29 +2764,128 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
settings.freq_params.center_freq1);
/* Perform CAC and switch channel */
iface->is_ch_switch_dfs = true;
hostapd_switch_channel_fallback(iface, &settings.freq_params);
return 0;
}
if (iface->cac_started) {
wpa_printf(MSG_DEBUG,
"CAC is in progress - switching channel without CSA");
return hostapd_force_channel_switch(iface, settings);
}
for (i = 0; i < iface->num_bss; i++) {
/* Save CHAN_SWITCH VHT, HE, and EHT config */
hostapd_chan_switch_config(iface->bss[i],
&settings.freq_params);
ret = hostapd_switch_channel(iface->bss[i], &settings);
if (ret) {
/* FIX: What do we do if CSA fails in the middle of
* submitting multi-BSS CSA requests? */
return ret;
err = hostapd_switch_channel(iface->bss[i], &settings);
if (err) {
ret = err;
num_err++;
}
}
return (iface->num_bss == num_err) ? ret : 0;
#else /* NEED_AP_MLME */
return -1;
#endif /* NEED_AP_MLME */
}
#ifdef CONFIG_IEEE80211AX
static int hostapd_ctrl_iface_color_change(struct hostapd_iface *iface,
const char *pos)
{
#ifdef NEED_AP_MLME
struct cca_settings settings;
struct hostapd_data *hapd = iface->bss[0];
int ret, color;
unsigned int i;
char *end;
os_memset(&settings, 0, sizeof(settings));
color = strtol(pos, &end, 10);
if (pos == end || color < 0 || color > 63) {
wpa_printf(MSG_ERROR, "color_change: Invalid color provided");
return -1;
}
/* Color value is expected to be [1-63]. If 0 comes, assumption is this
* is to disable the color. In this case no need to do CCA, just
* changing Beacon frames is sufficient. */
if (color == 0) {
if (iface->conf->he_op.he_bss_color_disabled) {
wpa_printf(MSG_ERROR,
"color_change: Color is already disabled");
return -1;
}
iface->conf->he_op.he_bss_color_disabled = 1;
for (i = 0; i < iface->num_bss; i++)
ieee802_11_set_beacon(iface->bss[i]);
return 0;
}
if (color == iface->conf->he_op.he_bss_color) {
if (!iface->conf->he_op.he_bss_color_disabled) {
wpa_printf(MSG_ERROR,
"color_change: Provided color is already set");
return -1;
}
iface->conf->he_op.he_bss_color_disabled = 0;
for (i = 0; i < iface->num_bss; i++)
ieee802_11_set_beacon(iface->bss[i]);
return 0;
}
if (hapd->cca_in_progress) {
wpa_printf(MSG_ERROR,
"color_change: CCA is already in progress");
return -1;
}
iface->conf->he_op.he_bss_color_disabled = 0;
for (i = 0; i < iface->num_bss; i++) {
struct hostapd_data *bss = iface->bss[i];
hostapd_cleanup_cca_params(bss);
bss->cca_color = color;
bss->cca_count = 10;
if (hostapd_fill_cca_settings(bss, &settings)) {
wpa_printf(MSG_DEBUG,
"color_change: Filling CCA settings failed for color: %d\n",
color);
hostapd_cleanup_cca_params(bss);
continue;
}
wpa_printf(MSG_DEBUG, "Setting user selected color: %d", color);
ret = hostapd_drv_switch_color(bss, &settings);
if (ret)
hostapd_cleanup_cca_params(bss);
free_beacon_data(&settings.beacon_cca);
free_beacon_data(&settings.beacon_after);
}
return 0;
#else /* NEED_AP_MLME */
return -1;
#endif /* NEED_AP_MLME */
}
#endif /* CONFIG_IEEE80211AX */
static u8 hostapd_maxnss(struct hostapd_data *hapd, struct sta_info *sta)
@ -3203,6 +3355,26 @@ static int hostapd_ctrl_iface_req_beacon(struct hostapd_data *hapd,
}
static int hostapd_ctrl_iface_req_link_measurement(struct hostapd_data *hapd,
const char *cmd, char *reply,
size_t reply_size)
{
u8 addr[ETH_ALEN];
int ret;
if (hwaddr_aton(cmd, addr)) {
wpa_printf(MSG_ERROR,
"CTRL: REQ_LINK_MEASUREMENT: Invalid MAC address");
return -1;
}
ret = hostapd_send_link_measurement_req(hapd, addr);
if (ret >= 0)
ret = os_snprintf(reply, reply_size, "%d", ret);
return ret;
}
static int hostapd_ctrl_iface_show_neighbor(struct hostapd_data *hapd,
char *buf, size_t buflen)
{
@ -3473,10 +3645,8 @@ static int hostapd_ctrl_iface_enable_mld(struct hostapd_iface *iface)
for (i = 0; i < iface->interfaces->count; ++i) {
struct hostapd_iface *h_iface = iface->interfaces->iface[i];
struct hostapd_data *h_hapd = h_iface->bss[0];
struct hostapd_bss_config *h_conf = h_hapd->conf;
if (!h_conf->mld_ap ||
h_conf->mld_id != iface->bss[0]->conf->mld_id)
if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
continue;
if (hostapd_enable_iface(h_iface)) {
@ -3500,7 +3670,6 @@ static void hostapd_disable_iface_bss(struct hostapd_iface *iface)
static int hostapd_ctrl_iface_disable_mld(struct hostapd_iface *iface)
{
unsigned int i;
struct hostapd_iface *first_iface = NULL;
if (!iface || !iface->bss[0]->conf->mld_ap) {
wpa_printf(MSG_ERROR,
@ -3514,32 +3683,19 @@ static int hostapd_ctrl_iface_disable_mld(struct hostapd_iface *iface)
for (i = 0; i < iface->interfaces->count; ++i) {
struct hostapd_iface *h_iface = iface->interfaces->iface[i];
struct hostapd_data *h_hapd = h_iface->bss[0];
struct hostapd_bss_config *h_conf = h_hapd->conf;
if (!h_conf->mld_ap ||
h_conf->mld_id != iface->bss[0]->conf->mld_id)
if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
continue;
if (!h_hapd->mld_first_bss) {
first_iface = h_iface;
continue;
}
hostapd_disable_iface_bss(iface);
}
if (first_iface)
hostapd_disable_iface_bss(first_iface);
/* Then, fully disable interfaces */
for (i = 0; i < iface->interfaces->count; ++i) {
struct hostapd_iface *h_iface = iface->interfaces->iface[i];
struct hostapd_data *h_hapd = h_iface->bss[0];
struct hostapd_bss_config *h_conf = h_hapd->conf;
if (!h_conf->mld_ap ||
h_conf->mld_id != iface->bss[0]->conf->mld_id ||
!h_hapd->mld_first_bss)
if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
continue;
if (hostapd_disable_iface(h_iface)) {
@ -3548,11 +3704,6 @@ static int hostapd_ctrl_iface_disable_mld(struct hostapd_iface *iface)
}
}
if (first_iface && hostapd_disable_iface(first_iface)) {
wpa_printf(MSG_ERROR, "Disabling AP MLD failed");
return -1;
}
return 0;
}
@ -3594,6 +3745,7 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
struct wpabuf *ssi = NULL;
int ret = -1;
enum nan_service_protocol_type srv_proto_type = 0;
bool p2p = false;
os_memset(&params, 0, sizeof(params));
/* USD shall use both solicited and unsolicited transmissions */
@ -3627,6 +3779,11 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
continue;
}
if (os_strcmp(token, "p2p=1") == 0) {
p2p = true;
continue;
}
if (os_strcmp(token, "solicited=0") == 0) {
params.solicited = false;
continue;
@ -3648,7 +3805,7 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
}
publish_id = hostapd_nan_usd_publish(hapd, service_name, srv_proto_type,
ssi, &params);
ssi, &params, p2p);
if (publish_id > 0)
ret = os_snprintf(buf, buflen, "%d", publish_id);
fail:
@ -3731,6 +3888,7 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
struct wpabuf *ssi = NULL;
int ret = -1;
enum nan_service_protocol_type srv_proto_type = 0;
bool p2p = false;
os_memset(&params, 0, sizeof(params));
@ -3764,6 +3922,11 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
continue;
}
if (os_strcmp(token, "p2p=1") == 0) {
p2p = true;
continue;
}
wpa_printf(MSG_INFO,
"CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
token);
@ -3772,7 +3935,7 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
subscribe_id = hostapd_nan_usd_subscribe(hapd, service_name,
srv_proto_type, ssi,
&params);
&params, p2p);
if (subscribe_id > 0)
ret = os_snprintf(buf, buflen, "%d", subscribe_id);
fail:
@ -4151,6 +4314,11 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
reply_len = -1;
#ifdef CONFIG_IEEE80211AX
} else if (os_strncmp(buf, "COLOR_CHANGE ", 13) == 0) {
if (hostapd_ctrl_iface_color_change(hapd->iface, buf + 13))
reply_len = -1;
#endif /* CONFIG_IEEE80211AX */
} else if (os_strncmp(buf, "NOTIFY_CW_CHANGE ", 17) == 0) {
if (hostapd_ctrl_iface_notify_cw_change(hapd, buf + 17))
reply_len = -1;
@ -4202,6 +4370,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "REQ_BEACON ", 11) == 0) {
reply_len = hostapd_ctrl_iface_req_beacon(hapd, buf + 11,
reply, reply_size);
} else if (os_strncmp(buf, "REQ_LINK_MEASUREMENT ", 21) == 0) {
reply_len = hostapd_ctrl_iface_req_link_measurement(
hapd, buf + 21, reply, reply_size);
} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
reply_size);
@ -4563,23 +4734,360 @@ done:
}
#ifdef CONFIG_IEEE80211BE
#ifndef CONFIG_CTRL_IFACE_UDP
static int hostapd_mld_ctrl_iface_receive_process(struct hostapd_mld *mld,
char *buf, char *reply,
size_t reply_size,
struct sockaddr_storage *from,
socklen_t fromlen)
{
struct hostapd_data *link_hapd, *link_itr;
int reply_len = -1, link_id = -1;
char *cmd;
bool found = false;
os_memcpy(reply, "OK\n", 3);
reply_len = 3;
cmd = buf;
/* Check whether the link ID is provided in the command */
if (os_strncmp(cmd, "LINKID ", 7) == 0) {
cmd += 7;
link_id = atoi(cmd);
if (link_id < 0 || link_id >= 15) {
os_memcpy(reply, "INVALID LINK ID\n", 16);
reply_len = 16;
goto out;
}
cmd = os_strchr(cmd, ' ');
if (!cmd)
goto out;
cmd++;
}
if (link_id >= 0) {
link_hapd = mld->fbss;
if (!link_hapd) {
os_memcpy(reply, "NO LINKS ACTIVE\n", 16);
reply_len = 16;
goto out;
}
for_each_mld_link(link_itr, link_hapd) {
if (link_itr->mld_link_id == link_id) {
found = true;
break;
}
}
if (!found)
goto out;
link_hapd = link_itr;
} else {
link_hapd = mld->fbss;
}
if (os_strcmp(cmd, "PING") == 0) {
os_memcpy(reply, "PONG\n", 5);
reply_len = 5;
} else if (os_strcmp(cmd, "ATTACH") == 0) {
if (ctrl_iface_attach(&mld->ctrl_dst, from, fromlen, NULL))
reply_len = -1;
} else if (os_strncmp(cmd, "ATTACH ", 7) == 0) {
if (ctrl_iface_attach(&mld->ctrl_dst, from, fromlen, cmd + 7))
reply_len = -1;
} else if (os_strcmp(cmd, "DETACH") == 0) {
if (ctrl_iface_detach(&mld->ctrl_dst, from, fromlen))
reply_len = -1;
} else {
if (link_id == -1)
wpa_printf(MSG_DEBUG,
"Link ID not provided, using the first link BSS (if available)");
if (!link_hapd)
reply_len = -1;
else
reply_len =
hostapd_ctrl_iface_receive_process(
link_hapd, cmd, reply, reply_size,
from, fromlen);
}
out:
if (reply_len < 0) {
os_memcpy(reply, "FAIL\n", 5);
reply_len = 5;
}
return reply_len;
}
static void hostapd_mld_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
struct hostapd_mld *mld = eloop_ctx;
char buf[4096];
int res;
struct sockaddr_storage from;
socklen_t fromlen = sizeof(from);
char *reply, *pos = buf;
const size_t reply_size = 4096;
int reply_len;
int level = MSG_DEBUG;
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
(struct sockaddr *) &from, &fromlen);
if (res < 0) {
wpa_printf(MSG_ERROR, "recvfrom(mld ctrl_iface): %s",
strerror(errno));
return;
}
buf[res] = '\0';
reply = os_malloc(reply_size);
if (!reply) {
if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
fromlen) < 0) {
wpa_printf(MSG_DEBUG, "MLD CTRL: sendto failed: %s",
strerror(errno));
}
return;
}
if (os_strcmp(pos, "PING") == 0)
level = MSG_EXCESSIVE;
wpa_hexdump_ascii(level, "RX MLD ctrl_iface", pos, res);
reply_len = hostapd_mld_ctrl_iface_receive_process(mld, pos,
reply, reply_size,
&from, fromlen);
if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
fromlen) < 0) {
wpa_printf(MSG_DEBUG, "MLD CTRL: sendto failed: %s",
strerror(errno));
}
os_free(reply);
}
static char * hostapd_mld_ctrl_iface_path(struct hostapd_mld *mld)
{
size_t len;
char *buf;
int ret;
if (!mld->ctrl_interface)
return NULL;
len = os_strlen(mld->ctrl_interface) + os_strlen(mld->name) + 2;
buf = os_malloc(len);
if (!buf)
return NULL;
ret = os_snprintf(buf, len, "%s/%s", mld->ctrl_interface, mld->name);
if (os_snprintf_error(len, ret)) {
os_free(buf);
return NULL;
}
return buf;
}
#endif /* !CONFIG_CTRL_IFACE_UDP */
int hostapd_mld_ctrl_iface_init(struct hostapd_mld *mld)
{
#ifndef CONFIG_CTRL_IFACE_UDP
struct sockaddr_un addr;
int s = -1;
char *fname = NULL;
if (!mld)
return -1;
if (mld->ctrl_sock > -1) {
wpa_printf(MSG_DEBUG, "MLD %s ctrl_iface already exists!",
mld->name);
return 0;
}
dl_list_init(&mld->ctrl_dst);
if (!mld->ctrl_interface)
return 0;
if (mkdir(mld->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
if (errno == EEXIST) {
wpa_printf(MSG_DEBUG,
"Using existing control interface directory.");
} else {
wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
strerror(errno));
goto fail;
}
}
if (os_strlen(mld->ctrl_interface) + 1 + os_strlen(mld->name) >=
sizeof(addr.sun_path))
goto fail;
s = socket(PF_UNIX, SOCK_DGRAM, 0);
if (s < 0) {
wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
goto fail;
}
os_memset(&addr, 0, sizeof(addr));
#ifdef __FreeBSD__
addr.sun_len = sizeof(addr);
#endif /* __FreeBSD__ */
addr.sun_family = AF_UNIX;
fname = hostapd_mld_ctrl_iface_path(mld);
if (!fname)
goto fail;
os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
wpa_printf(MSG_DEBUG, "Setting up MLD %s ctrl_iface", mld->name);
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
strerror(errno));
if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not allow connections - assuming it was left over from forced program termination");
if (unlink(fname) < 0) {
wpa_printf(MSG_ERROR,
"Could not unlink existing ctrl_iface socket '%s': %s",
fname, strerror(errno));
goto fail;
}
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
0) {
wpa_printf(MSG_ERROR,
"hostapd-ctrl-iface: bind(PF_UNIX): %s",
strerror(errno));
goto fail;
}
wpa_printf(MSG_DEBUG,
"Successfully replaced leftover ctrl_iface socket '%s'",
fname);
} else {
wpa_printf(MSG_INFO,
"ctrl_iface exists and seems to be in use - cannot override it");
wpa_printf(MSG_INFO,
"Delete '%s' manually if it is not used anymore", fname);
os_free(fname);
fname = NULL;
goto fail;
}
}
if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
strerror(errno));
goto fail;
}
os_free(fname);
mld->ctrl_sock = s;
if (eloop_register_read_sock(s, hostapd_mld_ctrl_iface_receive, mld,
NULL) < 0)
return -1;
return 0;
fail:
if (s >= 0)
close(s);
if (fname) {
unlink(fname);
os_free(fname);
}
return -1;
#endif /* !CONFIG_CTRL_IFACE_UDP */
return 0;
}
void hostapd_mld_ctrl_iface_deinit(struct hostapd_mld *mld)
{
#ifndef CONFIG_CTRL_IFACE_UDP
struct wpa_ctrl_dst *dst, *prev;
if (mld->ctrl_sock > -1) {
char *fname;
eloop_unregister_read_sock(mld->ctrl_sock);
close(mld->ctrl_sock);
mld->ctrl_sock = -1;
fname = hostapd_mld_ctrl_iface_path(mld);
if (fname) {
unlink(fname);
os_free(fname);
}
if (mld->ctrl_interface &&
rmdir(mld->ctrl_interface) < 0) {
if (errno == ENOTEMPTY) {
wpa_printf(MSG_DEBUG,
"MLD control interface directory not empty - leaving it behind");
} else {
wpa_printf(MSG_ERROR,
"rmdir[ctrl_interface=%s]: %s",
mld->ctrl_interface,
strerror(errno));
}
}
}
dl_list_for_each_safe(dst, prev, &mld->ctrl_dst, struct wpa_ctrl_dst,
list)
os_free(dst);
#endif /* !CONFIG_CTRL_IFACE_UDP */
os_free(mld->ctrl_interface);
}
#endif /* CONFIG_IEEE80211BE */
#ifndef CONFIG_CTRL_IFACE_UDP
static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
{
char *buf;
size_t len;
const char *ctrl_sock_iface;
#ifdef CONFIG_IEEE80211BE
ctrl_sock_iface = hapd->ctrl_sock_iface;
#else /* CONFIG_IEEE80211BE */
ctrl_sock_iface = hapd->conf->iface;
#endif /* CONFIG_IEEE80211BE */
if (hapd->conf->ctrl_interface == NULL)
return NULL;
len = os_strlen(hapd->conf->ctrl_interface) +
os_strlen(hapd->conf->iface) + 2;
os_strlen(ctrl_sock_iface) + 2;
buf = os_malloc(len);
if (buf == NULL)
return NULL;
os_snprintf(buf, len, "%s/%s",
hapd->conf->ctrl_interface, hapd->conf->iface);
hapd->conf->ctrl_interface, ctrl_sock_iface);
buf[len - 1] = '\0';
return buf;
}
@ -4695,6 +5203,7 @@ fail:
struct sockaddr_un addr;
int s = -1;
char *fname = NULL;
size_t iflen;
if (hapd->ctrl_sock > -1) {
wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
@ -4749,8 +5258,13 @@ fail:
}
#endif /* ANDROID */
#ifdef CONFIG_IEEE80211BE
iflen = os_strlen(hapd->ctrl_sock_iface);
#else /* CONFIG_IEEE80211BE */
iflen = os_strlen(hapd->conf->iface);
#endif /* CONFIG_IEEE80211BE */
if (os_strlen(hapd->conf->ctrl_interface) + 1 +
os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
iflen >= sizeof(addr.sun_path))
goto fail;
s = socket(PF_UNIX, SOCK_DGRAM, 0);
@ -5358,7 +5872,7 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
reply_len = -1;
} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
reply_len = hostapd_global_ctrl_iface_interfaces(
interfaces, buf + 10, reply, sizeof(buffer));
interfaces, buf + 10, reply, reply_size);
} else if (os_strcmp(buf, "TERMINATE") == 0) {
eloop_terminate();
} else {

View file

@ -14,6 +14,8 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd);
void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd);
int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface);
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface);
int hostapd_mld_ctrl_iface_init(struct hostapd_mld *mld);
void hostapd_mld_ctrl_iface_deinit(struct hostapd_mld *mld);
#else /* CONFIG_NO_CTRL_IFACE */
static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
{

View file

@ -141,6 +141,9 @@ CONFIG_PKCS12=y
# Build IPv6 support for RADIUS operations
CONFIG_IPV6=y
# Include support fo RADIUS/TLS into the RADIUS client
#CONFIG_RADIUS_TLS=y
# IEEE Std 802.11r-2008 (Fast BSS Transition)
#CONFIG_IEEE80211R=y

View file

@ -522,6 +522,25 @@ wmm_ac_vo_acm=0
# even if they are still in range of the AP. This can be done by setting
# skip_inactivity_poll to 1 (default 0).
#skip_inactivity_poll=0
#
# BSS max idle period management
# 0 = disabled (do not advertise and manage BSS max idle period)
# 1 = enabled (advertise and manage BSS max idle period; default)
# 2 = enabled requiring protected frames (advertise and manage BSS max idle
# period and require STAs to use protected keep-alive frames)
#bss_max_idle=1
#
# Maximum acceptable BSS maximum idle period
# If this is set to a nonzero value, the AP allows STAs to request different
# maximum idle period values. This is in the units to 1000 TUs (1.024 s)
#max_acceptable_idle_period=600
#
# Allow STA to skip group key handshake without getting disconnection when
# BSS max idle period management is enabled.
# 0 = disconnect STA if it does not reply to group key handshake (default)
# 1 = do not disconnect STA if it does not reply to group key handshake and
# if BSS max idle period management is enabled
#no_disconnect_on_group_keyerror=0
# Disassociate stations based on excessive transmission failures or other
# indications of connection loss. This depends on the driver capabilities and
@ -646,6 +665,12 @@ wmm_ac_vo_acm=0
# no co-existence issues with neighboring devices are found.
#obss_interval=0
# ht_vht_twt_responder: Whether TWT responder is enabled in HT and VHT modes
# 0 = disable; Disable TWT responder support in HT and VHT modes (default).
# 1 = enable; Enable TWT responder support in HT and VHT modes if supported by
# the driver.
#ht_vht_twt_responder=0
##### IEEE 802.11ac related configuration #####################################
# ieee80211ac: Whether IEEE 802.11ac (VHT) is enabled
@ -1071,9 +1096,6 @@ wmm_ac_vo_acm=0
# 1 = yes (MLO)
#mld_ap=0
# MLD ID - Affiliated MLD ID
#mld_id=1
# AP MLD MAC address
# The configured address will be set as the interface hardware address and used
# as the AP MLD MAC address. If not set, the current interface hardware address
@ -1581,6 +1603,16 @@ own_ip_addr=127.0.0.1
#acct_server_port=1813
#acct_server_shared_secret=secret2
# RADIUS/TLS instead of RADIUS/UDP
#auth_server_addr=127.0.0.1
#auth_server_port=2083
#auth_server_type=TLS
#auth_server_shared_secret=radsec
#auth_server_ca_cert=<path to trusted CA certificate(s)>
#auth_server_client_cert=<path to client certificate>
#auth_server_private_key=<path to private key>
#auth_server_private_key_passwd=<password for decrypting private key>
# Retry interval for trying to return to the primary RADIUS server (in
# seconds). RADIUS client code will automatically try to use the next server
# when the current server is not replying to requests. If this interval is set,
@ -1588,6 +1620,17 @@ own_ip_addr=127.0.0.1
# currently used secondary server is still working.
#radius_retry_primary_interval=600
# Message-Authenticator attribute requirement for non-EAP cases
# hostapd requires Message-Authenticator attribute to be included in all cases
# where RADIUS is used for EAP authentication. This is also required for cases
# where RADIUS is used for MAC ACL (macaddr_acl=2) by default, but that case
# can be configured to not require this for compatibility with RADIUS servers
# that do not include the attribute. This is not recommended due to potential
# security concerns, but can be used as a temporary workaround in networks where
# the connection to the RADIUS server is secure.
# 0 = Do not require Message-Authenticator in MAC ACL response
# 1 = Require Message-Authenticator in all authentication cases (default)
#radius_require_message_authenticator=1
# Interim accounting update interval
# If this is set (larger than 0) and acct_server is configured, hostapd will
@ -2076,7 +2119,7 @@ own_ip_addr=127.0.0.1
# Maximum number of SAE synchronization errors (dot11RSNASAESync)
# The offending SAE peer will be disconnected if more than this many
# synchronization errors happen.
#sae_sync=5
#sae_sync=3
# Enabled SAE finite cyclic groups
# SAE implementation are required to support group 19 (ECC group defined over a
@ -2236,6 +2279,86 @@ own_ip_addr=127.0.0.1
# (default: 1 = activated)
#pasn_noauth=1
# SSID protection in 4-way handshake
# The IEEE 802.11i-2004 RSN design did not provide means for protecting the
# SSID in the general case. IEEE P802.11REVme/D6.0 added support for this in
# 4-way handshake. This capability allows a STA to confirm that the AP has the
# same understanding on which SSID is being used for an association in a
# protected manner in cases where both the AP and the STA has this capability.
# This can be used to mitigate CVE-2023-52424 (a.k.a. the SSID Confusion
# Attack).
#
# Ideally, this capability would be enabled by default on the AP, but since this
# is new functionality with limited testing, the default is to disable this for
# now and require explicitly configuration to enable. The default behavior is
# like to change once this capability has received more testing.
#
# 0 = SSID protection in 4-way handshake disabled (default)
# 1 = SSID protection in 4-way handshake enabled
#
#ssid_protection=0
# RSNE/RSNXE override
#
# These parameters can be used to configure RSN parameters for STAs that support
# the override elements. The RSN parameters for STAs that do not support these
# mechanisms are configured in the referenced configuration parameters. The AP
# allows STAs to use either of the configured sets for negotiating RSN
# parameters.
#
# The main purpose of this mechanism is to make the AP look like it is using an
# older security mechanism (e.g., WPA2-Personal) to older STAs while allowing
# new stations use newer security mechanisms (e.g., WPA3-Personal) based on the
# override values. This might be needed to work around issues with deployed
# STAs that do not implement RSNE extensibility correctly and may fail to
# connect when the AP is using a transition mode like WPA3-Personal transition
# mode.
#
# Key management; see wpa_key_mgmt for RSNE configuration
#rsn_override_key_mgmt=<accepted key management algorithms>
#
# Pairwise cipher suites; see rsn_pairwise for RSNE configuration
#rsn_override_pairwise=<accepted cipher suites)
#
# Management frame protection (MFP/PMF); see ieee80211w for RSNE configuration
# 0 = disabled
# 1 = optional
# 2 = required
#rsn_override_mfp=<0/1/2>
#
# Second set of similar parameters. These are required to be used for
# Wi-Fi 7 (EHT/MLO) associations with RSN overriding and can optionally be used
# in cases that do not use Wi-Fi 7.
#rsn_override_key_mgmt_2
#rsn_override_pairwise_2
#rsn_override_mfp_2
#
# The RSNXE is normally included if any of the extended RSN capabilities is
# enabled/supported. When using RSN overriding, a separate RSNXOE is included
# and it may be more interoperable to omit the RSNXE completely. This
# configuration parameter can be used to do that.
# 0 = Include the RSNXE if any extended RSN capability is enabled/supported
# (default).
# 1 = Do not include the RSNXE.
#rsn_override_omit_rsnxe=0
#
# Example configuration for WPA2-Personal/PMF-optional in RSNE and
# WPA3-Personal/PMF-required/MLO in override elements
#wpa_key_mgmt=WPA-PSK
#rsn_pairwise=CCMP
#ieee80211w=1
#rsn_override_key_mgmt=SAE
#rsn_override_pairwise=GCMP-256
#rsn_override_mfp=2
#rsn_override_key_mgmt_2=SAE-EXT-KEY
#rsn_override_pairwise_2=GCMP-256
#rsn_override_mfp_2=2
#beacon_prot=1
#sae_groups=19 20
#sae_require_mfp=1
#sae_pwe=2
##### IEEE 802.11r configuration ##############################################
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
@ -2555,6 +2678,23 @@ own_ip_addr=127.0.0.1
#multi_ap_backhaul_wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
#multi_ap_backhaul_wpa_passphrase=secret passphrase
# Multi-AP Profile
# Indicate the supported Multi-AP profile (default: 2)
# 1 = Supports Multi-AP profile 1 as defined in Wi-Fi EasyMesh specification
# 2 = Supports Multi-AP profile 2 as defined in Wi-Fi EasyMesh specification
#multi_ap_profile=2
# Multi-AP client disallow
# Used to disallow profile specific backhaul STA association
# Bitmap of the disallowed Profile-X profiles
# 1 = Profile-1 Backhaul STA association disallowed
# 2 = Profile-2 Backhaul STA association disallowed
#multi_ap_client_disallow=0
# Multi-AP VLAN ID
# A valid non-zero VLAN ID will be used to update Default IEEE 802.1Q Setting
#multi_ap_vlanid=0
# WPS UPnP interface
# If set, support for external Registrars is enabled.
#upnp_iface=br0
@ -3088,6 +3228,9 @@ own_ip_addr=127.0.0.1
# Enable neighbor report via radio measurements
#rrm_neighbor_report=1
# Enable link measurement report via radio measurements
#rrm_link_measurement_report=1
# Enable beacon report via radio measurements
#rrm_beacon_report=1
@ -3189,6 +3332,13 @@ own_ip_addr=127.0.0.1
# attempt (wpa_pairwise_update_count). This will trigger a timeout on all
# previous attempts and thus delays the frame. (testing only)
#delay_eapol_tx=0
#
# Additional elements for Probe Response frames.
# This parameter can be used to add additional element(s) to the end of the
# Probe Response frames. The format for these element(s) is a hexdump of the
# raw information elements (id+len+payload for one or more elements).
# These elements are added after the 'vendor_elements'.
#presp_elements=
##### Multiple BSSID support ##################################################
#

View file

@ -21,7 +21,7 @@
static const char *const hostapd_cli_version =
"hostapd_cli v" VERSION_STR "\n"
"Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi> and contributors";
"Copyright (c) 2004-2024, Jouni Malinen <j@w1.fi> and contributors";
static struct wpa_ctrl *ctrl_conn;
static int hostapd_cli_quit = 0;
@ -54,7 +54,11 @@ static void usage(void)
fprintf(stderr, "%s\n", hostapd_cli_version);
fprintf(stderr,
"\n"
"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvBr] "
"usage: hostapd_cli [-p<path>] [-i<ifname>] "
#ifdef CONFIG_IEEE80211BE
"[-l<link_id>] "
#endif /* CONFIG_IEEE80211BE */
"[-hvBr] "
"[-a<path>] \\\n"
" [-P<pid file>] [-G<ping interval>] [command..]\n"
"\n"
@ -74,7 +78,11 @@ static void usage(void)
" -B run a daemon in the background\n"
" -i<ifname> Interface to listen on (default: first "
"interface found in the\n"
" socket path)\n\n");
" socket path)\n"
#ifdef CONFIG_IEEE80211BE
" -l<link_id> Link ID of the interface in case of Multi-Link Operation\n"
#endif /* CONFIG_IEEE80211BE */
"\n");
print_help(stderr, NULL);
}
@ -1168,6 +1176,15 @@ static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
#endif /* CONFIG_FST */
#ifdef CONFIG_IEEE80211AX
static int hostapd_cli_cmd_color_change(struct wpa_ctrl *ctrl,
int argc, char *argv[])
{
return hostapd_cli_cmd(ctrl, "COLOR_CHANGE", 1, argc, argv);
}
#endif /* CONFIG_IEEE80211AX */
static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
int argc, char *argv[])
{
@ -1215,14 +1232,14 @@ static int hostapd_cli_cmd_notify_cw_change(struct wpa_ctrl *ctrl,
static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
char *argv[])
char *argv[])
{
return wpa_ctrl_command(ctrl, "ENABLE");
}
static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
char *argv[])
char *argv[])
{
return wpa_ctrl_command(ctrl, "RELOAD");
}
@ -1243,7 +1260,7 @@ static int hostapd_cli_cmd_reload_config(struct wpa_ctrl *ctrl, int argc,
static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
char *argv[])
char *argv[])
{
return wpa_ctrl_command(ctrl, "DISABLE");
}
@ -1257,19 +1274,26 @@ static int hostapd_cli_cmd_enable_mld(struct wpa_ctrl *ctrl, int argc,
static int hostapd_cli_cmd_disable_mld(struct wpa_ctrl *ctrl, int argc,
char *argv[])
char *argv[])
{
return wpa_ctrl_command(ctrl, "DISABLE_MLD");
}
static int hostapd_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc,
char *argv[])
char *argv[])
{
return wpa_ctrl_command(ctrl, "UPDATE_BEACON");
}
static int hostapd_cli_cmd_stop_ap(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return wpa_ctrl_command(ctrl, "STOP_AP");
}
static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char cmd[256];
@ -1598,6 +1622,13 @@ static int hostapd_cli_cmd_req_beacon(struct wpa_ctrl *ctrl, int argc,
}
static int hostapd_cli_cmd_req_link_measurement(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return hostapd_cli_cmd(ctrl, "REQ_LINK_MEASUREMENT", 1, argc, argv);
}
static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@ -1732,6 +1763,11 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
"<cs_count> <freq> [sec_channel_offset=] [center_freq1=]\n"
" [center_freq2=] [bandwidth=] [blocktx] [ht|vht]\n"
" = initiate channel switch announcement" },
#ifdef CONFIG_IEEE80211AX
{ "color_change", hostapd_cli_cmd_color_change, NULL,
"<color> = initiate BSS color change to set the specified color\n"
"Value 0 will disable the color.\n"},
#endif /* CONFIG_IEEE80211AX */
{ "notify_cw_change", hostapd_cli_cmd_notify_cw_change, NULL,
"<channel_width> = 0 - 20 MHz, 1 - 40 MHz, 2 - 80 MHz, 3 - 160 MHz" },
{ "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL,
@ -1759,6 +1795,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
"= disable AP MLD to which the interface is affiliated" },
{ "update_beacon", hostapd_cli_cmd_update_beacon, NULL,
"= update Beacon frame contents\n"},
{ "stop_ap", hostapd_cli_cmd_stop_ap, NULL,
"= stop AP\n"},
{ "erp_flush", hostapd_cli_cmd_erp_flush, NULL,
"= drop all ERP keys"},
{ "log_level", hostapd_cli_cmd_log_level, NULL,
@ -1838,6 +1876,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
"<addr> = poll a STA to check connectivity with a QoS null frame" },
{ "req_beacon", hostapd_cli_cmd_req_beacon, NULL,
"<addr> [req_mode=] <measurement request hexdump> = send a Beacon report request to a station" },
{ "req_link_measurement", hostapd_cli_cmd_req_link_measurement, NULL,
"<addr> = send a link measurement report request to a station"},
{ "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
"= reload wpa_psk_file only" },
#ifdef CONFIG_IEEE80211R_AP
@ -2180,12 +2220,15 @@ int main(int argc, char *argv[])
int c;
int daemonize = 0;
int reconnect = 0;
#ifdef CONFIG_IEEE80211BE
int link_id = -1;
#endif /* CONFIG_IEEE80211BE */
if (os_program_init())
return -1;
for (;;) {
c = getopt(argc, argv, "a:BhG:i:p:P:rs:v");
c = getopt(argc, argv, "a:BhG:i:l:p:P:rs:v");
if (c < 0)
break;
switch (c) {
@ -2220,6 +2263,11 @@ int main(int argc, char *argv[])
case 's':
client_socket_dir = optarg;
break;
#ifdef CONFIG_IEEE80211BE
case 'l':
link_id = atoi(optarg);
break;
#endif /* CONFIG_IEEE80211BE */
default:
usage();
return -1;
@ -2253,6 +2301,24 @@ int main(int argc, char *argv[])
closedir(dir);
}
}
#ifdef CONFIG_IEEE80211BE
if (link_id >= 0 && ctrl_ifname) {
int ret;
char buf[300];
ret = os_snprintf(buf, sizeof(buf), "%s_%s%d",
ctrl_ifname, WPA_CTRL_IFACE_LINK_NAME,
link_id);
if (os_snprintf_error(sizeof(buf), ret))
return -1;
os_free(ctrl_ifname);
ctrl_ifname = os_strdup(buf);
link_id = -1;
}
#endif /* CONFIG_IEEE80211BE */
hostapd_cli_reconnect(ctrl_ifname);
if (ctrl_conn) {
if (warning_displayed)

View file

@ -158,6 +158,9 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
struct hostapd_bss_config *conf = hapd->conf;
u8 *b = conf->bssid;
struct wpa_driver_capa capa;
#ifdef CONFIG_IEEE80211BE
struct hostapd_data *h_hapd = NULL;
#endif /* CONFIG_IEEE80211BE */
if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
@ -165,30 +168,12 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
}
#ifdef CONFIG_IEEE80211BE
for (i = 0; conf->mld_ap && i < iface->interfaces->count; i++) {
struct hostapd_iface *h = iface->interfaces->iface[i];
struct hostapd_data *h_hapd = h->bss[0];
struct hostapd_bss_config *hconf = h_hapd->conf;
if (h == iface) {
wpa_printf(MSG_DEBUG, "MLD: Skip own interface");
continue;
}
if (!hconf->mld_ap || hconf->mld_id != conf->mld_id) {
wpa_printf(MSG_DEBUG,
"MLD: Skip non matching mld_id");
continue;
}
wpa_printf(MSG_DEBUG, "MLD: Found matching MLD interface");
if (!h_hapd->drv_priv) {
wpa_printf(MSG_DEBUG,
"MLD: Matching MLD BSS not initialized yet");
continue;
}
if (conf->mld_ap)
h_hapd = hostapd_mld_get_first_bss(hapd);
if (h_hapd) {
hapd->drv_priv = h_hapd->drv_priv;
hapd->interface_added = h_hapd->interface_added;
/*
* All interfaces participating in the AP MLD would have
@ -198,20 +183,17 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
* is not configured, and otherwise it would be the
* configured BSSID.
*/
os_memcpy(hapd->mld_addr, h_hapd->mld_addr, ETH_ALEN);
if (is_zero_ether_addr(b)) {
os_memcpy(hapd->own_addr, h_hapd->mld_addr, ETH_ALEN);
os_memcpy(hapd->own_addr, h_hapd->mld->mld_addr,
ETH_ALEN);
random_mac_addr_keep_oui(hapd->own_addr);
} else {
os_memcpy(hapd->own_addr, b, ETH_ALEN);
}
/*
* Mark the interface as a secondary interface, as this
* is needed for the de-initialization flow
*/
hapd->mld_first_bss = h_hapd;
hapd->mld_link_id = hapd->mld_first_bss->mld_next_link_id++;
wpa_printf(MSG_DEBUG,
"Setup of non first link (%d) BSS of MLD %s",
hapd->mld_link_id, hapd->conf->iface);
goto setup_mld;
}
@ -288,13 +270,15 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
* configured, and otherwise it would be the configured BSSID.
*/
if (hapd->conf->mld_ap) {
os_memcpy(hapd->mld_addr, hapd->own_addr, ETH_ALEN);
hapd->mld_next_link_id = 0;
hapd->mld_link_id = hapd->mld_next_link_id++;
os_memcpy(hapd->mld->mld_addr, hapd->own_addr, ETH_ALEN);
if (!b)
random_mac_addr_keep_oui(hapd->own_addr);
else
os_memcpy(hapd->own_addr, b, ETH_ALEN);
wpa_printf(MSG_DEBUG, "Setup of first link (%d) BSS of MLD %s",
hapd->mld_link_id, hapd->conf->iface);
}
setup_mld:
@ -306,6 +290,7 @@ setup_mld:
iface->drv_flags = capa.flags;
iface->drv_flags2 = capa.flags2;
iface->drv_rrm_flags = capa.rrm_flags;
iface->probe_resp_offloads = capa.probe_resp_offloads;
/*
* Use default extended capa values from per-radio information
@ -348,11 +333,17 @@ setup_mld:
wpa_printf(MSG_DEBUG,
"MLD: Set link_id=%u, mld_addr=" MACSTR
", own_addr=" MACSTR,
hapd->mld_link_id, MAC2STR(hapd->mld_addr),
hapd->mld_link_id, MAC2STR(hapd->mld->mld_addr),
MAC2STR(hapd->own_addr));
hostapd_drv_link_add(hapd, hapd->mld_link_id,
hapd->own_addr);
if (hostapd_drv_link_add(hapd, hapd->mld_link_id,
hapd->own_addr)) {
wpa_printf(MSG_ERROR,
"MLD: Failed to add link %d in MLD %s",
hapd->mld_link_id, hapd->conf->iface);
return -1;
}
hostapd_mld_add_link(hapd);
}
#endif /* CONFIG_IEEE80211BE */
@ -568,7 +559,7 @@ static void show_version(void)
"hostapd v%s\n"
"User space daemon for IEEE 802.11 AP management,\n"
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
"Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> "
"Copyright (c) 2002-2024, Jouni Malinen <j@w1.fi> "
"and contributors\n",
VERSION_STR);
}
@ -749,6 +740,30 @@ static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx)
}
static void hostapd_global_cleanup_mld(struct hapd_interfaces *interfaces)
{
#ifdef CONFIG_IEEE80211BE
size_t i;
if (!interfaces || !interfaces->mld)
return;
for (i = 0; i < interfaces->mld_count; i++) {
if (!interfaces->mld[i])
continue;
interfaces->mld_ctrl_iface_deinit(interfaces->mld[i]);
os_free(interfaces->mld[i]);
interfaces->mld[i] = NULL;
}
os_free(interfaces->mld);
interfaces->mld = NULL;
interfaces->mld_count = 0;
#endif /* CONFIG_IEEE80211BE */
}
int main(int argc, char *argv[])
{
struct hapd_interfaces interfaces;
@ -783,6 +798,10 @@ int main(int argc, char *argv[])
interfaces.global_iface_path = NULL;
interfaces.global_iface_name = NULL;
interfaces.global_ctrl_sock = -1;
#ifdef CONFIG_IEEE80211BE
interfaces.mld_ctrl_iface_init = hostapd_mld_ctrl_iface_init;
interfaces.mld_ctrl_iface_deinit = hostapd_mld_ctrl_iface_deinit;
#endif /* CONFIG_IEEE80211BE */
dl_list_init(&interfaces.global_ctrl_dst);
#ifdef CONFIG_ETH_P_OUI
dl_list_init(&interfaces.eth_p_oui);
@ -1029,6 +1048,8 @@ int main(int argc, char *argv[])
interfaces.iface = NULL;
interfaces.count = 0;
hostapd_global_cleanup_mld(&interfaces);
#ifdef CONFIG_DPP
dpp_global_deinit(interfaces.dpp);
#endif /* CONFIG_DPP */

View file

@ -12,6 +12,7 @@
#include "utils/common.h"
#include "utils/list.h"
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "common/hw_features_common.h"
#include "common/wpa_ctrl.h"
@ -75,7 +76,7 @@
*
* This corresponds to:
* ---
* (busy time - tx time) / (active time - tx time) * 2^(chan_nf + band_min_nf)
* (busy time - tx time) / (active time - tx time) * 2^(chan_nf - band_min_nf)
* ---
*
* The coefficient of 2 reflects the way power in "far-field"
@ -92,7 +93,7 @@
* calculated easily.
* ---
* (busy time - tx time) / (active time - tx time) *
* 2^(10^(chan_nf/10) + 10^(band_min_nf/10))
* 2^(10^(chan_nf/10) - 10^(band_min_nf/10))
* ---
*
* However to account for cases where busy/rx time is 0 (channel load is then
@ -100,7 +101,7 @@
* channel with lower noise floor is preferred. The equation becomes:
* ---
* 10^(chan_nf/5) + (busy time - tx time) / (active time - tx time) *
* 2^(10^(chan_nf/10) + 10^(band_min_nf/10))
* 2^(10^(chan_nf/10) - 10^(band_min_nf/10))
* ---
*
* All this "interference factor" is purely subjective and only time
@ -307,6 +308,7 @@ static const struct bw_item *bw_desc[] = {
static int acs_request_scan(struct hostapd_iface *iface);
static int acs_survey_is_sufficient(struct freq_survey *survey);
static void acs_scan_retry(void *eloop_data, void *user_data);
static void acs_clean_chan_surveys(struct hostapd_channel_data *chan)
@ -352,6 +354,8 @@ void acs_cleanup(struct hostapd_iface *iface)
iface->chans_surveyed = 0;
iface->acs_num_completed_scans = 0;
iface->acs_num_retries = 0;
eloop_cancel_timeout(acs_scan_retry, iface, NULL);
}
@ -507,7 +511,7 @@ static int acs_survey_list_is_sufficient(struct hostapd_channel_data *chan)
}
if (ret == -1)
ret = 1; /* no survey list entries */
ret = 0; /* no survey list entries */
if (!ret) {
wpa_printf(MSG_INFO,
@ -830,6 +834,9 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
int bw320_offset = 0, ideal_bw320_offset = 0;
unsigned int k;
int secondary_channel = 1, freq_offset;
#ifdef CONFIG_IEEE80211BE
int index_primary = 0;
#endif /* CONFIG_IEEE80211BE */
if (is_24ghz_mode(mode->mode))
secondary_channel = iface->conf->secondary_channel;
@ -969,6 +976,9 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
best->chan, chan->chan,
chan->interference_factor,
best->interference_factor);
#ifdef CONFIG_IEEE80211BE
index_primary = (chan->freq - best->freq) / 20;
#endif /* CONFIG_IEEE80211BE */
chan = best;
}
@ -1057,7 +1067,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
if (iface->conf->ieee80211be)
acs_update_puncturing_bitmap(iface, mode, bw,
n_chans, chan,
factor, 0);
factor,
index_primary);
#endif /* CONFIG_IEEE80211BE */
}
@ -1317,6 +1328,7 @@ static void acs_scan_complete(struct hostapd_iface *iface)
int err;
iface->scan_cb = NULL;
iface->acs_num_retries = 0;
wpa_printf(MSG_DEBUG, "ACS: Using survey based algorithm (acs_num_scans=%d)",
iface->conf->acs_num_scans);
@ -1329,7 +1341,7 @@ static void acs_scan_complete(struct hostapd_iface *iface)
if (++iface->acs_num_completed_scans < iface->conf->acs_num_scans) {
err = acs_request_scan(iface);
if (err) {
if (err && err != -EBUSY) {
wpa_printf(MSG_ERROR, "ACS: Failed to request scan");
goto fail;
}
@ -1382,7 +1394,7 @@ static int * acs_request_scan_add_freqs(struct hostapd_iface *iface,
static int acs_request_scan(struct hostapd_iface *iface)
{
struct wpa_driver_scan_params params;
int i, *freq;
int i, *freq, ret;
int num_channels;
struct hostapd_hw_modes *mode;
@ -1415,24 +1427,62 @@ static int acs_request_scan(struct hostapd_iface *iface)
return -1;
}
iface->scan_cb = acs_scan_complete;
if (!iface->acs_num_retries)
wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
iface->acs_num_completed_scans + 1,
iface->conf->acs_num_scans);
else
wpa_printf(MSG_DEBUG,
"ACS: Re-try scanning attempt %d (%d / %d)",
iface->acs_num_retries,
iface->acs_num_completed_scans + 1,
iface->conf->acs_num_scans);
wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
iface->acs_num_completed_scans + 1,
iface->conf->acs_num_scans);
ret = hostapd_driver_scan(iface->bss[0], &params);
os_free(params.freqs);
if (hostapd_driver_scan(iface->bss[0], &params) < 0) {
if (ret == -EBUSY) {
iface->acs_num_retries++;
if (iface->acs_num_retries >= ACS_SCAN_RETRY_MAX_COUNT) {
wpa_printf(MSG_ERROR,
"ACS: Failed to request initial scan (all re-attempts failed)");
acs_fail(iface);
return -1;
}
wpa_printf(MSG_INFO,
"Failed to request acs scan ret=%d (%s) - try to scan after %d seconds",
ret, strerror(-ret), ACS_SCAN_RETRY_INTERVAL);
eloop_cancel_timeout(acs_scan_retry, iface, NULL);
eloop_register_timeout(ACS_SCAN_RETRY_INTERVAL, 0,
acs_scan_retry, iface, NULL);
return 0;
}
if (ret < 0) {
wpa_printf(MSG_ERROR, "ACS: Failed to request initial scan");
acs_cleanup(iface);
os_free(params.freqs);
return -1;
}
os_free(params.freqs);
iface->scan_cb = acs_scan_complete;
return 0;
}
static void acs_scan_retry(void *eloop_data, void *user_data)
{
struct hostapd_iface *iface = eloop_data;
if (acs_request_scan(iface)) {
wpa_printf(MSG_ERROR,
"ACS: Failed to request re-try of initial scan");
acs_fail(iface);
}
}
enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
{
int err;

View file

@ -15,6 +15,9 @@
enum hostapd_chan_status acs_init(struct hostapd_iface *iface);
void acs_cleanup(struct hostapd_iface *iface);
#define ACS_SCAN_RETRY_MAX_COUNT 15
#define ACS_SCAN_RETRY_INTERVAL 5
#else /* CONFIG_ACS */
static inline enum hostapd_chan_status acs_init(struct hostapd_iface *iface)

View file

@ -92,6 +92,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
bss->eap_sim_id = 3;
bss->eap_sim_aka_fast_reauth_limit = 1000;
bss->ap_max_inactivity = AP_MAX_INACTIVITY;
bss->bss_max_idle = 1;
bss->eapol_version = EAPOL_VERSION;
bss->max_listen_interval = 65535;
@ -121,9 +122,10 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
#endif /* CONFIG_IEEE80211R_AP */
bss->radius_das_time_window = 300;
bss->radius_require_message_authenticator = 1;
bss->anti_clogging_threshold = 5;
bss->sae_sync = 5;
bss->sae_sync = 3;
bss->gas_frag_limit = 1400;
@ -163,6 +165,8 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
/* Default to strict CRL checking. */
bss->check_crl_strict = 1;
bss->multi_ap_profile = MULTI_AP_PROFILE_2;
#ifdef CONFIG_TESTING_OPTIONS
bss->sae_commit_status = -1;
bss->test_assoc_comeback_type = -1;
@ -487,20 +491,33 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
#ifdef CONFIG_SAE
struct hostapd_ssid *ssid = &conf->ssid;
struct sae_password_entry *pw;
int *groups = conf->sae_groups;
int default_groups[] = { 19, 0, 0 };
if ((conf->sae_pwe == SAE_PWE_HUNT_AND_PECK &&
!hostapd_sae_pw_id_in_use(conf) &&
!wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt) &&
!wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt |
conf->rsn_override_key_mgmt |
conf->rsn_override_key_mgmt_2) &&
!hostapd_sae_pk_in_use(conf)) ||
conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK ||
!wpa_key_mgmt_sae(conf->wpa_key_mgmt))
!wpa_key_mgmt_sae(conf->wpa_key_mgmt |
conf->rsn_override_key_mgmt |
conf->rsn_override_key_mgmt_2))
return 0; /* PT not needed */
if (!groups) {
groups = default_groups;
if (wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt |
conf->rsn_override_key_mgmt |
conf->rsn_override_key_mgmt_2))
default_groups[1] = 20;
}
sae_deinit_pt(ssid->pt);
ssid->pt = NULL;
if (ssid->wpa_passphrase) {
ssid->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
ssid->ssid_len,
ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
(const u8 *) ssid->wpa_passphrase,
os_strlen(ssid->wpa_passphrase),
NULL);
@ -510,8 +527,7 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
for (pw = conf->sae_passwords; pw; pw = pw->next) {
sae_deinit_pt(pw->pt);
pw->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
ssid->ssid_len,
pw->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
(const u8 *) pw->password,
os_strlen(pw->password),
pw->identifier);
@ -555,6 +571,10 @@ static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
for (i = 0; i < num_servers; i++) {
os_free(servers[i].shared_secret);
os_free(servers[i].ca_cert);
os_free(servers[i].client_cert);
os_free(servers[i].private_key);
os_free(servers[i].private_key_passwd);
}
os_free(servers);
}
@ -952,6 +972,11 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
#ifdef CONFIG_TESTING_OPTIONS
wpabuf_free(conf->own_ie_override);
wpabuf_free(conf->rsne_override);
wpabuf_free(conf->rsnoe_override);
wpabuf_free(conf->rsno2e_override);
wpabuf_free(conf->rsnxe_override);
wpabuf_free(conf->rsnxoe_override);
wpabuf_free(conf->sae_commit_override);
wpabuf_free(conf->rsne_override_eapol);
wpabuf_free(conf->rsnxe_override_eapol);
@ -961,6 +986,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
wpabuf_free(conf->igtk_rsc_override);
wpabuf_free(conf->eapol_m1_elements);
wpabuf_free(conf->eapol_m3_elements);
wpabuf_free(conf->presp_elements);
#endif /* CONFIG_TESTING_OPTIONS */
os_free(conf->no_probe_resp_if_seen_on);

View file

@ -309,6 +309,7 @@ struct hostapd_bss_config {
struct hostapd_ip_addr own_ip_addr;
char *nas_identifier;
struct hostapd_radius_servers *radius;
int radius_require_message_authenticator;
int acct_interim_interval;
int radius_request_cui;
struct hostapd_radius_attr *radius_auth_req_attr;
@ -357,7 +358,11 @@ struct hostapd_bss_config {
int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
int extended_key_id;
int wpa_key_mgmt;
int rsn_override_key_mgmt;
int rsn_override_key_mgmt_2;
enum mfp_options ieee80211w;
enum mfp_options rsn_override_mfp;
enum mfp_options rsn_override_mfp_2;
int group_mgmt_cipher;
int beacon_prot;
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
@ -386,9 +391,13 @@ struct hostapd_bss_config {
u32 wpa_pairwise_update_count;
int wpa_disable_eapol_key_retries;
int rsn_pairwise;
int rsn_override_pairwise;
int rsn_override_pairwise_2;
int rsn_preauth;
char *rsn_preauth_interfaces;
int rsn_override_omit_rsnxe;
#ifdef CONFIG_IEEE80211R_AP
/* IEEE 802.11r - Fast BSS Transition */
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
@ -465,6 +474,9 @@ struct hostapd_bss_config {
*/
int ap_max_inactivity;
int bss_max_idle;
int max_acceptable_idle_period;
bool no_disconnect_on_group_keyerror;
int ignore_broadcast_ssid;
int no_probe_resp_if_max_sta;
@ -684,6 +696,11 @@ struct hostapd_bss_config {
u8 bss_load_test[5];
u8 bss_load_test_set;
struct wpabuf *own_ie_override;
struct wpabuf *rsne_override;
struct wpabuf *rsnoe_override;
struct wpabuf *rsno2e_override;
struct wpabuf *rsnxe_override;
struct wpabuf *rsnxoe_override;
int sae_reflection_attack;
int sae_commit_status;
int sae_pk_omit;
@ -708,7 +725,9 @@ struct hostapd_bss_config {
struct wpabuf *eapol_m1_elements;
struct wpabuf *eapol_m3_elements;
bool eapol_m3_no_encrypt;
bool eapol_key_reserved_random;
int test_assoc_comeback_type;
struct wpabuf *presp_elements;
#ifdef CONFIG_IEEE80211BE
u16 eht_oper_puncturing_override;
@ -800,6 +819,14 @@ struct hostapd_bss_config {
#define BACKHAUL_BSS 1
#define FRONTHAUL_BSS 2
int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
int multi_ap_profile;
/* Multi-AP Profile-1 clients not allowed to connect */
#define PROFILE1_CLIENT_ASSOC_DISALLOW BIT(0)
/* Multi-AP Profile-2 clients not allowed to connect */
#define PROFILE2_CLIENT_ASSOC_DISALLOW BIT(1)
unsigned int multi_ap_client_disallow;
/* Primary VLAN ID to use in Multi-AP */
int multi_ap_vlanid;
#ifdef CONFIG_AIRTIME_POLICY
unsigned int airtime_weight;
@ -948,6 +975,8 @@ struct hostapd_bss_config {
char *config_id;
bool xrates_supported;
bool ssid_protection;
#ifdef CONFIG_IEEE80211BE
/* The AP is part of an AP MLD */
u8 mld_ap;
@ -1217,6 +1246,9 @@ struct hostapd_config {
MBSSID_ENABLED = 1,
ENHANCED_MBSSID_ENABLED = 2,
} mbssid;
/* Whether to enable TWT responder in HT and VHT modes */
bool ht_vht_twt_responder;
};

View file

@ -208,6 +208,9 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
add_buf(&beacon, hapd->conf->vendor_elements);
add_buf(&proberesp, hapd->conf->vendor_elements);
#ifdef CONFIG_TESTING_OPTIONS
add_buf(&proberesp, hapd->conf->presp_elements);
#endif /* CONFIG_TESTING_OPTIONS */
add_buf(&assocresp, hapd->conf->assocresp_elements);
*beacon_ret = beacon;
@ -265,8 +268,8 @@ int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
}
static bool hostapd_sta_is_link_sta(struct hostapd_data *hapd,
struct sta_info *sta)
bool hostapd_sta_is_link_sta(struct hostapd_data *hapd,
struct sta_info *sta)
{
#ifdef CONFIG_IEEE80211BE
if (ap_sta_is_mld(hapd, sta) &&
@ -572,12 +575,33 @@ int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
}
#ifdef CONFIG_IEEE80211BE
int hostapd_if_link_remove(struct hostapd_data *hapd,
enum wpa_driver_if_type type,
const char *ifname, u8 link_id)
{
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->link_remove)
return -1;
return hapd->driver->link_remove(hapd->drv_priv, type, ifname,
hapd->mld_link_id);
}
#endif /* CONFIG_IEEE80211BE */
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
const char *ifname)
{
if (hapd->driver == NULL || hapd->drv_priv == NULL ||
hapd->driver->if_remove == NULL)
return -1;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap)
return hostapd_if_link_remove(hapd, type, ifname,
hapd->mld_link_id);
#endif /* CONFIG_IEEE80211BE */
return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
}
@ -603,9 +627,17 @@ int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
int hostapd_flush(struct hostapd_data *hapd)
{
int link_id = -1;
if (hapd->driver == NULL || hapd->driver->flush == NULL)
return 0;
return hapd->driver->flush(hapd->drv_priv);
#ifdef CONFIG_IEEE80211BE
if (hapd->conf && hapd->conf->mld_ap)
link_id = hapd->mld_link_id;
#endif /* CONFIG_IEEE80211BE */
return hapd->driver->flush(hapd->drv_priv, link_id);
}
@ -629,7 +661,7 @@ int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
&cmode->he_capab[IEEE80211_MODE_AP] : NULL,
cmode ?
&cmode->eht_capab[IEEE80211_MODE_AP] :
NULL))
NULL, hostapd_get_punct_bitmap(hapd)))
return -1;
if (hapd->driver == NULL)
@ -758,6 +790,8 @@ int hostapd_driver_scan(struct hostapd_data *hapd,
struct wpa_scan_results * hostapd_driver_get_scan_results(
struct hostapd_data *hapd)
{
if (hapd->driver && hapd->driver->get_scan_results)
return hapd->driver->get_scan_results(hapd->drv_priv, NULL);
if (hapd->driver && hapd->driver->get_scan_results2)
return hapd->driver->get_scan_results2(hapd->drv_priv);
return NULL;
@ -840,7 +874,7 @@ int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
link_id = hapd->mld_link_id;
if (ap_sta_is_mld(hapd, sta))
own_addr = hapd->mld_addr;
own_addr = hapd->mld->mld_addr;
}
#endif /* CONFIG_IEEE80211BE */
@ -861,7 +895,7 @@ int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
struct sta_info *sta = ap_get_sta(hapd, addr);
if (ap_sta_is_mld(hapd, sta))
own_addr = hapd->mld_addr;
own_addr = hapd->mld->mld_addr;
}
#endif /* CONFIG_IEEE80211BE */
@ -919,7 +953,7 @@ static int hapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
sta = ap_get_sta(hapd, dst);
if (ap_sta_is_mld(hapd, sta)) {
own_addr = hapd->mld_addr;
own_addr = hapd->mld->mld_addr;
bssid = own_addr;
}
#endif /* CONFIG_IEEE80211BE */
@ -977,7 +1011,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
center_segment1,
cmode->vht_capab,
&cmode->he_capab[IEEE80211_MODE_AP],
&cmode->eht_capab[IEEE80211_MODE_AP])) {
&cmode->eht_capab[IEEE80211_MODE_AP],
hostapd_get_punct_bitmap(hapd))) {
wpa_printf(MSG_ERROR, "Can't set freq params");
return -1;
}
@ -999,7 +1034,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
const u8 *qos_map_set, u8 qos_map_set_len)
{
if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv)
if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv ||
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING))
return 0;
return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set,
qos_map_set_len);
@ -1214,3 +1250,14 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd,
return hapd->driver->set_secure_ranging_ctx(hapd->drv_priv, &params);
}
#endif /* CONFIG_PASN */
struct hostapd_multi_hw_info *
hostapd_get_multi_hw_info(struct hostapd_data *hapd,
unsigned int *num_multi_hws)
{
if (!hapd->driver || !hapd->driver->get_multi_hw_info)
return NULL;
return hapd->driver->get_multi_hw_info(hapd->drv_priv, num_multi_hws);
}

View file

@ -26,6 +26,8 @@ void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon,
struct wpabuf *assocresp);
int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd);
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
bool hostapd_sta_is_link_sta(struct hostapd_data *hapd,
struct sta_info *sta);
int hostapd_set_authorized(struct hostapd_data *hapd,
struct sta_info *sta, int authorized);
int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta);
@ -59,6 +61,9 @@ int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
const char *bridge, int use_existing);
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
const char *ifname);
int hostapd_if_link_remove(struct hostapd_data *hapd,
enum wpa_driver_if_type type,
const char *ifname, u8 link_id);
int hostapd_set_ieee8021x(struct hostapd_data *hapd,
struct wpa_bss_params *params);
int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
@ -388,9 +393,15 @@ static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
{
int link_id = -1;
if (!hapd->driver || !hapd->driver->stop_ap || !hapd->drv_priv)
return 0;
return hapd->driver->stop_ap(hapd->drv_priv);
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap)
link_id = hapd->mld_link_id;
#endif /* CONFIG_IEEE80211BE */
return hapd->driver->stop_ap(hapd->drv_priv, link_id);
}
static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
@ -443,15 +454,32 @@ hostapd_drv_register_frame(struct hostapd_data *hapd, u16 type,
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_IEEE80211BE
static inline int hostapd_drv_link_add(struct hostapd_data *hapd,
u8 link_id, const u8 *addr)
{
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->link_add)
return -1;
return hapd->driver->link_add(hapd->drv_priv, link_id, addr);
return hapd->driver->link_add(hapd->drv_priv, link_id, addr, hapd);
}
static inline int hostapd_drv_link_sta_remove(struct hostapd_data *hapd,
const u8 *addr)
{
if (!hapd->conf->mld_ap || !hapd->driver || !hapd->drv_priv ||
!hapd->driver->link_sta_remove)
return -1;
return hapd->driver->link_sta_remove(hapd->drv_priv, hapd->mld_link_id,
addr);
}
#endif /* CONFIG_IEEE80211BE */
struct hostapd_multi_hw_info *
hostapd_get_multi_hw_info(struct hostapd_data *hapd,
unsigned int *num_multi_hws);
#endif /* AP_DRV_OPS */

View file

@ -107,13 +107,20 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
struct radius_server_conf srv;
struct hostapd_bss_config *conf = hapd->conf;
if (hapd->mld_first_bss) {
#ifdef CONFIG_IEEE80211BE
if (!hostapd_mld_is_first_bss(hapd)) {
struct hostapd_data *first;
wpa_printf(MSG_DEBUG,
"MLD: Using RADIUS server of the first BSS");
hapd->radius_srv = hapd->mld_first_bss->radius_srv;
first = hostapd_mld_get_first_bss(hapd);
if (!first)
return -1;
hapd->radius_srv = first->radius_srv;
return 0;
}
#endif /* CONFIG_IEEE80211BE */
os_memset(&srv, 0, sizeof(srv));
srv.client_file = conf->radius_server_clients;
@ -249,18 +256,34 @@ static struct eap_config * authsrv_eap_config(struct hostapd_data *hapd)
int authsrv_init(struct hostapd_data *hapd)
{
if (hapd->mld_first_bss) {
#ifdef CONFIG_IEEE80211BE
if (!hostapd_mld_is_first_bss(hapd)) {
struct hostapd_data *first;
first = hostapd_mld_get_first_bss(hapd);
if (!first)
return -1;
if (!first->eap_cfg) {
wpa_printf(MSG_DEBUG,
"MLD: First BSS auth_serv does not exist. Init on its behalf");
if (authsrv_init(first))
return -1;
}
wpa_printf(MSG_DEBUG, "MLD: Using auth_serv of the first BSS");
#ifdef EAP_TLS_FUNCS
hapd->ssl_ctx = hapd->mld_first_bss->ssl_ctx;
hapd->ssl_ctx = first->ssl_ctx;
#endif /* EAP_TLS_FUNCS */
hapd->eap_cfg = hapd->mld_first_bss->eap_cfg;
hapd->eap_cfg = first->eap_cfg;
#ifdef EAP_SIM_DB
hapd->eap_sim_db_priv = hapd->mld_first_bss->eap_sim_db_priv;
hapd->eap_sim_db_priv = first->eap_sim_db_priv;
#endif /* EAP_SIM_DB */
return 0;
}
#endif /* CONFIG_IEEE80211BE */
#ifdef EAP_TLS_FUNCS
if (hapd->conf->eap_server &&
@ -376,7 +399,8 @@ int authsrv_init(struct hostapd_data *hapd)
void authsrv_deinit(struct hostapd_data *hapd)
{
if (hapd->mld_first_bss) {
#ifdef CONFIG_IEEE80211BE
if (!hostapd_mld_is_first_bss(hapd)) {
wpa_printf(MSG_DEBUG,
"MLD: Deinit auth_serv of a non-first BSS");
@ -390,6 +414,7 @@ void authsrv_deinit(struct hostapd_data *hapd)
#endif /* EAP_TLS_FUNCS */
return;
}
#endif /* CONFIG_IEEE80211BE */
#ifdef RADIUS_SERVER
radius_server_deinit(hapd->radius_srv);

File diff suppressed because it is too large Load diff

View file

@ -33,4 +33,7 @@ void sta_track_claim_taxonomy_info(struct hostapd_iface *iface, const u8 *addr,
const u8 * hostapd_wpa_ie(struct hostapd_data *hapd, u8 eid);
u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
struct unsol_bcast_probe_resp *ubpr);
#endif /* BEACON_H */

View file

@ -277,6 +277,14 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
return len;
len += ret;
if (sta->max_idle_period) {
ret = os_snprintf(buf + len, buflen - len,
"max_idle_period=%d\n", sta->max_idle_period);
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
}
res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len);
if (res >= 0)
len += res;
@ -348,11 +356,15 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
if (sta->supp_op_classes &&
buflen - len > (unsigned) (17 + 2 * sta->supp_op_classes[0])) {
len += os_snprintf(buf + len, buflen - len, "supp_op_classes=");
res = os_snprintf(buf + len, buflen - len, "supp_op_classes=");
if (!os_snprintf_error(buflen - len, res))
len += res;
len += wpa_snprintf_hex(buf + len, buflen - len,
sta->supp_op_classes + 1,
sta->supp_op_classes[0]);
len += os_snprintf(buf + len, buflen - len, "\n");
res = os_snprintf(buf + len, buflen - len, "\n");
if (!os_snprintf_error(buflen - len, res))
len += res;
}
if (sta->power_capab) {
@ -364,6 +376,34 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
len += ret;
}
#ifdef CONFIG_IEEE80211AX
if ((sta->flags & WLAN_STA_HE) && sta->he_capab) {
res = os_snprintf(buf + len, buflen - len, "he_capab=");
if (!os_snprintf_error(buflen - len, res))
len += res;
len += wpa_snprintf_hex(buf + len, buflen - len,
(const u8 *) sta->he_capab,
sta->he_capab_len);
res = os_snprintf(buf + len, buflen - len, "\n");
if (!os_snprintf_error(buflen - len, res))
len += res;
}
#endif /* CONFIG_IEEE80211AX */
#ifdef CONFIG_IEEE80211BE
if ((sta->flags & WLAN_STA_EHT) && sta->eht_capab) {
res = os_snprintf(buf + len, buflen - len, "eht_capab=");
if (!os_snprintf_error(buflen - len, res))
len += res;
len += wpa_snprintf_hex(buf + len, buflen - len,
(const u8 *) sta->eht_capab,
sta->eht_capab_len);
res = os_snprintf(buf + len, buflen - len, "\n");
if (!os_snprintf_error(buflen - len, res))
len += res;
}
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_IEEE80211AC
if ((sta->flags & WLAN_STA_VHT) && sta->vht_capabilities) {
res = os_snprintf(buf + len, buflen - len,
@ -372,6 +412,16 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
vht_capabilities_info));
if (!os_snprintf_error(buflen - len, res))
len += res;
res = os_snprintf(buf + len, buflen - len, "vht_capab=");
if (!os_snprintf_error(buflen - len, res))
len += res;
len += wpa_snprintf_hex(buf + len, buflen - len,
(const u8 *) sta->vht_capabilities,
sizeof(*sta->vht_capabilities));
res = os_snprintf(buf + len, buflen - len, "\n");
if (!os_snprintf_error(buflen - len, res))
len += res;
}
#endif /* CONFIG_IEEE80211AC */
@ -386,11 +436,15 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
if (sta->ext_capability &&
buflen - len > (unsigned) (11 + 2 * sta->ext_capability[0])) {
len += os_snprintf(buf + len, buflen - len, "ext_capab=");
res = os_snprintf(buf + len, buflen - len, "ext_capab=");
if (!os_snprintf_error(buflen - len, res))
len += res;
len += wpa_snprintf_hex(buf + len, buflen - len,
sta->ext_capability + 1,
sta->ext_capability[0]);
len += os_snprintf(buf + len, buflen - len, "\n");
res = os_snprintf(buf + len, buflen - len, "\n");
if (!os_snprintf_error(buflen - len, res))
len += res;
}
if (sta->flags & WLAN_STA_WDS && sta->ifname_wds) {
@ -419,6 +473,21 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
len += ret;
}
#ifdef CONFIG_IEEE80211BE
if (sta->mld_info.mld_sta) {
for (i = 0; i < MAX_NUM_MLD_LINKS; ++i) {
if (!sta->mld_info.links[i].valid)
continue;
ret = os_snprintf(
buf + len, buflen - len,
"peer_addr[%d]=" MACSTR "\n",
i, MAC2STR(sta->mld_info.links[i].peer_addr));
if (!os_snprintf_error(buflen - len, ret))
len += ret;
}
}
#endif /* CONFIG_IEEE80211BE */
return len;
}
@ -592,15 +661,18 @@ int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
}
#endif /* CONFIG_P2P_MANAGER */
if (os_strstr(txtaddr, " tx=0"))
hostapd_drv_sta_remove(hapd, addr);
else
hostapd_drv_sta_deauth(hapd, addr, reason);
sta = ap_get_sta(hapd, addr);
if (sta)
ap_sta_deauthenticate(hapd, sta, reason);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
if (os_strstr(txtaddr, " tx=0")) {
hostapd_drv_sta_remove(hapd, addr);
if (sta)
ap_free_sta(hapd, sta);
} else {
hostapd_drv_sta_deauth(hapd, addr, reason);
if (sta)
ap_sta_deauthenticate(hapd, sta, reason);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
}
return 0;
}
@ -654,15 +726,18 @@ int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
}
#endif /* CONFIG_P2P_MANAGER */
if (os_strstr(txtaddr, " tx=0"))
hostapd_drv_sta_remove(hapd, addr);
else
hostapd_drv_sta_disassoc(hapd, addr, reason);
sta = ap_get_sta(hapd, addr);
if (sta)
ap_sta_disassociate(hapd, sta, reason);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
if (os_strstr(txtaddr, " tx=0")) {
hostapd_drv_sta_remove(hapd, addr);
if (sta)
ap_free_sta(hapd, sta);
} else {
hostapd_drv_sta_disassoc(hapd, addr, reason);
if (sta)
ap_sta_disassociate(hapd, sta, reason);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
}
return 0;
}
@ -841,6 +916,42 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
return len;
len += ret;
}
if (hapd->conf->mld_ap) {
struct hostapd_data *link_bss;
ret = os_snprintf(buf + len, buflen - len,
"num_links=%d\n",
hapd->mld->num_links);
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
/* Self BSS */
ret = os_snprintf(buf + len, buflen - len,
"link_id=%d\n"
"link_addr=" MACSTR "\n",
hapd->mld_link_id,
MAC2STR(hapd->own_addr));
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
/* Partner BSSs */
for_each_mld_link(link_bss, hapd) {
if (link_bss == hapd)
continue;
ret = os_snprintf(buf + len, buflen - len,
"partner_link[%d]=" MACSTR
"\n",
link_bss->mld_link_id,
MAC2STR(link_bss->own_addr));
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
}
}
}
#endif /* CONFIG_IEEE80211BE */
@ -966,8 +1077,8 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
"mld_addr[%d]=" MACSTR "\n"
"mld_id[%d]=%d\n"
"mld_link_id[%d]=%d\n",
(int) i, MAC2STR(bss->mld_addr),
(int) i, bss->conf->mld_id,
(int) i, MAC2STR(bss->mld->mld_addr),
(int) i, hostapd_get_mld_id(bss),
(int) i, bss->mld_link_id);
if (os_snprintf_error(buflen - len, ret))
return len;
@ -1032,8 +1143,9 @@ int hostapd_parse_csa_settings(const char *pos,
SET_CSA_SETTING_EXT(punct_bitmap);
settings->freq_params.ht_enabled = !!os_strstr(pos, " ht");
settings->freq_params.vht_enabled = !!os_strstr(pos, " vht");
settings->freq_params.he_enabled = !!os_strstr(pos, " he");
settings->freq_params.eht_enabled = !!os_strstr(pos, " eht");
settings->freq_params.he_enabled = !!os_strstr(pos, " he") ||
settings->freq_params.eht_enabled;
settings->block_tx = !!os_strstr(pos, " blocktx");
#undef SET_CSA_SETTING
#undef SET_CSA_SETTING_EXT

View file

@ -14,6 +14,7 @@
#include "common/hw_features_common.h"
#include "common/wpa_ctrl.h"
#include "hostapd.h"
#include "beacon.h"
#include "ap_drv_ops.h"
#include "drivers/driver.h"
#include "dfs.h"
@ -252,6 +253,13 @@ static int dfs_find_channel(struct hostapd_iface *iface,
for (i = 0; i < mode->num_channels; i++) {
chan = &mode->channels[i];
if (!chan_in_current_hw_info(iface->current_hw_info, chan)) {
wpa_printf(MSG_DEBUG,
"DFS: channel %d (%d) is not under current hardware index",
chan->freq, chan->chan);
continue;
}
/* Skip HT40/VHT incompatible channels */
if (iface->conf->ieee80211n &&
iface->conf->secondary_channel &&
@ -972,6 +980,7 @@ static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
struct csa_settings csa_settings;
u8 new_vht_oper_chwidth;
unsigned int i;
unsigned int num_err = 0;
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", channel);
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
@ -1009,7 +1018,8 @@ static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
oper_centr_freq_seg1_idx,
cmode->vht_capab,
&cmode->he_capab[ieee80211_mode],
&cmode->eht_capab[ieee80211_mode]);
&cmode->eht_capab[ieee80211_mode],
hostapd_get_punct_bitmap(iface->bss[0]));
if (err) {
wpa_printf(MSG_ERROR,
@ -1021,10 +1031,10 @@ static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
for (i = 0; i < iface->num_bss; i++) {
err = hostapd_switch_channel(iface->bss[i], &csa_settings);
if (err)
break;
num_err++;
}
if (err) {
if (num_err == iface->num_bss) {
wpa_printf(MSG_WARNING,
"DFS failed to schedule CSA (%d) - trying fallback",
err);
@ -1141,14 +1151,23 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
int cf1, int cf2)
{
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED
"success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
"success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d radar_detected=%d",
success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2,
iface->radar_detected);
if (success) {
/* Complete iface/ap configuration */
if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
/* Complete AP configuration for the first bring up. */
if (iface->state != HAPD_IFACE_ENABLED)
/* Complete AP configuration for the first bring up. If
* a radar was detected in this channel, interface setup
* will be handled in
* 1. hostapd_event_ch_switch() if switching to a
* non-DFS channel
* 2. on next CAC complete event if switching to another
* DFS channel.
*/
if (iface->state != HAPD_IFACE_ENABLED &&
!iface->radar_detected)
hostapd_setup_interface_complete(iface, 0);
else
iface->cac_started = 0;
@ -1193,6 +1212,7 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
hostapd_dfs_update_background_chain(iface);
}
iface->radar_detected = false;
return 0;
}
@ -1436,6 +1456,8 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
iface->radar_detected = true;
/* Proceed only if DFS is not offloaded to the driver */
if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
return 0;
@ -1529,9 +1551,17 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
iface->radar_background.cac_started = 1;
} else {
/* This is called when the driver indicates that an offloaded
* DFS has started CAC. */
* DFS has started CAC. radar_detected might be set for previous
* DFS channel. Clear it for this new CAC process. */
hostapd_set_state(iface, HAPD_IFACE_DFS);
iface->cac_started = 1;
/* Clear radar_detected in case it is for the previous
* frequency. Also remove disabled link's information in RNR
* element from other links. */
iface->radar_detected = false;
if (iface->interfaces && iface->interfaces->count > 1)
ieee802_11_set_beacons(iface);
}
/* TODO: How to check CAC time for ETSI weather channels? */
iface->dfs_cac_ms = 60000;

View file

@ -3941,6 +3941,7 @@ int hostapd_dpp_push_button(struct hostapd_data *hapd, const char *cmd)
eloop_register_timeout(100, 0, hostapd_dpp_push_button_expire,
hapd, NULL);
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_STATUS "started");
return 0;
}

View file

@ -73,6 +73,8 @@ void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd,
p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
elems.fils_session,
sta->fils_hlp_resp);
if (!p)
return;
reply_res = hostapd_sta_assoc(hapd, sta->addr,
sta->fils_pending_assoc_is_reassoc,
@ -248,6 +250,52 @@ out:
#endif /* CONFIG_IEEE80211BE */
#if defined(HOSTAPD) || defined(CONFIG_IEEE80211BE)
static struct hostapd_data * hostapd_find_by_sta(struct hostapd_iface *iface,
const u8 *src, bool rsn,
struct sta_info **sta_ret)
{
struct hostapd_data *hapd;
struct sta_info *sta;
unsigned int j;
if (sta_ret)
*sta_ret = NULL;
for (j = 0; j < iface->num_bss; j++) {
hapd = iface->bss[j];
sta = ap_get_sta(hapd, src);
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
(!rsn || sta->wpa_sm)) {
if (sta_ret)
*sta_ret = sta;
return hapd;
}
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
struct hostapd_data *p_hapd;
for_each_mld_link(p_hapd, hapd) {
if (p_hapd == hapd)
continue;
sta = ap_get_sta(p_hapd, src);
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
(!rsn || sta->wpa_sm)) {
if (sta_ret)
*sta_ret = sta;
return p_hapd;
}
}
}
#endif /* CONFIG_IEEE80211BE */
}
return NULL;
}
#endif /* HOSTAPD || CONFIG_IEEE80211BE */
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
const u8 *req_ies, size_t req_ies_len,
const u8 *resp_ies, size_t resp_ies_len,
@ -513,11 +561,13 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
"Failed to initialize WPA state machine");
return -1;
}
wpa_auth_set_rsn_selection(sta->wpa_sm, elems.rsn_selection,
elems.rsn_selection_len);
#ifdef CONFIG_IEEE80211BE
if (ap_sta_is_mld(hapd, sta)) {
wpa_printf(MSG_DEBUG,
"MLD: Set ML info in RSN Authenticator");
wpa_auth_set_ml_info(sta->wpa_sm, hapd->mld_addr,
wpa_auth_set_ml_info(sta->wpa_sm,
sta->mld_assoc_link_id,
&sta->mld_info);
}
@ -528,7 +578,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
elems.rsnxe ? elems.rsnxe - 2 : NULL,
elems.rsnxe ? elems.rsnxe_len + 2 : 0,
elems.mdie, elems.mdie_len,
elems.owe_dh, elems.owe_dh_len);
elems.owe_dh, elems.owe_dh_len, NULL);
reason = WLAN_REASON_INVALID_IE;
status = WLAN_STATUS_INVALID_IE;
switch (res) {
@ -773,6 +823,9 @@ skip_wpa_check:
p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
elems.fils_session,
sta->fils_hlp_resp);
if (!p)
goto fail;
wpa_hexdump(MSG_DEBUG, "FILS Assoc Resp BUF (IEs)",
buf, p - buf);
}
@ -910,6 +963,54 @@ fail:
}
static void hostapd_remove_sta(struct hostapd_data *hapd, struct sta_info *sta)
{
ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
hostapd_set_sta_flags(hapd, sta);
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
ap_free_sta(hapd, sta);
}
#ifdef CONFIG_IEEE80211BE
static void hostapd_notif_disassoc_mld(struct hostapd_data *assoc_hapd,
struct sta_info *sta,
const u8 *addr)
{
unsigned int link_id, i;
struct hostapd_data *tmp_hapd;
struct hapd_interfaces *interfaces = assoc_hapd->iface->interfaces;
/* Remove STA entry in non-assoc links */
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
if (!sta->mld_info.links[link_id].valid)
continue;
for (i = 0; i < interfaces->count; i++) {
struct sta_info *tmp_sta;
tmp_hapd = interfaces->iface[i]->bss[0];
if (!tmp_hapd->conf->mld_ap ||
assoc_hapd == tmp_hapd ||
assoc_hapd->conf->mld_id != tmp_hapd->conf->mld_id)
continue;
tmp_sta = ap_get_sta(tmp_hapd, addr);
if (tmp_sta)
ap_free_sta(tmp_hapd, tmp_sta);
}
}
/* Remove STA in assoc link */
hostapd_remove_sta(assoc_hapd, sta);
}
#endif /* CONFIG_IEEE80211BE */
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
{
struct sta_info *sta;
@ -931,6 +1032,50 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
HOSTAPD_LEVEL_INFO, "disassociated");
sta = ap_get_sta(hapd, addr);
#ifdef CONFIG_IEEE80211BE
if (hostapd_is_mld_ap(hapd)) {
struct hostapd_data *assoc_hapd;
unsigned int i;
if (!sta) {
/* Find non-MLO cases from any of the affiliated AP
* links. */
for (i = 0; i < hapd->iface->interfaces->count; ++i) {
struct hostapd_iface *h =
hapd->iface->interfaces->iface[i];
struct hostapd_data *h_hapd = h->bss[0];
struct hostapd_bss_config *hconf = h_hapd->conf;
if (!hconf->mld_ap ||
hconf->mld_id != hapd->conf->mld_id)
continue;
sta = ap_get_sta(h_hapd, addr);
if (sta) {
if (!sta->mld_info.mld_sta) {
hapd = h_hapd;
goto legacy;
}
break;
}
}
} else if (!sta->mld_info.mld_sta) {
goto legacy;
}
if (!sta) {
wpa_printf(MSG_DEBUG,
"Disassociation notification for unknown STA "
MACSTR, MAC2STR(addr));
return;
}
sta = hostapd_ml_get_assoc_sta(hapd, sta, &assoc_hapd);
if (sta)
hostapd_notif_disassoc_mld(assoc_hapd, sta, addr);
return;
}
legacy:
#endif /* CONFIG_IEEE80211BE */
if (sta == NULL) {
wpa_printf(MSG_DEBUG,
"Disassociation notification for unknown STA "
@ -938,19 +1083,27 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
return;
}
ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
hostapd_set_sta_flags(hapd, sta);
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
ap_free_sta(hapd, sta);
hostapd_remove_sta(hapd, sta);
}
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
{
struct sta_info *sta = ap_get_sta(hapd, addr);
#ifdef CONFIG_IEEE80211BE
struct hostapd_data *orig_hapd = hapd;
if (!sta && hapd->conf->mld_ap) {
hapd = hostapd_find_by_sta(hapd->iface, addr, true, &sta);
if (!hapd) {
wpa_printf(MSG_DEBUG,
"No partner link BSS found for STA " MACSTR
" - fallback to received context",
MAC2STR(addr));
hapd = orig_hapd;
}
}
#endif /* CONFIG_IEEE80211BE */
if (!sta || !hapd->conf->disassoc_low_ack || sta->agreed_to_steer)
return;
@ -1451,7 +1604,6 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
#ifdef CONFIG_IEEE80211R_AP
static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst,
const u8 *bssid,
u16 auth_transaction, u16 status,
const u8 *ies, size_t ies_len)
{
@ -1527,7 +1679,7 @@ static void hostapd_notif_auth(struct hostapd_data *hapd,
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
goto fail;
}
wpa_ft_process_auth(sta->wpa_sm, rx_auth->bssid,
wpa_ft_process_auth(sta->wpa_sm,
rx_auth->auth_transaction, rx_auth->ies,
rx_auth->ies_len,
hostapd_notify_auth_ft_finish, hapd);
@ -1663,10 +1815,38 @@ switch_link_hapd(struct hostapd_data *hapd, int link_id)
}
static struct hostapd_data *
switch_link_scan(struct hostapd_data *hapd, u64 scan_cookie)
{
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap && scan_cookie != 0) {
unsigned int i;
for (i = 0; i < hapd->iface->interfaces->count; i++) {
struct hostapd_iface *h;
struct hostapd_data *h_hapd;
h = hapd->iface->interfaces->iface[i];
h_hapd = h->bss[0];
if (!hostapd_is_ml_partner(hapd, h_hapd))
continue;
if (h_hapd->scan_cookie == scan_cookie) {
h_hapd->scan_cookie = 0;
return h_hapd;
}
}
}
#endif /* CONFIG_IEEE80211BE */
return hapd;
}
#define HAPD_BROADCAST ((struct hostapd_data *) -1)
static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
const u8 *bssid)
const u8 *bssid, int link_id)
{
size_t i;
@ -1677,8 +1857,35 @@ static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
return HAPD_BROADCAST;
for (i = 0; i < iface->num_bss; i++) {
if (ether_addr_equal(bssid, iface->bss[i]->own_addr))
return iface->bss[i];
struct hostapd_data *hapd;
#ifdef CONFIG_IEEE80211BE
struct hostapd_data *p_hapd;
#endif /* CONFIG_IEEE80211BE */
hapd = iface->bss[i];
if (ether_addr_equal(bssid, hapd->own_addr))
return hapd;
#ifdef CONFIG_IEEE80211BE
if (ether_addr_equal(bssid, hapd->own_addr) ||
(hapd->conf->mld_ap &&
ether_addr_equal(bssid, hapd->mld->mld_addr) &&
link_id == hapd->mld_link_id))
return hapd;
if (!hapd->conf->mld_ap)
continue;
for_each_mld_link(p_hapd, hapd) {
if (p_hapd == hapd)
continue;
if (ether_addr_equal(bssid, p_hapd->own_addr) ||
(ether_addr_equal(bssid, p_hapd->mld->mld_addr) &&
link_id == p_hapd->mld_link_id))
return p_hapd;
}
#endif /* CONFIG_IEEE80211BE */
}
return NULL;
@ -1689,7 +1896,7 @@ static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
const u8 *bssid, const u8 *addr,
int wds)
{
hapd = get_hapd_bssid(hapd->iface, bssid);
hapd = get_hapd_bssid(hapd->iface, bssid, -1);
if (hapd == NULL || hapd == HAPD_BROADCAST)
return;
@ -1704,8 +1911,9 @@ static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
const u8 *bssid;
struct hostapd_frame_info fi;
int ret;
bool is_mld = false;
if (rx_mgmt->ctx)
hapd = rx_mgmt->ctx;
hapd = switch_link_hapd(hapd, rx_mgmt->link_id);
iface = hapd->iface;
@ -1729,14 +1937,7 @@ static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
if (bssid == NULL)
return 0;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap &&
ether_addr_equal(hapd->mld_addr, bssid))
is_mld = true;
#endif /* CONFIG_IEEE80211BE */
if (!is_mld)
hapd = get_hapd_bssid(iface, bssid);
hapd = get_hapd_bssid(iface, bssid, rx_mgmt->link_id);
if (!hapd) {
u16 fc = le_to_host16(hdr->frame_control);
@ -1788,22 +1989,17 @@ static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
struct ieee80211_hdr *hdr;
struct hostapd_data *orig_hapd, *tmp_hapd;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap && link_id != -1) {
tmp_hapd = hostapd_mld_get_link_bss(hapd, link_id);
if (tmp_hapd)
hapd = tmp_hapd;
}
#endif /* CONFIG_IEEE80211BE */
orig_hapd = hapd;
hdr = (struct ieee80211_hdr *) buf;
tmp_hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
hapd = switch_link_hapd(hapd, link_id);
tmp_hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len), link_id);
if (tmp_hapd) {
hapd = tmp_hapd;
#ifdef CONFIG_IEEE80211BE
} else if (hapd->conf->mld_ap &&
ether_addr_equal(hapd->mld_addr, get_hdr_bssid(hdr, len))) {
ether_addr_equal(hapd->mld->mld_addr,
get_hdr_bssid(hdr, len))) {
/* AP MLD address match - use hapd pointer as-is */
#endif /* CONFIG_IEEE80211BE */
} else {
@ -1814,7 +2010,7 @@ static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
if (stype != WLAN_FC_STYPE_ACTION || len <= 25 ||
buf[24] != WLAN_ACTION_PUBLIC)
return;
hapd = get_hapd_bssid(orig_hapd->iface, hdr->addr2);
hapd = get_hapd_bssid(orig_hapd->iface, hdr->addr2, link_id);
if (!hapd || hapd == HAPD_BROADCAST)
return;
/*
@ -1850,57 +2046,6 @@ static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
}
static struct hostapd_data * hostapd_find_by_sta(struct hostapd_iface *iface,
const u8 *src, bool rsn)
{
struct sta_info *sta;
unsigned int j;
for (j = 0; j < iface->num_bss; j++) {
sta = ap_get_sta(iface->bss[j], src);
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
(!rsn || sta->wpa_sm))
return iface->bss[j];
}
return NULL;
}
#ifdef CONFIG_IEEE80211BE
static bool search_mld_sta(struct hostapd_data **p_hapd, const u8 *src)
{
struct hostapd_data *hapd = *p_hapd;
unsigned int i;
/* Search for STA on other MLO BSSs */
for (i = 0; i < hapd->iface->interfaces->count; i++) {
struct hostapd_iface *h =
hapd->iface->interfaces->iface[i];
struct hostapd_data *h_hapd = h->bss[0];
struct hostapd_bss_config *hconf = h_hapd->conf;
if (!hconf->mld_ap ||
hconf->mld_id != hapd->conf->mld_id)
continue;
h_hapd = hostapd_find_by_sta(h, src, false);
if (h_hapd) {
struct sta_info *sta = ap_get_sta(h_hapd, src);
if (sta && sta->mld_info.mld_sta &&
sta->mld_assoc_link_id != h_hapd->mld_link_id)
continue;
*p_hapd = h_hapd;
return true;
}
}
return false;
}
#endif /* CONFIG_IEEE80211BE */
static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
const u8 *data, size_t data_len,
enum frame_encryption encrypted,
@ -1909,28 +2054,10 @@ static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
struct hostapd_data *orig_hapd = hapd;
#ifdef CONFIG_IEEE80211BE
if (link_id != -1) {
struct hostapd_data *h_hapd;
hapd = switch_link_hapd(hapd, link_id);
h_hapd = hostapd_find_by_sta(hapd->iface, src, true);
if (!h_hapd)
h_hapd = hostapd_find_by_sta(orig_hapd->iface, src,
true);
if (!h_hapd)
h_hapd = hostapd_find_by_sta(hapd->iface, src, false);
if (!h_hapd)
h_hapd = hostapd_find_by_sta(orig_hapd->iface, src,
false);
if (h_hapd)
hapd = h_hapd;
} else if (hapd->conf->mld_ap) {
search_mld_sta(&hapd, src);
} else {
hapd = hostapd_find_by_sta(hapd->iface, src, false);
}
hapd = switch_link_hapd(hapd, link_id);
hapd = hostapd_find_by_sta(hapd->iface, src, true, NULL);
#else /* CONFIG_IEEE80211BE */
hapd = hostapd_find_by_sta(hapd->iface, src, false);
hapd = hostapd_find_by_sta(hapd->iface, src, false, NULL);
#endif /* CONFIG_IEEE80211BE */
if (!hapd) {
@ -2257,6 +2384,136 @@ err:
#endif /* CONFIG_OWE */
#ifdef NEED_AP_MLME
static void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
const u8 *data, size_t len, int ack,
int link_id)
{
struct sta_info *sta;
hapd = switch_link_hapd(hapd, link_id);
hapd = hostapd_find_by_sta(hapd->iface, dst, false, &sta);
if (!sta) {
wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA "
MACSTR " that is not currently associated",
MAC2STR(dst));
return;
}
ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
}
#endif /* NEED_AP_MLME */
#ifdef CONFIG_IEEE80211AX
static void hostapd_event_color_change(struct hostapd_data *hapd, bool success)
{
struct hostapd_data *bss;
size_t i;
for (i = 0; i < hapd->iface->num_bss; i++) {
bss = hapd->iface->bss[i];
if (bss->cca_color == 0)
continue;
if (success)
hapd->iface->conf->he_op.he_bss_color = bss->cca_color;
bss->cca_in_progress = 0;
if (ieee802_11_set_beacon(bss)) {
wpa_printf(MSG_ERROR, "Failed to remove BCCA element");
bss->cca_in_progress = 1;
} else {
hostapd_cleanup_cca_params(bss);
}
}
}
#endif /* CONFIG_IEEE80211AX */
static void hostapd_iface_enable(struct hostapd_data *hapd)
{
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
if (hapd->disabled && hapd->started) {
hapd->disabled = 0;
/*
* Try to re-enable interface if the driver stopped it
* when the interface got disabled.
*/
if (hapd->wpa_auth)
wpa_auth_reconfig_group_keys(hapd->wpa_auth);
else
hostapd_reconfig_encryption(hapd);
hapd->reenable_beacon = 1;
ieee802_11_set_beacon(hapd);
#ifdef NEED_AP_MLME
} else if (hapd->disabled && hapd->iface->cac_started) {
wpa_printf(MSG_DEBUG, "DFS: restarting pending CAC");
hostapd_handle_dfs(hapd->iface);
#endif /* NEED_AP_MLME */
}
}
static void hostapd_iface_disable(struct hostapd_data *hapd)
{
hostapd_free_stas(hapd);
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
hapd->disabled = 1;
}
#ifdef CONFIG_IEEE80211BE
static void hostapd_mld_iface_enable(struct hostapd_data *hapd)
{
struct hostapd_data *first_link, *link_bss;
first_link = hostapd_mld_is_first_bss(hapd) ? hapd :
hostapd_mld_get_first_bss(hapd);
/* Links have been removed. Re-add all links and enable them, but
* enable the first link BSS before doing that. */
if (hostapd_drv_link_add(first_link, first_link->mld_link_id,
first_link->own_addr)) {
wpa_printf(MSG_ERROR, "MLD: Failed to re-add link %d in MLD %s",
first_link->mld_link_id, first_link->conf->iface);
return;
}
hostapd_iface_enable(first_link);
/* Add other affiliated links */
for_each_mld_link(link_bss, first_link) {
if (link_bss == first_link)
continue;
if (hostapd_drv_link_add(link_bss, link_bss->mld_link_id,
link_bss->own_addr)) {
wpa_printf(MSG_ERROR,
"MLD: Failed to re-add link %d in MLD %s",
link_bss->mld_link_id,
link_bss->conf->iface);
continue;
}
hostapd_iface_enable(link_bss);
}
}
static void hostapd_mld_iface_disable(struct hostapd_data *hapd)
{
struct hostapd_data *link_bss;
for_each_mld_link(link_bss, hapd)
hostapd_iface_disable(link_bss);
}
#endif /* CONFIG_IEEE80211BE */
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data)
{
@ -2289,8 +2546,29 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
break;
case EVENT_SCAN_RESULTS:
#ifdef NEED_AP_MLME
if (data)
hapd = switch_link_scan(hapd,
data->scan_info.scan_cookie);
#endif /* NEED_AP_MLME */
if (hapd->iface->scan_cb)
hapd->iface->scan_cb(hapd->iface);
#ifdef CONFIG_IEEE80211BE
if (!hapd->iface->scan_cb && hapd->conf->mld_ap) {
/* Other links may be waiting for HT scan result */
unsigned int i;
for (i = 0; i < hapd->iface->interfaces->count; i++) {
struct hostapd_iface *h =
hapd->iface->interfaces->iface[i];
struct hostapd_data *h_hapd = h->bss[0];
if (hostapd_is_ml_partner(hapd, h_hapd) &&
h_hapd->iface->scan_cb)
h_hapd->iface->scan_cb(h_hapd->iface);
}
}
#endif /* CONFIG_IEEE80211BE */
break;
case EVENT_WPS_BUTTON_PUSHED:
hostapd_wps_button_pushed(hapd, NULL);
@ -2314,11 +2592,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
}
break;
case EVENT_EAPOL_TX_STATUS:
hapd = switch_link_hapd(hapd, data->eapol_tx_status.link_id);
hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst,
data->eapol_tx_status.data,
data->eapol_tx_status.data_len,
data->eapol_tx_status.ack);
data->eapol_tx_status.ack,
data->eapol_tx_status.link_id);
break;
case EVENT_DRIVER_CLIENT_POLL_OK:
hostapd_client_poll_ok(hapd, data->client_poll.addr);
@ -2513,30 +2791,22 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
#endif /* NEED_AP_MLME */
case EVENT_INTERFACE_ENABLED:
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
if (hapd->disabled && hapd->started) {
hapd->disabled = 0;
/*
* Try to re-enable interface if the driver stopped it
* when the interface got disabled.
*/
if (hapd->wpa_auth)
wpa_auth_reconfig_group_keys(hapd->wpa_auth);
else
hostapd_reconfig_encryption(hapd);
hapd->reenable_beacon = 1;
ieee802_11_set_beacon(hapd);
#ifdef NEED_AP_MLME
} else if (hapd->disabled && hapd->iface->cac_started) {
wpa_printf(MSG_DEBUG, "DFS: restarting pending CAC");
hostapd_handle_dfs(hapd->iface);
#endif /* NEED_AP_MLME */
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
hostapd_mld_iface_enable(hapd);
break;
}
#endif /* CONFIG_IEEE80211BE */
hostapd_iface_enable(hapd);
break;
case EVENT_INTERFACE_DISABLED:
hostapd_free_stas(hapd);
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
hapd->disabled = 1;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
hostapd_mld_iface_disable(hapd);
break;
}
#endif /* CONFIG_IEEE80211BE */
hostapd_iface_disable(hapd);
break;
#ifdef CONFIG_ACS
case EVENT_ACS_CHANNEL_SELECTED:
@ -2561,28 +2831,41 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
/* The BSS color is shared amongst all BBSs on a specific phy.
* Therefore we always start the color change on the primary
* BSS. */
hapd = switch_link_hapd(hapd,
data->bss_color_collision.link_id);
wpa_printf(MSG_DEBUG, "BSS color collision on %s",
hapd->conf->iface);
hostapd_switch_color(hapd->iface->bss[0],
data->bss_color_collision.bitmap);
break;
case EVENT_CCA_STARTED_NOTIFY:
wpa_printf(MSG_DEBUG, "CCA started on on %s",
hapd = switch_link_hapd(hapd,
data->bss_color_collision.link_id);
wpa_printf(MSG_DEBUG, "CCA started on %s",
hapd->conf->iface);
break;
case EVENT_CCA_ABORTED_NOTIFY:
wpa_printf(MSG_DEBUG, "CCA aborted on on %s",
hapd = switch_link_hapd(hapd,
data->bss_color_collision.link_id);
wpa_printf(MSG_DEBUG, "CCA aborted on %s",
hapd->conf->iface);
hostapd_cleanup_cca_params(hapd);
hostapd_event_color_change(hapd, false);
break;
case EVENT_CCA_NOTIFY:
wpa_printf(MSG_DEBUG, "CCA finished on on %s",
hapd = switch_link_hapd(hapd,
data->bss_color_collision.link_id);
wpa_printf(MSG_DEBUG, "CCA finished on %s",
hapd->conf->iface);
if (hapd->cca_color)
hapd->iface->conf->he_op.he_bss_color = hapd->cca_color;
hostapd_cleanup_cca_params(hapd);
hostapd_event_color_change(hapd, true);
break;
#endif /* CONFIG_IEEE80211AX */
#ifdef CONFIG_IEEE80211BE
case EVENT_MLD_INTERFACE_FREED:
wpa_printf(MSG_DEBUG, "MLD: Interface %s freed",
hapd->conf->iface);
hostapd_mld_interface_freed(hapd);
break;
#endif /* CONFIG_IEEE80211BE */
default:
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
break;

File diff suppressed because it is too large Load diff

View file

@ -44,6 +44,7 @@ struct mesh_conf;
#endif /* CONFIG_CTRL_IFACE_UDP */
struct hostapd_iface;
struct hostapd_mld;
struct hapd_interfaces {
int (*reload_config)(struct hostapd_iface *iface);
@ -93,6 +94,12 @@ struct hapd_interfaces {
unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN];
#endif /* CONFIG_CTRL_IFACE_UDP */
#ifdef CONFIG_IEEE80211BE
struct hostapd_mld **mld;
size_t mld_count;
int (*mld_ctrl_iface_init)(struct hostapd_mld *mld);
void (*mld_ctrl_iface_deinit)(struct hostapd_mld *mld);
#endif /* CONFIG_IEEE80211BE */
};
enum hostapd_chan_status {
@ -162,6 +169,21 @@ struct hostapd_sae_commit_queue {
u8 msg[];
};
struct mld_link_info {
u8 valid:1;
u8 nstr_bitmap_len:2;
u8 local_addr[ETH_ALEN];
u8 peer_addr[ETH_ALEN];
u8 nstr_bitmap[2];
u16 capability;
u16 status;
u16 resp_sta_profile_len;
u8 *resp_sta_profile;
};
/**
* struct hostapd_data - hostapd per-BSS data structure
*/
@ -175,12 +197,6 @@ struct hostapd_data {
unsigned int reenable_beacon:1;
u8 own_addr[ETH_ALEN];
u8 mld_addr[ETH_ALEN];
u8 mld_link_id;
/* Used for mld_link_id assignment - valid on the first MLD BSS only */
u8 mld_next_link_id;
struct hostapd_data *mld_first_bss;
int num_sta; /* number of entries in sta_list */
struct sta_info *sta_list; /* STA info list head */
@ -293,7 +309,8 @@ struct hostapd_data {
void *wps_event_cb_ctx;
void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr,
int authorized, const u8 *p2p_dev_addr);
int authorized, const u8 *p2p_dev_addr,
const u8 *ip);
void *sta_authorized_cb_ctx;
void (*setup_complete_cb)(void *ctx);
@ -405,8 +422,10 @@ struct hostapd_data {
u8 beacon_req_token;
u8 lci_req_token;
u8 range_req_token;
u8 link_measurement_req_token;
unsigned int lci_req_active:1;
unsigned int range_req_active:1;
unsigned int link_mesr_req_active:1;
int dhcp_sock; /* UDP socket used with the DHCP server */
@ -471,6 +490,17 @@ struct hostapd_data {
#ifdef CONFIG_IEEE80211BE
u8 eht_mld_bss_param_change;
struct hostapd_mld *mld;
struct dl_list link;
u8 mld_link_id;
/* Cached partner info for ML probe response */
struct mld_link_info partner_links[MAX_NUM_MLD_LINKS];
/* 5 characters for "_link", up to 2 characters for <link ID>, so in
* total, additional 7 characters required. */
char ctrl_sock_iface[IFNAMSIZ + 7 + 1];
#ifdef CONFIG_TESTING_OPTIONS
u8 eht_mld_link_removal_count;
#endif /* CONFIG_TESTING_OPTIONS */
@ -479,6 +509,9 @@ struct hostapd_data {
#ifdef CONFIG_NAN_USD
struct nan_de *nan_de;
#endif /* CONFIG_NAN_USD */
u64 scan_cookie; /* Scan instance identifier for the ongoing HT40 scan
*/
};
@ -492,6 +525,33 @@ struct hostapd_sta_info {
#endif /* CONFIG_TAXONOMY */
};
#ifdef CONFIG_IEEE80211BE
/**
* struct hostapd_mld - hostapd per-mld data structure
*/
struct hostapd_mld {
char name[IFNAMSIZ + 1];
u8 mld_addr[ETH_ALEN];
u8 next_link_id;
u8 num_links;
/* Number of hostapd_data (hapd) referencing this. num_links cannot be
* used since num_links can go to 0 even when a BSS is disabled and
* when it is re-enabled, the MLD should exist and hence it cannot be
* freed when num_links is 0.
*/
u8 refcount;
struct hostapd_data *fbss;
struct dl_list links; /* List head of all affiliated links */
int ctrl_sock;
struct dl_list ctrl_dst;
char *ctrl_interface; /* Directory for UNIX domain sockets */
};
#define HOSTAPD_MLD_MAX_REF_COUNT 0xFF
#endif /* CONFIG_IEEE80211BE */
/**
* struct hostapd_iface - hostapd per-interface data structure
*/
@ -548,6 +608,7 @@ struct hostapd_iface {
u64 drv_flags;
u64 drv_flags2;
unsigned int drv_rrm_flags;
/*
* A bitmap of supported protocols for probe response offload. See
@ -573,6 +634,8 @@ struct hostapd_iface {
int *basic_rates;
int freq;
bool radar_detected;
/* Background radar configuration */
struct {
int channel;
@ -648,6 +711,7 @@ struct hostapd_iface {
#ifdef CONFIG_ACS
unsigned int acs_num_completed_scans;
unsigned int acs_num_retries;
#endif /* CONFIG_ACS */
void (*scan_cb)(struct hostapd_iface *iface);
@ -674,6 +738,12 @@ struct hostapd_iface {
/* Configured freq of interface is NO_IR */
bool is_no_ir;
bool is_ch_switch_dfs; /* Channel switch from ACS to DFS */
struct hostapd_multi_hw_info *multi_hw_info;
unsigned int num_multi_hws;
struct hostapd_multi_hw_info *current_hw_info;
};
/* hostapd.c */
@ -716,6 +786,8 @@ void hostapd_chan_switch_config(struct hostapd_data *hapd,
struct hostapd_freq_params *freq_params);
int hostapd_switch_channel(struct hostapd_data *hapd,
struct csa_settings *settings);
int hostapd_force_channel_switch(struct hostapd_iface *iface,
struct csa_settings settings);
void
hostapd_switch_channel_fallback(struct hostapd_iface *iface,
const struct hostapd_freq_params *freq_params);
@ -780,24 +852,37 @@ int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd);
struct hostapd_data * hostapd_mld_get_link_bss(struct hostapd_data *hapd,
u8 link_id);
int hostapd_link_remove(struct hostapd_data *hapd, u32 count);
bool hostapd_is_ml_partner(struct hostapd_data *hapd1,
struct hostapd_data *hapd2);
u8 hostapd_get_mld_id(struct hostapd_data *hapd);
int hostapd_mld_add_link(struct hostapd_data *hapd);
int hostapd_mld_remove_link(struct hostapd_data *hapd);
struct hostapd_data * hostapd_mld_get_first_bss(struct hostapd_data *hapd);
void free_beacon_data(struct beacon_data *beacon);
int hostapd_fill_cca_settings(struct hostapd_data *hapd,
struct cca_settings *settings);
#ifdef CONFIG_IEEE80211BE
#define for_each_mld_link(_link, _bss_idx, _iface_idx, _ifaces, _mld_id) \
for (_iface_idx = 0; \
_iface_idx < (_ifaces)->count; \
_iface_idx++) \
for (_bss_idx = 0; \
_bss_idx < \
(_ifaces)->iface[_iface_idx]->num_bss; \
_bss_idx++) \
for (_link = \
(_ifaces)->iface[_iface_idx]->bss[_bss_idx]; \
_link && _link->conf->mld_ap && \
_link->conf->mld_id == _mld_id; \
_link = NULL)
bool hostapd_mld_is_first_bss(struct hostapd_data *hapd);
void hostapd_mld_interface_freed(struct hostapd_data *hapd);
#define for_each_mld_link(partner, self) \
dl_list_for_each(partner, &self->mld->links, struct hostapd_data, link)
#else /* CONFIG_IEEE80211BE */
#define for_each_mld_link(_link, _bss_idx, _iface_idx, _ifaces, _mld_id) \
static inline bool hostapd_mld_is_first_bss(struct hostapd_data *hapd)
{
return true;
}
#define for_each_mld_link(partner, self) \
if (false)
#endif /* CONFIG_IEEE80211BE */
u16 hostapd_get_punct_bitmap(struct hostapd_data *hapd);
#endif /* HOSTAPD_H */

View file

@ -76,12 +76,15 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
{
struct hostapd_data *hapd = iface->bss[0];
int i, j;
unsigned int k;
u16 num_modes, flags;
struct hostapd_hw_modes *modes;
u8 dfs_domain;
enum hostapd_hw_mode mode = HOSTAPD_MODE_IEEE80211ANY;
bool is_6ghz = false;
bool orig_mode_valid = false;
struct hostapd_multi_hw_info *multi_hw_info;
unsigned int num_multi_hws;
if (hostapd_drv_none(hapd))
return -1;
@ -107,9 +110,7 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
*/
orig_mode_valid = true;
mode = iface->current_mode->mode;
is_6ghz = mode == HOSTAPD_MODE_IEEE80211A &&
iface->current_mode->num_channels > 0 &&
is_6ghz_freq(iface->current_mode->channels[0].freq);
is_6ghz = iface->current_mode->is_6ghz;
iface->current_mode = NULL;
}
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
@ -170,6 +171,25 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
__func__);
}
multi_hw_info = hostapd_get_multi_hw_info(hapd, &num_multi_hws);
if (!multi_hw_info)
return 0;
hostapd_free_multi_hw_info(iface->multi_hw_info);
iface->multi_hw_info = multi_hw_info;
iface->num_multi_hws = num_multi_hws;
wpa_printf(MSG_DEBUG, "Multiple underlying hardwares info:");
for (k = 0; k < num_multi_hws; k++) {
struct hostapd_multi_hw_info *hw_info = &multi_hw_info[k];
wpa_printf(MSG_DEBUG,
" %d. hw_idx=%u, frequency range: %d-%d MHz",
k + 1, hw_info->hw_idx, hw_info->start_freq,
hw_info->end_freq);
}
return 0;
}
@ -508,6 +528,12 @@ static void ap_ht40_scan_retry(void *eloop_data, void *user_data)
else
ieee80211n_scan_channels_5g(iface, &params);
params.link_id = -1;
#ifdef CONFIG_IEEE80211BE
if (iface->bss[0]->conf->mld_ap)
params.link_id = iface->bss[0]->mld_link_id;
#endif /* CONFIG_IEEE80211BE */
ret = hostapd_driver_scan(iface->bss[0], &params);
iface->num_ht40_scan_tries++;
os_free(params.freqs);
@ -523,6 +549,7 @@ static void ap_ht40_scan_retry(void *eloop_data, void *user_data)
if (ret == 0) {
iface->scan_cb = ieee80211n_check_scan;
iface->bss[0]->scan_cookie = params.scan_cookie;
return;
}
@ -558,6 +585,11 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
else
ieee80211n_scan_channels_5g(iface, &params);
params.link_id = -1;
#ifdef CONFIG_IEEE80211BE
if (iface->bss[0]->conf->mld_ap)
params.link_id = iface->bss[0]->mld_link_id;
#endif /* CONFIG_IEEE80211BE */
ret = hostapd_driver_scan(iface->bss[0], &params);
os_free(params.freqs);
@ -579,6 +611,7 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
}
iface->scan_cb = ieee80211n_check_scan;
iface->bss[0]->scan_cookie = params.scan_cookie;
return 1;
}
@ -1070,9 +1103,7 @@ static bool skip_mode(struct hostapd_iface *iface,
return true;
if (is_6ghz_op_class(iface->conf->op_class) && iface->freq == 0 &&
(mode->mode != HOSTAPD_MODE_IEEE80211A ||
mode->num_channels == 0 ||
!is_6ghz_freq(mode->channels[0].freq)))
!mode->is_6ghz)
return true;
return false;
@ -1382,3 +1413,34 @@ int hostapd_hw_skip_mode(struct hostapd_iface *iface,
}
return 0;
}
void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info)
{
os_free(multi_hw_info);
}
int hostapd_set_current_hw_info(struct hostapd_iface *iface, int oper_freq)
{
struct hostapd_multi_hw_info *hw_info;
unsigned int i;
if (!iface->num_multi_hws)
return 0;
for (i = 0; i < iface->num_multi_hws; i++) {
hw_info = &iface->multi_hw_info[i];
if (hw_info->start_freq <= oper_freq &&
hw_info->end_freq >= oper_freq) {
iface->current_hw_info = hw_info;
wpa_printf(MSG_DEBUG,
"Mode: Selected underlying hardware: hw_idx=%u",
iface->current_hw_info->hw_idx);
return 0;
}
}
return -1;
}

View file

@ -30,6 +30,8 @@ void hostapd_stop_setup_timers(struct hostapd_iface *iface);
int hostapd_hw_skip_mode(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode);
int hostapd_determine_mode(struct hostapd_iface *iface);
void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info);
int hostapd_set_current_hw_info(struct hostapd_iface *iface, int oper_freq);
#else /* NEED_AP_MLME */
static inline void
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
@ -103,6 +105,16 @@ static inline int hostapd_determine_mode(struct hostapd_iface *iface)
return 0;
}
static inline
void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info)
{
}
static inline int hostapd_set_current_hw_info(struct hostapd_iface *iface,
u32 oper_freq)
{
return 0;
}
#endif /* NEED_AP_MLME */
#endif /* HW_FEATURES_H */

File diff suppressed because it is too large Load diff

View file

@ -63,7 +63,7 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts);
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
enum ieee80211_op_mode opmode);
@ -129,11 +129,10 @@ u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *he_6ghz_capab);
int hostapd_get_he_twt_responder(struct hostapd_data *hapd,
enum ieee80211_op_mode mode);
bool hostapd_get_ht_vht_twt_responder(struct hostapd_data *hapd);
u8 * hostapd_eid_cca(struct hostapd_data *hapd, u8 *eid);
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
const u8 *buf, size_t len, int ack);
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
const u8 *data, size_t len, int ack);
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
int wds);
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
@ -148,7 +147,8 @@ u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid);
int hostapd_update_time_adv(struct hostapd_data *hapd);
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid,
u16 value);
int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta);
#ifdef CONFIG_SAE
@ -227,8 +227,10 @@ void auth_sae_process_commit(void *eloop_ctx, void *user_ctx);
u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len);
u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ext_capab_ie, size_t ext_capab_ie_len);
size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type);
u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type);
size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type,
bool include_mld_params);
u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type,
bool include_mld_params);
int ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
int res, struct radius_sta *info);
size_t hostapd_eid_eht_capab_len(struct hostapd_data *hapd,
@ -248,8 +250,6 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
u8 **elem_offset,
const u8 *known_bss, size_t known_bss_len, u8 *rnr_eid,
u8 *rnr_count, u8 **rnr_offset, size_t rnr_len);
void punct_update_legacy_bw(u16 bitmap, u8 pri_chan,
enum oper_chan_width *width, u8 *seg0, u8 *seg1);
bool hostapd_is_mld_ap(struct hostapd_data *hapd);
const char * sae_get_password(struct hostapd_data *hapd,
struct sta_info *sta, const char *rx_id,

View file

@ -128,6 +128,9 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
goto fail;
}
if (!radius_msg_add_msg_auth(msg))
goto fail;
os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr));
if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf,
os_strlen(buf))) {
@ -505,7 +508,9 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
"Found matching Access-Request for RADIUS message (id=%d)",
query->radius_id);
if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) {
if (radius_msg_verify(
msg, shared_secret, shared_secret_len, req,
hapd->conf->radius_require_message_authenticator)) {
wpa_printf(MSG_INFO,
"Incoming RADIUS packet did not have correct authenticator - dropped");
return RADIUS_RX_INVALID_AUTHENTICATOR;
@ -596,7 +601,8 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
if (query->radius_psk) {
struct sta_info *sta;
bool success = cache->accepted == HOSTAPD_ACL_ACCEPT;
bool success = cache->accepted == HOSTAPD_ACL_ACCEPT ||
cache->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT;
sta = ap_get_sta(hapd, query->addr);
if (!sta || !sta->wpa_sm) {

View file

@ -206,19 +206,11 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid)
enum oper_chan_width chwidth;
size_t elen = 1 + 4;
bool eht_oper_info_present;
u16 punct_bitmap = conf->punct_bitmap;
u16 punct_bitmap = hostapd_get_punct_bitmap(hapd);
if (!hapd->iface->current_mode)
return eid;
#ifdef CONFIG_TESTING_OPTIONS
if (!punct_bitmap && hapd->conf->eht_oper_puncturing_override) {
wpa_printf(MSG_DEBUG, "EHT: Puncturing mask override=0x%x",
hapd->conf->eht_oper_puncturing_override);
punct_bitmap = hapd->conf->eht_oper_puncturing_override;
}
#endif /* CONFIG_TESTING_OPTIONS */
if (is_6ghz_op_class(conf->op_class))
chwidth = op_class_to_ch_width(conf->op_class);
else
@ -458,6 +450,8 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
size_t len, slice_len;
u8 link_id;
u8 common_info_len;
u16 mld_cap;
u8 max_simul_links, active_links;
/*
* As the Multi-Link element can exceed the size of 255 bytes need to
@ -495,7 +489,7 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
wpabuf_put_u8(buf, common_info_len);
/* Own MLD MAC Address */
wpabuf_put_data(buf, hapd->mld_addr, ETH_ALEN);
wpabuf_put_data(buf, hapd->mld->mld_addr, ETH_ALEN);
/* Own Link ID */
wpabuf_put_u8(buf, hapd->mld_link_id);
@ -507,14 +501,31 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
hapd->iface->mld_eml_capa);
wpabuf_put_le16(buf, hapd->iface->mld_eml_capa);
mld_cap = hapd->iface->mld_mld_capa;
max_simul_links = mld_cap & EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK;
active_links = hapd->mld->num_links - 1;
if (active_links > max_simul_links) {
wpa_printf(MSG_ERROR,
"MLD: Error in max simultaneous links, advertised: 0x%x current: 0x%x",
max_simul_links, active_links);
active_links = max_simul_links;
}
mld_cap &= ~EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK;
mld_cap |= active_links & EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK;
/* TODO: Advertise T2LM based on driver support as well */
mld_cap &= ~EHT_ML_MLD_CAPA_TID_TO_LINK_MAP_NEG_SUPP_MSK;
wpa_printf(MSG_DEBUG, "MLD: MLD Capabilities and Operations=0x%x",
hapd->iface->mld_mld_capa);
wpabuf_put_le16(buf, hapd->iface->mld_mld_capa);
mld_cap);
wpabuf_put_le16(buf, mld_cap);
if (include_mld_id) {
wpa_printf(MSG_DEBUG, "MLD: AP MLD ID=0x%x",
hapd->conf->mld_id);
wpabuf_put_u8(buf, hapd->conf->mld_id);
hostapd_get_mld_id(hapd));
wpabuf_put_u8(buf, hostapd_get_mld_id(hapd));
}
if (!mld_info)
@ -578,7 +589,8 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
wpabuf_put_le64(buf, 0);
/* DTIM Info */
wpabuf_put_le16(buf, link_bss->conf->dtim_period);
wpabuf_put_u8(buf, 0); /* DTIM Count */
wpabuf_put_u8(buf, link_bss->conf->dtim_period);
/* BSS Parameters Change Count */
wpabuf_put_u8(buf, hapd->eht_mld_bss_param_change);
@ -812,7 +824,7 @@ struct wpabuf * hostapd_ml_auth_resp(struct hostapd_data *hapd)
wpabuf_put_u8(buf, WLAN_EID_EXT_MULTI_LINK);
wpabuf_put_le16(buf, MULTI_LINK_CONTROL_TYPE_BASIC);
wpabuf_put_u8(buf, ETH_ALEN + 1);
wpabuf_put_data(buf, hapd->mld_addr, ETH_ALEN);
wpabuf_put_data(buf, hapd->mld->mld_addr, ETH_ALEN);
return buf;
}
@ -859,6 +871,8 @@ sae_commit_skip_fixed_fields(const struct ieee80211_mgmt *mgmt, size_t len,
wpa_printf(MSG_DEBUG, "EHT: SAE scalar length is %zu", prime_len);
if (len - 2 < prime_len * (ec ? 3 : 2))
goto truncated;
/* scalar */
pos += prime_len;
@ -870,6 +884,7 @@ sae_commit_skip_fixed_fields(const struct ieee80211_mgmt *mgmt, size_t len,
}
if (pos - mgmt->u.auth.variable > (int) len) {
truncated:
wpa_printf(MSG_DEBUG,
"EHT: Too short SAE commit Authentication frame");
return NULL;
@ -893,16 +908,38 @@ sae_confirm_skip_fixed_fields(struct hostapd_data *hapd,
return pos;
/* send confirm integer */
if (len < 2)
goto truncated;
pos += 2;
/*
* At this stage we should already have an MLD station and actually SA
* will be replaced with the MLD MAC address by the driver.
* will be replaced with the MLD MAC address by the driver. However,
* there is at least a theoretical race condition in a case where the
* peer sends the SAE confirm message quickly enough for the driver
* translation mechanism to not be available to update the SAE confirm
* message addresses. Work around that by searching for the STA entry
* using the link address of the non-AP MLD if no match is found based
* on the MLD MAC address.
*/
sta = ap_get_sta(hapd, mgmt->sa);
if (!sta) {
wpa_printf(MSG_DEBUG, "SAE: No MLD STA for SAE confirm");
return NULL;
for (sta = hapd->sta_list; sta; sta = sta->next) {
int link_id = hapd->mld_link_id;
if (!sta->mld_info.mld_sta ||
sta->mld_info.links[link_id].valid ||
!ether_addr_equal(
mgmt->sa,
sta->mld_info.links[link_id].peer_addr))
continue;
wpa_printf(MSG_DEBUG,
"SAE: Found MLD STA for SAE confirm based on link address");
break;
}
if (!sta)
return NULL;
}
if (!sta->sae || sta->sae->state < SAE_COMMITTED || !sta->sae->tmp) {
@ -917,9 +954,12 @@ sae_confirm_skip_fixed_fields(struct hostapd_data *hapd,
wpa_printf(MSG_DEBUG, "SAE: confirm: kck_len=%zu",
sta->sae->tmp->kck_len);
if (len - 2 < sta->sae->tmp->kck_len)
goto truncated;
pos += sta->sae->tmp->kck_len;
if (pos - mgmt->u.auth.variable > (int) len) {
truncated:
wpa_printf(MSG_DEBUG,
"EHT: Too short SAE confirm Authentication frame");
return NULL;
@ -1018,7 +1058,7 @@ const u8 * hostapd_process_ml_auth(struct hostapd_data *hapd,
static int hostapd_mld_validate_assoc_info(struct hostapd_data *hapd,
struct sta_info *sta)
{
u8 i, link_id;
u8 link_id;
struct mld_info *info = &sta->mld_info;
if (!ap_sta_is_mld(hapd, sta)) {
@ -1038,32 +1078,18 @@ static int hostapd_mld_validate_assoc_info(struct hostapd_data *hapd,
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
struct hostapd_data *other_hapd;
if (!info->links[link_id].valid)
if (!info->links[link_id].valid || link_id == hapd->mld_link_id)
continue;
for (i = 0; i < hapd->iface->interfaces->count; i++) {
other_hapd = hapd->iface->interfaces->iface[i]->bss[0];
if (hapd == other_hapd)
continue;
if (other_hapd->conf->mld_ap &&
other_hapd->conf->mld_id == hapd->conf->mld_id &&
link_id == other_hapd->mld_link_id)
break;
}
if (i == hapd->iface->interfaces->count &&
link_id != hapd->mld_link_id) {
other_hapd = hostapd_mld_get_link_bss(hapd, link_id);
if (!other_hapd) {
wpa_printf(MSG_DEBUG, "MLD: Invalid link ID=%u",
link_id);
return -1;
}
if (i < hapd->iface->interfaces->count)
os_memcpy(info->links[link_id].local_addr,
other_hapd->own_addr,
ETH_ALEN);
os_memcpy(info->links[link_id].local_addr, other_hapd->own_addr,
ETH_ALEN);
}
return 0;

View file

@ -12,6 +12,7 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/hw_features_common.h"
#include "hostapd.h"
#include "ap_config.h"
#include "beacon.h"
@ -224,10 +225,11 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
u8 seg0 = hapd->iconf->he_oper_centr_freq_seg0_idx;
u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
u8 control;
#ifdef CONFIG_IEEE80211BE
if (hapd->iconf->punct_bitmap) {
punct_update_legacy_bw(hapd->iconf->punct_bitmap,
u16 punct_bitmap = hostapd_get_punct_bitmap(hapd);
if (punct_bitmap) {
punct_update_legacy_bw(punct_bitmap,
hapd->iconf->channel,
&oper_chwidth, &seg0, &seg1);
}

View file

@ -79,6 +79,51 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
}
static void set_ht_param(struct hostapd_data *hapd,
struct ieee80211_ht_operation *oper)
{
int secondary_channel = hapd->iconf->secondary_channel;
#ifdef CONFIG_IEEE80211BE
enum oper_chan_width chwidth = hostapd_get_oper_chwidth(hapd->iconf);
u16 bw = 0, punct_bitmap = hostapd_get_punct_bitmap(hapd);
u8 offset, chan_bit_pos;
switch (chwidth) {
case CONF_OPER_CHWIDTH_80MHZ:
bw = 80;
offset = 6;
break;
case CONF_OPER_CHWIDTH_160MHZ:
bw = 160;
offset = 14;
break;
case CONF_OPER_CHWIDTH_320MHZ:
bw = 320;
offset = 30;
break;
default:
goto no_update;
}
chan_bit_pos = (hapd->iconf->channel -
hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf) +
offset) / 4;
/* Check if secondary channel is punctured */
if (bw >= 80 && punct_bitmap && secondary_channel &&
(punct_bitmap & BIT(chan_bit_pos + secondary_channel)))
return; /* Do not indicate punctured secondary channel for HT */
no_update:
#endif /* CONFIG_IEEE80211BE */
if (secondary_channel == 1)
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
if (secondary_channel == -1)
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
}
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
{
struct ieee80211_ht_operation *oper;
@ -96,12 +141,7 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
oper->primary_chan = hapd->iconf->channel;
oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
if (hapd->iconf->secondary_channel == 1)
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
if (hapd->iconf->secondary_channel == -1)
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
set_ht_param(hapd, oper);
pos += sizeof(*oper);

View file

@ -121,7 +121,7 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
#ifdef CONFIG_IEEE80211BE
if (ap_sta_is_mld(hapd, sta))
own_addr = hapd->mld_addr;
own_addr = hapd->mld->mld_addr;
#endif /* CONFIG_IEEE80211BE */
mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
@ -219,7 +219,7 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
#ifdef CONFIG_IEEE80211BE
if (ap_sta_is_mld(hapd, sta))
own_addr = hapd->mld_addr;
own_addr = hapd->mld->mld_addr;
#endif /* CONFIG_IEEE80211BE */
resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
@ -441,6 +441,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx,
if (hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
*pos |= 0x40; /* Bit 78 - TWT responder */
#endif /* CONFIG_IEEE80211AX */
if (hostapd_get_ht_vht_twt_responder(hapd))
*pos |= 0x40; /* Bit 78 - TWT responder */
break;
case 10: /* Bits 80-87 */
#ifdef CONFIG_SAE
@ -735,12 +737,14 @@ int hostapd_update_time_adv(struct hostapd_data *hapd)
}
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid,
u16 value)
{
u8 *pos = eid;
#ifdef CONFIG_WNM_AP
if (hapd->conf->ap_max_inactivity > 0) {
if (hapd->conf->ap_max_inactivity > 0 &&
hapd->conf->bss_max_idle) {
unsigned int val;
*pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
*pos++ = 3;
@ -753,9 +757,13 @@ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
val = 1;
if (val > 65535)
val = 65535;
if (value)
val = value;
WPA_PUT_LE16(pos, val);
pos += 2;
*pos++ = 0x00; /* TODO: Protected Keep-Alive Required */
/* Set the Protected Keep-Alive Required bit based on
* configuration */
*pos++ = hapd->conf->bss_max_idle == 2 ? BIT(0) : 0x00;
}
#endif /* CONFIG_WNM_AP */
@ -1089,7 +1097,7 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
{
u8 *pos = eid;
bool sae_pk = false;
u16 capab = 0;
u32 capab = 0, tmp;
size_t flen;
if (!(hapd->conf->wpa & WPA_PROTO_RSN))
@ -1118,18 +1126,28 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP)
capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
if (hapd->conf->ssid_protection)
capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
flen = (capab & 0xff00) ? 2 : 1;
if (len < 2 + flen || !capab)
if (!capab)
return eid; /* no supported extended RSN capabilities */
tmp = capab;
flen = 0;
while (tmp) {
flen++;
tmp >>= 8;
}
if (len < 2 + flen)
return eid; /* no supported extended RSN capabilities */
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
*pos++ = WLAN_EID_RSNX;
*pos++ = flen;
*pos++ = capab & 0x00ff;
capab >>= 8;
if (capab)
*pos++ = capab;
while (capab) {
*pos++ = capab & 0xff;
capab >>= 8;
}
return pos;
}
@ -1138,13 +1156,11 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ext_capab_ie, size_t ext_capab_ie_len)
{
#ifdef CONFIG_INTERWORKING
/* check for QoS Map support */
if (ext_capab_ie_len >= 5) {
if (ext_capab_ie[4] & 0x01)
sta->qos_map_enabled = 1;
}
#endif /* CONFIG_INTERWORKING */
if (ext_capab_ie_len > 0) {
sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
@ -1200,3 +1216,13 @@ struct sta_info * hostapd_ml_get_assoc_sta(struct hostapd_data *hapd,
return sta;
}
bool hostapd_get_ht_vht_twt_responder(struct hostapd_data *hapd)
{
return hapd->iconf->ht_vht_twt_responder &&
((hapd->iconf->ieee80211n && !hapd->conf->disable_11n) ||
(hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac)) &&
(hapd->iface->drv_flags2 &
WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER);
}

View file

@ -12,6 +12,7 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
#include "common/hw_features_common.h"
#include "hostapd.h"
#include "ap_config.h"
#include "sta_info.h"
@ -79,6 +80,9 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
hostapd_get_oper_chwidth(hapd->iconf);
u8 seg0 = hapd->iconf->vht_oper_centr_freq_seg0_idx;
u8 seg1 = hapd->iconf->vht_oper_centr_freq_seg1_idx;
#ifdef CONFIG_IEEE80211BE
u16 punct_bitmap = hostapd_get_punct_bitmap(hapd);
#endif /* CONFIG_IEEE80211BE */
if (is_6ghz_op_class(hapd->iconf->op_class))
return eid;
@ -90,8 +94,8 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
os_memset(oper, 0, sizeof(*oper));
#ifdef CONFIG_IEEE80211BE
if (hapd->iconf->punct_bitmap) {
punct_update_legacy_bw(hapd->iconf->punct_bitmap,
if (punct_bitmap) {
punct_update_legacy_bw(punct_bitmap,
hapd->iconf->channel,
&oper_chwidth, &seg0, &seg1);
}

View file

@ -172,8 +172,7 @@ static void ieee802_1x_ml_set_sta_authorized(struct hostapd_data *hapd,
struct hostapd_data *tmp_hapd =
hapd->iface->interfaces->iface[i]->bss[0];
if (!tmp_hapd->conf->mld_ap ||
hapd->conf->mld_id != tmp_hapd->conf->mld_id)
if (!hostapd_is_ml_partner(hapd, tmp_hapd))
continue;
for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
@ -768,6 +767,9 @@ void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
goto fail;
}
if (!radius_msg_add_msg_auth(msg))
goto fail;
if (sm->identity &&
!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME,
sm->identity, sm->identity_len)) {
@ -2040,16 +2042,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
}
sta = sm->sta;
/* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be
* present when packet contains an EAP-Message attribute */
if (hdr->code == RADIUS_CODE_ACCESS_REJECT &&
radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL,
0) < 0 &&
radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) {
wpa_printf(MSG_DEBUG,
"Allowing RADIUS Access-Reject without Message-Authenticator since it does not include EAP-Message");
} else if (radius_msg_verify(msg, shared_secret, shared_secret_len,
req, 1)) {
if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 1)) {
wpa_printf(MSG_INFO,
"Incoming RADIUS packet did not have correct Message-Authenticator - dropped");
return RADIUS_RX_INVALID_AUTHENTICATOR;
@ -2540,13 +2533,29 @@ int ieee802_1x_init(struct hostapd_data *hapd)
struct eapol_auth_config conf;
struct eapol_auth_cb cb;
if (hapd->mld_first_bss) {
#ifdef CONFIG_IEEE80211BE
if (!hostapd_mld_is_first_bss(hapd)) {
struct hostapd_data *first;
first = hostapd_mld_get_first_bss(hapd);
if (!first)
return -1;
if (!first->eapol_auth) {
wpa_printf(MSG_DEBUG,
"MLD: First BSS IEEE 802.1X state machine does not exist. Init on its behalf");
if (ieee802_1x_init(first))
return -1;
}
wpa_printf(MSG_DEBUG,
"MLD: Using IEEE 802.1X state machine of the first BSS");
hapd->eapol_auth = hapd->mld_first_bss->eapol_auth;
hapd->eapol_auth = first->eapol_auth;
return 0;
}
#endif /* CONFIG_IEEE80211BE */
dl_list_init(&hapd->erp_keys);
@ -2632,13 +2641,15 @@ void ieee802_1x_erp_flush(struct hostapd_data *hapd)
void ieee802_1x_deinit(struct hostapd_data *hapd)
{
if (hapd->mld_first_bss) {
#ifdef CONFIG_IEEE80211BE
if (!hostapd_mld_is_first_bss(hapd)) {
wpa_printf(MSG_DEBUG,
"MLD: Deinit IEEE 802.1X state machine of a non-first BSS");
hapd->eapol_auth = NULL;
return;
}
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_WEP
eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL);

View file

@ -158,7 +158,7 @@ int hostapd_nan_usd_init(struct hostapd_data *hapd)
cb.subscribe_terminated = hostapd_nan_de_subscribe_terminated;
cb.receive = hostapd_nan_de_receive;
hapd->nan_de = nan_de_init(hapd->own_addr, true, &cb);
hapd->nan_de = nan_de_init(hapd->own_addr, false, true, &cb);
if (!hapd->nan_de)
return -1;
return 0;
@ -192,7 +192,7 @@ void hostapd_nan_usd_flush(struct hostapd_data *hapd)
int hostapd_nan_usd_publish(struct hostapd_data *hapd, 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;
@ -201,7 +201,7 @@ int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
return -1;
publish_id = nan_de_publish(hapd->nan_de, service_name, srv_proto_type,
ssi, elems, params);
ssi, elems, params, p2p);
wpabuf_free(elems);
return publish_id;
}
@ -231,7 +231,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
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;
@ -240,7 +240,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
return -1;
subscribe_id = nan_de_subscribe(hapd->nan_de, service_name,
srv_proto_type, ssi, elems, params);
srv_proto_type, ssi, elems, params, p2p);
wpabuf_free(elems);
return subscribe_id;
}

View file

@ -21,7 +21,7 @@ void hostapd_nan_usd_flush(struct hostapd_data *hapd);
int hostapd_nan_usd_publish(struct hostapd_data *hapd, 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 hostapd_nan_usd_cancel_publish(struct hostapd_data *hapd, int publish_id);
int hostapd_nan_usd_update_publish(struct hostapd_data *hapd, int publish_id,
const struct wpabuf *ssi);
@ -29,7 +29,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
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 hostapd_nan_usd_cancel_subscribe(struct hostapd_data *hapd,
int subscribe_id);
int hostapd_nan_usd_transmit(struct hostapd_data *hapd, int handle,

View file

@ -61,6 +61,7 @@ void sta_ip6addr_del(struct hostapd_data *hapd, struct sta_info *sta)
dl_list_for_each_safe(ip6addr, prev, &sta->ip6addr, struct ip6addr,
list) {
hostapd_drv_br_delete_ip_neigh(hapd, 6, (u8 *) &ip6addr->addr);
dl_list_del(&ip6addr->list);
os_free(ip6addr);
}
}

View file

@ -99,7 +99,10 @@ static void hostapd_neighbor_clear_entry(struct hostapd_neighbor_entry *nr)
nr->civic = NULL;
os_memset(nr->bssid, 0, sizeof(nr->bssid));
os_memset(&nr->ssid, 0, sizeof(nr->ssid));
os_memset(&nr->lci_date, 0, sizeof(nr->lci_date));
nr->stationary = 0;
nr->short_ssid = 0;
nr->bss_parameters = 0;
}
@ -165,6 +168,14 @@ fail:
}
static void hostapd_neighbor_free(struct hostapd_neighbor_entry *nr)
{
hostapd_neighbor_clear_entry(nr);
dl_list_del(&nr->list);
os_free(nr);
}
int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
const struct wpa_ssid_value *ssid)
{
@ -174,9 +185,7 @@ int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
if (!nr)
return -1;
hostapd_neighbor_clear_entry(nr);
dl_list_del(&nr->list);
os_free(nr);
hostapd_neighbor_free(nr);
return 0;
}
@ -188,9 +197,7 @@ void hostapd_free_neighbor_db(struct hostapd_data *hapd)
dl_list_for_each_safe(nr, prev, &hapd->nr_db,
struct hostapd_neighbor_entry, list) {
hostapd_neighbor_clear_entry(nr);
dl_list_del(&nr->list);
os_free(nr);
hostapd_neighbor_free(nr);
}
}
@ -325,3 +332,35 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
wpabuf_free(nr);
#endif /* NEED_AP_MLME */
}
static struct hostapd_neighbor_entry *
hostapd_neighbor_get_diff_short_ssid(struct hostapd_data *hapd, const u8 *bssid)
{
struct hostapd_neighbor_entry *nr;
dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
list) {
if (ether_addr_equal(bssid, nr->bssid) &&
nr->short_ssid != hapd->conf->ssid.short_ssid)
return nr;
}
return NULL;
}
int hostapd_neighbor_sync_own_report(struct hostapd_data *hapd)
{
struct hostapd_neighbor_entry *nr;
nr = hostapd_neighbor_get_diff_short_ssid(hapd, hapd->own_addr);
if (!nr)
return -1;
/* Clear old entry due to SSID change */
hostapd_neighbor_free(nr);
hostapd_neighbor_set_own_report(hapd);
return 0;
}

View file

@ -20,6 +20,7 @@ int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid,
const struct wpabuf *civic, int stationary,
u8 bss_parameters);
void hostapd_neighbor_set_own_report(struct hostapd_data *hapd);
int hostapd_neighbor_sync_own_report(struct hostapd_data *hapd);
int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
const struct wpa_ssid_value *ssid);
void hostapd_free_neighbor_db(struct hostapd_data *hapd);

View file

@ -334,6 +334,53 @@ static void hostapd_handle_nei_report_req(struct hostapd_data *hapd,
}
static void hostapd_link_mesr_rep_timeout_handler(void *eloop_data,
void *user_ctx)
{
struct hostapd_data *hapd = eloop_data;
wpa_printf(MSG_DEBUG,
"RRM: Link measurement request (token %u) timed out",
hapd->link_measurement_req_token);
hapd->link_mesr_req_active = 0;
}
static void hostapd_handle_link_mesr_report(struct hostapd_data *hapd,
const u8 *buf, size_t len)
{
const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *) buf;
const struct rrm_link_measurement_report *report;
const u8 *pos, *end;
char report_msg[2 * 8 + 1];
end = buf + len;
pos = mgmt->u.action.u.rrm.variable;
report = (const struct rrm_link_measurement_report *) (pos - 1);
if (end - (const u8 *) report < (int) sizeof(*report))
return;
if (!hapd->link_mesr_req_active ||
(hapd->link_measurement_req_token != report->dialog_token)) {
wpa_printf(MSG_INFO,
"Unexpected Link measurement report, token %u",
report->dialog_token);
return;
}
hapd->link_mesr_req_active = 0;
eloop_cancel_timeout(hostapd_link_mesr_rep_timeout_handler, hapd, NULL);
report_msg[0] = '\0';
if (wpa_snprintf_hex(report_msg, sizeof(report_msg),
pos, end - pos) < 0)
return;
wpa_msg(hapd->msg_ctx, MSG_INFO, LINK_MSR_RESP_RX MACSTR " %u %s",
MAC2STR(mgmt->sa), report->dialog_token, report_msg);
}
void hostapd_handle_radio_measurement(struct hostapd_data *hapd,
const u8 *buf, size_t len)
{
@ -356,6 +403,9 @@ void hostapd_handle_radio_measurement(struct hostapd_data *hapd,
case WLAN_RRM_NEIGHBOR_REPORT_REQUEST:
hostapd_handle_nei_report_req(hapd, buf, len);
break;
case WLAN_RRM_LINK_MEASUREMENT_REPORT:
hostapd_handle_link_mesr_report(hapd, buf, len);
break;
default:
wpa_printf(MSG_DEBUG, "RRM action %u is not supported",
mgmt->u.action.u.rrm.action);
@ -563,6 +613,7 @@ void hostapd_clean_rrm(struct hostapd_data *hapd)
hapd->lci_req_active = 0;
eloop_cancel_timeout(hostapd_range_rep_timeout_handler, hapd, NULL);
hapd->range_req_active = 0;
eloop_cancel_timeout(hostapd_link_mesr_rep_timeout_handler, hapd, NULL);
}
@ -672,3 +723,73 @@ void hostapd_rrm_beacon_req_tx_status(struct hostapd_data *hapd,
" %u ack=%d", MAC2STR(mgmt->da),
mgmt->u.action.u.rrm.dialog_token, ok);
}
int hostapd_send_link_measurement_req(struct hostapd_data *hapd, const u8 *addr)
{
struct wpabuf *buf;
struct sta_info *sta;
int ret;
wpa_printf(MSG_DEBUG, "Request Link Measurement: dest addr " MACSTR,
MAC2STR(addr));
if (!(hapd->iface->drv_rrm_flags &
WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
wpa_printf(MSG_INFO,
"Request Link Measurement: the driver does not support TX power insertion");
return -1;
}
sta = ap_get_sta(hapd, addr);
if (!sta || !(sta->flags & WLAN_STA_AUTHORIZED)) {
wpa_printf(MSG_INFO,
"Request Link Measurement: specied STA is not connected");
return -1;
}
if (!(sta->rrm_enabled_capa[0] & WLAN_RRM_CAPS_LINK_MEASUREMENT)) {
wpa_printf(MSG_INFO,
"Request Link Measurement: destination STA does not support link measurement");
return -1;
}
if (hapd->link_mesr_req_active) {
wpa_printf(MSG_DEBUG,
"Request Link Measurement: request already in process - overriding");
hapd->link_mesr_req_active = 0;
eloop_cancel_timeout(hostapd_link_mesr_rep_timeout_handler,
hapd, NULL);
}
/* Action + Action type + token + Tx Power used + Max Tx Power = 5 */
buf = wpabuf_alloc(5);
if (!buf)
return -1;
hapd->link_measurement_req_token++;
if (!hapd->link_measurement_req_token)
hapd->link_measurement_req_token++;
wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REQUEST);
wpabuf_put_u8(buf, hapd->link_measurement_req_token);
/* NOTE: The driver is expected to fill the Tx Power Used and Max Tx
* Power */
wpabuf_put_u8(buf, 0);
wpabuf_put_u8(buf, 0);
ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
wpabuf_head(buf), wpabuf_len(buf));
wpabuf_free(buf);
if (ret < 0)
return ret;
hapd->link_mesr_req_active = 1;
eloop_register_timeout(HOSTAPD_RRM_REQUEST_TIMEOUT, 0,
hostapd_link_mesr_rep_timeout_handler, hapd,
NULL);
return hapd->link_measurement_req_token;
}

View file

@ -29,5 +29,7 @@ int hostapd_send_beacon_req(struct hostapd_data *hapd, const u8 *addr,
void hostapd_rrm_beacon_req_tx_status(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt,
size_t len, int ok);
int hostapd_send_link_measurement_req(struct hostapd_data *hapd,
const u8 *addr);
#endif /* RRM_H */

View file

@ -180,13 +180,48 @@ void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta)
sta->pasn->fils.erp_resp = NULL;
#endif /* CONFIG_FILS */
bin_clear_free(sta->pasn, sizeof(*sta->pasn));
pasn_data_deinit(sta->pasn);
sta->pasn = NULL;
}
}
#endif /* CONFIG_PASN */
static void __ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
{
#ifdef CONFIG_IEEE80211BE
if (hostapd_sta_is_link_sta(hapd, sta) &&
!hostapd_drv_link_sta_remove(hapd, sta->addr))
return;
#endif /* CONFIG_IEEE80211BE */
hostapd_drv_sta_remove(hapd, sta->addr);
}
#ifdef CONFIG_IEEE80211BE
static void clear_wpa_sm_for_each_partner_link(struct hostapd_data *hapd,
struct sta_info *psta)
{
struct sta_info *lsta;
struct hostapd_data *lhapd;
if (!ap_sta_is_mld(hapd, psta))
return;
for_each_mld_link(lhapd, hapd) {
if (lhapd == hapd)
continue;
lsta = ap_get_sta(lhapd, psta->addr);
if (lsta)
lsta->wpa_sm = NULL;
}
}
#endif /* CONFIG_IEEE80211BE */
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
{
int set_beacon = 0;
@ -200,6 +235,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
if ((sta->flags & WLAN_STA_WDS) ||
(sta->flags & WLAN_STA_MULTI_AP &&
(hapd->conf->multi_ap & BACKHAUL_BSS) &&
hapd->conf->wds_sta &&
!(sta->flags & WLAN_STA_WPS)))
hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
@ -209,7 +245,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
if (!hapd->iface->driver_ap_teardown &&
!(sta->flags & WLAN_STA_PREAUTH)) {
hostapd_drv_sta_remove(hapd, sta->addr);
__ap_free_sta(hapd, sta);
sta->added_unassoc = 0;
}
@ -304,9 +340,17 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
#ifdef CONFIG_IEEE80211BE
if (!ap_sta_is_mld(hapd, sta) ||
hapd->mld_link_id == sta->mld_assoc_link_id)
hapd->mld_link_id == sta->mld_assoc_link_id) {
wpa_auth_sta_deinit(sta->wpa_sm);
#else
/* Remove references from partner links. */
clear_wpa_sm_for_each_partner_link(hapd, sta);
}
/* Release group references in case non-association link STA is removed
* before association link STA */
if (hostapd_sta_is_link_sta(hapd, sta))
wpa_release_link_auth_ref(sta->wpa_sm, hapd->mld_link_id);
#else /* CONFIG_IEEE80211BE */
wpa_auth_sta_deinit(sta->wpa_sm);
#endif /* CONFIG_IEEE80211BE */
@ -454,6 +498,27 @@ void hostapd_free_stas(struct hostapd_data *hapd)
}
#ifdef CONFIG_IEEE80211BE
void hostapd_free_link_stas(struct hostapd_data *hapd)
{
struct sta_info *sta, *prev;
sta = hapd->sta_list;
while (sta) {
prev = sta;
sta = sta->next;
if (!hostapd_sta_is_link_sta(hapd, prev))
continue;
wpa_printf(MSG_DEBUG, "Removing link station from MLD " MACSTR,
MAC2STR(prev->addr));
ap_free_sta(hapd, prev);
}
}
#endif /* CONFIG_IEEE80211BE */
/**
* ap_handle_timer - Per STA timer handler
* @eloop_ctx: struct hostapd_data *
@ -468,6 +533,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
struct sta_info *sta = timeout_ctx;
unsigned long next_time = 0;
int reason;
int max_inactivity = hapd->conf->ap_max_inactivity;
wpa_printf(MSG_DEBUG, "%s: %s: " MACSTR " flags=0x%x timeout_next=%d",
hapd->conf->iface, __func__, MAC2STR(sta->addr), sta->flags,
@ -480,6 +546,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
return;
}
if (sta->max_idle_period)
max_inactivity = (sta->max_idle_period * 1024 + 999) / 1000;
if ((sta->flags & WLAN_STA_ASSOC) &&
(sta->timeout_next == STA_NULLFUNC ||
sta->timeout_next == STA_DISASSOC)) {
@ -501,7 +570,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
* Anyway, try again after the next inactivity timeout,
* but do not disconnect the station now.
*/
next_time = hapd->conf->ap_max_inactivity + fuzz;
next_time = max_inactivity + fuzz;
} else if (inactive_sec == -ENOENT) {
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
"Station " MACSTR " has lost its driver entry",
@ -510,20 +579,19 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
/* Avoid sending client probe on removed client */
sta->timeout_next = STA_DISASSOC;
goto skip_poll;
} else if (inactive_sec < hapd->conf->ap_max_inactivity) {
} else if (inactive_sec < max_inactivity) {
/* station activity detected; reset timeout state */
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
"Station " MACSTR " has been active %is ago",
MAC2STR(sta->addr), inactive_sec);
sta->timeout_next = STA_NULLFUNC;
next_time = hapd->conf->ap_max_inactivity + fuzz -
inactive_sec;
next_time = max_inactivity + fuzz - inactive_sec;
} else {
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
"Station " MACSTR " has been "
"inactive too long: %d sec, max allowed: %d",
MAC2STR(sta->addr), inactive_sec,
hapd->conf->ap_max_inactivity);
max_inactivity);
if (hapd->conf->skip_inactivity_poll)
sta->timeout_next = STA_DISASSOC;
@ -539,7 +607,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
/* data nullfunc frame poll did not produce TX errors; assume
* station ACKed it */
sta->timeout_next = STA_NULLFUNC;
next_time = hapd->conf->ap_max_inactivity;
next_time = max_inactivity;
}
skip_poll:
@ -727,6 +795,7 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
{
struct sta_info *sta;
int i;
int max_inactivity = hapd->conf->ap_max_inactivity;
sta = ap_get_sta(hapd, addr);
if (sta)
@ -760,12 +829,15 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
}
sta->supported_rates_len = i;
if (sta->max_idle_period)
max_inactivity = (sta->max_idle_period * 1024 + 999) / 1000;
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) {
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
"for " MACSTR " (%d seconds - ap_max_inactivity)",
__func__, MAC2STR(addr),
hapd->conf->ap_max_inactivity);
eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
max_inactivity);
eloop_register_timeout(max_inactivity, 0,
ap_handle_timer, hapd, sta);
}
@ -869,9 +941,11 @@ static void ap_sta_disconnect_common(struct hostapd_data *hapd,
ieee802_1x_free_station(hapd, sta);
#ifdef CONFIG_IEEE80211BE
if (!hapd->conf->mld_ap ||
hapd->mld_link_id == sta->mld_assoc_link_id)
hapd->mld_link_id == sta->mld_assoc_link_id) {
wpa_auth_sta_deinit(sta->wpa_sm);
#else
clear_wpa_sm_for_each_partner_link(hapd, sta);
}
#else /* CONFIG_IEEE80211BE */
wpa_auth_sta_deinit(sta->wpa_sm);
#endif /* CONFIG_IEEE80211BE */
@ -970,16 +1044,15 @@ static bool ap_sta_ml_disconnect(struct hostapd_data *hapd,
interfaces = assoc_hapd->iface->interfaces;
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
if (!assoc_sta->mld_info.links[link_id].valid)
continue;
for (i = 0; i < interfaces->count; i++) {
struct sta_info *tmp_sta;
if (!assoc_sta->mld_info.links[link_id].valid)
continue;
tmp_hapd = interfaces->iface[i]->bss[0];
if (!tmp_hapd->conf->mld_ap ||
assoc_hapd->conf->mld_id != tmp_hapd->conf->mld_id)
if (!hostapd_is_ml_partner(tmp_hapd, assoc_hapd))
continue;
for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
@ -1433,6 +1506,7 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
u8 addr[ETH_ALEN];
u8 ip_addr_buf[4];
#endif /* CONFIG_P2P */
const u8 *ip_ptr = NULL;
#ifdef CONFIG_P2P
if (hapd->p2p_group == NULL) {
@ -1449,10 +1523,6 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
#endif /* CONFIG_P2P */
os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
if (hapd->sta_authorized_cb)
hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
sta->addr, authorized, dev_addr);
if (authorized) {
const u8 *dpp_pkhash;
const char *keyid;
@ -1469,6 +1539,7 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
" ip_addr=%u.%u.%u.%u",
ip_addr_buf[0], ip_addr_buf[1],
ip_addr_buf[2], ip_addr_buf[3]);
ip_ptr = ip_addr_buf;
}
#endif /* CONFIG_P2P */
@ -1508,6 +1579,11 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
AP_STA_DISCONNECTED "%s", buf);
}
if (hapd->sta_authorized_cb)
hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
sta->addr, authorized, dev_addr,
ip_ptr);
#ifdef CONFIG_FST
if (hapd->iface->fst) {
if (authorized)
@ -1725,10 +1801,8 @@ static void ap_sta_remove_link_sta(struct hostapd_data *hapd,
struct sta_info *sta)
{
struct hostapd_data *tmp_hapd;
unsigned int i, j;
for_each_mld_link(tmp_hapd, i, j, hapd->iface->interfaces,
hapd->conf->mld_id) {
for_each_mld_link(tmp_hapd, hapd) {
struct sta_info *tmp_sta;
if (hapd == tmp_hapd)

View file

@ -81,22 +81,7 @@ struct mld_info {
u16 mld_capa;
} common_info;
struct mld_link_info {
u8 valid:1;
u8 nstr_bitmap_len:2;
u8 local_addr[ETH_ALEN];
u8 peer_addr[ETH_ALEN];
u8 nstr_bitmap[2];
u16 capability;
u16 status;
u16 resp_sta_profile_len;
u8 *resp_sta_profile;
const u8 *rsne, *rsnxe;
} links[MAX_NUM_MLD_LINKS];
struct mld_link_info links[MAX_NUM_MLD_LINKS];
};
struct sta_info {
@ -334,6 +319,9 @@ struct sta_info {
struct mld_info mld_info;
u8 mld_assoc_link_id;
#endif /* CONFIG_IEEE80211BE */
u16 max_idle_period; /* if nonzero, the granted BSS max idle period in
* units of 1000 TUs */
};
@ -440,4 +428,6 @@ static inline void ap_sta_set_mld(struct sta_info *sta, bool mld)
void ap_sta_free_sta_profile(struct mld_info *info);
void hostapd_free_link_stas(struct hostapd_data *hapd);
#endif /* STA_INFO_H */

View file

@ -51,7 +51,7 @@ static const u8 * wnm_ap_get_own_addr(struct hostapd_data *hapd,
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap && (!sta || ap_sta_is_mld(hapd, sta)))
own_addr = hapd->mld_addr;
own_addr = hapd->mld->mld_addr;
#endif /* CONFIG_IEEE80211BE */
return own_addr;

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,7 @@
struct vlan_description;
struct mld_info;
#define MAX_OWN_IE_OVERRIDE 256
#define MAX_OWN_IE_OVERRIDE 257
#ifdef _MSC_VER
#pragma pack(push, 1)
@ -173,6 +173,8 @@ struct wpa_auth_config {
int wpa;
int extended_key_id;
int wpa_key_mgmt;
int rsn_override_key_mgmt;
int rsn_override_key_mgmt_2;
int wpa_pairwise;
int wpa_group;
int wpa_group_rekey;
@ -184,6 +186,8 @@ struct wpa_auth_config {
u32 wpa_pairwise_update_count;
int wpa_disable_eapol_key_retries;
int rsn_pairwise;
int rsn_override_pairwise;
int rsn_override_pairwise_2;
int rsn_preauth;
int eapol_version;
int wmm_enabled;
@ -192,15 +196,17 @@ struct wpa_auth_config {
int okc;
int tx_status;
enum mfp_options ieee80211w;
enum mfp_options rsn_override_mfp;
enum mfp_options rsn_override_mfp_2;
int beacon_prot;
int group_mgmt_cipher;
int sae_require_mfp;
#ifdef CONFIG_OCV
int ocv; /* Operating Channel Validation */
#endif /* CONFIG_OCV */
#ifdef CONFIG_IEEE80211R_AP
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
#ifdef CONFIG_IEEE80211R_AP
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
u8 r0_key_holder[FT_R0KH_ID_MAX_LEN];
size_t r0_key_holder_len;
@ -224,6 +230,21 @@ struct wpa_auth_config {
double corrupt_gtk_rekey_mic_probability;
u8 own_ie_override[MAX_OWN_IE_OVERRIDE];
size_t own_ie_override_len;
bool rsne_override_set;
u8 rsne_override[MAX_OWN_IE_OVERRIDE];
size_t rsne_override_len;
bool rsnoe_override_set;
u8 rsnoe_override[MAX_OWN_IE_OVERRIDE];
size_t rsnoe_override_len;
bool rsno2e_override_set;
u8 rsno2e_override[MAX_OWN_IE_OVERRIDE];
size_t rsno2e_override_len;
bool rsnxe_override_set;
u8 rsnxe_override[MAX_OWN_IE_OVERRIDE];
size_t rsnxe_override_len;
bool rsnxoe_override_set;
u8 rsnxoe_override[MAX_OWN_IE_OVERRIDE];
size_t rsnxoe_override_len;
u8 rsne_override_eapol[MAX_OWN_IE_OVERRIDE];
size_t rsne_override_eapol_len;
u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE];
@ -245,6 +266,7 @@ struct wpa_auth_config {
struct wpabuf *eapol_m1_elements;
struct wpabuf *eapol_m3_elements;
bool eapol_m3_no_encrypt;
bool eapol_key_reserved_random;
#endif /* CONFIG_TESTING_OPTIONS */
unsigned int oci_freq_override_eapol_m3;
unsigned int oci_freq_override_eapol_g1;
@ -281,10 +303,22 @@ struct wpa_auth_config {
bool radius_psk;
bool no_disconnect_on_group_keyerror;
/* Pointer to Multi-BSSID transmitted BSS authenticator instance.
* Set only in nontransmitted BSSs, i.e., is NULL for transmitted BSS
* and in BSSs that are not part of a Multi-BSSID set. */
struct wpa_authenticator *tx_bss_auth;
#ifdef CONFIG_IEEE80211BE
const u8 *mld_addr;
int link_id;
struct wpa_authenticator *first_link_auth;
#endif /* CONFIG_IEEE80211BE */
bool ssid_protection;
int rsn_override_omit_rsnxe;
};
typedef enum {
@ -297,16 +331,6 @@ typedef enum {
WPA_EAPOL_keyDone, WPA_EAPOL_inc_EapolFramesTx
} wpa_eapol_variable;
struct wpa_auth_ml_rsn_info {
unsigned int n_mld_links;
struct wpa_auth_ml_link_rsn_info {
unsigned int link_id;
const u8 *rsn_ies;
size_t rsn_ies_len;
} links[MAX_NUM_MLD_LINKS];
};
struct wpa_auth_ml_key_info {
unsigned int n_mld_links;
bool mgmt_frame_prot;
@ -400,8 +424,8 @@ struct wpa_auth_callbacks {
size_t ltf_keyseed_len);
#endif /* CONFIG_PASN */
#ifdef CONFIG_IEEE80211BE
int (*get_ml_rsn_info)(void *ctx, struct wpa_auth_ml_rsn_info *info);
int (*get_ml_key_info)(void *ctx, struct wpa_auth_ml_key_info *info);
int (*get_ml_key_info)(void *ctx, struct wpa_auth_ml_key_info *info,
bool rekey);
#endif /* CONFIG_IEEE80211BE */
int (*get_drv_flags)(void *ctx, u64 *drv_flags, u64 *drv_flags2);
};
@ -429,7 +453,8 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
const u8 *wpa_ie, size_t wpa_ie_len,
const u8 *rsnxe, size_t rsnxe_len,
const u8 *mdie, size_t mdie_len,
const u8 *owe_dh, size_t owe_dh_len);
const u8 *owe_dh, size_t owe_dh_len,
struct wpa_state_machine *assoc_sm);
int wpa_validate_osen(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm,
const u8 *osen_ie, size_t osen_ie_len);
@ -520,9 +545,9 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
size_t max_len, int auth_alg,
const u8 *req_ies, size_t req_ies_len,
int omit_rsnxe);
void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
void wpa_ft_process_auth(struct wpa_state_machine *sm,
u16 auth_transaction, const u8 *ies, size_t ies_len,
void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
void (*cb)(void *ctx, const u8 *dst,
u16 auth_transaction, u16 resp,
const u8 *ies, size_t ies_len),
void *ctx);
@ -605,7 +630,10 @@ u8 * wpa_auth_write_assoc_resp_fils(struct wpa_state_machine *sm,
bool wpa_auth_write_fd_rsn_info(struct wpa_authenticator *wpa_auth,
u8 *fd_rsn_info);
void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg);
void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie,
size_t len);
void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z);
void wpa_auth_set_ssid_protection(struct wpa_state_machine *sm, bool val);
void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
u8 val);
@ -639,12 +667,20 @@ void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success);
void wpa_auth_set_ml_info(struct wpa_state_machine *sm, const u8 *mld_addr,
void wpa_auth_set_ml_info(struct wpa_state_machine *sm,
u8 mld_assoc_link_id, struct mld_info *info);
void wpa_auth_ml_get_rsn_info(struct wpa_authenticator *a,
struct wpa_auth_ml_link_rsn_info *info);
void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
struct wpa_auth_ml_link_key_info *info,
bool mgmt_frame_prot, bool beacon_prot);
bool mgmt_frame_prot, bool beacon_prot,
bool rekey);
void wpa_release_link_auth_ref(struct wpa_state_machine *sm,
int release_link_id);
#define for_each_sm_auth(sm, link_id) \
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) \
if (sm->mld_links[link_id].valid && \
sm->mld_links[link_id].wpa_auth && \
sm->wpa_auth != sm->mld_links[link_id].wpa_auth)
#endif /* WPA_AUTH_H */

View file

@ -3442,9 +3442,9 @@ out:
}
void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
void wpa_ft_process_auth(struct wpa_state_machine *sm,
u16 auth_transaction, const u8 *ies, size_t ies_len,
void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
void (*cb)(void *ctx, const u8 *dst,
u16 auth_transaction, u16 status,
const u8 *ies, size_t ies_len),
void *ctx)
@ -3462,7 +3462,8 @@ void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
wpa_printf(MSG_DEBUG, "FT: Received authentication frame: STA=" MACSTR
" BSSID=" MACSTR " transaction=%d",
MAC2STR(sm->addr), MAC2STR(bssid), auth_transaction);
MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr),
auth_transaction);
sm->ft_pending_cb = cb;
sm->ft_pending_cb_ctx = ctx;
sm->ft_pending_auth_transaction = auth_transaction;
@ -3480,8 +3481,7 @@ void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
MAC2STR(sm->addr), auth_transaction + 1, status,
status2str(status));
wpa_hexdump(MSG_DEBUG, "FT: Response IEs", resp_ies, resp_ies_len);
cb(ctx, sm->addr, bssid, auth_transaction + 1, status,
resp_ies, resp_ies_len);
cb(ctx, sm->addr, auth_transaction + 1, status, resp_ies, resp_ies_len);
os_free(resp_ies);
}
@ -3810,7 +3810,7 @@ int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len)
}
static void wpa_ft_rrb_rx_request_cb(void *ctx, const u8 *dst, const u8 *bssid,
static void wpa_ft_rrb_rx_request_cb(void *ctx, const u8 *dst,
u16 auth_transaction, u16 resp,
const u8 *ies, size_t ies_len)
{
@ -4339,7 +4339,7 @@ static void ft_finish_pull(struct wpa_state_machine *sm)
wpa_printf(MSG_DEBUG, "FT: Postponed auth callback result for " MACSTR
" - status %u", MAC2STR(sm->addr), status);
sm->ft_pending_cb(sm->ft_pending_cb_ctx, sm->addr, sm->wpa_auth->addr,
sm->ft_pending_cb(sm->ft_pending_cb_ctx, sm->addr,
sm->ft_pending_auth_transaction + 1, status,
resp_ies, resp_ies_len);
os_free(resp_ies);

View file

@ -45,6 +45,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wconf->wpa = conf->wpa;
wconf->extended_key_id = conf->extended_key_id;
wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
wconf->rsn_override_key_mgmt = conf->rsn_override_key_mgmt;
wconf->rsn_override_key_mgmt_2 = conf->rsn_override_key_mgmt_2;
wconf->wpa_pairwise = conf->wpa_pairwise;
wconf->wpa_group = conf->wpa_group;
wconf->wpa_group_rekey = conf->wpa_group_rekey;
@ -56,6 +58,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
conf->wpa_disable_eapol_key_retries;
wconf->wpa_pairwise_update_count = conf->wpa_pairwise_update_count;
wconf->rsn_pairwise = conf->rsn_pairwise;
wconf->rsn_override_pairwise = conf->rsn_override_pairwise;
wconf->rsn_override_pairwise_2 = conf->rsn_override_pairwise_2;
wconf->rsn_preauth = conf->rsn_preauth;
wconf->eapol_version = conf->eapol_version;
#ifdef CONFIG_MACSEC
@ -70,14 +74,17 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
#endif /* CONFIG_OCV */
wconf->okc = conf->okc;
wconf->ieee80211w = conf->ieee80211w;
wconf->rsn_override_mfp = conf->rsn_override_mfp;
wconf->rsn_override_mfp_2 = conf->rsn_override_mfp_2;
wconf->beacon_prot = conf->beacon_prot;
wconf->group_mgmt_cipher = conf->group_mgmt_cipher;
wconf->sae_require_mfp = conf->sae_require_mfp;
#ifdef CONFIG_IEEE80211R_AP
wconf->ssid_protection = conf->ssid_protection;
wconf->ssid_len = conf->ssid.ssid_len;
if (wconf->ssid_len > SSID_MAX_LEN)
wconf->ssid_len = SSID_MAX_LEN;
os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len);
#ifdef CONFIG_IEEE80211R_AP
os_memcpy(wconf->mobility_domain, conf->mobility_domain,
MOBILITY_DOMAIN_ID_LEN);
if (conf->nas_identifier &&
@ -125,6 +132,46 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wpabuf_head(conf->own_ie_override),
wconf->own_ie_override_len);
}
if (conf->rsne_override &&
wpabuf_len(conf->rsne_override) <= MAX_OWN_IE_OVERRIDE) {
wconf->rsne_override_len = wpabuf_len(conf->rsne_override);
os_memcpy(wconf->rsne_override,
wpabuf_head(conf->rsne_override),
wconf->rsne_override_len);
wconf->rsne_override_set = true;
}
if (conf->rsnoe_override &&
wpabuf_len(conf->rsnoe_override) <= MAX_OWN_IE_OVERRIDE) {
wconf->rsnoe_override_len = wpabuf_len(conf->rsnoe_override);
os_memcpy(wconf->rsnoe_override,
wpabuf_head(conf->rsnoe_override),
wconf->rsnoe_override_len);
wconf->rsnoe_override_set = true;
}
if (conf->rsno2e_override &&
wpabuf_len(conf->rsno2e_override) <= MAX_OWN_IE_OVERRIDE) {
wconf->rsno2e_override_len = wpabuf_len(conf->rsno2e_override);
os_memcpy(wconf->rsno2e_override,
wpabuf_head(conf->rsno2e_override),
wconf->rsno2e_override_len);
wconf->rsno2e_override_set = true;
}
if (conf->rsnxe_override &&
wpabuf_len(conf->rsnxe_override) <= MAX_OWN_IE_OVERRIDE) {
wconf->rsnxe_override_len = wpabuf_len(conf->rsnxe_override);
os_memcpy(wconf->rsnxe_override,
wpabuf_head(conf->rsnxe_override),
wconf->rsnxe_override_len);
wconf->rsnxe_override_set = true;
}
if (conf->rsnxoe_override &&
wpabuf_len(conf->rsnxoe_override) <= MAX_OWN_IE_OVERRIDE) {
wconf->rsnxoe_override_len = wpabuf_len(conf->rsnxoe_override);
os_memcpy(wconf->rsnxoe_override,
wpabuf_head(conf->rsnxoe_override),
wconf->rsnxoe_override_len);
wconf->rsnxoe_override_set = true;
}
if (conf->rsne_override_eapol &&
wpabuf_len(conf->rsne_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
wconf->rsne_override_eapol_set = 1;
@ -189,6 +236,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
if (conf->eapol_m3_elements)
wconf->eapol_m3_elements = wpabuf_dup(conf->eapol_m3_elements);
wconf->eapol_m3_no_encrypt = conf->eapol_m3_no_encrypt;
wconf->eapol_key_reserved_random = conf->eapol_key_reserved_random;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_P2P
os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);
@ -224,6 +272,11 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
#endif /* CONFIG_PASN */
wconf->radius_psk = conf->wpa_psk_radius == PSK_RADIUS_DURING_4WAY_HS;
wconf->no_disconnect_on_group_keyerror =
conf->bss_max_idle && conf->ap_max_inactivity &&
conf->no_disconnect_on_group_keyerror;
wconf->rsn_override_omit_rsnxe = conf->rsn_override_omit_rsnxe;
}
@ -1533,54 +1586,12 @@ static int hostapd_set_ltf_keyseed(void *ctx, const u8 *peer_addr,
#ifdef CONFIG_IEEE80211BE
static int hostapd_wpa_auth_get_ml_rsn_info(void *ctx,
struct wpa_auth_ml_rsn_info *info)
{
struct hostapd_data *hapd = ctx;
unsigned int i, j;
wpa_printf(MSG_DEBUG, "WPA_AUTH: MLD: Get RSN info CB: n_mld_links=%u",
info->n_mld_links);
if (!hapd->conf->mld_ap || !hapd->iface || !hapd->iface->interfaces)
return -1;
for (i = 0; i < info->n_mld_links; i++) {
unsigned int link_id = info->links[i].link_id;
wpa_printf(MSG_DEBUG,
"WPA_AUTH: MLD: Get link RSN CB: link_id=%u",
link_id);
for (j = 0; j < hapd->iface->interfaces->count; j++) {
struct hostapd_iface *iface =
hapd->iface->interfaces->iface[j];
if (!iface->bss[0]->conf->mld_ap ||
hapd->conf->mld_id != iface->bss[0]->conf->mld_id ||
link_id != iface->bss[0]->mld_link_id ||
!iface->bss[0]->wpa_auth)
continue;
wpa_auth_ml_get_rsn_info(iface->bss[0]->wpa_auth,
&info->links[i]);
break;
}
if (j == hapd->iface->interfaces->count)
wpa_printf(MSG_DEBUG,
"WPA_AUTH: MLD: link=%u not found", link_id);
}
return 0;
}
static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
struct wpa_auth_ml_key_info *info)
struct wpa_auth_ml_key_info *info,
bool rekey)
{
struct hostapd_data *hapd = ctx;
unsigned int i, j;
unsigned int i;
wpa_printf(MSG_DEBUG, "WPA_AUTH: MLD: Get key info CB: n_mld_links=%u",
info->n_mld_links);
@ -1589,30 +1600,37 @@ static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
return -1;
for (i = 0; i < info->n_mld_links; i++) {
struct hostapd_data *bss;
u8 link_id = info->links[i].link_id;
bool link_bss_found = false;
wpa_printf(MSG_DEBUG,
"WPA_AUTH: MLD: Get link info CB: link_id=%u",
link_id);
for (j = 0; j < hapd->iface->interfaces->count; j++) {
struct hostapd_iface *iface =
hapd->iface->interfaces->iface[j];
if (!iface->bss[0]->conf->mld_ap ||
hapd->conf->mld_id != iface->bss[0]->conf->mld_id ||
link_id != iface->bss[0]->mld_link_id ||
!iface->bss[0]->wpa_auth)
continue;
wpa_auth_ml_get_key_info(iface->bss[0]->wpa_auth,
if (hapd->mld_link_id == link_id) {
wpa_auth_ml_get_key_info(hapd->wpa_auth,
&info->links[i],
info->mgmt_frame_prot,
info->beacon_prot);
info->beacon_prot,
rekey);
continue;
}
for_each_mld_link(bss, hapd) {
if (bss == hapd || bss->mld_link_id != link_id)
continue;
wpa_auth_ml_get_key_info(bss->wpa_auth,
&info->links[i],
info->mgmt_frame_prot,
info->beacon_prot,
rekey);
link_bss_found = true;
break;
}
if (j == hapd->iface->interfaces->count)
if (!link_bss_found)
wpa_printf(MSG_DEBUG,
"WPA_AUTH: MLD: link=%u not found", link_id);
}
@ -1688,7 +1706,6 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
.set_ltf_keyseed = hostapd_set_ltf_keyseed,
#endif /* CONFIG_PASN */
#ifdef CONFIG_IEEE80211BE
.get_ml_rsn_info = hostapd_wpa_auth_get_ml_rsn_info,
.get_ml_key_info = hostapd_wpa_auth_get_ml_key_info,
#endif /* CONFIG_IEEE80211BE */
.get_drv_flags = hostapd_wpa_auth_get_drv_flags,
@ -1739,6 +1756,27 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
!!(hapd->iface->drv_flags2 &
WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP);
#ifdef CONFIG_IEEE80211BE
_conf.mld_addr = NULL;
_conf.link_id = -1;
_conf.first_link_auth = NULL;
if (hapd->conf->mld_ap) {
struct hostapd_data *lhapd;
_conf.mld_addr = hapd->mld->mld_addr;
_conf.link_id = hapd->mld_link_id;
for_each_mld_link(lhapd, hapd) {
if (lhapd == hapd)
continue;
if (lhapd->wpa_auth)
_conf.first_link_auth = lhapd->wpa_auth;
}
}
#endif /* CONFIG_IEEE80211BE */
hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd);
if (hapd->wpa_auth == NULL) {
wpa_printf(MSG_ERROR, "WPA initialization failed.");

View file

@ -111,6 +111,8 @@ struct wpa_state_machine {
size_t wpa_ie_len;
u8 *rsnxe;
size_t rsnxe_len;
u8 *rsn_selection;
size_t rsn_selection_len;
enum {
WPA_VERSION_NO_WPA = 0 /* WPA not used */,
@ -124,6 +126,9 @@ struct wpa_state_machine {
u32 dot11RSNAStatsTKIPLocalMICFailures;
u32 dot11RSNAStatsTKIPRemoteMICFailures;
bool rsn_override;
bool rsn_override_2;
#ifdef CONFIG_IEEE80211R_AP
u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the
* first 384 bits of MSK */
@ -136,7 +141,7 @@ struct wpa_state_machine {
size_t r0kh_id_len;
u8 *assoc_resp_ftie;
void (*ft_pending_cb)(void *ctx, const u8 *dst, const u8 *bssid,
void (*ft_pending_cb)(void *ctx, const u8 *dst,
u16 auth_transaction, u16 status,
const u8 *ies, size_t ies_len);
void *ft_pending_cb_ctx;
@ -172,7 +177,6 @@ struct wpa_state_machine {
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_IEEE80211BE
u8 own_mld_addr[ETH_ALEN];
u8 peer_mld_addr[ETH_ALEN];
s8 mld_assoc_link_id;
u8 n_mld_affiliated_links;
@ -180,14 +184,12 @@ struct wpa_state_machine {
struct mld_link {
bool valid;
u8 peer_addr[ETH_ALEN];
u8 own_addr[ETH_ALEN];
const u8 *rsne;
size_t rsne_len;
const u8 *rsnxe;
size_t rsnxe_len;
struct wpa_authenticator *wpa_auth;
} mld_links[MAX_NUM_MLD_LINKS];
#endif /* CONFIG_IEEE80211BE */
bool ssid_protection;
};
@ -262,6 +264,13 @@ struct wpa_authenticator {
#ifdef CONFIG_P2P
struct bitfield *ip_pool;
#endif /* CONFIG_P2P */
#ifdef CONFIG_IEEE80211BE
bool is_ml;
u8 mld_addr[ETH_ALEN];
u8 link_id;
bool primary_auth;
#endif /* CONFIG_IEEE80211BE */
};

View file

@ -89,7 +89,8 @@ static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
}
static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf)
static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf,
enum mfp_options mfp)
{
u16 capab = 0;
@ -99,9 +100,9 @@ static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf)
/* 4 PTKSA replay counters when using WMM */
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
}
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
if (mfp != NO_MGMT_FRAME_PROTECTION) {
capab |= WPA_CAPABILITY_MFPC;
if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
if (mfp == MGMT_FRAME_PROTECTION_REQUIRED)
capab |= WPA_CAPABILITY_MFPR;
}
#ifdef CONFIG_OCV
@ -119,24 +120,19 @@ static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf)
}
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
const u8 *pmkid)
static u8 * rsne_write_data(u8 *buf, size_t len, u8 *pos, int group,
int pairwise, int key_mgmt, u16 rsn_capab,
const u8 *pmkid, enum mfp_options mfp,
int group_mgmt_cipher)
{
struct rsn_ie_hdr *hdr;
int num_suites, res;
u8 *pos, *count;
u8 *count;
u32 suite;
hdr = (struct rsn_ie_hdr *) buf;
hdr->elem_id = WLAN_EID_RSN;
WPA_PUT_LE16(hdr->version, RSN_VERSION);
pos = (u8 *) (hdr + 1);
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group);
if (suite == 0) {
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
conf->wpa_group);
return -1;
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", group);
return NULL;
}
RSN_SELECTOR_PUT(pos, suite);
pos += RSN_SELECTOR_LEN;
@ -153,7 +149,7 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
}
#endif /* CONFIG_RSN_TESTING */
res = rsn_cipher_put_suites(pos, conf->rsn_pairwise);
res = rsn_cipher_put_suites(pos, pairwise);
num_suites += res;
pos += res * RSN_SELECTOR_LEN;
@ -167,8 +163,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
if (num_suites == 0) {
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
conf->rsn_pairwise);
return -1;
pairwise);
return NULL;
}
WPA_PUT_LE16(count, num_suites);
@ -184,102 +180,102 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
}
#endif /* CONFIG_RSN_TESTING */
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
if (key_mgmt & WPA_KEY_MGMT_PSK) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#ifdef CONFIG_IEEE80211R_AP
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#ifdef CONFIG_SHA384
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_SHA384 */
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
if (key_mgmt & WPA_KEY_MGMT_FT_PSK) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_SHA384
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA384);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_SHA384 */
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#ifdef CONFIG_SAE
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
if (key_mgmt & WPA_KEY_MGMT_SAE) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
if (key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE_EXT_KEY);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
if (key_mgmt & WPA_KEY_MGMT_FT_SAE) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
if (key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_SAE */
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#ifdef CONFIG_FILS
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
if (key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA256);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
if (key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA384);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#ifdef CONFIG_IEEE80211R_AP
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384);
pos += RSN_SELECTOR_LEN;
num_suites++;
@ -287,28 +283,28 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
#endif /* CONFIG_IEEE80211R_AP */
#endif /* CONFIG_FILS */
#ifdef CONFIG_OWE
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) {
if (key_mgmt & WPA_KEY_MGMT_OWE) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_OWE */
#ifdef CONFIG_DPP
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) {
if (key_mgmt & WPA_KEY_MGMT_DPP) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_DPP */
#ifdef CONFIG_HS20
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_OSEN) {
if (key_mgmt & WPA_KEY_MGMT_OSEN) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_HS20 */
#ifdef CONFIG_PASN
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PASN) {
if (key_mgmt & WPA_KEY_MGMT_PASN) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PASN);
pos += RSN_SELECTOR_LEN;
num_suites++;
@ -325,18 +321,18 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
if (num_suites == 0) {
wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
conf->wpa_key_mgmt);
return -1;
key_mgmt);
return NULL;
}
WPA_PUT_LE16(count, num_suites);
/* RSN Capabilities */
WPA_PUT_LE16(pos, wpa_own_rsn_capab(conf));
WPA_PUT_LE16(pos, rsn_capab);
pos += 2;
if (pmkid) {
if (2 + PMKID_LEN > buf + len - pos)
return -1;
return NULL;
/* PMKID Count */
WPA_PUT_LE16(pos, 1);
pos += 2;
@ -344,18 +340,19 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
pos += PMKID_LEN;
}
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
conf->group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) {
if (mfp != NO_MGMT_FRAME_PROTECTION &&
group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) {
if (2 + 4 > buf + len - pos)
return -1;
if (pmkid == NULL) {
return NULL;
if (!pmkid) {
/* PMKID Count */
WPA_PUT_LE16(pos, 0);
pos += 2;
}
/* Management Group Cipher Suite */
switch (conf->group_mgmt_cipher) {
switch (group_mgmt_cipher) {
case WPA_CIPHER_AES_128_CMAC:
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
break;
@ -371,8 +368,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
default:
wpa_printf(MSG_DEBUG,
"Invalid group management cipher (0x%x)",
conf->group_mgmt_cipher);
return -1;
group_mgmt_cipher);
return NULL;
}
pos += RSN_SELECTOR_LEN;
}
@ -384,12 +381,12 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
* the element.
*/
int pmkid_count_set = pmkid != NULL;
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
if (mfp != NO_MGMT_FRAME_PROTECTION)
pmkid_count_set = 1;
/* PMKID Count */
WPA_PUT_LE16(pos, 0);
pos += 2;
if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
if (mfp == NO_MGMT_FRAME_PROTECTION) {
/* Management Group Cipher Suite */
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
pos += RSN_SELECTOR_LEN;
@ -399,6 +396,27 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
pos += 17;
}
#endif /* CONFIG_RSN_TESTING */
return pos;
}
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
const u8 *pmkid)
{
struct rsn_ie_hdr *hdr;
u8 *pos;
hdr = (struct rsn_ie_hdr *) buf;
hdr->elem_id = WLAN_EID_RSN;
WPA_PUT_LE16(hdr->version, RSN_VERSION);
pos = (u8 *) (hdr + 1);
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
conf->rsn_pairwise, conf->wpa_key_mgmt,
wpa_own_rsn_capab(conf, conf->ieee80211w), pmkid,
conf->ieee80211w, conf->group_mgmt_cipher);
if (!pos)
return -1;
hdr->len = (pos - buf) - 2;
@ -406,16 +424,74 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
}
int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
static int wpa_write_rsne_override(struct wpa_auth_config *conf, u8 *buf,
size_t len)
{
u8 *pos = buf;
u16 capab = 0;
size_t flen;
u8 *pos, *len_pos;
if (wpa_key_mgmt_sae(conf->wpa_key_mgmt) &&
pos = buf;
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
len_pos = pos++;
WPA_PUT_BE32(pos, RSNE_OVERRIDE_IE_VENDOR_TYPE);
pos += 4;
WPA_PUT_LE16(pos, RSN_VERSION);
pos += 2;
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
conf->rsn_override_pairwise,
conf->rsn_override_key_mgmt,
wpa_own_rsn_capab(conf, conf->rsn_override_mfp),
NULL, conf->rsn_override_mfp,
conf->group_mgmt_cipher);
if (!pos)
return -1;
*len_pos = (pos - buf) - 2;
return pos - buf;
}
static int wpa_write_rsne_override_2(struct wpa_auth_config *conf, u8 *buf,
size_t len)
{
u8 *pos, *len_pos;
pos = buf;
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
len_pos = pos++;
WPA_PUT_BE32(pos, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
pos += 4;
WPA_PUT_LE16(pos, RSN_VERSION);
pos += 2;
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
conf->rsn_override_pairwise_2,
conf->rsn_override_key_mgmt_2,
wpa_own_rsn_capab(conf, conf->rsn_override_mfp_2),
NULL, conf->rsn_override_mfp_2,
conf->group_mgmt_cipher);
if (!pos)
return -1;
*len_pos = (pos - buf) - 2;
return pos - buf;
}
static u32 rsnxe_capab(struct wpa_auth_config *conf, int key_mgmt)
{
u32 capab = 0;
if (wpa_key_mgmt_sae(key_mgmt) &&
(conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
conf->sae_pwe == SAE_PWE_BOTH || conf->sae_pk ||
wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt))) {
wpa_key_mgmt_sae_ext_key(key_mgmt))) {
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
#ifdef CONFIG_SAE_PK
if (conf->sae_pk)
@ -429,20 +505,75 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
if (conf->prot_range_neg)
capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
if (conf->ssid_protection)
capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
return capab;
}
int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
{
u8 *pos = buf;
u32 capab = 0, tmp;
size_t flen;
capab = rsnxe_capab(conf, conf->wpa_key_mgmt);
flen = (capab & 0xff00) ? 2 : 1;
if (!capab)
return 0; /* no supported extended RSN capabilities */
tmp = capab;
flen = 0;
while (tmp) {
flen++;
tmp >>= 8;
}
if (len < 2 + flen)
return -1;
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
*pos++ = WLAN_EID_RSNX;
*pos++ = flen;
*pos++ = capab & 0x00ff;
capab >>= 8;
if (capab)
*pos++ = capab;
while (capab) {
*pos++ = capab & 0xff;
capab >>= 8;
}
return pos - buf;
}
static int wpa_write_rsnxe_override(struct wpa_auth_config *conf, u8 *buf,
size_t len)
{
u8 *pos = buf;
u32 capab, tmp;
size_t flen;
capab = rsnxe_capab(conf, conf->rsn_override_key_mgmt |
conf->rsn_override_key_mgmt_2);
if (!capab)
return 0; /* no supported extended RSN capabilities */
tmp = capab;
flen = 0;
while (tmp) {
flen++;
tmp >>= 8;
}
if (len < 2 + flen)
return -1;
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 4 + flen;
WPA_PUT_BE32(pos, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
pos += 4;
while (capab) {
*pos++ = capab & 0xff;
capab >>= 8;
}
return pos - buf;
}
@ -501,7 +632,7 @@ static u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid)
int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
{
u8 *pos, buf[128];
u8 *pos, buf[1500];
int res;
#ifdef CONFIG_TESTING_OPTIONS
@ -527,17 +658,54 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
pos = wpa_write_osen(&wpa_auth->conf, pos);
}
if (wpa_auth->conf.wpa & WPA_PROTO_RSN) {
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_auth->conf.rsne_override_set) {
wpa_hexdump(MSG_DEBUG,
"RSN: Forced own RSNE for testing",
wpa_auth->conf.rsne_override,
wpa_auth->conf.rsne_override_len);
if (sizeof(buf) - (pos - buf) <
wpa_auth->conf.rsne_override_len)
return -1;
os_memcpy(pos, wpa_auth->conf.rsne_override,
wpa_auth->conf.rsne_override_len);
pos += wpa_auth->conf.rsne_override_len;
goto rsnxe;
}
#endif /* CONFIG_TESTING_OPTIONS */
res = wpa_write_rsn_ie(&wpa_auth->conf,
pos, buf + sizeof(buf) - pos, NULL);
if (res < 0)
return res;
pos += res;
res = wpa_write_rsnxe(&wpa_auth->conf, pos,
buf + sizeof(buf) - pos);
#ifdef CONFIG_TESTING_OPTIONS
rsnxe:
if (wpa_auth->conf.rsnxe_override_set) {
wpa_hexdump(MSG_DEBUG,
"RSN: Forced own RSNXE for testing",
wpa_auth->conf.rsnxe_override,
wpa_auth->conf.rsnxe_override_len);
if (sizeof(buf) - (pos - buf) <
wpa_auth->conf.rsnxe_override_len)
return -1;
os_memcpy(pos, wpa_auth->conf.rsnxe_override,
wpa_auth->conf.rsnxe_override_len);
pos += wpa_auth->conf.rsnxe_override_len;
goto fte;
}
#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_auth->conf.rsn_override_omit_rsnxe)
res = 0;
else
res = wpa_write_rsnxe(&wpa_auth->conf, pos,
buf + sizeof(buf) - pos);
if (res < 0)
return res;
pos += res;
}
#ifdef CONFIG_TESTING_OPTIONS
fte:
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
res = wpa_write_mdie(&wpa_auth->conf, pos,
@ -554,7 +722,87 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
return res;
pos += res;
}
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
wpa_auth->conf.rsn_override_key_mgmt) {
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_auth->conf.rsnoe_override_set) {
wpa_hexdump(MSG_DEBUG,
"RSN: Forced own RSNOE for testing",
wpa_auth->conf.rsnoe_override,
wpa_auth->conf.rsnoe_override_len);
if (sizeof(buf) - (pos - buf) <
wpa_auth->conf.rsnoe_override_len)
return -1;
os_memcpy(pos, wpa_auth->conf.rsnoe_override,
wpa_auth->conf.rsnoe_override_len);
pos += wpa_auth->conf.rsnoe_override_len;
goto rsno2e;
}
#endif /* CONFIG_TESTING_OPTIONS */
res = wpa_write_rsne_override(&wpa_auth->conf,
pos, buf + sizeof(buf) - pos);
if (res < 0)
return res;
pos += res;
}
#ifdef CONFIG_TESTING_OPTIONS
rsno2e:
#endif /* CONFIG_TESTING_OPTIONS */
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
wpa_auth->conf.rsn_override_key_mgmt_2) {
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_auth->conf.rsno2e_override_set) {
wpa_hexdump(MSG_DEBUG,
"RSN: Forced own RSNO2E for testing",
wpa_auth->conf.rsno2e_override,
wpa_auth->conf.rsno2e_override_len);
if (sizeof(buf) - (pos - buf) <
wpa_auth->conf.rsno2e_override_len)
return -1;
os_memcpy(pos, wpa_auth->conf.rsno2e_override,
wpa_auth->conf.rsno2e_override_len);
pos += wpa_auth->conf.rsno2e_override_len;
goto rsnxoe;
}
#endif /* CONFIG_TESTING_OPTIONS */
res = wpa_write_rsne_override_2(&wpa_auth->conf, pos,
buf + sizeof(buf) - pos);
if (res < 0)
return res;
pos += res;
}
#ifdef CONFIG_TESTING_OPTIONS
rsnxoe:
#endif /* CONFIG_TESTING_OPTIONS */
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
(wpa_auth->conf.rsn_override_key_mgmt ||
wpa_auth->conf.rsn_override_key_mgmt_2)) {
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_auth->conf.rsnxoe_override_set) {
wpa_hexdump(MSG_DEBUG,
"RSN: Forced own RSNXOE for testing",
wpa_auth->conf.rsnxoe_override,
wpa_auth->conf.rsnxoe_override_len);
if (sizeof(buf) - (pos - buf) <
wpa_auth->conf.rsnxoe_override_len)
return -1;
os_memcpy(pos, wpa_auth->conf.rsnxoe_override,
wpa_auth->conf.rsnxoe_override_len);
pos += wpa_auth->conf.rsnxoe_override_len;
goto done;
}
#endif /* CONFIG_TESTING_OPTIONS */
res = wpa_write_rsnxe_override(&wpa_auth->conf, pos,
buf + sizeof(buf) - pos);
if (res < 0)
return res;
pos += res;
}
#ifdef CONFIG_TESTING_OPTIONS
done:
#endif /* CONFIG_TESTING_OPTIONS */
wpa_hexdump(MSG_DEBUG, "RSN: Own IEs", buf, pos - buf);
os_free(wpa_auth->wpa_ie);
wpa_auth->wpa_ie = os_malloc(pos - buf);
if (wpa_auth->wpa_ie == NULL)
@ -608,7 +856,8 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
const u8 *wpa_ie, size_t wpa_ie_len,
const u8 *rsnxe, size_t rsnxe_len,
const u8 *mdie, size_t mdie_len,
const u8 *owe_dh, size_t owe_dh_len)
const u8 *owe_dh, size_t owe_dh_len,
struct wpa_state_machine *assoc_sm)
{
struct wpa_auth_config *conf = &wpa_auth->conf;
struct wpa_ie_data data;
@ -765,7 +1014,13 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
return WPA_INVALID_GROUP;
}
key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
if (sm->rsn_override_2)
key_mgmt = data.key_mgmt &
wpa_auth->conf.rsn_override_key_mgmt_2;
else if (sm->rsn_override)
key_mgmt = data.key_mgmt & wpa_auth->conf.rsn_override_key_mgmt;
else
key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
if (!key_mgmt) {
wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
MACSTR, data.key_mgmt, MAC2STR(sm->addr));
@ -834,7 +1089,13 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
else
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
if (version == WPA_PROTO_RSN)
if (version == WPA_PROTO_RSN && sm->rsn_override_2)
ciphers = data.pairwise_cipher &
wpa_auth->conf.rsn_override_pairwise_2;
else if (version == WPA_PROTO_RSN && sm->rsn_override)
ciphers = data.pairwise_cipher &
wpa_auth->conf.rsn_override_pairwise;
else if (version == WPA_PROTO_RSN)
ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise;
else
ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
@ -956,6 +1217,15 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
else
sm->wpa = WPA_VERSION_WPA;
if (assoc_sm) {
/* For ML association link STA cannot choose a different
* AKM or pairwise cipher from association STA */
if (sm->wpa_key_mgmt != assoc_sm->wpa_key_mgmt)
return WPA_INVALID_AKMP;
if (sm->pairwise != assoc_sm->pairwise)
return WPA_INVALID_PAIRWISE;
}
#if defined(CONFIG_IEEE80211R_AP) && defined(CONFIG_FILS)
if ((sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA256 ||
sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA384) &&
@ -1212,7 +1482,7 @@ bool wpa_auth_write_fd_rsn_info(struct wpa_authenticator *wpa_auth,
return false;
/* RSN Capability (B0..B15) */
WPA_PUT_LE16(pos, wpa_own_rsn_capab(conf));
WPA_PUT_LE16(pos, wpa_own_rsn_capab(conf, conf->ieee80211w));
pos += 2;
/* Group Data Cipher Suite Selector (B16..B21) */

View file

@ -80,16 +80,19 @@ endif
_DIRS := $(BUILDDIR)/$(PROJ)
.PHONY: _make_dirs
_make_dirs:
@mkdir -p $(_DIRS)
@mkdir -p $(sort $(_DIRS))
$(BUILDDIR)/$(PROJ)/src/%.o: $(ROOTDIR)src/%.c $(CONFIG_FILE) | _make_dirs
@echo $(CURDIR): '$(CC) -c -o $@ $(CFLAGS) $<' >$@.cmd
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
@$(E) " CC " $<
$(BUILDDIR)/$(PROJ)/%.o: %.c $(CONFIG_FILE) | _make_dirs
@echo $(CURDIR): '$(CC) -c -o $@ $(CFLAGS) $<' >$@.cmd
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
@$(E) " CC " $<
# for the fuzzing tests
$(BUILDDIR)/$(PROJ)/wpa_supplicant/%.o: $(ROOTDIR)wpa_supplicant/%.c $(CONFIG_FILE) | _make_dirs
@echo $(CURDIR): '$(CC) -c -o $@ $(CFLAGS) $<' >$@.cmd
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
@$(E) " CC " $<

View file

@ -532,4 +532,9 @@ enum sae_pwe {
SAE_PWE_NOT_SET = 4,
};
#define USEC_80211_TU 1024
#define USEC_TO_TU(m) ((m) / USEC_80211_TU)
#define TU_TO_USEC(m) ((m) * USEC_80211_TU)
#endif /* DEFS_H */

View file

@ -1035,6 +1035,10 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
json_value_sep(json);
json_add_string(json, "pkcs10", csr);
}
#ifdef CONFIG_DPP3
json_value_sep(json);
json_add_int(json, "capabilities", DPP_ENROLLEE_CAPAB_SAE_PW_ID);
#endif /* CONFIG_DPP3 */
if (extra_name && extra_value && extra_name[0] && extra_value[0]) {
json_value_sep(json);
wpabuf_printf(json, "\"%s\":%s", extra_name, extra_value);
@ -1139,8 +1143,18 @@ int dpp_configuration_valid(const struct dpp_configuration *conf)
return 0;
if (dpp_akm_psk(conf->akm) && !conf->passphrase && !conf->psk_set)
return 0;
if (dpp_akm_psk(conf->akm) && conf->passphrase) {
size_t len = os_strlen(conf->passphrase);
if (len > 63 || len < 8)
return 0;
}
if (dpp_akm_sae(conf->akm) && !conf->passphrase)
return 0;
#ifdef CONFIG_DPP3
if (conf->idpass && (!conf->passphrase || !dpp_akm_sae(conf->akm)))
return 0;
#endif /* CONFIG_DPP3 */
return 1;
}
@ -1150,6 +1164,9 @@ void dpp_configuration_free(struct dpp_configuration *conf)
if (!conf)
return;
str_clear_free(conf->passphrase);
#ifdef CONFIG_DPP3
os_free(conf->idpass);
#endif /* CONFIG_DPP3 */
os_free(conf->group_id);
os_free(conf->csrattrs);
os_free(conf->extra_name);
@ -1228,14 +1245,28 @@ static int dpp_configuration_parse_helper(struct dpp_authentication *auth,
end = os_strchr(pos, ' ');
pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
pass_len /= 2;
if (pass_len > 63 || pass_len < 8)
goto fail;
conf->passphrase = os_zalloc(pass_len + 1);
if (!conf->passphrase ||
hexstr2bin(pos, (u8 *) conf->passphrase, pass_len) < 0)
goto fail;
}
#ifdef CONFIG_DPP3
pos = os_strstr(cmd, " idpass=");
if (pos) {
size_t idpass_len;
pos += 8;
end = os_strchr(pos, ' ');
idpass_len = end ? (size_t) (end - pos) : os_strlen(pos);
idpass_len /= 2;
conf->idpass = os_zalloc(idpass_len + 1);
if (!conf->idpass ||
hexstr2bin(pos, (u8 *) conf->idpass, idpass_len) < 0)
goto fail;
}
#endif /* CONFIG_DPP3 */
pos = os_strstr(cmd, " psk=");
if (pos) {
pos += 5;
@ -1595,6 +1626,13 @@ static void dpp_build_legacy_cred_params(struct wpabuf *buf,
if (conf->passphrase && os_strlen(conf->passphrase) < 64) {
json_add_string_escape(buf, "pass", conf->passphrase,
os_strlen(conf->passphrase));
#ifdef CONFIG_DPP3
if (conf->idpass) {
json_value_sep(buf);
json_add_string_escape(buf, "idpass", conf->idpass,
os_strlen(conf->idpass));
}
#endif /* CONFIG_DPP3 */
} else if (conf->psk_set) {
char psk[2 * sizeof(conf->psk) + 1];
@ -1917,6 +1955,16 @@ dpp_build_conf_obj_legacy(struct dpp_authentication *auth,
const char *akm_str;
size_t len = 1000;
#ifdef CONFIG_DPP3
if (conf->idpass &&
!(auth->enrollee_capabilities & DPP_ENROLLEE_CAPAB_SAE_PW_ID)) {
wpa_printf(MSG_DEBUG,
"DPP: Enrollee does not support SAE Password Identifier - cannot generate config object");
return NULL;
}
#endif /* CONFIG_DPP3 */
if (conf->extra_name && conf->extra_value)
len += 10 + os_strlen(conf->extra_name) +
os_strlen(conf->extra_value);
@ -2535,6 +2583,18 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
cont:
#endif /* CONFIG_DPP2 */
#ifdef CONFIG_DPP3
token = json_get_member(root, "capabilities");
if (token && token->type == JSON_NUMBER) {
wpa_printf(MSG_DEBUG, "DPP: capabilities = 0x%x",
token->number);
wpa_msg(auth->msg_ctx, MSG_INFO,
DPP_EVENT_ENROLLEE_CAPABILITY "%d",
token->number);
auth->enrollee_capabilities = token->number;
}
#endif /* CONFIG_DPP3 */
resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole,
cert_req);
@ -2558,13 +2618,25 @@ static int dpp_parse_cred_legacy(struct dpp_config_obj *conf,
if (pass && pass->type == JSON_STRING) {
size_t len = os_strlen(pass->string);
#ifdef CONFIG_DPP3
struct json_token *saepi = json_get_member(cred, "idpass");
#endif /* CONFIG_DPP3 */
wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase",
pass->string, len);
if (len < 8 || len > 63)
if (dpp_akm_psk(conf->akm) && (len < 8 || len > 63)) {
wpa_printf(MSG_DEBUG,
"DPP: Unexpected pass length %zu for a config object that includes PSK",
len);
return -1;
}
os_strlcpy(conf->passphrase, pass->string,
sizeof(conf->passphrase));
#ifdef CONFIG_DPP3
if (saepi && saepi->type == JSON_STRING)
os_strlcpy(conf->password_id, saepi->string,
sizeof(conf->password_id));
#endif /* CONFIG_DPP3 */
} else if (psk_hex && psk_hex->type == JSON_STRING) {
if (dpp_akm_sae(conf->akm) && !dpp_akm_psk(conf->akm)) {
wpa_printf(MSG_DEBUG,

View file

@ -134,6 +134,9 @@ enum dpp_connector_key {
#define DPP_MAX_SHARED_SECRET_LEN 66
#define DPP_CP_LEN 64
/* DPP Configuration Request - Enrollee Capabilities */
#define DPP_ENROLLEE_CAPAB_SAE_PW_ID BIT(0)
struct dpp_curve_params {
const char *name;
size_t hash_len;
@ -260,6 +263,7 @@ struct dpp_configuration {
/* For legacy configuration */
char *passphrase;
char *idpass;
u8 psk[32];
int psk_set;
@ -356,6 +360,9 @@ struct dpp_authentication {
u8 ssid_len;
int ssid_charset;
char passphrase[64];
#ifdef CONFIG_DPP3
char password_id[64];
#endif /* CONFIG_DPP3 */
u8 psk[PMK_LEN];
int psk_set;
enum dpp_akm akm;
@ -393,6 +400,7 @@ struct dpp_authentication {
char *e_name;
char *e_mud_url;
int *e_band_support;
unsigned int enrollee_capabilities;
#ifdef CONFIG_TESTING_OPTIONS
char *config_obj_override;
char *discovery_override;

View file

@ -381,6 +381,75 @@ int check_40mhz_2g4(struct hostapd_hw_modes *mode,
}
static void punct_update_legacy_bw_80(u8 bitmap, u8 pri_chan, u8 *seg0)
{
u8 first_chan = *seg0 - 6, sec_chan;
switch (bitmap) {
case 0x6:
*seg0 = 0;
return;
case 0x8:
case 0x4:
case 0x2:
case 0x1:
case 0xC:
case 0x3:
if (pri_chan < *seg0)
*seg0 -= 4;
else
*seg0 += 4;
break;
}
if (pri_chan < *seg0)
sec_chan = pri_chan + 4;
else
sec_chan = pri_chan - 4;
if (bitmap & BIT((sec_chan - first_chan) / 4))
*seg0 = 0;
}
static void punct_update_legacy_bw_160(u8 bitmap, u8 pri,
enum oper_chan_width *width, u8 *seg0)
{
if (pri < *seg0) {
*seg0 -= 8;
if (bitmap & 0x0F) {
*width = 0;
punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0);
}
} else {
*seg0 += 8;
if (bitmap & 0xF0) {
*width = 0;
punct_update_legacy_bw_80((bitmap & 0xF0) >> 4, pri,
seg0);
}
}
}
void punct_update_legacy_bw(u16 bitmap, u8 pri, enum oper_chan_width *width,
u8 *seg0, u8 *seg1)
{
if (*width == CONF_OPER_CHWIDTH_80MHZ && (bitmap & 0xF)) {
*width = CONF_OPER_CHWIDTH_USE_HT;
punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0);
}
if (*width == CONF_OPER_CHWIDTH_160MHZ && (bitmap & 0xFF)) {
*width = CONF_OPER_CHWIDTH_80MHZ;
*seg1 = 0;
punct_update_legacy_bw_160(bitmap & 0xFF, pri, width, seg0);
}
/* TODO: 320 MHz */
}
int hostapd_set_freq_params(struct hostapd_freq_params *data,
enum hostapd_hw_mode mode,
int freq, int channel, int enable_edmg,
@ -391,8 +460,12 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
int center_segment0,
int center_segment1, u32 vht_caps,
struct he_capabilities *he_cap,
struct eht_capabilities *eht_cap)
struct eht_capabilities *eht_cap,
u16 punct_bitmap)
{
enum oper_chan_width oper_chwidth_legacy;
u8 seg0_legacy, seg1_legacy;
if (!he_cap || !he_cap->he_supported)
he_enabled = 0;
if (!eht_cap || !eht_cap->eht_supported)
@ -578,6 +651,14 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
break;
}
oper_chwidth_legacy = oper_chwidth;
seg0_legacy = center_segment0;
seg1_legacy = center_segment1;
if (punct_bitmap)
punct_update_legacy_bw(punct_bitmap, channel,
&oper_chwidth_legacy,
&seg0_legacy, &seg1_legacy);
if (data->eht_enabled || data->he_enabled ||
data->vht_enabled) switch (oper_chwidth) {
case CONF_OPER_CHWIDTH_USE_HT:
@ -602,7 +683,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
/* fall through */
case CONF_OPER_CHWIDTH_80MHZ:
data->bandwidth = 80;
if (!sec_channel_offset) {
if (!sec_channel_offset &&
oper_chwidth_legacy != CONF_OPER_CHWIDTH_USE_HT) {
wpa_printf(MSG_ERROR,
"80/80+80 MHz: no second channel offset");
return -1;
@ -660,7 +742,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
"160 MHz: center segment 1 should not be set");
return -1;
}
if (!sec_channel_offset) {
if (!sec_channel_offset &&
oper_chwidth_legacy != CONF_OPER_CHWIDTH_USE_HT) {
wpa_printf(MSG_ERROR,
"160 MHz: second channel offset not set");
return -1;
@ -950,3 +1033,18 @@ bool is_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 punct_bitmap)
return false;
}
bool chan_in_current_hw_info(struct hostapd_multi_hw_info *current_hw_info,
struct hostapd_channel_data *chan)
{
/* Assuming that if current_hw_info is not set full
* iface->current_mode->channels[] can be used to scan for channels,
* hence we return true.
*/
if (!current_hw_info)
return true;
return current_hw_info->start_freq <= chan->freq &&
current_hw_info->end_freq >= chan->freq;
}

View file

@ -35,6 +35,8 @@ int check_40mhz_5g(struct wpa_scan_results *scan_res,
int check_40mhz_2g4(struct hostapd_hw_modes *mode,
struct wpa_scan_results *scan_res, int pri_chan,
int sec_chan);
void punct_update_legacy_bw(u16 bitmap, u8 pri_chan,
enum oper_chan_width *width, u8 *seg0, u8 *seg1);
int hostapd_set_freq_params(struct hostapd_freq_params *data,
enum hostapd_hw_mode mode,
int freq, int channel, int edmg, u8 edmg_channel,
@ -45,7 +47,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
int center_segment0,
int center_segment1, u32 vht_caps,
struct he_capabilities *he_caps,
struct eht_capabilities *eht_cap);
struct eht_capabilities *eht_cap,
u16 punct_bitmap);
void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps,
int disabled);
int ieee80211ac_cap_check(u32 hw, u32 conf);
@ -55,5 +58,7 @@ int chan_bw_allowed(const struct hostapd_channel_data *chan, u32 bw,
int ht40_plus, int pri);
int chan_pri_allowed(const struct hostapd_channel_data *chan);
bool is_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 punct_bitmap);
bool chan_in_current_hw_info(struct hostapd_multi_hw_info *current_hw_info,
struct hostapd_channel_data *chan);
#endif /* HW_FEATURES_COMMON_H */

View file

@ -140,6 +140,28 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
elems->sae_pk = pos + 4;
elems->sae_pk_len = elen - 4;
break;
case WFA_RSNE_OVERRIDE_OUI_TYPE:
elems->rsne_override = pos;
elems->rsne_override_len = elen;
break;
case WFA_RSNE_OVERRIDE_2_OUI_TYPE:
elems->rsne_override_2 = pos;
elems->rsne_override_2_len = elen;
break;
case WFA_RSN_SELECTION_OUI_TYPE:
if (elen < 4 + 1) {
wpa_printf(MSG_DEBUG,
"Too short RSN Selection element ignored");
return -1;
}
elems->rsn_selection = pos + 4;
elems->rsn_selection_len = elen - 4;
break;
case P2P2_OUI_TYPE:
/* Wi-Fi Alliance - P2P2 IE */
elems->p2p2_ie = pos;
elems->p2p2_ie_len = elen;
break;
default:
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
"information element ignored "
@ -607,6 +629,12 @@ static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len,
elems->rrm_enabled = pos;
elems->rrm_enabled_len = elen;
break;
case WLAN_EID_MULTIPLE_BSSID:
if (elen < 1)
break;
elems->mbssid = pos;
elems->mbssid_len = elen;
break;
case WLAN_EID_CAG_NUMBER:
elems->cag_number = pos;
elems->cag_number_len = elen;
@ -1487,8 +1515,6 @@ ieee80211_freq_to_channel_ext(unsigned int freq, int sec_channel,
*op_class = 126;
else if (sec_channel == -1)
*op_class = 127;
else if (freq <= 5805)
*op_class = 124;
else
*op_class = 125;
@ -2040,6 +2066,13 @@ int is_dfs_global_op_class(u8 op_class)
}
bool is_80plus_op_class(u8 op_class)
{
/* Operating classes with "80+" behavior indication in Table E-4 */
return op_class == 130 || op_class == 135;
}
static int is_11b(u8 rate)
{
return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
@ -2406,9 +2439,17 @@ const struct oper_class_map global_op_class[] = {
* channel center frequency index value, but it happens to be a 20 MHz
* channel and the channel number in the channel set would match the
* value in for the frequency center.
*
* Operating class value pair 128 and 130 is used to describe a 80+80
* MHz channel on the 5 GHz band. 130 is identified with "80+", so this
* is encoded with two octets 130 and 128. Similarly, operating class
* value pair 133 and 135 is used to describe a 80+80 MHz channel on
* the 6 GHz band (135 being the one with "80+" indication). All other
* operating classes listed here are used as 1-octet values.
*/
{ HOSTAPD_MODE_IEEE80211A, 128, 36, 177, 4, BW80, P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 129, 36, 177, 4, BW160, P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 130, 36, 177, 4, BW80P80, P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, P2P_SUPP },
@ -2416,6 +2457,9 @@ const struct oper_class_map global_op_class[] = {
{ HOSTAPD_MODE_IEEE80211A, 135, 1, 233, 16, BW80P80, NO_P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 136, 2, 2, 4, BW20, NO_P2P_SUPP },
/* IEEE P802.11be/D5.0, Table E-4 (Global operating classes) */
{ HOSTAPD_MODE_IEEE80211A, 137, 31, 191, 32, BW320, NO_P2P_SUPP },
/*
* IEEE Std 802.11ad-2012 and P802.ay/D5.0 60 GHz operating classes.
* Class 180 has the legacy channels 1-6. Classes 181-183 include
@ -2426,11 +2470,6 @@ const struct oper_class_map global_op_class[] = {
{ HOSTAPD_MODE_IEEE80211AD, 182, 17, 20, 1, BW6480, P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211AD, 183, 25, 27, 1, BW8640, P2P_SUPP },
/* Keep the operating class 130 as the last entry as a workaround for
* the OneHundredAndThirty Delimiter value used in the Supported
* Operating Classes element to indicate the end of the Operating
* Classes field. */
{ HOSTAPD_MODE_IEEE80211A, 130, 36, 177, 4, BW80P80, P2P_SUPP },
{ -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
};
@ -2558,21 +2597,141 @@ size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len)
}
size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value)
u16 check_multi_ap_ie(const u8 *multi_ap_ie, size_t multi_ap_len,
struct multi_ap_params *multi_ap)
{
const struct element *elem;
bool ext_present = false;
unsigned int vlan_id;
os_memset(multi_ap, 0, sizeof(*multi_ap));
/* Default profile is 1, when Multi-AP profile subelement is not
* present in the element. */
multi_ap->profile = 1;
for_each_element(elem, multi_ap_ie, multi_ap_len) {
u8 id = elem->id, elen = elem->datalen;
const u8 *pos = elem->data;
switch (id) {
case MULTI_AP_SUB_ELEM_TYPE:
if (elen >= 1) {
multi_ap->capability = *pos;
ext_present = true;
} else {
wpa_printf(MSG_DEBUG,
"Multi-AP invalid Multi-AP subelement");
return WLAN_STATUS_INVALID_IE;
}
break;
case MULTI_AP_PROFILE_SUB_ELEM_TYPE:
if (elen < 1) {
wpa_printf(MSG_DEBUG,
"Multi-AP IE invalid Multi-AP profile subelement");
return WLAN_STATUS_INVALID_IE;
}
multi_ap->profile = *pos;
if (multi_ap->profile > MULTI_AP_PROFILE_MAX) {
wpa_printf(MSG_DEBUG,
"Multi-AP IE with invalid profile 0x%02x",
multi_ap->profile);
return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
}
break;
case MULTI_AP_VLAN_SUB_ELEM_TYPE:
if (multi_ap->profile < MULTI_AP_PROFILE_2) {
wpa_printf(MSG_DEBUG,
"Multi-AP IE invalid profile to read VLAN IE");
return WLAN_STATUS_INVALID_IE;
}
if (elen < 2) {
wpa_printf(MSG_DEBUG,
"Multi-AP IE invalid Multi-AP VLAN subelement");
return WLAN_STATUS_INVALID_IE;
}
vlan_id = WPA_GET_LE16(pos);
if (vlan_id < 1 || vlan_id > 4094) {
wpa_printf(MSG_INFO,
"Multi-AP IE invalid Multi-AP VLAN ID %d",
vlan_id);
return WLAN_STATUS_INVALID_IE;
}
multi_ap->vlanid = vlan_id;
break;
default:
wpa_printf(MSG_DEBUG,
"Ignore unknown subelement %u in Multi-AP IE",
id);
break;
}
}
if (!for_each_element_completed(elem, multi_ap_ie, multi_ap_len)) {
wpa_printf(MSG_DEBUG, "Multi AP IE parse failed @%d",
(int) (multi_ap_ie + multi_ap_len -
(const u8 *) elem));
wpa_hexdump(MSG_MSGDUMP, "IEs", multi_ap_ie, multi_ap_len);
}
if (!ext_present) {
wpa_printf(MSG_DEBUG,
"Multi-AP element without Multi-AP Extension subelement");
return WLAN_STATUS_INVALID_IE;
}
return WLAN_STATUS_SUCCESS;
}
size_t add_multi_ap_ie(u8 *buf, size_t len,
const struct multi_ap_params *multi_ap)
{
u8 *pos = buf;
u8 *len_ptr;
if (len < 9)
if (len < 6)
return 0;
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 7; /* len */
len_ptr = pos; /* Length field to be set at the end */
pos++;
WPA_PUT_BE24(pos, OUI_WFA);
pos += 3;
*pos++ = MULTI_AP_OUI_TYPE;
/* Multi-AP Extension subelement */
if (buf + len - pos < 3)
return 0;
*pos++ = MULTI_AP_SUB_ELEM_TYPE;
*pos++ = 1; /* len */
*pos++ = value;
*pos++ = multi_ap->capability;
/* Add Multi-AP Profile subelement only for R2 or newer configuration */
if (multi_ap->profile >= MULTI_AP_PROFILE_2) {
if (buf + len - pos < 3)
return 0;
*pos++ = MULTI_AP_PROFILE_SUB_ELEM_TYPE;
*pos++ = 1;
*pos++ = multi_ap->profile;
}
/* Add Multi-AP Default 802.1Q Setting subelement only for backhaul BSS
*/
if (multi_ap->vlanid &&
multi_ap->profile >= MULTI_AP_PROFILE_2 &&
(multi_ap->capability & MULTI_AP_BACKHAUL_BSS)) {
if (buf + len - pos < 4)
return 0;
*pos++ = MULTI_AP_VLAN_SUB_ELEM_TYPE;
*pos++ = 2;
WPA_PUT_LE16(pos, multi_ap->vlanid);
pos += 2;
}
*len_ptr = pos - len_ptr - 1;
return pos - buf;
}
@ -2737,6 +2896,8 @@ int oper_class_bw_to_int(const struct oper_class_map *map)
case BW80P80:
case BW160:
return 160;
case BW320:
return 320;
case BW2160:
return 2160;
default:
@ -2984,8 +3145,12 @@ bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab)
{
return ieee802_11_rsnx_capab_len(rsnxe ? rsnxe + 2 : NULL,
rsnxe ? rsnxe[1] : 0, capab);
if (!rsnxe)
return false;
if (rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC && rsnxe[1] >= 4 + 1)
return ieee802_11_rsnx_capab_len(rsnxe + 2 + 4, rsnxe[1] - 4,
capab);
return ieee802_11_rsnx_capab_len(rsnxe + 2, rsnxe[1], capab);
}

View file

@ -30,6 +30,12 @@ struct mb_ies_info {
u8 nof_ies;
};
struct multi_ap_params {
u8 capability;
u8 profile;
u16 vlanid;
};
/* Parsed Information Elements */
struct ieee802_11_elems {
const u8 *ssid;
@ -59,6 +65,7 @@ struct ieee802_11_elems {
const u8 *vendor_ht_cap;
const u8 *vendor_vht;
const u8 *p2p;
const u8 *p2p2_ie;
const u8 *wfd;
const u8 *link_id;
const u8 *interworking;
@ -109,6 +116,10 @@ struct ieee802_11_elems {
const u8 *tdls_mle;
const u8 *prior_access_mle;
const u8 *mbssid_known_bss;
const u8 *mbssid;
const u8 *rsne_override;
const u8 *rsne_override_2;
const u8 *rsn_selection;
u8 ssid_len;
u8 supp_rates_len;
@ -129,6 +140,7 @@ struct ieee802_11_elems {
u8 vendor_ht_cap_len;
u8 vendor_vht_len;
u8 p2p_len;
u8 p2p2_ie_len;
u8 wfd_len;
u8 interworking_len;
u8 qos_map_set_len;
@ -171,6 +183,10 @@ struct ieee802_11_elems {
size_t tdls_mle_len;
size_t prior_access_mle_len;
u8 mbssid_known_bss_len;
u8 mbssid_len;
size_t rsne_override_len;
size_t rsne_override_2_len;
size_t rsn_selection_len;
struct mb_ies_info mb_ies;
@ -235,6 +251,7 @@ int ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth,
int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
u16 num_modes);
int is_dfs_global_op_class(u8 op_class);
bool is_80plus_op_class(u8 op_class);
enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht);
int supp_rates_11b_only(struct ieee802_11_elems *elems);
@ -253,7 +270,7 @@ struct oper_class_map {
u8 max_chan;
u8 inc;
enum { BW20, BW40PLUS, BW40MINUS, BW40, BW80, BW2160, BW160, BW80P80,
BW4320, BW6480, BW8640} bw;
BW320, BW4320, BW6480, BW8640} bw;
enum { P2P_SUPP, NO_P2P_SUPP } p2p;
};
@ -266,7 +283,10 @@ const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type);
size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len);
size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value);
u16 check_multi_ap_ie(const u8 *multi_ap_ie, size_t multi_ap_len,
struct multi_ap_params *multi_ap);
size_t add_multi_ap_ie(u8 *buf, size_t len,
const struct multi_ap_params *multi_ap);
struct country_op_class {
u8 country_op_class;

View file

@ -504,6 +504,7 @@
#define WLAN_EID_EXT_HE_MU_EDCA_PARAMS 38
#define WLAN_EID_EXT_SPATIAL_REUSE 39
#define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
#define WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME 52
#define WLAN_EID_EXT_OCV_OCI 54
#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
#define WLAN_EID_EXT_NON_INHERITANCE 56
@ -524,6 +525,7 @@
#define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
#define WLAN_EID_EXT_QOS_CHARACTERISTICS 113
#define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
#define WLAN_EID_EXT_BANDWIDTH_INDICATION 135
/* Extended Capabilities field */
#define WLAN_EXT_CAPAB_20_40_COEX 0
@ -616,6 +618,7 @@
#define WLAN_RSNX_CAPAB_SECURE_RTT 9
#define WLAN_RSNX_CAPAB_URNM_MFPR_X20 10
#define WLAN_RSNX_CAPAB_URNM_MFPR 15
#define WLAN_RSNX_CAPAB_SSID_PROTECTION 21
/* Multiple BSSID element subelements */
#define WLAN_MBSSID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
@ -1424,6 +1427,7 @@ struct ieee80211_ampe_ie {
#define WPS_IE_VENDOR_TYPE 0x0050f204
#define OUI_WFA 0x506f9a
#define P2P_IE_VENDOR_TYPE 0x506f9a09
#define P2P2_IE_VENDOR_TYPE 0x506f9a28
#define WFD_IE_VENDOR_TYPE 0x506f9a0a
#define WFD_OUI_TYPE 10
#define HS20_IE_VENDOR_TYPE 0x506f9a10
@ -1445,13 +1449,30 @@ struct ieee80211_ampe_ie {
#define QM_IE_OUI_TYPE 0x22
#define WFA_CAPA_IE_VENDOR_TYPE 0x506f9a23
#define WFA_CAPA_OUI_TYPE 0x23
#define WFA_RSNE_OVERRIDE_OUI_TYPE 0x29
#define WFA_RSNE_OVERRIDE_2_OUI_TYPE 0x2a
#define WFA_RSNXE_OVERRIDE_OUI_TYPE 0x2b
#define WFA_RSN_SELECTION_OUI_TYPE 0x2c
#define RSNE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a29
#define RSNE_OVERRIDE_2_IE_VENDOR_TYPE 0x506f9a2a
#define RSNXE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a2b
#define RSN_SELECTION_IE_VENDOR_TYPE 0x506f9a2c
#define MULTI_AP_SUB_ELEM_TYPE 0x06
#define MULTI_AP_PROFILE_SUB_ELEM_TYPE 0x07
#define MULTI_AP_VLAN_SUB_ELEM_TYPE 0x08
#define MULTI_AP_PROFILE2_BACKHAUL_STA_DISALLOWED BIT(2)
#define MULTI_AP_PROFILE1_BACKHAUL_STA_DISALLOWED BIT(3)
#define MULTI_AP_TEAR_DOWN BIT(4)
#define MULTI_AP_FRONTHAUL_BSS BIT(5)
#define MULTI_AP_BACKHAUL_BSS BIT(6)
#define MULTI_AP_BACKHAUL_STA BIT(7)
#define MULTI_AP_PROFILE_1 1
#define MULTI_AP_PROFILE_2 2
#define MULTI_AP_PROFILE_MAX 6
#define WMM_OUI_TYPE 2
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1
@ -1700,6 +1721,7 @@ enum mbo_transition_reject_reason {
/* Wi-Fi Direct (P2P) */
#define P2P_OUI_TYPE 9
#define P2P2_OUI_TYPE 0x28
enum p2p_attr_id {
P2P_ATTR_STATUS = 0,
@ -1730,6 +1752,13 @@ enum p2p_attr_id {
P2P_ATTR_SESSION_ID = 26,
P2P_ATTR_FEATURE_CAPABILITY = 27,
P2P_ATTR_PERSISTENT_GROUP = 28,
P2P_ATTR_CAPABILITY_EXTENSION = 29,
P2P_ATTR_WLAN_AP_INFORMATION = 30,
P2P_ATTR_DEVICE_IDENTITY_KEY = 31,
P2P_ATTR_DEVICE_IDENTITY_RESOLUTION = 32,
P2P_ATTR_PAIRING_AND_BOOTSTRAPPING = 33,
P2P_ATTR_PASSWORD = 34,
P2P_ATTR_ACTION_FRAME_WRAPPER = 35,
P2P_ATTR_VENDOR_SPECIFIC = 221
};
@ -1754,6 +1783,31 @@ enum p2p_attr_id {
#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6)
#define P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION BIT(7)
/* P2P Capability Extension attribute - Capability info */
#define P2P_PCEA_LEN_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
#define P2P_PCEA_6GHZ BIT(4)
#define P2P_PCEA_REG_INFO BIT(5)
#define P2P_PCEA_DFS_OWNER BIT(6)
#define P2P_PCEA_CLI_REQ_CS BIT(7)
#define P2P_PCEA_PAIRING_CAPABLE BIT(8)
#define P2P_PCEA_PAIRING_SETUP_ENABLED BIT(9)
#define P2P_PCEA_PMK_CACHING BIT(10)
#define P2P_PCEA_PASN_TYPE BIT(11)
#define P2P_PCEA_TWT_POWER_MGMT BIT(12)
/* P2P Pairing Bootstrapping Method attribute - Bootstrapping Method */
#define P2P_PBMA_OPPORTUNISTIC BIT(0)
#define P2P_PBMA_PIN_CODE_DISPLAY BIT(1)
#define P2P_PBMA_PASSPHRASE_DISPLAY BIT(2)
#define P2P_PBMA_QR_DISPLAY BIT(3)
#define P2P_PBMA_NFC_TAG BIT(4)
#define P2P_PBMA_PIN_CODE_KEYPAD BIT(5)
#define P2P_PBMA_PASSPHRASE_KEYPAD BIT(6)
#define P2P_PBMA_QR_SCAN BIT(7)
#define P2P_PBMA_NFC_READER BIT(8)
#define P2P_PBMA_SERVICE_MANAGED BIT(14)
#define P2P_PBMA_HANDSHAKE_SKIP BIT(15)
/* P2PS Coordination Protocol Transport Bitmap */
#define P2PS_FEATURE_CAPAB_UDP_TRANSPORT BIT(0)
#define P2PS_FEATURE_CAPAB_MAC_TRANSPORT BIT(1)
@ -1785,6 +1839,7 @@ enum p2p_status_code {
P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10,
P2P_SC_FAIL_REJECTED_BY_USER = 11,
P2P_SC_SUCCESS_DEFERRED = 12,
P2P_SC_COMEBACK = 13,
};
enum p2p_role_indication {
@ -2853,6 +2908,33 @@ enum ieee80211_eht_ml_sub_elem {
EHT_ML_SUB_ELEM_FRAGMENT = 254,
};
/* IEEE P802.11be/D7.0, 9.4.2.329 (Bandwidth Indication element) defines the
* Bandwidth Indication Information field to have the same definition as the
* EHT Operation Information field in the EHT Operation element.
*/
struct ieee80211_bw_ind_info {
u8 control; /* B0..B2: Channel Width */
u8 ccfs0;
u8 ccfs1;
le16 disabled_chan_bitmap; /* 0 or 2 octets */
} STRUCT_PACKED;
/* Control subfield: Channel Width subfield; see Table 9-417e (Channel width,
* CCFS0, and CCFS1 subfields) in IEEE P802.11be/D7.0. */
#define BW_IND_CHANNEL_WIDTH_20MHZ EHT_OPER_CHANNEL_WIDTH_20MHZ
#define BW_IND_CHANNEL_WIDTH_40MHZ EHT_OPER_CHANNEL_WIDTH_40MHZ
#define BW_IND_CHANNEL_WIDTH_80MHZ EHT_OPER_CHANNEL_WIDTH_80MHZ
#define BW_IND_CHANNEL_WIDTH_160MHZ EHT_OPER_CHANNEL_WIDTH_160MHZ
#define BW_IND_CHANNEL_WIDTH_320MHZ EHT_OPER_CHANNEL_WIDTH_320MHZ
/* IEEE P802.11be/D7.0, 9.4.2.329 (Bandwidth Indication element) */
struct ieee80211_bw_ind_element {
u8 bw_ind_params; /* Bandwidth Indication Parameters */
struct ieee80211_bw_ind_info bw_ind_info; /* 3 or 5 octets */
} STRUCT_PACKED;
#define BW_IND_PARAMETER_DISABLED_SUBCHAN_BITMAP_PRESENT BIT(1)
/* IEEE P802.11ay/D4.0, 9.4.2.251 - EDMG Operation element */
#define EDMG_BSS_OPERATING_CHANNELS_OFFSET 6
#define EDMG_OPERATING_CHANNEL_WIDTH_OFFSET 7

View file

@ -58,10 +58,12 @@ struct nan_de_service {
struct os_reltime next_publish_state;
struct os_reltime next_publish_chan;
unsigned int next_publish_duration;
bool is_p2p;
};
struct nan_de {
u8 nmi[ETH_ALEN];
bool offload;
bool ap;
struct nan_callbacks cb;
@ -77,7 +79,7 @@ struct nan_de {
};
struct nan_de * nan_de_init(const u8 *nmi, bool ap,
struct nan_de * nan_de_init(const u8 *nmi, bool offload, bool ap,
const struct nan_callbacks *cb)
{
struct nan_de *de;
@ -87,6 +89,7 @@ struct nan_de * nan_de_init(const u8 *nmi, bool ap,
return NULL;
os_memcpy(de->nmi, nmi, ETH_ALEN);
de->offload = offload;
de->ap = ap;
os_memcpy(&de->cb, cb, sizeof(*cb));
@ -590,7 +593,7 @@ static void nan_de_timer(void *eloop_ctx, void *timeout_ctx)
if (srv_next >= 0 && (next == -1 || srv_next < next))
next = srv_next;
if (srv_next == 0 && !started &&
if (srv_next == 0 && !started && !de->offload &&
de->listen_freq == 0 && de->ext_listen_freq == 0 &&
de->tx_wait_end_freq == 0 &&
nan_de_next_multicast(de, srv, &now) == 0) {
@ -598,7 +601,7 @@ static void nan_de_timer(void *eloop_ctx, void *timeout_ctx)
nan_de_tx_multicast(de, srv, 0);
}
if (!started && de->cb.listen &&
if (!started && !de->offload && de->cb.listen &&
de->listen_freq == 0 && de->ext_listen_freq == 0 &&
de->tx_wait_end_freq == 0 &&
((srv->type == NAN_DE_PUBLISH &&
@ -774,6 +777,34 @@ static void nan_de_get_sdea(const u8 *buf, size_t len, u8 instance_id,
}
static void nan_de_process_elem_container(struct nan_de *de, const u8 *buf,
size_t len, const u8 *peer_addr,
unsigned int freq, bool p2p)
{
const u8 *elem;
u16 elem_len;
elem = nan_de_get_attr(buf, len, NAN_ATTR_ELEM_CONTAINER, 0);
if (!elem)
return;
elem++;
elem_len = WPA_GET_LE16(elem);
elem += 2;
/* Skip the attribute if there is not enough froom for an element. */
if (elem_len < 1 + 2)
return;
/* Skip Map ID */
elem++;
elem_len--;
if (p2p && de->cb.process_p2p_usd_elems)
de->cb.process_p2p_usd_elems(de->cb.ctx, elem, elem_len,
peer_addr, freq);
}
static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
const u8 *peer_addr, u8 instance_id,
u8 req_instance_id, u16 sdea_control,
@ -787,13 +818,13 @@ static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
nan_de_run_timer(de);
}
if (srv->subscribe.active && req_instance_id == 0) {
if (!de->offload && srv->subscribe.active && req_instance_id == 0) {
/* Active subscriber replies with a Subscribe message if it
* received a matching unsolicited Publish message. */
nan_de_tx_multicast(de, srv, instance_id);
}
if (!srv->subscribe.active && req_instance_id == 0) {
if (!de->offload && !srv->subscribe.active && req_instance_id == 0) {
/* Passive subscriber replies with a Follow-up message without
* Service Specific Info field if it received a matching
* unsolicited Publish message. */
@ -873,6 +904,9 @@ static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv,
return;
}
if (de->offload)
goto offload;
/* Reply with a solicited Publish message */
/* Service Descriptor attribute */
sda_len = NAN_SERVICE_ID_LEN + 1 + 1 + 1;
@ -939,6 +973,7 @@ static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv,
nan_de_pause_state(srv, peer_addr, instance_id);
offload:
if (!srv->publish.disable_events && de->cb.replied)
de->cb.replied(de->cb.ctx, srv->id, peer_addr, instance_id,
srv_proto_type, ssi, ssi_len);
@ -1094,6 +1129,8 @@ static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr,
wpa_hexdump(MSG_MSGDUMP, "NAN: ssi",
ssi, ssi_len);
}
nan_de_process_elem_container(de, buf, len, peer_addr,
freq, srv->is_p2p);
}
switch (type) {
@ -1196,10 +1233,23 @@ static int nan_de_derive_service_id(struct nan_de_service *srv)
}
const u8 * nan_de_get_service_id(struct nan_de *de, int id)
{
struct nan_de_service *srv;
if (id < 1 || id > NAN_DE_MAX_SERVICE)
return NULL;
srv = de->service[id - 1];
if (!srv)
return NULL;
return srv->service_id;
}
int nan_de_publish(struct nan_de *de, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi, const struct wpabuf *elems,
struct nan_publish_params *params)
struct nan_publish_params *params, bool p2p)
{
int publish_id;
struct nan_de_service *srv;
@ -1209,6 +1259,12 @@ int nan_de_publish(struct nan_de *de, const char *service_name,
return -1;
}
if (!params->unsolicited && !params->solicited) {
wpa_printf(MSG_INFO,
"NAN: Publish() - both unsolicited and solicited disabled is invalid");
return -1;
}
publish_id = nan_de_get_handle(de);
if (publish_id < 1)
return -1;
@ -1255,6 +1311,7 @@ int nan_de_publish(struct nan_de *de, const char *service_name,
wpa_printf(MSG_DEBUG, "NAN: Assigned new publish handle %d for %s",
publish_id, service_name);
srv->id = publish_id;
srv->is_p2p = p2p;
nan_de_add_srv(de, srv);
nan_de_run_timer(de);
return publish_id;
@ -1306,7 +1363,7 @@ int nan_de_update_publish(struct nan_de *de, int publish_id,
int nan_de_subscribe(struct nan_de *de, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi, const struct wpabuf *elems,
struct nan_subscribe_params *params)
struct nan_subscribe_params *params, bool p2p)
{
int subscribe_id;
struct nan_de_service *srv;
@ -1331,6 +1388,17 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name,
if (nan_de_derive_service_id(srv) < 0)
goto fail;
os_memcpy(&srv->subscribe, params, sizeof(*params));
if (params->freq_list) {
size_t len;
len = (int_array_len(params->freq_list) + 1) * sizeof(int);
srv->freq_list = os_memdup(params->freq_list, len);
if (!srv->freq_list)
goto fail;
}
srv->subscribe.freq_list = NULL;
srv->srv_proto_type = srv_proto_type;
if (ssi) {
srv->ssi = wpabuf_dup(ssi);
@ -1346,6 +1414,7 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name,
wpa_printf(MSG_DEBUG, "NAN: Assigned new subscribe handle %d for %s",
subscribe_id, service_name);
srv->id = subscribe_id;
srv->is_p2p = p2p;
nan_de_add_srv(de, srv);
nan_de_run_timer(de);
return subscribe_id;

View file

@ -53,9 +53,13 @@ struct nan_callbacks {
void (*receive)(void *ctx, int id, int peer_instance_id,
const u8 *ssi, size_t ssi_len,
const u8 *peer_addr);
void (*process_p2p_usd_elems)(void *ctx, const u8 *buf,
u16 buf_len, const u8 *peer_addr,
unsigned int freq);
};
struct nan_de * nan_de_init(const u8 *nmi, bool ap,
struct nan_de * nan_de_init(const u8 *nmi, bool offload, bool ap,
const struct nan_callbacks *cb);
void nan_de_flush(struct nan_de *de);
void nan_de_deinit(struct nan_de *de);
@ -68,6 +72,7 @@ void nan_de_tx_wait_ended(struct nan_de *de);
void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, unsigned int freq,
const u8 *buf, size_t len);
const u8 * nan_de_get_service_id(struct nan_de *de, int id);
struct nan_publish_params {
/* configuration_parameters */
@ -105,7 +110,7 @@ struct nan_publish_params {
int nan_de_publish(struct nan_de *de, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi, const struct wpabuf *elems,
struct nan_publish_params *params);
struct nan_publish_params *params, bool p2p);
void nan_de_cancel_publish(struct nan_de *de, int publish_id);
@ -124,6 +129,9 @@ struct nan_subscribe_params {
/* Selected frequency */
unsigned int freq;
/* Multi-channel frequencies (publishChannelList) */
const int *freq_list;
/* Query period in ms; 0 = use default */
unsigned int query_period;
};
@ -132,7 +140,7 @@ struct nan_subscribe_params {
int nan_de_subscribe(struct nan_de *de, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi, const struct wpabuf *elems,
struct nan_subscribe_params *params);
struct nan_subscribe_params *params, bool p2p);
void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id);

View file

@ -19,6 +19,8 @@ struct ptksa_cache {
unsigned int n_ptksa;
};
#ifdef CONFIG_PTKSA_CACHE
static void ptksa_cache_set_expiration(struct ptksa_cache *ptksa);
@ -342,3 +344,44 @@ struct ptksa_cache_entry * ptksa_cache_add(struct ptksa_cache *ptksa,
return entry;
}
#else /* CONFIG_PTKSA_CACHE */
struct ptksa_cache * ptksa_cache_init(void)
{
return (struct ptksa_cache *) 1;
}
void ptksa_cache_deinit(struct ptksa_cache *ptksa)
{
}
struct ptksa_cache_entry *
ptksa_cache_get(struct ptksa_cache *ptksa, const u8 *addr, u32 cipher)
{
return NULL;
}
int ptksa_cache_list(struct ptksa_cache *ptksa, char *buf, size_t len)
{
return -1;
}
struct ptksa_cache_entry *
ptksa_cache_add(struct ptksa_cache *ptksa, const u8 *own_addr, const u8 *addr,
u32 cipher, u32 life_time, const struct wpa_ptk *ptk,
void (*cb)(struct ptksa_cache_entry *e), void *ctx, u32 akmp)
{
return NULL;
}
void ptksa_cache_flush(struct ptksa_cache *ptksa, const u8 *addr, u32 cipher)
{
}
#endif /* CONFIG_PTKSA_CACHE */

View file

@ -29,7 +29,6 @@ struct ptksa_cache_entry {
u32 akmp;
};
#ifdef CONFIG_PTKSA_CACHE
struct ptksa_cache;
@ -48,41 +47,4 @@ struct ptksa_cache_entry * ptksa_cache_add(struct ptksa_cache *ptksa,
void *ctx, u32 akmp);
void ptksa_cache_flush(struct ptksa_cache *ptksa, const u8 *addr, u32 cipher);
#else /* CONFIG_PTKSA_CACHE */
static inline struct ptksa_cache * ptksa_cache_init(void)
{
return (struct ptksa_cache *) 1;
}
static inline void ptksa_cache_deinit(struct ptksa_cache *ptksa)
{
}
static inline struct ptksa_cache_entry *
ptksa_cache_get(struct ptksa_cache *ptksa, const u8 *addr, u32 cipher)
{
return NULL;
}
static inline int ptksa_cache_list(struct ptksa_cache *ptksa,
char *buf, size_t len)
{
return -1;
}
static inline struct ptksa_cache_entry *
ptksa_cache_add(struct ptksa_cache *ptksa, const u8 *own_addr, const u8 *addr,
u32 cipher, u32 life_time, const struct wpa_ptk *ptk,
void (*cb)(struct ptksa_cache_entry *e), void *ctx, u32 akmp)
{
return NULL;
}
static inline void ptksa_cache_flush(struct ptksa_cache *ptksa,
const u8 *addr, u32 cipher)
{
}
#endif /* CONFIG_PTKSA_CACHE */
#endif /* PTKSA_CACHE_H */

File diff suppressed because it is too large Load diff

View file

@ -2103,8 +2103,11 @@ static int sae_parse_rejected_groups(struct sae_data *sae,
wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
*pos, end - *pos);
if (!sae_is_rejected_groups_elem(*pos, end))
if (!sae_is_rejected_groups_elem(*pos, end)) {
wpabuf_free(sae->tmp->peer_rejected_groups);
sae->tmp->peer_rejected_groups = NULL;
return WLAN_STATUS_SUCCESS;
}
epos = *pos;
epos++; /* skip IE type */
@ -2113,6 +2116,12 @@ static int sae_parse_rejected_groups(struct sae_data *sae,
return WLAN_STATUS_UNSPECIFIED_FAILURE;
epos++; /* skip ext ID */
len--;
if (len & 1) {
wpa_printf(MSG_DEBUG,
"SAE: Invalid length of the Rejected Groups element payload: %u",
len);
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
wpabuf_free(sae->tmp->peer_rejected_groups);
sae->tmp->peer_rejected_groups = wpabuf_alloc(len);
@ -2196,6 +2205,9 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
res = sae_parse_rejected_groups(sae, &pos, end);
if (res != WLAN_STATUS_SUCCESS)
return res;
} else {
wpabuf_free(sae->tmp->peer_rejected_groups);
sae->tmp->peer_rejected_groups = NULL;
}
/* Optional Anti-Clogging Token Container element */

View file

@ -82,6 +82,8 @@ struct sae_temporary_data {
bool omit_pk_elem;
#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_SAE_PK */
struct os_reltime disabled_until;
};
struct sae_pt {

View file

@ -9,6 +9,6 @@
#define GIT_VERSION_STR_POSTFIX ""
#endif /* GIT_VERSION_STR_POSTFIX */
#define VERSION_STR "2.11-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
#define VERSION_STR "2.12-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
#endif /* VERSION_H */

View file

@ -1031,9 +1031,6 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
const u8 *end, *pos;
u8 link_id;
parse->ftie = ie;
parse->ftie_len = ie_len;
pos = opt;
end = ie + ie_len;
wpa_hexdump(MSG_DEBUG, "FT: Parse FTE subelements", pos, end - pos);
@ -1104,7 +1101,7 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
link_id = pos[2] & 0x0f;
wpa_printf(MSG_DEBUG, "FT: MLO GTK (Link ID %u)",
link_id);
if (link_id >= MAX_NUM_MLO_LINKS)
if (link_id >= MAX_NUM_MLD_LINKS)
break;
parse->valid_mlo_gtks |= BIT(link_id);
parse->mlo_gtk[link_id] = pos;
@ -1119,7 +1116,7 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
link_id = pos[2 + 6] & 0x0f;
wpa_printf(MSG_DEBUG, "FT: MLO IGTK (Link ID %u)",
link_id);
if (link_id >= MAX_NUM_MLO_LINKS)
if (link_id >= MAX_NUM_MLD_LINKS)
break;
parse->valid_mlo_igtks |= BIT(link_id);
parse->mlo_igtk[link_id] = pos;
@ -1134,7 +1131,7 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
link_id = pos[2 + 6] & 0x0f;
wpa_printf(MSG_DEBUG, "FT: MLO BIGTK (Link ID %u)",
link_id);
if (link_id >= MAX_NUM_MLO_LINKS)
if (link_id >= MAX_NUM_MLD_LINKS)
break;
parse->valid_mlo_bigtks |= BIT(link_id);
parse->mlo_bigtk[link_id] = pos;
@ -1339,6 +1336,11 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
}
if (res < 0)
goto fail;
/* FTE might be fragmented. If it is, the separate Fragment
* elements are included in MIC calculation as full elements. */
parse->ftie = fte;
parse->ftie_len = fte_len;
}
if (prot_ie_count == 0)
@ -1353,7 +1355,7 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
/* TODO: This count should be done based on all _requested_,
* not _accepted_ links. */
for (link_id = 0; link_id < MAX_NUM_MLO_LINKS; link_id++) {
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
if (parse->mlo_gtk[link_id]) {
if (parse->rsn)
prot_ie_count--;
@ -1888,6 +1890,14 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
data->has_group = 1;
data->key_mgmt = WPA_KEY_MGMT_OSEN;
data->proto = WPA_PROTO_OSEN;
} else if (rsn_ie_len >= 2 + 4 + 2 && rsn_ie[1] >= 4 + 2 &&
rsn_ie[1] == rsn_ie_len - 2 &&
(WPA_GET_BE32(&rsn_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE ||
WPA_GET_BE32(&rsn_ie[2]) ==
RSNE_OVERRIDE_2_IE_VENDOR_TYPE) &&
WPA_GET_LE16(&rsn_ie[2 + 4]) == RSN_VERSION) {
pos = rsn_ie + 2 + 4 + 2;
left = rsn_ie_len - 2 - 4 - 2;
} else {
const struct rsn_ie_hdr *hdr;
@ -3438,7 +3448,7 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
const u8 *p;
size_t left;
u8 link_id;
char title[50];
char title[100];
int ret;
if (len == 0)
@ -3551,7 +3561,7 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
selector == RSN_KEY_DATA_MLO_GTK) {
link_id = (p[0] & RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_MASK) >>
RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_SHIFT;
if (link_id >= MAX_NUM_MLO_LINKS)
if (link_id >= MAX_NUM_MLD_LINKS)
return 2;
ie->valid_mlo_gtks |= BIT(link_id);
@ -3569,7 +3579,7 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
selector == RSN_KEY_DATA_MLO_IGTK) {
link_id = (p[8] & RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_MASK) >>
RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_SHIFT;
if (link_id >= MAX_NUM_MLO_LINKS)
if (link_id >= MAX_NUM_MLD_LINKS)
return 2;
ie->valid_mlo_igtks |= BIT(link_id);
@ -3587,7 +3597,7 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
selector == RSN_KEY_DATA_MLO_BIGTK) {
link_id = (p[8] & RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_MASK) >>
RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_SHIFT;
if (link_id >= MAX_NUM_MLO_LINKS)
if (link_id >= MAX_NUM_MLD_LINKS)
return 2;
ie->valid_mlo_bigtks |= BIT(link_id);
@ -3605,7 +3615,7 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
selector == RSN_KEY_DATA_MLO_LINK) {
link_id = (p[0] & RSN_MLO_LINK_KDE_LI_LINK_ID_MASK) >>
RSN_MLO_LINK_KDE_LI_LINK_ID_SHIFT;
if (link_id >= MAX_NUM_MLO_LINKS)
if (link_id >= MAX_NUM_MLD_LINKS)
return 2;
ie->valid_mlo_links |= BIT(link_id);
@ -3619,6 +3629,57 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
return 0;
}
if (left >= 1 && selector == WFA_KEY_DATA_RSN_OVERRIDE_LINK) {
link_id = p[0];
if (link_id >= MAX_NUM_MLD_LINKS)
return 2;
ie->rsn_override_link[link_id] = p;
ie->rsn_override_link_len[link_id] = left;
ret = os_snprintf(title, sizeof(title),
"RSN: Link ID %u - RSN Override Link KDE in EAPOL-Key",
link_id);
if (!os_snprintf_error(sizeof(title), ret))
wpa_hexdump(MSG_DEBUG, title, pos, dlen);
return 0;
}
if (selector == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
ie->rsne_override = pos;
ie->rsne_override_len = dlen;
wpa_hexdump(MSG_DEBUG,
"RSN: RSNE Override element in EAPOL-Key",
ie->rsne_override, ie->rsne_override_len);
return 0;
}
if (selector == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
ie->rsne_override_2 = pos;
ie->rsne_override_2_len = dlen;
wpa_hexdump(MSG_DEBUG,
"RSN: RSNE Override 2 element in EAPOL-Key",
ie->rsne_override_2, ie->rsne_override_2_len);
return 0;
}
if (selector == RSNXE_OVERRIDE_IE_VENDOR_TYPE) {
ie->rsnxe_override = pos;
ie->rsnxe_override_len = dlen;
wpa_hexdump(MSG_DEBUG,
"RSN: RSNXE Override element in EAPOL-Key",
ie->rsnxe_override, ie->rsnxe_override_len);
return 0;
}
if (selector == RSN_SELECTION_IE_VENDOR_TYPE) {
ie->rsn_selection = p;
ie->rsn_selection_len = left;
wpa_hexdump(MSG_DEBUG,
"RSN: RSN Selection element in EAPOL-Key",
ie->rsn_selection, ie->rsn_selection_len);
return 0;
}
return 2;
}
@ -3743,6 +3804,11 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
ie->supp_oper_classes = pos + 2;
ie->supp_oper_classes_len = pos[1];
}
} else if (*pos == WLAN_EID_SSID) {
ie->ssid = pos + 2;
ie->ssid_len = pos[1];
wpa_hexdump_ascii(MSG_DEBUG, "RSN: SSID in EAPOL-Key",
ie->ssid, ie->ssid_len);
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
ret = wpa_parse_generic(pos, ie);
if (ret == 1) {
@ -4253,3 +4319,24 @@ int wpa_pasn_add_extra_ies(struct wpabuf *buf, const u8 *extra_ies, size_t len)
}
#endif /* CONFIG_PASN */
void rsn_set_snonce_cookie(u8 *snonce)
{
u8 *pos;
pos = snonce + WPA_NONCE_LEN - 6;
WPA_PUT_BE24(pos, OUI_WFA);
pos += 3;
WPA_PUT_BE24(pos, 0x000029);
}
bool rsn_is_snonce_cookie(const u8 *snonce)
{
const u8 *pos;
pos = snonce + WPA_NONCE_LEN - 6;
return WPA_GET_BE24(pos) == OUI_WFA &&
WPA_GET_BE24(pos + 3) == 0x000029;
}

View file

@ -9,12 +9,15 @@
#ifndef WPA_COMMON_H
#define WPA_COMMON_H
#include "common/defs.h"
/* IEEE 802.11i */
#define PMKID_LEN 16
#define PMK_LEN 32
#define PMK_LEN_SUITE_B_192 48
#define PMK_LEN_MAX 64
#define WPA_REPLAY_COUNTER_LEN 8
#define RSN_PN_LEN 6
#define WPA_NONCE_LEN 32
#define WPA_KEY_RSC_LEN 8
#define WPA_GMK_LEN 32
@ -141,6 +144,7 @@ WPA_CIPHER_BIP_CMAC_256)
#define WFA_KEY_DATA_IP_ADDR_ALLOC RSN_SELECTOR(0x50, 0x6f, 0x9a, 5)
#define WFA_KEY_DATA_TRANSITION_DISABLE RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x20)
#define WFA_KEY_DATA_DPP RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x21)
#define WFA_KEY_DATA_RSN_OVERRIDE_LINK RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x2d)
#define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
@ -336,52 +340,54 @@ struct rsn_ie_hdr {
} STRUCT_PACKED;
#define KDE_HDR_LEN (1 + 1 + RSN_SELECTOR_LEN)
struct rsn_error_kde {
be16 mui;
be16 error_type;
} STRUCT_PACKED;
#define WPA_IGTK_KDE_PREFIX_LEN (2 + 6)
#define WPA_IGTK_KDE_PREFIX_LEN (2 + RSN_PN_LEN)
struct wpa_igtk_kde {
u8 keyid[2];
u8 pn[6];
u8 pn[RSN_PN_LEN];
u8 igtk[WPA_IGTK_MAX_LEN];
} STRUCT_PACKED;
#define WPA_BIGTK_KDE_PREFIX_LEN (2 + 6)
#define WPA_BIGTK_KDE_PREFIX_LEN (2 + RSN_PN_LEN)
struct wpa_bigtk_kde {
u8 keyid[2];
u8 pn[6];
u8 pn[RSN_PN_LEN];
u8 bigtk[WPA_BIGTK_MAX_LEN];
} STRUCT_PACKED;
#define RSN_MLO_GTK_KDE_PREFIX_LENGTH (1 + 6)
#define RSN_MLO_GTK_KDE_PREFIX_LENGTH (1 + RSN_PN_LEN)
#define RSN_MLO_GTK_KDE_PREFIX0_KEY_ID_MASK 0x03
#define RSN_MLO_GTK_KDE_PREFIX0_TX 0x04
#define RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_SHIFT 4
#define RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_MASK 0xF0
#define RSN_MLO_IGTK_KDE_PREFIX_LENGTH (2 + 6 + 1)
#define RSN_MLO_IGTK_KDE_PREFIX_LENGTH (2 + RSN_PN_LEN + 1)
#define RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_SHIFT 4
#define RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_MASK 0xF0
struct rsn_mlo_igtk_kde {
u8 keyid[2];
u8 pn[6];
u8 pn[RSN_PN_LEN];
u8 prefix8;
u8 igtk[WPA_IGTK_MAX_LEN];
} STRUCT_PACKED;
#define RSN_MLO_BIGTK_KDE_PREFIX_LENGTH (2 + 6 + 1)
#define RSN_MLO_BIGTK_KDE_PREFIX_LENGTH (2 + RSN_PN_LEN + 1)
#define RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_SHIFT 4
#define RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_MASK 0xF0
struct rsn_mlo_bigtk_kde {
u8 keyid[2];
u8 pn[6];
u8 pn[RSN_PN_LEN];
u8 prefix8;
u8 bigtk[WPA_BIGTK_MAX_LEN];
} STRUCT_PACKED;
#define RSN_MLO_LINK_KDE_FIXED_LENGTH (1 + 6)
#define RSN_MLO_LINK_KDE_FIXED_LENGTH (1 + ETH_ALEN)
#define RSN_MLO_LINK_KDE_LINK_INFO_INDEX 0
#define RSN_MLO_LINK_KDE_LI_LINK_ID_SHIFT 0
#define RSN_MLO_LINK_KDE_LI_LINK_ID_MASK 0x0F
@ -557,8 +563,6 @@ int wpa_compare_rsn_ie(int ft_initial_assoc,
const u8 *ie2, size_t ie2len);
int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid, bool replace);
#define MAX_NUM_MLO_LINKS 15
struct wpa_ft_ies {
const u8 *mdie;
size_t mdie_len;
@ -596,14 +600,14 @@ struct wpa_ft_ies {
const u8 *rsnxe;
size_t rsnxe_len;
u16 valid_mlo_gtks; /* bitmap of valid link GTK subelements */
const u8 *mlo_gtk[MAX_NUM_MLO_LINKS];
size_t mlo_gtk_len[MAX_NUM_MLO_LINKS];
const u8 *mlo_gtk[MAX_NUM_MLD_LINKS];
size_t mlo_gtk_len[MAX_NUM_MLD_LINKS];
u16 valid_mlo_igtks; /* bitmap of valid link IGTK subelements */
const u8 *mlo_igtk[MAX_NUM_MLO_LINKS];
size_t mlo_igtk_len[MAX_NUM_MLO_LINKS];
const u8 *mlo_igtk[MAX_NUM_MLD_LINKS];
size_t mlo_igtk_len[MAX_NUM_MLD_LINKS];
u16 valid_mlo_bigtks; /* bitmap of valid link BIGTK subelements */
const u8 *mlo_bigtk[MAX_NUM_MLO_LINKS];
size_t mlo_bigtk_len[MAX_NUM_MLO_LINKS];
const u8 *mlo_bigtk[MAX_NUM_MLD_LINKS];
size_t mlo_bigtk_len[MAX_NUM_MLD_LINKS];
struct wpabuf *fte_buf;
};
@ -640,6 +644,14 @@ struct wpa_pasn_params_data {
#define WPA_PASN_PUBKEY_COMPRESSED_1 0x03
#define WPA_PASN_PUBKEY_UNCOMPRESSED 0x04
/* WPA3 specification - RSN Selection element */
enum rsn_selection_variant {
RSN_SELECTION_RSNE = 0,
RSN_SELECTION_RSNE_OVERRIDE = 1,
RSN_SELECTION_RSNE_OVERRIDE_2 = 2,
};
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
int key_mgmt, bool reassoc_resp);
void wpa_ft_parse_ies_free(struct wpa_ft_ies *parse);
@ -695,22 +707,34 @@ struct wpa_eapol_ie_parse {
size_t supp_channels_len;
const u8 *supp_oper_classes;
size_t supp_oper_classes_len;
const u8 *ssid;
size_t ssid_len;
u8 qosinfo;
u16 aid;
const u8 *wmm;
size_t wmm_len;
const u8 *rsn_selection;
size_t rsn_selection_len;
const u8 *rsne_override;
size_t rsne_override_len;
const u8 *rsne_override_2;
size_t rsne_override_2_len;
const u8 *rsnxe_override;
size_t rsnxe_override_len;
u16 valid_mlo_gtks; /* bitmap of valid link GTK KDEs */
const u8 *mlo_gtk[MAX_NUM_MLO_LINKS];
size_t mlo_gtk_len[MAX_NUM_MLO_LINKS];
const u8 *mlo_gtk[MAX_NUM_MLD_LINKS];
size_t mlo_gtk_len[MAX_NUM_MLD_LINKS];
u16 valid_mlo_igtks; /* bitmap of valid link IGTK KDEs */
const u8 *mlo_igtk[MAX_NUM_MLO_LINKS];
size_t mlo_igtk_len[MAX_NUM_MLO_LINKS];
const u8 *mlo_igtk[MAX_NUM_MLD_LINKS];
size_t mlo_igtk_len[MAX_NUM_MLD_LINKS];
u16 valid_mlo_bigtks; /* bitmap of valid link BIGTK KDEs */
const u8 *mlo_bigtk[MAX_NUM_MLO_LINKS];
size_t mlo_bigtk_len[MAX_NUM_MLO_LINKS];
const u8 *mlo_bigtk[MAX_NUM_MLD_LINKS];
size_t mlo_bigtk_len[MAX_NUM_MLD_LINKS];
u16 valid_mlo_links; /* bitmap of valid MLO link KDEs */
const u8 *mlo_link[MAX_NUM_MLO_LINKS];
size_t mlo_link_len[MAX_NUM_MLO_LINKS];
const u8 *mlo_link[MAX_NUM_MLD_LINKS];
size_t mlo_link_len[MAX_NUM_MLD_LINKS];
const u8 *rsn_override_link[MAX_NUM_MLD_LINKS];
size_t rsn_override_link_len[MAX_NUM_MLD_LINKS];
};
int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie);
@ -782,4 +806,7 @@ int wpa_pasn_parse_parameter_ie(const u8 *data, u8 len, bool from_ap,
void wpa_pasn_add_rsnxe(struct wpabuf *buf, u16 capab);
int wpa_pasn_add_extra_ies(struct wpabuf *buf, const u8 *extra_ies, size_t len);
void rsn_set_snonce_cookie(u8 *snonce);
bool rsn_is_snonce_cookie(const u8 *snonce);
#endif /* WPA_COMMON_H */

View file

@ -13,6 +13,8 @@
extern "C" {
#endif
#define WPA_CTRL_IFACE_LINK_NAME "link"
/* wpa_supplicant control interface - fixed message prefixes */
/** Interactive request for identity/password/pin */
@ -204,6 +206,7 @@ extern "C" {
#define DPP_EVENT_CONFOBJ_SSID "DPP-CONFOBJ-SSID "
#define DPP_EVENT_CONFOBJ_SSID_CHARSET "DPP-CONFOBJ-SSID-CHARSET "
#define DPP_EVENT_CONFOBJ_PASS "DPP-CONFOBJ-PASS "
#define DPP_EVENT_CONFOBJ_IDPASS "DPP-CONFOBJ-IDPASS "
#define DPP_EVENT_CONFOBJ_PSK "DPP-CONFOBJ-PSK "
#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR "
#define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY "
@ -225,6 +228,7 @@ extern "C" {
#define DPP_EVENT_CHIRP_STOPPED "DPP-CHIRP-STOPPED "
#define DPP_EVENT_MUD_URL "DPP-MUD-URL "
#define DPP_EVENT_BAND_SUPPORT "DPP-BAND-SUPPORT "
#define DPP_EVENT_ENROLLEE_CAPABILITY "DPP-ENROLLEE-CAPABILITY "
#define DPP_EVENT_CSR "DPP-CSR "
#define DPP_EVENT_CHIRP_RX "DPP-CHIRP-RX "
#define DPP_EVENT_CONF_NEEDED "DPP-CONF-NEEDED "
@ -413,6 +417,9 @@ extern "C" {
/* parameters: <STA address> <dialog token> <report mode> <beacon report> */
#define BEACON_RESP_RX "BEACON-RESP-RX "
/* parameters: <STA address> <dialog token> <link measurement report> */
#define LINK_MSR_RESP_RX "LINK-MSR-RESP-RX "
/* PMKSA cache entry added; parameters: <BSSID> <network_id> */
#define PMKSA_CACHE_ADDED "PMKSA-CACHE-ADDED "
/* PMKSA cache entry removed; parameters: <BSSID> <network_id> */

View file

@ -1835,6 +1835,7 @@ int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
ret = 0;
fail:
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(emac);
return ret;
#else /* OpenSSL version >= 3.0 */
CMAC_CTX *ctx;
@ -3932,9 +3933,10 @@ static int openssl_evp_pkey_ec_prime_len(struct crypto_ec_key *key)
group = EC_GROUP_new_by_curve_name(nid);
prime = BN_new();
if (!group || !prime)
return -1;
goto fail;
if (EC_GROUP_get_curve(group, prime, NULL, NULL, NULL) == 1)
prime_len = BN_num_bytes(prime);
fail:
EC_GROUP_free(group);
BN_free(prime);
return prime_len;
@ -4880,7 +4882,7 @@ hpke_labeled_expand(struct hpke_context *ctx, bool kem, const u8 *prk,
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
hmac = EVP_MAC_fetch(NULL, "HMAC", NULL);
if (!hmac)
return -1;
goto fail;
params[0] = OSSL_PARAM_construct_utf8_string(
"digest",
@ -4889,7 +4891,7 @@ hpke_labeled_expand(struct hpke_context *ctx, bool kem, const u8 *prk,
#else /* OpenSSL version >= 3.0 */
hctx = HMAC_CTX_new();
if (!hctx)
return -1;
goto fail;
#endif /* OpenSSL version >= 3.0 */
while (left > 0) {
@ -4898,7 +4900,7 @@ hpke_labeled_expand(struct hpke_context *ctx, bool kem, const u8 *prk,
EVP_MAC_CTX_free(hctx);
hctx = EVP_MAC_CTX_new(hmac);
if (!hctx)
return -1;
goto fail;
if (EVP_MAC_init(hctx, prk, mdlen, params) != 1)
goto fail;

View file

@ -27,6 +27,10 @@
#endif /* CONFIG_MACSEC */
#include "utils/list.h"
struct nan_subscribe_params;
struct nan_publish_params;
enum nan_service_protocol_type;
#define HOSTAPD_CHAN_DISABLED 0x00000001
#define HOSTAPD_CHAN_NO_IR 0x00000002
#define HOSTAPD_CHAN_RADAR 0x00000008
@ -43,6 +47,7 @@
#define HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL 0x00000800
#define HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL 0x00001000
#define HOSTAPD_CHAN_EHT_320MHZ_SUBCHANNEL 0x00002000
#define HOSTAPD_CHAN_INDOOR_ONLY 0x00010000
#define HOSTAPD_CHAN_GO_CONCURRENT 0x00020000
@ -246,6 +251,11 @@ struct hostapd_hw_modes {
*/
enum hostapd_hw_mode mode;
/**
* is_6ghz - Whether the mode information is for the 6 GHz band
*/
bool is_6ghz;
/**
* num_channels - Number of entries in the channels array
*/
@ -311,6 +321,27 @@ struct hostapd_hw_modes {
};
/**
* struct hostapd_multi_hw_info: Supported multiple underlying hardware info
*/
struct hostapd_multi_hw_info {
/**
* hw_idx - Hardware index
*/
u8 hw_idx;
/**
* start_freq - Frequency range start in MHz
*/
int start_freq;
/**
* end_freq - Frequency range end in MHz
*/
int end_freq;
};
#define IEEE80211_CAP_ESS 0x0001
#define IEEE80211_CAP_IBSS 0x0002
#define IEEE80211_CAP_PRIVACY 0x0010
@ -695,6 +726,14 @@ struct wpa_driver_scan_params {
*/
unsigned int min_probe_req_content:1;
/**
* link_id - Specify the link that is requesting the scan on an MLD
*
* This is set when operating as an AP MLD and doing an OBSS scan.
* -1 indicates that no particular link ID is set.
*/
s8 link_id;
/*
* NOTE: Whenever adding new parameters here, please make sure
* wpa_scan_clone_params() and wpa_scan_free_params() get updated with
@ -1349,6 +1388,12 @@ struct wpa_driver_associate_params {
* mld_params - MLD association parameters
*/
struct wpa_driver_mld_params mld_params;
/**
* rsn_overriding - wpa_supplicant RSN overriding support
*/
bool rsn_overriding;
};
enum hide_ssid {
@ -1372,6 +1417,23 @@ struct wowlan_triggers {
u8 rfkill_release;
};
struct unsol_bcast_probe_resp {
/**
* Unsolicited broadcast Probe Response interval in TUs
*/
unsigned int unsol_bcast_probe_resp_interval;
/**
* Unsolicited broadcast Probe Response template data
*/
u8 *unsol_bcast_probe_resp_tmpl;
/**
* Unsolicited broadcast Probe Response template length
*/
size_t unsol_bcast_probe_resp_tmpl_len;
};
struct wpa_driver_ap_params {
/**
* head - Beacon head from IEEE 802.11 header to IEs before TIM IE
@ -1714,21 +1776,6 @@ struct wpa_driver_ap_params {
*/
size_t fd_frame_tmpl_len;
/**
* Unsolicited broadcast Probe Response interval in TUs
*/
unsigned int unsol_bcast_probe_resp_interval;
/**
* Unsolicited broadcast Probe Response template data
*/
u8 *unsol_bcast_probe_resp_tmpl;
/**
* Unsolicited broadcast Probe Response template length
*/
size_t unsol_bcast_probe_resp_tmpl_len;
/**
* mbssid_tx_iface - Transmitting interface of the MBSSID set
*/
@ -1795,6 +1842,9 @@ struct wpa_driver_ap_params {
*/
u8 **rnr_elem_offset;
/* Unsolicited broadcast Probe Response data */
struct unsol_bcast_probe_resp ubpr;
/**
* allowed_freqs - List of allowed 20 MHz channel center frequencies in
* MHz for AP operation. Drivers which support this parameter will
@ -2309,6 +2359,12 @@ struct wpa_driver_capa {
#define WPA_DRIVER_FLAGS2_OWE_OFFLOAD_AP 0x0000000000080000ULL
/** Driver support AP SAE authentication offload */
#define WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP 0x0000000000100000ULL
/** Driver supports TWT responder in HT and VHT modes */
#define WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER 0x0000000000200000ULL
/** Driver supports RSN override elements */
#define WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA 0x0000000000400000ULL
/** Driver supports NAN offload */
#define WPA_DRIVER_FLAGS2_NAN_OFFLOAD 0x0000000000800000ULL
u64 flags2;
#define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
@ -2711,6 +2767,7 @@ struct beacon_data {
* @counter_offset_presp: Offset to the count field in probe resp.
* @punct_bitmap - Preamble puncturing bitmap
* @link_id: Link ID to determine the link for MLD; -1 for non-MLD
* @ubpr: Unsolicited broadcast Probe Response frame data
*/
struct csa_settings {
u8 cs_count;
@ -2725,6 +2782,8 @@ struct csa_settings {
u16 punct_bitmap;
int link_id;
struct unsol_bcast_probe_resp ubpr;
};
/**
@ -2736,6 +2795,8 @@ struct csa_settings {
* @beacon_after: Next Beacon/Probe Response/(Re)Association Response frame info
* @counter_offset_beacon: Offset to the count field in Beacon frame tail
* @counter_offset_presp: Offset to the count field in Probe Response frame
* @ubpr: Unsolicited broadcast Probe Response frame data
* @link_id: If >= 0 indicates the link of the AP MLD to configure
*/
struct cca_settings {
u8 cca_count;
@ -2746,6 +2807,10 @@ struct cca_settings {
u16 counter_offset_beacon;
u16 counter_offset_presp;
struct unsol_bcast_probe_resp ubpr;
int link_id;
};
/* TDLS peer capabilities for send_tdls_mgmt() */
@ -3360,6 +3425,17 @@ struct wpa_driver_ops {
int (*update_ft_ies)(void *priv, const u8 *md, const u8 *ies,
size_t ies_len);
/**
* get_scan_results - Fetch the latest scan results
* @priv: Private driver interface data
* @bssid: Return results only for the specified BSSID, %NULL for all
*
* Returns: Allocated buffer of scan results (caller is responsible for
* freeing the data structure) on success, NULL on failure
*/
struct wpa_scan_results * (*get_scan_results)(void *priv,
const u8 *bssid);
/**
* get_scan_results2 - Fetch the latest scan results
* @priv: private driver interface data
@ -3561,13 +3637,15 @@ struct wpa_driver_ops {
/**
* flush - Flush all association stations (AP only)
* @priv: Private driver interface data
* @link_id: In case of MLO, valid link ID on which all associated
* stations will be flushed, -1 otherwise.
* Returns: 0 on success, -1 on failure
*
* This function requests the driver to disassociate all associated
* stations. This function does not need to be implemented if the
* driver does not process association frames internally.
*/
int (*flush)(void *priv);
int (*flush)(void *priv, int link_id);
/**
* set_generic_elem - Add IEs into Beacon/Probe Response frames (AP)
@ -4544,13 +4622,14 @@ struct wpa_driver_ops {
/**
* stop_ap - Removes beacon from AP
* @priv: Private driver interface data
* @link_id: Link ID of the specified link; -1 for non-MLD
* Returns: 0 on success, -1 on failure (or if not supported)
*
* This optional function can be used to disable AP mode related
* configuration. Unlike deinit_ap, it does not change to station
* mode.
*/
int (*stop_ap)(void *priv);
int (*stop_ap)(void *priv, int link_id);
/**
* get_survey - Retrieve survey data
@ -5130,15 +5209,137 @@ struct wpa_driver_ops {
* @priv: Private driver interface data
* @link_id: The link ID
* @addr: The MAC address to use for the link
* @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces
* Returns: 0 on success, negative value on failure
*/
int (*link_add)(void *priv, u8 link_id, const u8 *addr);
int (*link_add)(void *priv, u8 link_id, const u8 *addr, void *bss_ctx);
/**
* link_remove - Remove a link from the AP MLD interface
* @priv: Private driver interface data
* @type: Interface type
* @ifname: Interface name of the virtual interface from where the link
* is to be removed.
* @link_id: Valid link ID to remove
* Returns: 0 on success, -1 on failure
*/
int (*link_remove)(void *priv, enum wpa_driver_if_type type,
const char *ifname, u8 link_id);
/**
* is_drv_shared - Check whether the driver interface is shared
* @priv: Private driver interface data from init()
* @link_id: Link ID to match
* Returns: true if it is being used or else false.
*
* Checks whether the driver interface is being used by other partner
* BSS(s) or not. This is used to decide whether the driver interface
* needs to be deinitilized when one interface is getting deinitialized.
*
* NOTE: @link_id will be used only when there is only one BSS
* present and if that single link is active. In that case, the
* link ID is matched with the active link_id to decide whether the
* driver interface is being used by other partner BSS(s).
*/
bool (*is_drv_shared)(void *priv, int link_id);
/**
* link_sta_remove - Remove a link STA from an MLD STA
* @priv: Private driver interface data
* @link_id: The link ID which the link STA is using
* @addr: The MLD MAC address of the MLD STA
* Returns: 0 on success, negative value on failure
*/
int (*link_sta_remove)(void *priv, u8 link_id, const u8 *addr);
/**
* nan_flush - Flush all NAN offload services
* @priv: Private driver interface data
* Returns: 0 on success, negative value on failure
*/
int (*nan_flush)(void *priv);
/**
* nan_publish - NAN offload for Publish()
* @priv: Private driver interface data
* @src: Source P2P device addr
* @publish_id: Publish instance to add
* @service_name: Service name
* @service_id: Service ID (6 octet value derived from service name)
* @srv_proto_type: Service protocol type
* @ssi: Service specific information or %NULL
* @elems: Information elements for Element Container attribute or %NULL
* @params: Configuration parameters
* Returns: 0 on success, negative value on failure
*/
int (*nan_publish)(void *priv, const u8 *src, 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);
/**
* nan_cancel_publish - NAN offload for CancelPublish()
* @priv: Private driver interface data
* @publish_id: Publish instance to cancel
* Returns: 0 on success, negative value on failure
*/
int (*nan_cancel_publish)(void *priv, int publish_id);
/**
* nan_update_publish - NAN offload for UpdatePublish()
* @priv: Private driver interface data
* @ssi: Service specific information or %NULL
* Returns: 0 on success, negative value on failure
*/
int (*nan_update_publish)(void *priv, int publish_id,
const struct wpabuf *ssi);
/**
* nan_subscribe - NAN offload for Subscribe()
* @priv: Private driver interface data
* @src: Source P2P device addr
* @subscribe_id: Subscribe instance to add
* @service_name: Service name
* @service_id: Service ID (6 octet value derived from service name)
* @srv_proto_type: Service protocol type
* @ssi: Service specific information or %NULL
* @elems: Information elements for Element Container attribute or %NULL
* @params: Configuration parameters
* Returns: 0 on success, negative value on failure
*/
int (*nan_subscribe)(void *priv, const u8 *src, 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);
/**
* nan_cancel_subscribe - NAN offload for CancelSubscribe()
* @priv: Private driver interface data
* @subscribe_id: Subscribe instance to cancel
* Returns: 0 on success, negative value on failure
*/
int (*nan_cancel_subscribe)(void *priv, int subscribe_id);
#ifdef CONFIG_TESTING_OPTIONS
int (*register_frame)(void *priv, u16 type,
const u8 *match, size_t match_len,
bool multicast);
#endif /* CONFIG_TESTING_OPTIONS */
/**
* get_multi_hw_info - Get multiple underlying hardware information
* (hardware IDx and supported frequency range)
* @priv: Private driver interface data
* @num_multi_hws: Variable for returning the number of returned
* hardware info data
* Returns: Pointer to allocated multiple hardware data on success
* or %NULL on failure. Caller is responsible for freeing this.
*/
struct hostapd_multi_hw_info *
(*get_multi_hw_info)(void *priv, unsigned int *num_multi_hws);
};
/**
@ -5766,6 +5967,11 @@ enum wpa_event_type {
* EVENT_LINK_RECONFIG - Notification that AP links removed
*/
EVENT_LINK_RECONFIG,
/**
* EVENT_MLD_INTERFACE_FREED - Notification of AP MLD interface removal
*/
EVENT_MLD_INTERFACE_FREED,
};
@ -6292,6 +6498,14 @@ union wpa_event_data {
*/
void *drv_priv;
/**
* ctx - Pointer to store ctx of private BSS information
*
* If not set to NULL, this is used for forwarding the packet
* to right link BSS of ML BSS.
*/
void *ctx;
/**
* freq - Frequency (in MHz) on which the frame was received
*/
@ -6342,6 +6556,8 @@ union wpa_event_data {
* (if available).
* @scan_start_tsf_bssid: The BSSID according to which %scan_start_tsf
* is set.
* @scan_cookie: Unique identification representing the corresponding
* scan request. 0 if no unique identification is available.
*/
struct scan_info {
int aborted;
@ -6353,6 +6569,7 @@ union wpa_event_data {
int nl_scan_event;
u64 scan_start_tsf;
u8 scan_start_tsf_bssid[ETH_ALEN];
u64 scan_cookie;
} scan_info;
/**
@ -6709,6 +6926,7 @@ union wpa_event_data {
*/
struct bss_color_collision {
u64 bitmap;
int link_id;
} bss_color_collision;
/**

View file

@ -632,7 +632,7 @@ atheros_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
static int
atheros_flush(void *priv)
atheros_flush(void *priv, int link_id)
{
u8 allsta[IEEE80211_ADDR_LEN];
os_memset(allsta, 0xff, IEEE80211_ADDR_LEN);

View file

@ -946,7 +946,7 @@ bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
static int
bsd_flush(void *priv)
bsd_flush(void *priv, int link_id)
{
u8 allsta[IEEE80211_ADDR_LEN];

View file

@ -100,6 +100,7 @@ const char * event_to_string(enum wpa_event_type event)
E2S(LINK_CH_SWITCH_STARTED);
E2S(TID_LINK_MAP);
E2S(LINK_RECONFIG);
E2S(MLD_INTERFACE_FREED);
}
return "UNKNOWN";

View file

@ -572,7 +572,7 @@ static int hostap_set_ssid(void *priv, const u8 *buf, int len)
}
static int hostap_flush(void *priv)
static int hostap_flush(void *priv, int link_id)
{
struct hostap_driver_data *drv = priv;
struct prism2_hostapd_param param;

View file

@ -19,6 +19,7 @@
#include <netlink/route/link.h>
#include <netlink/route/link/macsec.h>
#include <linux/if_macsec.h>
#include <linux/version.h>
#include <inttypes.h>
#include "utils/common.h"
@ -32,7 +33,8 @@
#define UNUSED_SCI 0xffffffffffffffff
#if LIBNL_VER_NUM >= LIBNL_VER(3, 6)
#if (LIBNL_VER_NUM >= LIBNL_VER(3, 6) && \
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
#define LIBNL_HAS_OFFLOAD
#endif

File diff suppressed because it is too large Load diff

View file

@ -55,7 +55,6 @@ struct nl80211_wiphy_data {
struct i802_link {
unsigned int beacon_set:1;
s8 link_id;
int freq;
int bandwidth;
u8 addr[ETH_ALEN];
@ -66,9 +65,9 @@ struct i802_bss {
struct wpa_driver_nl80211_data *drv;
struct i802_bss *next;
size_t n_links;
u16 valid_links;
struct i802_link links[MAX_NUM_MLD_LINKS];
struct i802_link *flink;
struct i802_link *flink, *scan_link;
int ifindex;
int br_ifindex;
@ -201,6 +200,7 @@ struct wpa_driver_nl80211_data {
unsigned int secure_ranging_ctx_vendor_cmd_avail:1;
unsigned int puncturing:1;
unsigned int qca_ap_allowed_freqs:1;
unsigned int connect_ext_vendor_cmd_avail:1;
u32 ignore_next_local_disconnect;
u32 ignore_next_local_deauth;
@ -353,6 +353,20 @@ const char * nl80211_iftype_str(enum nl80211_iftype mode);
void nl80211_restore_ap_mode(struct i802_bss *bss);
struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id);
u8 nl80211_get_link_id_from_link(struct i802_bss *bss, struct i802_link *link);
int nl80211_remove_link(struct i802_bss *bss, int link_id);
static inline bool nl80211_link_valid(u16 links, s8 link_id)
{
if (link_id < 0 || link_id >= MAX_NUM_MLD_LINKS)
return false;
if (links & BIT(link_id))
return true;
return false;
}
static inline bool
nl80211_attr_supported(struct wpa_driver_nl80211_data *drv, unsigned int attr)
@ -391,11 +405,14 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
int wpa_driver_nl80211_sched_scan(void *priv,
struct wpa_driver_scan_params *params);
int wpa_driver_nl80211_stop_sched_scan(void *priv);
struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv);
struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv,
const u8 *bssid);
void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv);
int wpa_driver_nl80211_abort_scan(void *priv, u64 scan_cookie);
int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
struct wpa_driver_scan_params *params);
int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len);
struct hostapd_multi_hw_info *
nl80211_get_multi_hw_info(struct i802_bss *bss, unsigned int *num_multi_hws);
#endif /* DRIVER_NL80211_H */

View file

@ -889,6 +889,10 @@ static void wiphy_info_extended_capab(struct wpa_driver_nl80211_data *drv,
nla_get_u16(tb1[NL80211_ATTR_MLD_CAPA_AND_OPS]);
}
wpa_printf(MSG_DEBUG,
"nl80211: EML Capability: 0x%x MLD Capability: 0x%x",
capa->eml_capa, capa->mld_capa_and_ops);
drv->num_iface_capa++;
if (drv->num_iface_capa == NL80211_IFTYPE_MAX)
break;
@ -1116,6 +1120,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
case QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT:
drv->secure_ranging_ctx_vendor_cmd_avail = 1;
break;
case QCA_NL80211_VENDOR_SUBCMD_CONNECT_EXT:
drv->connect_ext_vendor_cmd_avail = 1;
break;
#endif /* CONFIG_DRIVER_NL80211_QCA */
}
#ifdef CONFIG_DRIVER_NL80211_BRCM
@ -1437,6 +1444,14 @@ static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv)
if (check_feature(QCA_WLAN_VENDOR_FEATURE_AP_ALLOWED_FREQ_LIST,
&info))
drv->qca_ap_allowed_freqs = 1;
if (check_feature(QCA_WLAN_VENDOR_FEATURE_HT_VHT_TWT_RESPONDER, &info))
drv->capa.flags2 |= WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER;
if (check_feature(QCA_WLAN_VENDOR_FEATURE_RSN_OVERRIDE_STA, &info)) {
wpa_printf(MSG_DEBUG,
"The driver supports RSN overriding in STA mode");
drv->capa.flags2 |= WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA;
}
os_free(info.flags);
}
@ -1464,6 +1479,7 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256 |
WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B |
WPA_DRIVER_CAPA_KEY_MGMT_OWE |
WPA_DRIVER_CAPA_KEY_MGMT_DPP;
@ -1479,6 +1495,7 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 |
WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 |
WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 |
WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY |
WPA_DRIVER_CAPA_KEY_MGMT_SAE;
else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)
drv->capa.key_mgmt |=
@ -2156,6 +2173,9 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
for (m = 0; m < *num_modes; m++) {
if (!modes[m].num_channels)
continue;
modes[m].is_6ghz = false;
if (modes[m].channels[0].freq < 2000) {
modes[m].num_channels = 0;
continue;
@ -2167,10 +2187,14 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
break;
}
}
} else if (modes[m].channels[0].freq > 50000)
} else if (modes[m].channels[0].freq > 50000) {
modes[m].mode = HOSTAPD_MODE_IEEE80211AD;
else
} else if (is_6ghz_freq(modes[m].channels[0].freq)) {
modes[m].mode = HOSTAPD_MODE_IEEE80211A;
modes[m].is_6ghz = true;
} else {
modes[m].mode = HOSTAPD_MODE_IEEE80211A;
}
}
/* Remove unsupported bands */
@ -2398,6 +2422,57 @@ static void nl80211_reg_rule_vht(struct nlattr *tb[],
}
static void nl80211_set_6ghz_mode(struct hostapd_hw_modes *mode, int start,
int end, int max_bw)
{
int c;
for (c = 0; c < mode->num_channels; c++) {
struct hostapd_channel_data *chan = &mode->channels[c];
if (chan->freq - 10 < start || chan->freq + 10 > end)
continue;
if (max_bw >= 80)
chan->flag |= HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL;
if (max_bw >= 160)
chan->flag |= HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL;
if (max_bw >= 320)
chan->flag |= HOSTAPD_CHAN_EHT_320MHZ_SUBCHANNEL;
}
}
static void nl80211_reg_rule_6ghz(struct nlattr *tb[],
struct phy_info_arg *results)
{
u32 start, end, max_bw;
u16 m;
if (!tb[NL80211_ATTR_FREQ_RANGE_START] ||
!tb[NL80211_ATTR_FREQ_RANGE_END] ||
!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
return;
start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
if (max_bw < 80)
return;
for (m = 0; m < *results->num_modes; m++) {
if (results->modes[m].num_channels == 0 ||
!is_6ghz_freq(results->modes[m].channels[0].freq))
continue;
nl80211_set_6ghz_mode(&results->modes[m], start, end, max_bw);
}
}
static void nl80211_set_dfs_domain(enum nl80211_dfs_regions region,
u8 *dfs_domain)
{
@ -2516,6 +2591,13 @@ static int nl80211_get_reg(struct nl_msg *msg, void *arg)
nl80211_reg_rule_vht(tb_rule, results);
}
nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
{
nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
nla_data(nl_rule), nla_len(nl_rule), reg_policy);
nl80211_reg_rule_6ghz(tb_rule, results);
}
return NL_SKIP;
}
@ -2657,3 +2739,133 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags,
return NULL;
}
static int phy_multi_hw_info_parse(struct hostapd_multi_hw_info *hw_info,
struct nlattr *radio_attr)
{
struct nlattr *tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_MAX + 1];
int start_freq, end_freq;
switch (nla_type(radio_attr)) {
case NL80211_WIPHY_RADIO_ATTR_INDEX:
hw_info->hw_idx = nla_get_u32(radio_attr);
return NL_OK;
case NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE:
nla_parse_nested(tb_freq, NL80211_WIPHY_RADIO_FREQ_ATTR_MAX,
radio_attr, NULL);
if (!tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_START] ||
!tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_END])
return NL_STOP;
start_freq = nla_get_u32(
tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_START]);
end_freq = nla_get_u32(
tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_END]);
/* Convert to MHz and store */
hw_info->start_freq = start_freq / 1000;
hw_info->end_freq = end_freq / 1000;
return NL_OK;
default:
return NL_OK;
}
}
struct phy_multi_hw_info_arg {
bool failed;
unsigned int *num_multi_hws;
struct hostapd_multi_hw_info *multi_hws;
};
static int phy_multi_hw_info_handler(struct nl_msg *msg, void *arg)
{
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct phy_multi_hw_info_arg *multi_hw_info = arg;
struct hostapd_multi_hw_info *multi_hws, hw_info;
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
struct nlattr *nl_hw, *radio_attr;
int rem_hw, rem_radio_prop, res;
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
if (!tb_msg[NL80211_ATTR_WIPHY_RADIOS])
return NL_SKIP;
*multi_hw_info->num_multi_hws = 0;
nla_for_each_nested(nl_hw, tb_msg[NL80211_ATTR_WIPHY_RADIOS], rem_hw) {
os_memset(&hw_info, 0, sizeof(hw_info));
nla_for_each_nested(radio_attr, nl_hw, rem_radio_prop) {
res = phy_multi_hw_info_parse(&hw_info, radio_attr);
if (res != NL_OK)
goto out;
}
if (hw_info.start_freq == 0 || hw_info.end_freq == 0)
goto out;
multi_hws = os_realloc_array(multi_hw_info->multi_hws,
*multi_hw_info->num_multi_hws + 1,
sizeof(*multi_hws));
if (!multi_hws)
goto out;
multi_hw_info->multi_hws = multi_hws;
os_memcpy(&multi_hws[*(multi_hw_info->num_multi_hws)],
&hw_info, sizeof(struct hostapd_multi_hw_info));
*(multi_hw_info->num_multi_hws) += 1;
}
return NL_OK;
out:
multi_hw_info->failed = true;
return NL_STOP;
}
struct hostapd_multi_hw_info *
nl80211_get_multi_hw_info(struct i802_bss *bss, unsigned int *num_multi_hws)
{
u32 feat;
struct wpa_driver_nl80211_data *drv = bss->drv;
int nl_flags = 0;
struct nl_msg *msg;
struct phy_multi_hw_info_arg result = {
.failed = false,
.num_multi_hws = num_multi_hws,
.multi_hws = NULL,
};
*num_multi_hws = 0;
if (!drv->has_capability || !(drv->capa.flags2 & WPA_DRIVER_FLAGS2_MLO))
return NULL;
feat = get_nl80211_protocol_features(drv);
if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
nl_flags = NLM_F_DUMP;
if (!(msg = nl80211_cmd_msg(bss, nl_flags, NL80211_CMD_GET_WIPHY)) ||
nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP)) {
nlmsg_free(msg);
return NULL;
}
if (send_and_recv_resp(drv, msg, phy_multi_hw_info_handler,
&result) == 0) {
if (result.failed) {
os_free(result.multi_hws);
*num_multi_hws = 0;
return NULL;
}
return result.multi_hws;
}
return NULL;
}

View file

@ -22,7 +22,7 @@
static void
nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv,
nl80211_control_port_frame_tx_status(struct i802_bss *bss,
const u8 *frame, size_t len,
struct nlattr *ack, struct nlattr *cookie);
@ -186,6 +186,7 @@ static const char * nl80211_command_to_string(enum nl80211_commands cmd)
C2S(NL80211_CMD_REMOVE_LINK_STA)
C2S(NL80211_CMD_SET_HW_TIMESTAMP)
C2S(NL80211_CMD_LINKS_REMOVED)
C2S(NL80211_CMD_SET_TID_TO_LINK_MAPPING)
C2S(__NL80211_CMD_AFTER_LAST)
}
#undef C2S
@ -477,10 +478,7 @@ static void qca_nl80211_link_reconfig_event(struct wpa_driver_nl80211_data *drv,
* links when the link used for (re)association is removed.
*/
if (removed_links & BIT(drv->sta_mlo_info.assoc_link_id)) {
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
if (!(drv->sta_mlo_info.valid_links & BIT(i)))
continue;
for_each_link(drv->sta_mlo_info.valid_links, i) {
os_memcpy(drv->bssid, drv->sta_mlo_info.links[i].bssid,
ETH_ALEN);
drv->sta_mlo_info.assoc_link_id = i;
@ -702,10 +700,7 @@ static int nl80211_update_rejected_links_info(struct driver_sta_mlo_info *mlo,
}
/* Get MLO links info for rejected links */
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
if (!((mlo->req_links & ~mlo->valid_links) & BIT(i)))
continue;
for_each_link((mlo->req_links & ~mlo->valid_links), i) {
os_memcpy(mlo->links[i].bssid, resp_info.addr[i], ETH_ALEN);
os_memcpy(mlo->links[i].addr, req_info.addr[i], ETH_ALEN);
}
@ -875,9 +870,7 @@ qca_nl80211_tid_to_link_map_event(struct wpa_driver_nl80211_data *drv,
wpa_printf(MSG_DEBUG,
"nl80211: TID-to-link: Received uplink %x downlink %x",
uplink, downlink);
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
if (!(drv->sta_mlo_info.valid_links & BIT(i)))
continue;
for_each_link(drv->sta_mlo_info.valid_links, i) {
if (uplink & BIT(i))
event.t2l_map_info.t2lmap[i].uplink |=
BIT(tidnum);
@ -1212,9 +1205,6 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
int chan_offset = 0;
int ifidx;
wpa_printf(MSG_DEBUG, "nl80211: Channel switch%s event",
finished ? "" : " started");
if (!freq)
return;
@ -1226,6 +1216,9 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
return;
}
wpa_printf(MSG_DEBUG, "nl80211: Channel switch%s event for %s",
finished ? "" : " started", bss->ifname);
if (type) {
enum nl80211_channel_type ch_type = nla_get_u32(type);
@ -1268,13 +1261,31 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
if (cf2)
data.ch_switch.cf2 = nla_get_u32(cf2);
if (finished)
bss->flink->freq = data.ch_switch.freq;
if (link)
if (link) {
data.ch_switch.link_id = nla_get_u8(link);
else
wpa_printf(MSG_DEBUG, "nl80211: Link ID: %d",
data.ch_switch.link_id);
} else {
data.ch_switch.link_id = NL80211_DRV_LINK_ID_NA;
}
if (finished) {
if (data.ch_switch.link_id != NL80211_DRV_LINK_ID_NA) {
struct i802_link *mld_link;
mld_link = nl80211_get_link(bss,
data.ch_switch.link_id);
mld_link->freq = data.ch_switch.freq;
if (bw)
mld_link->bandwidth = channel_width_to_int(
data.ch_switch.ch_width);
} else {
bss->flink->freq = data.ch_switch.freq;
if (bw)
bss->flink->bandwidth = channel_width_to_int(
data.ch_switch.ch_width);
}
}
if (link && is_sta_interface(drv->nlmode)) {
u8 link_id = data.ch_switch.link_id;
@ -1293,6 +1304,14 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
return;
}
if (link && is_ap_interface(drv->nlmode) &&
!nl80211_link_valid(bss->valid_links, data.ch_switch.link_id)) {
wpa_printf(MSG_WARNING,
"nl80211: Unknown link ID (%d) for channel switch (%s), ignoring",
data.ch_switch.link_id, bss->ifname);
return;
}
drv->assoc_freq = data.ch_switch.freq;
wpa_supplicant_event(bss->ctx, finished ?
@ -1366,18 +1385,20 @@ static void mlme_event_mgmt(struct i802_bss *bss,
event.rx_mgmt.frame_len = len;
event.rx_mgmt.ssi_signal = ssi_signal;
event.rx_mgmt.drv_priv = bss;
event.rx_mgmt.ctx = bss->ctx;
event.rx_mgmt.link_id = link_id;
wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
}
static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv,
static void mlme_event_mgmt_tx_status(struct i802_bss *bss,
struct nlattr *cookie, const u8 *frame,
size_t len, struct nlattr *ack)
{
union wpa_event_data event;
const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame;
struct wpa_driver_nl80211_data *drv = bss->drv;
u16 fc = le_to_host16(hdr->frame_control);
u64 cookie_val = 0;
@ -1396,7 +1417,7 @@ static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv,
WPA_GET_BE16(frame + 2 * ETH_ALEN) == ETH_P_PAE) {
wpa_printf(MSG_DEBUG,
"nl80211: Work around misdelivered control port TX status for EAPOL");
nl80211_control_port_frame_tx_status(drv, frame, len, ack,
nl80211_control_port_frame_tx_status(bss, frame, len, ack,
cookie);
return;
}
@ -1432,7 +1453,7 @@ static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv,
event.tx_status.ack = ack != NULL;
event.tx_status.link_id = cookie_val == drv->send_frame_cookie ?
drv->send_frame_link_id : NL80211_DRV_LINK_ID_NA;
wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);
wpa_supplicant_event(bss->ctx, EVENT_TX_STATUS, &event);
}
@ -1618,18 +1639,17 @@ static void mlme_event_unprot_beacon(struct wpa_driver_nl80211_data *drv,
}
static struct i802_link *
nl80211_get_mld_link_by_freq(struct i802_bss *bss, unsigned int freq)
static s8
nl80211_get_link_id_by_freq(struct i802_bss *bss, unsigned int freq)
{
unsigned int i;
for (i = 0; i < bss->n_links; i++) {
if ((unsigned int) bss->links[i].freq == freq &&
bss->links[i].link_id != -1)
return &bss->links[i];
for_each_link(bss->valid_links, i) {
if ((unsigned int) bss->links[i].freq == freq)
return i;
}
return NULL;
return NL80211_DRV_LINK_ID_NA;
}
@ -1663,12 +1683,12 @@ static void mlme_event(struct i802_bss *bss,
/* Determine the MLD link either by an explicitly provided link id or
* finding a match based on the frequency. */
if (link)
mld_link = nl80211_get_link(bss, nla_get_u8(link));
link_id = nla_get_u8(link);
else if (freq)
mld_link = nl80211_get_mld_link_by_freq(bss, nla_get_u32(freq));
link_id = nl80211_get_link_id_by_freq(bss, nla_get_u32(freq));
if (mld_link)
link_id = mld_link->link_id;
if (nl80211_link_valid(bss->valid_links, link_id))
mld_link = nl80211_get_link(bss, link_id);
data = nla_data(frame);
len = nla_len(frame);
@ -1741,7 +1761,7 @@ static void mlme_event(struct i802_bss *bss,
nla_len(frame), link_id);
break;
case NL80211_CMD_FRAME_TX_STATUS:
mlme_event_mgmt_tx_status(drv, cookie, nla_data(frame),
mlme_event_mgmt_tx_status(bss, cookie, nla_data(frame),
nla_len(frame), ack);
break;
case NL80211_CMD_UNPROT_DEAUTHENTICATE:
@ -1920,7 +1940,7 @@ static void mlme_event_dh_event(struct wpa_driver_nl80211_data *drv,
os_memset(&data, 0, sizeof(data));
addr = nla_data(tb[NL80211_ATTR_MAC]);
if (bss->links[0].link_id == NL80211_DRV_LINK_ID_NA &&
if (!bss->valid_links &&
(tb[NL80211_ATTR_MLO_LINK_ID] ||
tb[NL80211_ATTR_MLD_ADDR])) {
wpa_printf(MSG_ERROR,
@ -1957,9 +1977,10 @@ static void mlme_event_dh_event(struct wpa_driver_nl80211_data *drv,
}
static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
static void send_scan_event(struct i802_bss *bss, int aborted,
struct nlattr *tb[], int external_scan)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
union wpa_event_data event;
struct nlattr *nl;
int rem;
@ -1967,6 +1988,8 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
#define MAX_REPORT_FREQS 110
int freqs[MAX_REPORT_FREQS];
int num_freqs = 0;
struct i802_link *mld_link;
void *ctx = bss->ctx;
if (!external_scan && drv->scan_for_auth) {
drv->scan_for_auth = 0;
@ -2030,13 +2053,30 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
ETH_ALEN);
}
wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
/* Need to pass to the correct link ctx during AP MLD operation */
if (is_ap_interface(drv->nlmode)) {
mld_link = bss->scan_link;
if (!mld_link) {
wpa_printf(MSG_DEBUG,
"nl80211: Scan event on unknown link");
} else if (mld_link->ctx) {
u8 link_id = nl80211_get_link_id_from_link(bss,
mld_link);
wpa_printf(MSG_DEBUG,
"nl80211: Scan event for link_id %d",
link_id);
ctx = mld_link->ctx;
}
}
wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, &event);
}
static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
struct nlattr *tb[])
static void nl80211_cqm_event(struct i802_bss *bss, struct nlattr *tb[])
{
struct wpa_driver_nl80211_data *drv = bss->drv;
static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },
@ -2071,7 +2111,7 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
wpa_printf(MSG_DEBUG, "nl80211: Packet loss event for " MACSTR
" (num_packets %u)",
MAC2STR(ed.low_ack.addr), ed.low_ack.num_packets);
wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);
wpa_supplicant_event(bss->ctx, EVENT_STATION_LOW_ACK, &ed);
return;
}
@ -2184,7 +2224,7 @@ static void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv,
u8 *req_ies = NULL, *resp_ies = NULL;
size_t req_ies_len = 0, resp_ies_len = 0;
if (bss->links[0].link_id == NL80211_DRV_LINK_ID_NA &&
if (!bss->valid_links &&
(tb[NL80211_ATTR_MLO_LINK_ID] ||
tb[NL80211_ATTR_MLD_ADDR])) {
wpa_printf(MSG_ERROR,
@ -2403,10 +2443,33 @@ static void nl80211_tdls_oper_event(struct wpa_driver_nl80211_data *drv,
}
static void nl80211_stop_ap(struct wpa_driver_nl80211_data *drv,
struct nlattr **tb)
static void nl80211_stop_ap(struct i802_bss *bss, struct nlattr **tb)
{
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_UNAVAILABLE, NULL);
struct i802_link *mld_link = NULL;
void *ctx = bss->ctx;
int link_id = -1;
if (tb[NL80211_ATTR_MLO_LINK_ID]) {
link_id = nla_get_u8(tb[NL80211_ATTR_MLO_LINK_ID]);
if (!nl80211_link_valid(bss->valid_links, link_id)) {
wpa_printf(MSG_DEBUG,
"nl80211: Ignoring STOP_AP event for invalid link ID %d (valid: 0x%04x)",
link_id, bss->valid_links);
return;
}
mld_link = nl80211_get_link(bss, link_id);
wpa_printf(MSG_DEBUG,
"nl80211: STOP_AP event on link %d", link_id);
ctx = mld_link->ctx;
/* The driver would have already deleted the link and this call
* will return an error. Ignore that since nl80211_remove_link()
* is called here only to update the bss->links[] state. */
nl80211_remove_link(bss, link_id);
}
wpa_supplicant_event(ctx, EVENT_INTERFACE_UNAVAILABLE, NULL);
}
@ -2452,7 +2515,6 @@ static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
{
union wpa_event_data data;
enum nl80211_radar_event event_type;
struct i802_link *mld_link = NULL;
if (!tb[NL80211_ATTR_WIPHY_FREQ] || !tb[NL80211_ATTR_RADAR_EVENT])
return;
@ -2462,11 +2524,13 @@ static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
data.dfs_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
event_type = nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT]);
if (data.dfs_event.freq) {
mld_link = nl80211_get_mld_link_by_freq(drv->first_bss,
data.dfs_event.freq);
if (mld_link)
data.dfs_event.link_id = mld_link->link_id;
if (tb[NL80211_ATTR_MLO_LINK_ID]) {
data.dfs_event.link_id =
nla_get_u8(tb[NL80211_ATTR_MLO_LINK_ID]);
} else if (data.dfs_event.freq) {
data.dfs_event.link_id =
nl80211_get_link_id_by_freq(drv->first_bss,
data.dfs_event.freq);
}
/* Check HT params */
@ -2832,7 +2896,6 @@ static void qca_nl80211_dfs_offload_radar_event(
{
union wpa_event_data data;
struct nlattr *tb[NL80211_ATTR_MAX + 1];
struct i802_link *mld_link = NULL;
wpa_printf(MSG_DEBUG,
"nl80211: DFS offload radar vendor event received");
@ -2851,11 +2914,13 @@ static void qca_nl80211_dfs_offload_radar_event(
data.dfs_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
data.dfs_event.link_id = NL80211_DRV_LINK_ID_NA;
if (data.dfs_event.freq) {
mld_link = nl80211_get_mld_link_by_freq(drv->first_bss,
data.dfs_event.freq);
if (mld_link)
data.dfs_event.link_id = mld_link->link_id;
if (tb[NL80211_ATTR_MLO_LINK_ID]) {
data.dfs_event.link_id =
nla_get_u8(tb[NL80211_ATTR_MLO_LINK_ID]);
} else if (data.dfs_event.freq) {
data.dfs_event.link_id =
nl80211_get_link_id_by_freq(drv->first_bss,
data.dfs_event.freq);
}
wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz, link=%d",
@ -2967,6 +3032,7 @@ static void send_vendor_scan_event(struct wpa_driver_nl80211_data *drv,
info = &event.scan_info;
info->aborted = aborted;
info->external_scan = external_scan;
info->scan_cookie = nla_get_u64(tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]);
if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS]) {
nla_for_each_nested(nl,
@ -3044,7 +3110,7 @@ static void qca_nl80211_scan_done_event(struct wpa_driver_nl80211_data *drv,
drv->scan_state = SCAN_ABORTED;
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
drv->ctx);
drv->first_bss->ctx);
drv->vendor_scan_cookie = 0;
drv->last_scan_cmd = 0;
}
@ -3655,8 +3721,7 @@ static void nl80211_sta_opmode_change_event(struct wpa_driver_nl80211_data *drv,
}
static void nl80211_control_port_frame(struct wpa_driver_nl80211_data *drv,
struct nlattr **tb)
static void nl80211_control_port_frame(struct i802_bss *bss, struct nlattr **tb)
{
u8 *src_addr;
u16 ethertype;
@ -3685,7 +3750,7 @@ static void nl80211_control_port_frame(struct wpa_driver_nl80211_data *drv,
MAC2STR(src_addr));
break;
case ETH_P_PAE:
drv_event_eapol_rx2(drv->ctx, src_addr,
drv_event_eapol_rx2(bss->ctx, src_addr,
nla_data(tb[NL80211_ATTR_FRAME]),
nla_len(tb[NL80211_ATTR_FRAME]),
encrypted, link_id);
@ -3701,10 +3766,11 @@ static void nl80211_control_port_frame(struct wpa_driver_nl80211_data *drv,
static void
nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv,
nl80211_control_port_frame_tx_status(struct i802_bss *bss,
const u8 *frame, size_t len,
struct nlattr *ack, struct nlattr *cookie)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
union wpa_event_data event;
if (!cookie || len < ETH_HLEN)
@ -3723,7 +3789,7 @@ nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv,
nla_get_u64(cookie) == drv->eapol_tx_cookie ?
drv->eapol_tx_link_id : NL80211_DRV_LINK_ID_NA;
wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);
wpa_supplicant_event(bss->ctx, EVENT_EAPOL_TX_STATUS, &event);
}
@ -3749,8 +3815,11 @@ static void nl80211_frame_wait_cancel(struct wpa_driver_nl80211_data *drv,
(long long unsigned int) cookie,
match ? " (match)" : "",
drv->send_frame_cookie == cookie ? " (match-saved)" : "");
if (drv->send_frame_cookie == cookie)
if (drv->send_frame_cookie == cookie) {
drv->send_frame_cookie = (u64) -1;
if (!match)
goto send_event;
}
if (!match)
return;
@ -3760,6 +3829,7 @@ static void nl80211_frame_wait_cancel(struct wpa_driver_nl80211_data *drv,
(drv->num_send_frame_cookies - i - 1) * sizeof(u64));
drv->num_send_frame_cookies--;
send_event:
wpa_supplicant_event(drv->ctx, EVENT_TX_WAIT_EXPIRE, NULL);
}
@ -3777,48 +3847,62 @@ static void nl80211_assoc_comeback(struct wpa_driver_nl80211_data *drv,
#ifdef CONFIG_IEEE80211AX
static void nl80211_obss_color_collision(struct i802_bss *bss,
struct nlattr *tb[])
static void nl80211_obss_color_event(struct i802_bss *bss,
enum nl80211_commands cmd,
struct nlattr *tb[])
{
union wpa_event_data data;
if (!tb[NL80211_ATTR_OBSS_COLOR_BITMAP])
return;
enum wpa_event_type event_type;
os_memset(&data, 0, sizeof(data));
data.bss_color_collision.bitmap =
nla_get_u64(tb[NL80211_ATTR_OBSS_COLOR_BITMAP]);
data.bss_color_collision.link_id = NL80211_DRV_LINK_ID_NA;
wpa_printf(MSG_DEBUG, "nl80211: BSS color collision - bitmap %08llx",
(long long unsigned int) data.bss_color_collision.bitmap);
wpa_supplicant_event(bss->ctx, EVENT_BSS_COLOR_COLLISION, &data);
}
switch (cmd) {
case NL80211_CMD_OBSS_COLOR_COLLISION:
event_type = EVENT_BSS_COLOR_COLLISION;
if (!tb[NL80211_ATTR_OBSS_COLOR_BITMAP])
return;
data.bss_color_collision.bitmap =
nla_get_u64(tb[NL80211_ATTR_OBSS_COLOR_BITMAP]);
wpa_printf(MSG_DEBUG,
"nl80211: BSS color collision - bitmap %08llx",
(long long unsigned int)
data.bss_color_collision.bitmap);
break;
case NL80211_CMD_COLOR_CHANGE_STARTED:
event_type = EVENT_CCA_STARTED_NOTIFY;
wpa_printf(MSG_DEBUG, "nl80211: CCA started");
break;
case NL80211_CMD_COLOR_CHANGE_ABORTED:
event_type = EVENT_CCA_ABORTED_NOTIFY;
wpa_printf(MSG_DEBUG, "nl80211: CCA aborted");
break;
case NL80211_CMD_COLOR_CHANGE_COMPLETED:
event_type = EVENT_CCA_NOTIFY;
wpa_printf(MSG_DEBUG, "nl80211: CCA completed");
break;
default:
wpa_printf(MSG_DEBUG, "nl80211: Unknown CCA command %d", cmd);
return;
}
if (tb[NL80211_ATTR_MLO_LINK_ID]) {
data.bss_color_collision.link_id =
nla_get_u8(tb[NL80211_ATTR_MLO_LINK_ID]);
static void nl80211_color_change_announcement_started(struct i802_bss *bss)
{
union wpa_event_data data = {};
if (!nl80211_link_valid(bss->valid_links,
data.bss_color_collision.link_id)) {
wpa_printf(MSG_DEBUG,
"nl80211: Invalid BSS color event link ID %d",
data.bss_color_collision.link_id);
return;
}
wpa_printf(MSG_DEBUG, "nl80211: CCA started");
wpa_supplicant_event(bss->ctx, EVENT_CCA_STARTED_NOTIFY, &data);
}
wpa_printf(MSG_DEBUG, "nl80211: BSS color event - Link ID %d",
data.bss_color_collision.link_id);
}
static void nl80211_color_change_announcement_aborted(struct i802_bss *bss)
{
union wpa_event_data data = {};
wpa_printf(MSG_DEBUG, "nl80211: CCA aborted");
wpa_supplicant_event(bss->ctx, EVENT_CCA_ABORTED_NOTIFY, &data);
}
static void nl80211_color_change_announcement_completed(struct i802_bss *bss)
{
union wpa_event_data data = {};
wpa_printf(MSG_DEBUG, "nl80211: CCA completed");
wpa_supplicant_event(bss->ctx, EVENT_CCA_NOTIFY, &data);
wpa_supplicant_event(bss->ctx, event_type, &data);
}
#endif /* CONFIG_IEEE80211AX */
@ -3865,7 +3949,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
switch (cmd) {
case NL80211_CMD_TRIGGER_SCAN:
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger");
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Scan trigger");
drv->scan_state = SCAN_STARTED;
if (drv->scan_for_auth) {
/*
@ -3877,40 +3961,40 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
wpa_printf(MSG_DEBUG, "nl80211: Do not indicate scan-start event due to internal scan_for_auth");
break;
}
wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
wpa_supplicant_event(bss->ctx, EVENT_SCAN_STARTED, NULL);
break;
case NL80211_CMD_START_SCHED_SCAN:
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started");
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Sched scan started");
drv->scan_state = SCHED_SCAN_STARTED;
break;
case NL80211_CMD_SCHED_SCAN_STOPPED:
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
drv->scan_state = SCHED_SCAN_STOPPED;
wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
wpa_supplicant_event(bss->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
break;
case NL80211_CMD_NEW_SCAN_RESULTS:
wpa_dbg(drv->ctx, MSG_DEBUG,
wpa_dbg(bss->ctx, MSG_DEBUG,
"nl80211: New scan results available");
if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
drv->scan_state = SCAN_COMPLETED;
drv->scan_complete_events = 1;
if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
drv, drv->ctx);
drv, bss->ctx);
drv->last_scan_cmd = 0;
} else {
external_scan_event = 1;
}
send_scan_event(drv, 0, tb, external_scan_event);
send_scan_event(bss, 0, tb, external_scan_event);
break;
case NL80211_CMD_SCHED_SCAN_RESULTS:
wpa_dbg(drv->ctx, MSG_DEBUG,
wpa_dbg(bss->ctx, MSG_DEBUG,
"nl80211: New sched scan results available");
drv->scan_state = SCHED_SCAN_RESULTS;
send_scan_event(drv, 0, tb, 0);
send_scan_event(bss, 0, tb, 0);
break;
case NL80211_CMD_SCAN_ABORTED:
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Scan aborted");
if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
drv->scan_state = SCAN_ABORTED;
if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
@ -3919,12 +4003,12 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
* order not to make wpa_supplicant stop its scanning.
*/
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
drv, drv->ctx);
drv, bss->ctx);
drv->last_scan_cmd = 0;
} else {
external_scan_event = 1;
}
send_scan_event(drv, 1, tb, external_scan_event);
send_scan_event(bss, 1, tb, external_scan_event);
break;
case NL80211_CMD_AUTHENTICATE:
case NL80211_CMD_ASSOCIATE:
@ -4002,7 +4086,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
mlme_event_remain_on_channel(drv, 1, tb);
break;
case NL80211_CMD_NOTIFY_CQM:
nl80211_cqm_event(drv, tb);
nl80211_cqm_event(bss, tb);
break;
case NL80211_CMD_REG_CHANGE:
case NL80211_CMD_WIPHY_REG_CHANGE:
@ -4039,7 +4123,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
nl80211_radar_event(drv, tb);
break;
case NL80211_CMD_STOP_AP:
nl80211_stop_ap(drv, tb);
nl80211_stop_ap(bss, tb);
break;
case NL80211_CMD_VENDOR:
nl80211_vendor_event(drv, tb);
@ -4064,7 +4148,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
case NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS:
if (!frame)
break;
nl80211_control_port_frame_tx_status(drv,
nl80211_control_port_frame_tx_status(bss,
nla_data(frame),
nla_len(frame),
tb[NL80211_ATTR_ACK],
@ -4079,16 +4163,10 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
break;
#ifdef CONFIG_IEEE80211AX
case NL80211_CMD_OBSS_COLOR_COLLISION:
nl80211_obss_color_collision(bss, tb);
break;
case NL80211_CMD_COLOR_CHANGE_STARTED:
nl80211_color_change_announcement_started(bss);
break;
case NL80211_CMD_COLOR_CHANGE_ABORTED:
nl80211_color_change_announcement_aborted(bss);
break;
case NL80211_CMD_COLOR_CHANGE_COMPLETED:
nl80211_color_change_announcement_completed(bss);
nl80211_obss_color_event(bss, cmd, tb);
break;
#endif /* CONFIG_IEEE80211AX */
case NL80211_CMD_LINKS_REMOVED:
@ -4179,7 +4257,16 @@ int process_global_event(struct nl_msg *msg, void *arg)
wdev_id == bss->wdev_id)) {
processed = true;
do_process_drv_event(bss, gnlh->cmd, tb);
if (!wiphy_idx_set)
/* There are two types of events that may need
* to be delivered to multiple interfaces:
* 1. Events for a wiphy, as it can have
* multiple interfaces.
* 2. "Global" events, like
* NL80211_CMD_REG_CHANGE.
*
* Terminate early only if the event is directed
* to a specific interface or wdev. */
if (ifidx != -1 || wdev_id_set)
return NL_SKIP;
/* The driver instance could have been removed,
* e.g., due to NL80211_CMD_RADAR_DETECT event,
@ -4237,7 +4324,7 @@ int process_bss_event(struct nl_msg *msg, void *arg)
nl80211_external_auth(bss->drv, tb);
break;
case NL80211_CMD_CONTROL_PORT_FRAME:
nl80211_control_port_frame(bss->drv, tb);
nl80211_control_port_frame(bss, tb);
break;
default:
wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "

View file

@ -153,6 +153,7 @@ fail:
void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_driver_nl80211_data *drv = eloop_ctx;
struct i802_bss *bss;
wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it");
#ifdef CONFIG_DRIVER_NL80211_QCA
@ -160,14 +161,27 @@ void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
nl80211_abort_vendor_scan(drv, drv->vendor_scan_cookie) == 0)
return;
#endif /* CONFIG_DRIVER_NL80211_QCA */
if (!drv->vendor_scan_cookie &&
nl80211_abort_scan(drv->first_bss) == 0)
for (bss = drv->first_bss; bss; bss = bss->next) {
if (bss->scan_link)
break;
}
if (!bss) {
wpa_printf(MSG_DEBUG, "nl80211: Failed to find scan BSS");
return;
}
if (!drv->vendor_scan_cookie &&
nl80211_abort_scan(bss) == 0) {
bss->scan_link = NULL;
return;
}
wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED)
nl80211_restore_ap_mode(drv->first_bss);
nl80211_restore_ap_mode(bss);
wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results");
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
@ -347,7 +361,7 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
int ret = -1, timeout;
struct nl_msg *msg = NULL;
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: scan request");
drv->scan_for_auth = 0;
if (TEST_FAIL())
@ -402,23 +416,52 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
"(%s)", ret, strerror(-ret));
if (drv->hostapd && is_ap_interface(drv->nlmode)) {
enum nl80211_iftype old_mode = drv->nlmode;
#ifdef CONFIG_IEEE80211BE
/* For multi link BSS, retry scan if any other links
* are busy scanning. */
if (ret == -EBUSY &&
nl80211_link_valid(bss->valid_links,
params->link_id)) {
struct i802_bss *link_bss;
u8 link_id;
wpa_printf(MSG_DEBUG,
"nl80211: Scan trigger on multi link BSS failed (requested link=%d on interface %s)",
params->link_id, bss->ifname);
for (link_bss = drv->first_bss; link_bss;
link_bss = link_bss->next) {
if (link_bss->scan_link)
break;
}
if (!link_bss) {
wpa_printf(MSG_DEBUG,
"nl80211: BSS information already running scan not available");
goto fail;
}
link_id = nl80211_get_link_id_from_link(
link_bss, link_bss->scan_link);
wpa_printf(MSG_DEBUG,
"nl80211: Scan already running on interface %s link %d",
link_bss->ifname, link_id);
goto fail;
}
#endif /* CONFIG_IEEE80211BE */
/*
* mac80211 does not allow scan requests in AP mode, so
* try to do this in station mode.
*/
drv->ap_scan_as_station = drv->nlmode;
if (wpa_driver_nl80211_set_mode(
bss, NL80211_IFTYPE_STATION))
goto fail;
if (wpa_driver_nl80211_scan(bss, params)) {
wpa_driver_nl80211_set_mode(bss, old_mode);
bss, NL80211_IFTYPE_STATION) ||
wpa_driver_nl80211_scan(bss, params)) {
nl80211_restore_ap_mode(bss);
goto fail;
}
/* Restore AP mode when processing scan results */
drv->ap_scan_as_station = old_mode;
ret = 0;
} else
goto fail;
@ -440,11 +483,20 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
}
wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
"seconds", ret, timeout);
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx);
eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
drv, drv->ctx);
drv, bss->ctx);
drv->last_scan_cmd = NL80211_CMD_TRIGGER_SCAN;
bss->scan_link = bss->flink;
if (is_ap_interface(drv->nlmode) &&
nl80211_link_valid(bss->valid_links, params->link_id)) {
wpa_dbg(bss->ctx, MSG_DEBUG,
"nl80211: Scan requested for link %d",
params->link_id);
bss->scan_link = nl80211_get_link(bss, params->link_id);
}
fail:
nlmsg_free(msg);
return ret;
@ -728,7 +780,7 @@ static int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv,
static struct wpa_scan_res *
nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
struct nl_msg *msg)
struct nl_msg *msg, const u8 *bssid)
{
struct nlattr *tb[NL80211_ATTR_MAX + 1];
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
@ -762,6 +814,9 @@ nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
bss_policy))
return NULL;
if (bssid && bss[NL80211_BSS_BSSID] &&
!ether_addr_equal(bssid, nla_data(bss[NL80211_BSS_BSSID])))
return NULL;
if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
@ -866,6 +921,7 @@ nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
struct nl80211_bss_info_arg {
struct wpa_driver_nl80211_data *drv;
struct wpa_scan_results *res;
const u8 *bssid;
};
static int bss_info_handler(struct nl_msg *msg, void *arg)
@ -875,7 +931,7 @@ static int bss_info_handler(struct nl_msg *msg, void *arg)
struct wpa_scan_res **tmp;
struct wpa_scan_res *r;
r = nl80211_parse_bss_info(_arg->drv, msg);
r = nl80211_parse_bss_info(_arg->drv, msg, _arg->bssid);
if (!r)
return NL_SKIP;
@ -973,7 +1029,7 @@ static void nl80211_update_scan_res_noise(struct wpa_scan_res *res,
static struct wpa_scan_results *
nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv, const u8 *bssid)
{
struct nl_msg *msg;
struct wpa_scan_results *res;
@ -993,6 +1049,7 @@ try_again:
arg.drv = drv;
arg.res = res;
arg.bssid = bssid;
ret = send_and_recv_resp(drv, msg, bss_info_handler, &arg);
if (ret == -EAGAIN) {
count++;
@ -1029,16 +1086,18 @@ try_again:
/**
* wpa_driver_nl80211_get_scan_results - Fetch the latest scan results
* @priv: Pointer to private wext data from wpa_driver_nl80211_init()
* @priv: Pointer to private nl80211 data from wpa_driver_nl80211_init()
* @bssid: Return results only for the specified BSSID, %NULL for all
* Returns: Scan results on success, -1 on failure
*/
struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv)
struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv,
const u8 *bssid)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
struct wpa_scan_results *res;
res = nl80211_get_scan_results(drv);
res = nl80211_get_scan_results(drv, bssid);
if (res)
wpa_driver_nl80211_check_bss_status(drv, res);
return res;
@ -1055,7 +1114,7 @@ static int nl80211_dump_scan_handler(struct nl_msg *msg, void *arg)
struct nl80211_dump_scan_ctx *ctx = arg;
struct wpa_scan_res *r;
r = nl80211_parse_bss_info(ctx->drv, msg);
r = nl80211_parse_bss_info(ctx->drv, msg, NULL);
if (!r)
return NL_SKIP;
wpa_printf(MSG_DEBUG, "nl80211: %d " MACSTR " %d%s",
@ -1268,6 +1327,11 @@ int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
goto fail;
}
if (is_ap_interface(drv->nlmode) &&
params->link_id != NL80211_DRV_LINK_ID_NA &&
nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_SCAN_LINK_ID, params->link_id))
goto fail;
nla_nest_end(msg, attr);
ret = send_and_recv_resp(drv, msg, scan_cookie_handler, &cookie);
@ -1287,9 +1351,9 @@ int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
wpa_printf(MSG_DEBUG,
"nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx",
ret, (long long unsigned int) cookie);
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx);
eloop_register_timeout(30, 0, wpa_driver_nl80211_scan_timeout,
drv, drv->ctx);
drv, bss->ctx);
drv->last_scan_cmd = NL80211_CMD_VENDOR;
fail:

File diff suppressed because it is too large Load diff

View file

@ -255,8 +255,18 @@ static void * eap_wsc_init(struct eap_sm *sm)
cfg.new_ap_settings = &new_ap_settings;
}
if (os_strstr(phase1, "multi_ap=1"))
cfg.multi_ap_backhaul_sta = 1;
pos = os_strstr(phase1, "multi_ap=");
if (pos) {
u16 id = atoi(pos + 9);
if (id != 0) {
cfg.multi_ap_backhaul_sta = 1;
cfg.multi_ap_profile = id;
} else {
wpa_printf(MSG_DEBUG,
"EAP-WSC: Invalid multi_ap setting");
}
}
data->wps = wps_init(&cfg);
if (data->wps == NULL) {

View file

@ -18,11 +18,6 @@
#include "fst/fst_ctrl_defs.h"
#endif /* CONFIG_FST_TEST */
#define US_80211_TU 1024
#define US_TO_TU(m) ((m) * / US_80211_TU)
#define TU_TO_US(m) ((m) * US_80211_TU)
#define FST_LLT_SWITCH_IMMEDIATELY 0
#define fst_printf_session(s, level, format, ...) \
@ -182,7 +177,8 @@ static void fst_session_timeout_handler(void *eloop_data, void *user_ctx)
static void fst_session_stt_arm(struct fst_session *s)
{
/* Action frames sometimes get delayed. Use relaxed timeout (2*) */
eloop_register_timeout(0, 2 * TU_TO_US(FST_DEFAULT_SESSION_TIMEOUT_TU),
eloop_register_timeout(0,
2 * TU_TO_USEC(FST_DEFAULT_SESSION_TIMEOUT_TU),
fst_session_timeout_handler, NULL, s);
s->stt_armed = true;
}

View file

@ -30,6 +30,9 @@
#include "eloop.h"
#include "l2_packet.h"
#ifndef ETHER_VLAN_ENCAP_LEN
#define ETHER_VLAN_ENCAP_LEN 4
#endif
static const u8 pae_group_addr[ETH_ALEN] =
{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };

View file

@ -954,6 +954,7 @@ static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
dev->info.wps_vendor_ext[i] = NULL;
}
os_free(dev->bootstrap_params);
wpabuf_free(dev->info.wfd_subelems);
wpabuf_free(dev->info.vendor_elems);
wpabuf_free(dev->go_neg_conf);
@ -1599,7 +1600,8 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
int go_intent, const u8 *own_interface_addr,
unsigned int force_freq, int persistent_group,
const u8 *force_ssid, size_t force_ssid_len,
int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id)
int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id,
bool p2p2, u16 bootstrap, const char *password)
{
struct p2p_device *dev;
@ -1683,6 +1685,10 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
dev->wps_method = wps_method;
dev->oob_pw_id = oob_pw_id;
dev->p2p2 = p2p2;
dev->req_bootstrap_method = bootstrap;
if (password && os_strlen(password) < sizeof(dev->password))
os_strlcpy(dev->password, password, sizeof(dev->password));
dev->status = P2P_SC_SUCCESS;
if (p2p->p2p_scan_running) {
@ -1701,7 +1707,8 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
int go_intent, const u8 *own_interface_addr,
unsigned int force_freq, int persistent_group,
const u8 *force_ssid, size_t force_ssid_len,
unsigned int pref_freq, u16 oob_pw_id)
unsigned int pref_freq, u16 oob_pw_id, u16 bootstrap,
const char *password)
{
struct p2p_device *dev;
@ -1735,6 +1742,10 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
dev->flags &= ~P2P_DEV_USER_REJECTED;
dev->go_neg_req_sent = 0;
dev->go_state = UNKNOWN_GO;
dev->req_bootstrap_method = bootstrap;
if (password && os_strlen(password) < sizeof(dev->password))
os_strlcpy(dev->password, password, sizeof(dev->password));
p2p_set_dev_persistent(dev, persistent_group);
p2p->go_intent = go_intent;
os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
@ -1924,10 +1935,10 @@ static void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
break;
case P2P_PROV_DISC_REQ:
p2p_process_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
p2p_handle_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
break;
case P2P_PROV_DISC_RESP:
p2p_process_prov_disc_resp(p2p, sa, data + 1, len - 1);
p2p_handle_prov_disc_resp(p2p, sa, data + 1, len - 1, rx_freq);
break;
case P2P_DEV_DISC_REQ:
p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
@ -2968,6 +2979,44 @@ bool is_p2p_6ghz_disabled(struct p2p_data *p2p)
}
static void p2p_pairing_info_deinit(struct p2p_data *p2p)
{
os_free(p2p->pairing_info);
}
static int p2p_pairing_info_init(struct p2p_data *p2p)
{
struct p2p_pairing_info *pairing_info;
if (p2p->cfg->pairing_config.dik_len > DEVICE_IDENTITY_KEY_MAX_LEN)
return -1;
pairing_info = os_zalloc(sizeof(struct p2p_pairing_info));
if (!pairing_info)
return -1;
pairing_info->enable_pairing_setup =
p2p->cfg->pairing_config.enable_pairing_setup;
pairing_info->enable_pairing_cache =
p2p->cfg->pairing_config.enable_pairing_cache;
pairing_info->supported_bootstrap =
p2p->cfg->pairing_config.bootstrap_methods;
pairing_info->dev_ik.cipher_version =
p2p->cfg->pairing_config.dik_cipher;
pairing_info->dev_ik.dik_len = p2p->cfg->pairing_config.dik_len;
os_memcpy(pairing_info->dev_ik.dik_data,
p2p->cfg->pairing_config.dik_data,
p2p->cfg->pairing_config.dik_len);
p2p_pairing_info_deinit(p2p);
p2p->pairing_info = pairing_info;
return 0;
}
struct p2p_data * p2p_init(const struct p2p_config *cfg)
{
struct p2p_data *p2p;
@ -3023,6 +3072,10 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg)
p2p->go_timeout = 100;
p2p->client_timeout = 20;
p2p->num_p2p_sd_queries = 0;
/* Default comeback after one second */
if (!p2p->cfg->comeback_after)
p2p->cfg->comeback_after = 977; /* TUs */
p2p_pairing_info_init(p2p);
p2p_dbg(p2p, "initialized");
p2p_channels_dump(p2p, "channels", &p2p->cfg->channels);
@ -3066,6 +3119,7 @@ void p2p_deinit(struct p2p_data *p2p)
p2p_remove_wps_vendor_extensions(p2p);
os_free(p2p->no_go_freq.range);
p2p_service_flush_asp(p2p);
p2p_pairing_info_deinit(p2p);
os_free(p2p);
}
@ -3332,7 +3386,7 @@ skip_sd:
}
static void p2p_sd_cb(struct p2p_data *p2p, int success)
void p2p_sd_query_cb(struct p2p_data *p2p, int success)
{
p2p_dbg(p2p, "Service Discovery Query TX callback: success=%d",
success);
@ -3399,7 +3453,7 @@ static void p2p_retry_pd(struct p2p_data *p2p)
if (!ether_addr_equal(p2p->pending_pd_devaddr,
dev->info.p2p_device_addr))
continue;
if (!dev->req_config_methods)
if (!dev->req_config_methods && !dev->req_bootstrap_method)
continue;
p2p_dbg(p2p, "Send pending Provision Discovery Request to "
@ -3835,7 +3889,7 @@ void p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
p2p_go_neg_conf_cb(p2p, result);
break;
case P2P_PENDING_SD:
p2p_sd_cb(p2p, success);
p2p_sd_query_cb(p2p, success);
break;
case P2P_PENDING_PD:
p2p_prov_disc_cb(p2p, success);
@ -5688,3 +5742,184 @@ void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value)
{
p2p->allow_6ghz = value;
}
static int p2p_derive_nonce_tag(struct p2p_data *p2p)
{
u8 dira_nonce[DEVICE_IDENTITY_NONCE_LEN];
u8 dira_tag[DEVICE_MAX_HASH_LEN];
u8 data[DIR_STR_LEN + DEVICE_IDENTITY_NONCE_LEN + ETH_ALEN];
struct p2p_id_key *dev_ik;
dev_ik = &p2p->pairing_info->dev_ik;
if (dev_ik->cipher_version != DIRA_CIPHER_VERSION_128) {
wpa_printf(MSG_INFO,
"P2P: Unsupported DIRA Cipher version = %d",
dev_ik->cipher_version);
return -1;
}
if (dev_ik->dik_len != DEVICE_IDENTITY_KEY_LEN) {
wpa_printf(MSG_INFO, "P2P: Invalid DIK length = %zu",
dev_ik->dik_len);
return -1;
}
os_memset(data, 0, sizeof(data));
if (os_get_random(dira_nonce, DEVICE_IDENTITY_NONCE_LEN) < 0) {
wpa_printf(MSG_ERROR, "P2P: Failed to generate DIRA nonce");
return -1;
}
/* Tag = Truncate-64(HMAC-SHA-256(DevIK,
* "DIR" || P2P Device Address || Nonce))
*/
os_memcpy(data, "DIR", DIR_STR_LEN);
os_memcpy(&data[DIR_STR_LEN], p2p->cfg->dev_addr, ETH_ALEN);
os_memcpy(&data[DIR_STR_LEN + ETH_ALEN], dira_nonce,
DEVICE_IDENTITY_NONCE_LEN);
if (hmac_sha256(dev_ik->dik_data, dev_ik->dik_len, data, sizeof(data),
dira_tag) < 0) {
wpa_printf(MSG_ERROR, "P2P: Could not derive DIRA tag");
return -1;
}
dev_ik->dira_nonce_len = DEVICE_IDENTITY_NONCE_LEN;
os_memcpy(dev_ik->dira_nonce, dira_nonce, DEVICE_IDENTITY_NONCE_LEN);
dev_ik->dira_tag_len = DEVICE_IDENTITY_TAG_LEN;
os_memcpy(dev_ik->dira_tag, dira_tag, DEVICE_IDENTITY_TAG_LEN);
wpa_hexdump_key(MSG_DEBUG, "P2P: DIK", dev_ik->dik_data,
dev_ik->dik_len);
wpa_hexdump_key(MSG_DEBUG, "P2P: DIRA-NONCE", dev_ik->dira_nonce,
dev_ik->dira_nonce_len);
wpa_hexdump_key(MSG_DEBUG, "P2P: DIRA-TAG", dev_ik->dira_tag,
dev_ik->dira_tag_len);
return 0;
}
struct wpabuf * p2p_usd_elems(struct p2p_data *p2p)
{
struct wpabuf *buf;
u8 *len;
u8 group_capab;
buf = wpabuf_alloc(1000);
if (!buf)
return NULL;
len = p2p_buf_add_ie_hdr(buf);
/* P2P Capability attribute */
group_capab = 0;
if (p2p->num_groups) {
group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
(p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) &&
p2p->cross_connect)
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
}
if (p2p->cfg->p2p_intra_bss)
group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
p2p_buf_add_capability(buf, p2p->dev_capab &
~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
group_capab);
/* P2P Device Info attribute */
p2p_buf_add_device_info(buf, p2p, NULL);
p2p_buf_update_ie_hdr(buf, len);
len = p2p_buf_add_p2p2_ie_hdr(buf);
/* P2P Capability Extension attribute */
p2p_buf_add_pcea(buf, p2p);
/* P2P Pairing Bootstrapping Method attribute */
p2p_buf_add_pbma(buf, p2p->cfg->pairing_config.bootstrap_methods, NULL,
0, 0);
/* P2P Device Identity Resolution attribute */
if (p2p->pairing_info &&
p2p->cfg->pairing_config.pairing_capable &&
p2p->cfg->pairing_config.enable_pairing_cache &&
p2p->cfg->pairing_config.enable_pairing_verification &&
p2p_derive_nonce_tag(p2p) == 0)
p2p_buf_add_dira(buf, p2p);
p2p_buf_update_ie_hdr(buf, len);
return buf;
}
void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len,
const u8 *peer_addr, unsigned int freq)
{
struct p2p_device *dev;
struct p2p_message msg;
const u8 *p2p_dev_addr;
os_memset(&msg, 0, sizeof(msg));
if (p2p_parse_ies(ies, ies_len, &msg)) {
p2p_dbg(p2p, "Failed to parse P2P IE for a device entry");
p2p_parse_free(&msg);
return;
}
if (msg.p2p_device_addr)
p2p_dev_addr = msg.p2p_device_addr;
else
p2p_dev_addr = peer_addr;
dev = p2p_create_device(p2p, p2p_dev_addr);
if (!dev) {
p2p_parse_free(&msg);
p2p_dbg(p2p, "Failed to add a peer P2P Device");
return;
}
dev->p2p2 = true;
/* Reset info from old IEs */
dev->info.reg_info = 0;
os_memset(&dev->info.pairing_config, 0,
sizeof(struct p2p_pairing_config));
os_get_reltime(&dev->last_seen);
dev->listen_freq = freq;
dev->oper_freq = freq;
if (msg.capability) {
/*
* P2P Client Discoverability bit is reserved in all frames
* that use this function, so do not change its value here.
*/
dev->info.dev_capab &= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
dev->info.dev_capab |= msg.capability[0] &
~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
dev->info.group_capab = msg.capability[1];
}
if (msg.pcea_info && msg.pcea_info_len >= 2)
p2p_process_pcea(p2p, &msg, dev);
if (msg.pbma_info && msg.pbma_info_len == 2)
dev->info.pairing_config.bootstrap_methods =
WPA_GET_LE16(msg.pbma_info);
if (!ether_addr_equal(peer_addr, p2p_dev_addr))
os_memcpy(dev->interface_addr, peer_addr, ETH_ALEN);
p2p_dbg(p2p, "Updated device entry based on USD frame: " MACSTR
" dev_capab=0x%x group_capab=0x%x listen_freq=%d",
MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
dev->info.group_capab, dev->listen_freq);
p2p->cfg->dev_found(p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
&dev->info, !(dev->flags & P2P_DEV_REPORTED_ONCE));
p2p_parse_free(&msg);
}

View file

@ -12,6 +12,16 @@
#include "common/ieee802_11_defs.h"
#include "wps/wps.h"
#define DEVICE_IDENTITY_KEY_MAX_LEN 64
#define DEVICE_IDENTITY_KEY_LEN 16
#define DEVICE_IDENTITY_TAG_LEN 8
#define DEVICE_IDENTITY_NONCE_LEN 8
#define DEVICE_MAX_HASH_LEN 32
#define DIR_STR_LEN 3
/* DIRA Cipher versions */
#define DIRA_CIPHER_VERSION_128 0
struct weighted_pcl;
/* P2P ASP Setup Capability */
@ -320,6 +330,50 @@ enum p2p_scan_type {
#define P2P_MAX_WPS_VENDOR_EXT 10
/**
* struct p2p_pairing_config - P2P pairing configuration
*/
struct p2p_pairing_config {
/**
* Pairing capable
*/
bool pairing_capable;
/**
* Enable P2P pairing setup
*/
bool enable_pairing_setup;
/**
* Enable pairing cache to allow verification
*/
bool enable_pairing_cache;
/**
* Enable P2P pairing verification with cached NIK/NPK
*/
bool enable_pairing_verification;
/**
* P2P bootstrapping methods supported
*/
u16 bootstrap_methods;
/**
* Bitmap of supported PASN types
*/
u8 pasn_type;
/* Cipher version type */
int dik_cipher;
/* Buffer to hold the DevIK */
u8 dik_data[DEVICE_IDENTITY_KEY_MAX_LEN];
/* Length of DevIK in octets */
size_t dik_len;
};
/**
* struct p2p_peer_info - P2P peer information
*/
@ -411,6 +465,21 @@ struct p2p_peer_info {
* p2ps_instance - P2PS Application Service Info
*/
struct wpabuf *p2ps_instance;
/**
* pcea_cap_info - Capability info in PCEA
*/
u16 pcea_cap_info;
/**
* The regulatory info encoding for operation in 6 GHz band
*/
u8 reg_info;
/**
* p2p_pairing_config - P2P pairing configuration
*/
struct p2p_pairing_config pairing_config;
};
enum p2p_prov_disc_status {
@ -589,6 +658,33 @@ struct p2p_config {
*/
unsigned int passphrase_len;
/**
* p2p_pairing_config - P2P pairing configuration
*/
struct p2p_pairing_config pairing_config;
/**
* reg_info - Regulatory info encoding for operation in 6 GHz band
*/
u8 reg_info;
/**
* dfs_owner - Enable P2P GO to act as DFS Owner
*/
bool dfs_owner;
/**
* twt_power_mgmt - Enable TWT based power management for P2P
*/
bool twt_power_mgmt;
/**
* comeback_after - Bootstrap request unauthorized for peer
*
* Ask to come back after this many TUs.
*/
u16 comeback_after;
/**
* cb_ctx - Context to use with callback functions
*/
@ -1136,6 +1232,19 @@ struct p2p_config {
int (*get_pref_freq_list)(void *ctx, int go,
unsigned int *len,
struct weighted_pcl *freq_list);
/**
* register_bootstrap_comeback - Register timeout to initiate bootstrap
* comeback request
* @ctx: Callback context from cb_ctx
* @addr: P2P Device Address to which comeback request is to be sent
* @comeback_after: Time in TUs after which comeback request is sent
*
* This function can be used to send comeback request after given
* timeout.
*/
void (*register_bootstrap_comeback)(void *ctx, const u8 *addr,
u16 comeback_after);
};
@ -1319,6 +1428,10 @@ void p2p_stop_listen(struct p2p_data *p2p);
* formation
* @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if
* force_freq == 0)
* @oob_pw_id: OOB password identifier
* @p2p2: Device supports P2P2 features
* @bootstrap: Bootstrapping method requested for P2P2 provision discovery
* @password: P2P2 pairing password or %NULL for opportunistic method
* Returns: 0 on success, -1 on failure
*/
int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
@ -1326,7 +1439,8 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
int go_intent, const u8 *own_interface_addr,
unsigned int force_freq, int persistent_group,
const u8 *force_ssid, size_t force_ssid_len,
int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id);
int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id,
bool p2p2, u16 bootstrap, const char *password);
/**
* p2p_authorize - Authorize P2P group formation (GO negotiation)
@ -1344,6 +1458,9 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
* @force_ssid_len: Length of $force_ssid buffer
* @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if
* force_freq == 0)
* @oob_pw_id: OOB password identifier
* @bootstrap: Bootstrapping method requested for P2P2 provision discovery
* @password: P2P2 pairing password or %NULL for opportunistic method
* Returns: 0 on success, -1 on failure
*
* This is like p2p_connect(), but the actual group negotiation is not
@ -1354,7 +1471,8 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
int go_intent, const u8 *own_interface_addr,
unsigned int force_freq, int persistent_group,
const u8 *force_ssid, size_t force_ssid_len,
unsigned int pref_freq, u16 oob_pw_id);
unsigned int pref_freq, u16 oob_pw_id, u16 bootstrap,
const char *password);
/**
* p2p_reject - Reject peer device (explicitly block connection attempts)
@ -2429,5 +2547,8 @@ bool is_p2p_allow_6ghz(struct p2p_data *p2p);
void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value);
int p2p_remove_6ghz_channels(struct weighted_pcl *pref_freq_list, int size);
int p2p_channel_to_freq(int op_class, int channel);
struct wpabuf * p2p_usd_elems(struct p2p_data *p2p);
void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len,
const u8 *peer_addr, unsigned int freq);
#endif /* P2P_H */

View file

@ -55,11 +55,24 @@ u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf)
void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len)
{
/* Update P2P IE Length */
/* Update P2P/P2P2 IE Length */
*len = (u8 *) wpabuf_put(buf, 0) - len - 1;
}
u8 * p2p_buf_add_p2p2_ie_hdr(struct wpabuf *buf)
{
u8 *len;
/* P2P2 IE header */
wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
len = wpabuf_put(buf, 1); /* IE length to be filled */
wpabuf_put_be32(buf, P2P2_IE_VENDOR_TYPE);
wpa_printf(MSG_DEBUG, "P2P: * P2P2 IE header");
return len;
}
void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab)
{
/* P2P Capability */
@ -709,6 +722,111 @@ void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr,
}
void p2p_buf_add_pcea(struct wpabuf *buf, struct p2p_data *p2p)
{
u8 *len;
u16 capability_info = 0;
/* P2P Capability Extension */
wpabuf_put_u8(buf, P2P_ATTR_CAPABILITY_EXTENSION);
/* Length to be filled */
len = wpabuf_put(buf, 2);
if (!p2p->cfg->p2p_6ghz_disable)
capability_info |= P2P_PCEA_6GHZ;
if (p2p->cfg->reg_info)
capability_info |= P2P_PCEA_REG_INFO;
if (p2p->cfg->dfs_owner)
capability_info |= P2P_PCEA_DFS_OWNER;
if (p2p->cfg->pairing_config.pairing_capable)
capability_info |= P2P_PCEA_PAIRING_CAPABLE;
if (p2p->cfg->pairing_config.enable_pairing_setup)
capability_info |= P2P_PCEA_PAIRING_SETUP_ENABLED;
if (p2p->cfg->pairing_config.enable_pairing_cache)
capability_info |= P2P_PCEA_PMK_CACHING;
if (p2p->cfg->pairing_config.pasn_type)
capability_info |= P2P_PCEA_PASN_TYPE;
if (p2p->cfg->twt_power_mgmt)
capability_info |= P2P_PCEA_TWT_POWER_MGMT;
/* Field length is (n-1), n in octets */
capability_info |= (2 - 1) & P2P_PCEA_LEN_MASK;
wpabuf_put_le16(buf, capability_info);
if (capability_info & P2P_PCEA_REG_INFO)
wpabuf_put_u8(buf, p2p->cfg->reg_info);
if (capability_info & P2P_PCEA_PASN_TYPE)
wpabuf_put_u8(buf, p2p->cfg->pairing_config.pasn_type);
/* Update attribute length */
WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
wpa_printf(MSG_DEBUG, "P2P: * Capability Extension info=0x%x",
capability_info);
}
void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie,
size_t cookie_len, int comeback_after)
{
u8 *len;
/* P2P Pairing and Bootstrapping methods */
wpabuf_put_u8(buf, P2P_ATTR_PAIRING_AND_BOOTSTRAPPING);
/* Length to be filled */
len = wpabuf_put(buf, 2);
if (cookie && cookie_len) {
if (comeback_after)
wpabuf_put_le16(buf, comeback_after);
wpabuf_put_u8(buf, cookie_len);
wpabuf_put_data(buf, cookie, cookie_len);
}
wpabuf_put_le16(buf, bootstrap);
/* Update attribute length */
WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
wpa_printf(MSG_DEBUG, "P2P: * Bootstrapping method=0x%x",
bootstrap);
}
void p2p_buf_add_dira(struct wpabuf *buf, struct p2p_data *p2p)
{
u8 *len;
struct p2p_id_key *dev_ik;
if (!p2p->cfg->pairing_config.pairing_capable ||
!p2p->cfg->pairing_config.enable_pairing_cache ||
!p2p->cfg->pairing_config.enable_pairing_verification)
return;
dev_ik = &p2p->pairing_info->dev_ik;
/* P2P DIRA */
wpabuf_put_u8(buf, P2P_ATTR_DEVICE_IDENTITY_RESOLUTION);
/* Length to be filled */
len = wpabuf_put(buf, 2);
wpabuf_put_u8(buf, dev_ik->cipher_version);
wpabuf_put_data(buf, dev_ik->dira_nonce, dev_ik->dira_nonce_len);
wpabuf_put_data(buf, dev_ik->dira_tag, dev_ik->dira_tag_len);
/* Update attribute length */
WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
wpa_printf(MSG_DEBUG, "P2P: * DIRA");
}
static int p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
const char *val)
{

View file

@ -244,6 +244,8 @@ int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev)
config_method = WPS_CONFIG_PUSHBUTTON;
else if (dev->wps_method == WPS_P2PS)
config_method = WPS_CONFIG_P2PS;
else if (dev->p2p2 && dev->req_bootstrap_method)
config_method = WPS_NOT_READY;
else
return -1;
return p2p_prov_disc_req(p2p, dev->info.p2p_device_addr,

View file

@ -36,6 +36,26 @@ enum p2p_go_state {
REMOTE_GO
};
/**
* struct bootstrap_params - P2P Device bootstrap request parameters
*/
struct p2p_bootstrap_params {
/* Bootstrap method */
u16 bootstrap_method;
/* Status code */
enum p2p_status_code status;
/* Cookie for comeback */
u8 cookie[50];
/* Cookie length */
size_t cookie_len;
/* Comeback time in TUs after which receiver is requested to retry */
int comeback_after;
};
/**
* struct p2p_device - P2P Device data (internal to P2P module)
*/
@ -150,6 +170,18 @@ struct p2p_device {
int sd_pending_bcast_queries;
bool support_6ghz;
/* Supports P2P2 */
bool p2p2;
/* Requested bootstrap method */
u16 req_bootstrap_method;
/* Bootstrap parameters received from peer */
struct p2p_bootstrap_params *bootstrap_params;
/* Password for P2P2 GO negotiation */
char password[100];
};
struct p2p_sd_query {
@ -160,6 +192,39 @@ struct p2p_sd_query {
struct wpabuf *tlvs;
};
/* P2P Device Identity Key parameters */
struct p2p_id_key {
/* AKMP used for DevIK derviation */
int akmp;
/* Cipher version type */
int cipher_version;
/* Buffer to hold the DevIK */
u8 dik_data[DEVICE_IDENTITY_KEY_MAX_LEN];
/* Length of DevIK */
size_t dik_len;
/* Nonce used in DIRA attribute */
u8 dira_nonce[DEVICE_IDENTITY_NONCE_LEN];
/* Length of nonce */
size_t dira_nonce_len;
/* Tag computed for nonce using NIK */
u8 dira_tag[DEVICE_IDENTITY_TAG_LEN];
/* Length of tag in octets */
size_t dira_tag_len;
};
struct p2p_pairing_info {
/* P2P device own address */
u8 own_addr[ETH_ALEN];
/* device capability to enable pairing setup */
bool enable_pairing_setup;
/* device capability to enable pairing cache */
bool enable_pairing_cache;
/* device supported bootstrapping */
u16 supported_bootstrap;
/* P2P Device Identity Key info */
struct p2p_id_key dev_ik;
};
/**
* struct p2p_data - P2P module data (internal to P2P module)
*/
@ -554,6 +619,8 @@ struct p2p_data {
bool p2p_6ghz_capable;
bool include_6ghz;
bool allow_6ghz;
struct p2p_pairing_info *pairing_info;
};
/**
@ -561,6 +628,7 @@ struct p2p_data {
*/
struct p2p_message {
struct wpabuf *p2p_attributes;
struct wpabuf *p2p2_attributes;
struct wpabuf *wps_attributes;
struct wpabuf *wfd_subelems;
@ -659,6 +727,12 @@ struct p2p_message {
const u8 *pref_freq_list;
size_t pref_freq_list_len;
const u8 *pcea_info;
size_t pcea_info_len;
const u8 *pbma_info;
size_t pbma_info_len;
};
@ -748,6 +822,7 @@ void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token);
void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype,
u8 dialog_token);
u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf);
u8 * p2p_buf_add_p2p2_ie_hdr(struct wpabuf *buf);
void p2p_buf_add_status(struct wpabuf *buf, u8 status);
void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p,
struct p2p_device *peer);
@ -788,6 +863,10 @@ void p2p_buf_add_feature_capability(struct wpabuf *buf, u16 len,
const u8 *mask);
void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr,
const u8 *ssid, size_t ssid_len);
void p2p_buf_add_pcea(struct wpabuf *buf, struct p2p_data *p2p);
void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie,
size_t cookie_len, int comeback_after);
void p2p_buf_add_dira(struct wpabuf *buf, struct p2p_data *p2p);
int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
int all_attr);
void p2p_buf_add_pref_channel_list(struct wpabuf *buf,
@ -826,14 +905,16 @@ void p2p_check_pref_chan(struct p2p_data *p2p, int go,
struct p2p_device *dev, struct p2p_message *msg);
/* p2p_pd.c */
void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
void p2p_handle_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len, int rx_freq);
void p2p_handle_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len, int rx_freq);
void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len);
int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
int join, int force_freq);
void p2p_reset_pending_pd(struct p2p_data *p2p);
void p2ps_prov_free(struct p2p_data *p2p);
void p2p_process_pcea(struct p2p_data *p2p, struct p2p_message *msg,
struct p2p_device *dev);
/* p2p_invitation.c */
void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
@ -899,6 +980,9 @@ void p2p_pref_channel_filter(const struct p2p_channels *a,
const struct weighted_pcl *freq_list,
unsigned int num_channels,
struct p2p_channels *res, bool go);
void p2p_sd_query_cb(struct p2p_data *p2p, int success);
void p2p_dbg(struct p2p_data *p2p, const char *fmt, ...)
PRINTF_FORMAT(2, 3);
void p2p_info(struct p2p_data *p2p, const char *fmt, ...)

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