Replace instances of the ap_del_station() +
ap_sta_free()/ap_remove_sta() with calls to ap_station_disconnect to
make sure we consistently remove the station from the ap->sta_states
queue before using ap_del_station(). ap_del_station() may generate an
event to the ap.h API user (e.g. P2P) and this may end up tearing down
the AP completely.
For that scenario we also don't want ap_sta_free() to access sta->ap so
we make sure ap_del_station() performs these cleanup steps so that
ap_sta_free() has nothing to do that accesses sta->ap.
client_frame is not valid for a beacon frame as beacons are not sent in
response to another frame. Move the access to client_frame->address_2
to the conditional blocks for Probe Response and Association Response
frames.
ie_tlv_builder_init takes a size_t as input, yet for some reason
ie_tlv_builder_finalize takes an unsigned int argument as output. Fix
the latter to use size_t as well.
Change the char *addr_str and uint8_t prefix_len pair to an
l_rtnl_address object and use ell/rtnl.h utilities that use that
directly. Extend broadcast_from_ip to handle prefix_len.
We generate the DBus error reply type from the errno only when
ap_start() was failing synchronously, now also send the errno through
the callbacks so that we can also return a specific DBus reply when
failing asynchronously. Thea AP autotest relies on receiving the
AlreadyExists DBus error.
Deprecate the global [General].APRanges setting in favour of
[IPv4].APAddressPool with an extended (but backwards-compatible) syntax.
Drop the existing address pool creation code.
The new APAddressPool setting has the same syntax as the profile-local
[IPv4].Address setting and the subnet selection code will fall back
to the global setting if it's missing, this way we use common code to
handle both settings.
Extend the [IPv4].Address setting's syntax to allow a new format: a list
of <IP>/<prefix_len> -form strings that define the address space from
which a subnet is selected. Rewrite the DHCP settings loading with
other notable changes:
* validate some of the settings more thoroughly,
* name all netconfig-related ap_state members with the netconfig_
prefix,
* make sure we always call l_dhcp_server_set_netmask(),
* allow netmasks other than 24-bit and change the default to 28 bits,
* as requested avoid using the l_net_ ioctl-based functions although
l_dhcp still uses them internally,
* as requested avoid touching the ap_state members until the end of
some functions so that on error they're basically a no-op (for
readability).
ap_reset() seems to be called whenever the AP is stopped or removed due
to interface shutdown. For some reason ap_reset did not remove the DHCP
server object, resulting in leaks:
==211== at 0x483879F: malloc (vg_replace_malloc.c:307)
==211== by 0x46B5AD: l_malloc (util.c:62)
==211== by 0x49B0E2: l_dhcp_server_new (dhcp-server.c:715)
==211== by 0x433AA3: ap_setup_dhcp (ap.c:2615)
==211== by 0x433AA3: ap_load_dhcp (ap.c:2645)
==211== by 0x433AA3: ap_load_config (ap.c:2753)
==211== by 0x433AA3: ap_start (ap.c:2885)
==211== by 0x434A96: ap_dbus_start_profile (ap.c:3329)
==211== by 0x482DA9: _dbus_object_tree_dispatch (dbus-service.c:1815)
==211== by 0x47A4D9: message_read_handler (dbus.c:285)
==211== by 0x4720EB: io_callback (io.c:120)
==211== by 0x47130C: l_main_iterate (main.c:478)
==211== by 0x4713DB: l_main_run (main.c:525)
==211== by 0x4713DB: l_main_run (main.c:507)
==211== by 0x4715EB: l_main_run_with_signal (main.c:647)
==211== by 0x403EE1: main (main.c:550)
Previously resp was a simple array of bytes allocated on the stack.
This was changed to a dynamically allocated array, but the sizeof(resp)
argument to ap_build_beacon_pr_head() was never changed appropriately.
Fix this by introducing a new resp_len variable that holds the number of
bytes allocated for resp. Also, move the allocation after the basic
sanity checks have been performed to avoid allocating/freeing memory
unnecessarily.
Fixes: 18a63f91fd ("ap: Write extra frame IEs from the user")
Prior to this netdev_connect_ok set setting this which really
only applies to station mode. In addition this happens for each
new station that connects to the AP. Instead set the operstate /
link mode when AP starts and stops.
Change ap_start to load all of the AP configuration from a struct
l_settings, moving the 6 or so parameters from struct ap_config members
to the l_settings groups and keys. This extends the ap profile concept
used for the DHCP settings. ap_start callers create the l_settings
object and fill the values in it or read the settings in from a file.
Since ap_setup_dhcp and ap_load_profile_and_dhcp no longer do the
settings file loading, they needed to be refactored and some issues were
fixed in their logic, e.g. l_dhcp_server_set_ip_address() was never
called when the "IP pool" was used. Also the IP pool was previously only
used if the ap->config->profile was NULL and this didn't match what the
docs said:
"If [IPv4].Address is not provided and no IP address is set on the
interface prior to calling StartProfile the IP pool will be used."
It was seen that some full mac cards/drivers do not include any
rate information with the NEW_STATION event. This was causing
the NEW_STATION event to be ignored, preventing AP mode from
working on these cards.
Since the full mac path does not even require sta->rates the
parsing can be removed completely.
Make the WSC IE processing and writing more self-contained (i.e. so that
it can be more easily moved to a separate file if desired) by using the
new ap_write_extra_ies() mechanism.
Pass the string IEs from the incoming STA association frames to
the user in the AP event data. I drop
ap_event_station_added_data.rsn_ie because that probably wasn't
going to ever be useful and the RSN IE is included in the .assoc_ies
array in any case.
There is no functional change here but checking the return
value makes static analysis much happier. Checking the
return and setting the default inside the if clause is also
consistent with how IWD does it many other places.
The diagnostic interface serves no purpose until the AP has
been started. Any calls on it will return an error so instead
it makes more sense to bring it up when the AP is started, and
down when the AP is stopped.
Its useful being able to refer to the network Name/SSID once
an AP is started. For example opening an iwctl session with an
already started AP provides no way of obtaining the SSID.
Rather than the previous hack which disabled group traffic it
was found that the GTK RSC could be manually set to zero which
allows group traffic. This appears to fix AP mode on brcmfmac
along with the previous fixes. This is not documented in
nl80211, but appears to work with this driver.
This is how a fullmac card tells userspace that a station has
left. This fixes the issue where the same client cannot re-connect
to the same AP multiple times. ap_new_station was renamed to
ap_handle_new_station for consistency.
Some fullmac cards were found to be buggy with getting the GTK
where it returns a BIP key for the GTK index, even after creating
a GTK with NEW_KEY explicitly. In an effort to get these cards
semi-working we can treat this just as a warning and continue with
the handshake without a GTK set which disables group traffic. A
warning is printed in this case so the user is not completely in
the dark.
Since fullmac cards handle auth/assoc in firmware IWD must
react differently while in AP mode just as it does in station.
For fullmac cards a NEW_STATION event is emitted post association
and from here the 4-way handshake can begin. In this NEW_STATION
handler a new sta_state is created and the needed members are
set in order to inject us back into the normal code execution
for softmac post association (i.e. creating group keys and
starting the 4-way handshake). From here everything works the
same as softmac.
This adds a new AccessPointDiagnostic interface. This interface
provides similar low level functionality as StationDiagnostic, but
for when IWD is in AP mode. This uses netdev_get_all_stations
which will dump all stations, parse, and return each station in
an individual callback. Once the dump is complete the destroy is
called and all data is packaged as an array of dictionaries.
handshake_state_set_authenticator_ie must be called to set group_cipher
in struct handshake_shake before handshake_set_gtk_state, otherwise
handshake_set_gtk_state is unable to determine the key length to set
handshake state gtk.
Fixes: 4bc20a0979 ("ap: Start EAP-WSC authentication with WSC enrollees")
If EnableNetworkConfiguration was enabled ap.c required that
APRanges also be set. This prevents IWD from starting which
effects a perfectly valid station configuration. Instead if
APRanges is not provided IWD still allows ap_init to pass but
DHCP just will not be enabled.