Some users may need their own control over 2.4/5GHz preference. This
adds a new user option, 'rank_5g_factor', which allows users to increase
or decrease their 5G preference.
This is a VERY simple test for HT/VHT. Since there are so many potential
options in the IE this really just tests that drops in RSSI will cause
IWD to choose a different BSS, even if that means choosing HT over VHT,
or even basic rates over HT/VHT.
This adds support for parsing the VHT IE, which allows a BSS supporting
VHT (80211ac) to be ranked higher than a BSS supporting only HT/basic
rates. Now, with basic/HT/VHT parsing we can calculate the theoretical
maximum data rate for all three and rank the BSS based on that.
This adds HT IE parsing and data rate calculation for HT (80211n)
rates. Now, a BSS supporting HT rates will be ranked higher than
a basic rate BSS, assuming the RSSI is at an acceptable level.
The spec dictates RSSI thresholds for different modulation schemes, which
correlate to different data rates. Until now were were ranking a BSS with
only looking at its advertised data rate, which may not even be possible
if the RSSI does not meet the threshold.
Now, RSSI is taken into consideration and the data rate returned from
parsing (Ext) Supported Rates IE(s) will reflect that.
All over the place we do "ie[1] + 2" for getting the IE length. It
is much clearer to use a macro to do this. The macro also checks
for NULL, and returns zero in this case.
Supported rates will soon be parsed along with HT/VHT capabilities
to determine the best data rate. This will remove the need for the
supported_rates uintset element in scan_bss, as well as the single
API to only parse the supported rates IE. AP still does rely on
this though (since it only supports basic rates), so the parsing
function was moved into ap.c.
HT/VHT require setting the regulatory domain to something other
than 00. This adds an option to the hardware config which allows
the regulatory domain to be set to any country.
HT/VHT require channels who's use is restricted depending on
country. When using these channels, cfg80211 tries to load the
regulatory.db file in /lib/firmware and verify the signature.
This poses a problem as the host machine may not have a signed
regulatory.db, or it may have not been signed with the expected
signature which would cause cfg80211 to fail to load the database.
If cfg80211 fails to load the database the country will be set to
00, which is the most restrictive "world roaming" setting. This
does not allow HT/VHT to work properly.
In the context of test-runner we can simply disable the verification.
Unforunately this is not a very common practice, so CONFIG_EXPERT
must be enabled.
If your system does not have /lib/firmware/regulatory.db you must
get it. More info can be found here:
https://wireless.wiki.kernel.org/en/developers/regulatory/wireless-regdb
In the methods' check_settings do a more complete early check for
possible certificate / private key misconfiguration, including check
that the certificate and the private key are always present or absent
together and that they actually match each other. Do this by encrypting
and decrypting a small buffer because we have no better API for that.
A method's .check_settings method checks for inconsistent setting files
and prints readable errors so there's no need to do that again in
.load_settings, although at some point after removing the duplicate
error messages from the load_settings methods we agreed to keep minimum
checks that could cause a crash e.g. in a corner case like when the
setting file got modified between the check_settings and the
load_settings call. Some error messages have been re-added to
load_settings after that (e.g. in
bb4e1ebd4f) but they're incomplete and not
useful so remove them.
When this test was written only group 19 was supported. The 'bad_group'
test used, at the time, unsupported group 20. Now group 20 is supported
so this test was expecting a failure. This updates the test to use group
0xff, which is not a valid ECC group and should always fail.
Previously, the storage dir has only been created after a successful
network connection, causing removal of Known Network interface from
Dbus and failure to register dir watcher until daemon is restarted.
A length check was still assuming the 256 bit ECC group. This
was updated to scale with the group. The commit buffer was also
not properly sized. This was changed to allow for the largest
ECC group supported.
SAE was hardcoded to work only with group 19. This change fixes up the
hard coded lengths to allow it to work with group 20 since ELL supports
it. There was also good amount of logic added to support negotiating
groups. Before, since we only supported group 19, we would just reject
the connection to an AP unless it only supported group 19.
This did lead to a discovery of a potential bug in hostapd, which was
worked around in SAE in order to properly support group negotiation.
If an AP receives a commit request with a group it does not support it
should reject the authentication with code 77. According to the spec
it should also include the group number which it is rejecting. This is
not the case with hostapd. To fix this we needed to special case a
length check where we would otherwise fail the connection.
SAE has a clogging test which requires 4 radios to all simultaneously
connect. All the other tests are only using one of these radios, so
in these tests we explicitly disconnect these devices preventing them
from autoconnecting.
Since the EAP-PWD fragmentation test uses group 19 there is test
coverage there for that group. This changes connection_test to use
group 20 instead of 19.
Most of this work was already done after moving ECC into ELL, but
there were still a few places where the 256-bit group was assumed.
This allows the 384-bit group to be used, and theoretically any
other group added to ELL in the future.
If we have a BSS list where all BSS's have been blacklisted we still
need a way to force a connection to that network, instead of having
to wait for the blacklist entry to expire. network_bss_select now
takes a boolean 'fallback_to_blacklist' which causes the selection
to still return a connectable BSS even if the entire list was
blacklisted.
In most cases this is set to true, as these cases are initiated by
DBus calls. The only case where this is not true is inside
station_try_next_bss, where we do want to honor the blacklist.
This both prevents an explicit connect call (where all BSS's are
blacklisted) from trying all the blacklisted BSS's, as well as the
autoconnect case where we simply should not try to connect if all
the BSS's are blacklisted.
There are is some implied behavior here that may not be obvious:
On an explicit DBus connect call IWD will attempt to connect to
any non-blacklisted BSS found under the network. If unsuccessful,
the current BSS will be blacklisted and IWD will try the next
in the list. This will repeat until all BSS's are blacklisted,
and in this case the connect call will fail.
If a connect is tried again when all BSS's are blacklisted IWD
will attempt to connect to the first connectable blacklisted
BSS, and if this fails the connect call will fail. No more
connection attempts will happen until the next DBus call.
If IWD fails to connect to a BSS we can attempt to connect to a different
BSS under the same network and blacklist the first BSS. In the case of an
incorrect PSK (MMPDU code 2 or 23) we will still fail the connection.
station_connect_cb was refactored to better handle the dbus case. Now the
netdev result switch statement is handled before deciding whether to send
a dbus reply. This allows for both cases where we are trying to connect
to the next BSS in autoconnect, as well as in the dbus case.
This makes __station_connect_network even less intelligent by JUST
making it connect to a network, without any state changes. This makes
the rekey logic much cleaner.
We were also changing dbus properties when setting the state to
CONNECTING, so those dbus property change calls were moved into
station_enter_state.
A new driver extended feature bit was added signifying if the driver
supports PTK replacement/rekeying. During a connect, netdev checks
for the driver feature and sets the handshakes 'no_rekey' flag
accordingly.
At some point the AP will decide to rekey which is handled inside
eapol. If no_rekey is unset we rekey as normal and the connection
remains open. If we have set no_rekey eapol will emit
HANDSHAKE_EVENT_REKEY_FAILED, which is now caught inside station. If
this happens our only choice is to fully disconnect and reconnect.
If we receive handshake message 1/4 after we are already connected
the AP is attempting to rekey. This may not be allowed and if not
we do not process the rekey and emit HANDSHAKE_EVENT_REKEY_FAILED
so any listeners can handle accordingly.
The AP structure was getting cleaned up twice. When the DBus stop method came
in we do AP_STOP on nl80211. In this callback the AP was getting freed in
ap_reset. Also when the DBus interface was cleaned up it triggered ap_reset.
Since ap->started gets set to false in ap_reset, we now check this and bail
out if the AP is already stopped.
Fixes:
++++++++ backtrace ++++++++
0 0x7f099c11ef20 in /lib/x86_64-linux-gnu/libc.so.6
1 0x43fed0 in l_queue_foreach() at ell/queue.c:441 (discriminator 3)
2 0x423a6c in ap_reset() at src/ap.c:140
3 0x423b69 in ap_free() at src/ap.c:162
4 0x44ee86 in interface_instance_free() at ell/dbus-service.c:513
5 0x451730 in _dbus_object_tree_remove_interface() at ell/dbus-service.c:1650
6 0x405c07 in netdev_newlink_notify() at src/netdev.c:4449 (discriminator 9)
7 0x440775 in l_hashmap_foreach() at ell/hashmap.c:534
8 0x4455d3 in process_broadcast() at ell/netlink.c:158
9 0x4439b3 in io_callback() at ell/io.c:126
10 0x442c4e in l_main_iterate() at ell/main.c:473
11 0x442d1c in l_main_run() at ell/main.c:516
12 0x442f2b in l_main_run_with_signal() at ell/main.c:644
13 0x403ab3 in main() at src/main.c:504
14 0x7f099c101b97 in /lib/x86_64-linux-gnu/libc.so.6
+++++++++++++++++++++++++++
This will allow for blacklisting a BSS if the connection fails. The
actual blacklist module is simple and must be driven by station. All
it does is add BSS addresses, a timestamp, and a timeout to a queue.
Entries can also be removed, or checked if they exist. The blacklist
timeout is configuratble in main.conf, as well as the blacklist
timeout multiplier and maximum timeout. The multiplier is used after
a blacklisted BSS timeout expires but we still fail to connect on the
next connection attempt. We multiply the current timeout by the
multiplier so the BSS remains in the blacklist for a larger growing
amount of time until it reaches the maximum (24 hours by default).
Soon BSS blacklisting will be added, and in order to properly decide if
a BSS should be blacklisted we need the status code on a failed
connection. This change stores the status code when there is a failure
in netdev and adds a getter to retrieve later. In many cases we have
the actual status code from the AP, but in some corner cases its not
obtainable (e.g. an error sending an NL80211 command) in which case we
just default to MMPDU_REASON_CODE_UNSPECIFIED.
Rather than continue with the pattern of setting netdev->result and
now netdev->last_status_code, the netdev_connect_failed function was
redefined so its no longer used as both a NL80211 callback and called
directly. Instead a new function was added, netdev_disconnect_cb which
just calls netdev_connect_failed. netdev_disconnect_cb should not be
used for all the NL80211 disconnect commands. Now netdev_connect_failed
takes both a result and status code which it sets in the netdev object.
In the case where we were using netdev_connect_failed as a callback we
still need to set the result and last_status_code but at least this is
better than having to set those in all cases.