mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2025-08-02 17:37:22 +02:00
Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
601d9b0e02 | ||
![]() |
f209e00dde | ||
![]() |
86523b0597 | ||
![]() |
85a2637fc5 | ||
![]() |
2f991918b1 | ||
![]() |
5b5a9b60fb | ||
![]() |
5287809043 | ||
![]() |
ea9ff2dcaf | ||
![]() |
9dce36fe3d | ||
![]() |
c4718a5355 | ||
![]() |
c9c8790ff2 | ||
![]() |
d135bfc4b8 | ||
![]() |
e269beadba | ||
![]() |
3e55fc855a | ||
![]() |
c8d9936f9d | ||
![]() |
79940956ef | ||
![]() |
9f98c6c3c8 | ||
![]() |
93eef7b02d |
@ -1,3 +1,9 @@
|
||||
ver 3.9:
|
||||
Fix issue with Access Point mode and frequency unlocking.
|
||||
Fix issue with network configuration and BSS retry logic.
|
||||
Fix issue with handling busy notification from Access Point.
|
||||
Fix issue with handling P-192, P-224 and P-521 for SAE.
|
||||
|
||||
ver 3.8:
|
||||
Fix issue with handling unit tests and missing kernel features.
|
||||
|
||||
|
@ -3,4 +3,4 @@ RoamThreshold=-72
|
||||
CriticalRoamThreshold=-72
|
||||
|
||||
[Blacklist]
|
||||
InitialRoamRequestedTimeout=20
|
||||
InitialAccessPointBusyTimeout=20
|
||||
|
@ -91,16 +91,11 @@ class Test(unittest.TestCase):
|
||||
# using the same static config. The new client's ACD client should
|
||||
# detect an IP conflict and not allow the device to reach the
|
||||
# "connected" state although the DBus .Connect call will succeed.
|
||||
ordered_network.network_object.connect()
|
||||
self.assertEqual(dev2.state, iwd.DeviceState.connecting)
|
||||
try:
|
||||
# We should either stay in "connecting" indefinitely or move to
|
||||
# "disconnecting"
|
||||
condition = 'obj.state != DeviceState.connecting'
|
||||
with self.assertRaises(iwd.FailedEx):
|
||||
ordered_network.network_object.connect(timeout=500)
|
||||
|
||||
condition = 'obj.state == DeviceState.disconnected'
|
||||
iwd_ns0_1.wait_for_object_condition(dev2, condition, max_wait=21)
|
||||
self.assertEqual(dev2.state, iwd.DeviceState.disconnecting)
|
||||
except TimeoutError:
|
||||
dev2.disconnect()
|
||||
|
||||
iwd_ns0_1.unregister_psk_agent(psk_agent_ns0_1)
|
||||
del dev2
|
||||
|
@ -8,6 +8,8 @@ from iwd import PSKAgent
|
||||
from iwd import NetworkType
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def connect_failure(self, ex):
|
||||
self.failure_triggered = True
|
||||
|
||||
def test_netconfig_timeout(self):
|
||||
IWD.copy_to_storage('autoconnect.psk', name='ap-ns1.psk')
|
||||
@ -27,23 +29,34 @@ class Test(unittest.TestCase):
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
||||
|
||||
ordered_network.network_object.connect()
|
||||
self.failure_triggered = False
|
||||
|
||||
condition = 'obj.state == DeviceState.connecting'
|
||||
# Set our error handler here so we can check if it fails
|
||||
ordered_network.network_object.connect(
|
||||
wait=False,
|
||||
timeout=1000,
|
||||
error_handler=self.connect_failure
|
||||
)
|
||||
|
||||
# IWD should attempt to try both BSS's with both failing netconfig.
|
||||
# Then the autoconnect list should be exhausted, and IWD should
|
||||
# transition to a disconnected state, then proceed to full autoconnect.
|
||||
device.wait_for_event("netconfig-failed", timeout=1000)
|
||||
device.wait_for_event("netconfig-failed", timeout=1000)
|
||||
device.wait_for_event("disconnected")
|
||||
|
||||
device.wait_for_event("autoconnect_full")
|
||||
|
||||
# The connect call should have failed
|
||||
self.assertTrue(self.failure_triggered)
|
||||
|
||||
condition = "obj.scanning"
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
condition = "not obj.scanning"
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
device.wait_for_event("connecting (netconfig)")
|
||||
|
||||
# Netconfig should fail, and IWD should disconnect
|
||||
from_condition = 'obj.state == DeviceState.connecting'
|
||||
to_condition = 'obj.state == DeviceState.disconnecting'
|
||||
wd.wait_for_object_change(device, from_condition, to_condition, max_wait=60)
|
||||
|
||||
# Autoconnect should then try again
|
||||
condition = 'obj.state == DeviceState.connecting'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
device.wait_for_event("connecting (netconfig)")
|
||||
# IWD should attempt to connect, but it will of course fail again.
|
||||
device.wait_for_event("netconfig-failed", timeout=1000)
|
||||
|
||||
device.disconnect()
|
||||
condition = 'obj.state == DeviceState.disconnected'
|
||||
|
@ -19,7 +19,7 @@ class Test(unittest.TestCase):
|
||||
|
||||
device = wd.list_devices(1)[0]
|
||||
device.get_ordered_network('TestFT', full_scan=True)
|
||||
device.connect_bssid(self.bss_hostapd[1].bssid)
|
||||
device.connect_bssid(self.bss_hostapd[1].bssid, wait=False)
|
||||
|
||||
self.bss_hostapd[1].wait_for_event(f'AP-STA-CONNECTED {device.address}')
|
||||
device.wait_for_event("connecting (netconfig)")
|
||||
|
@ -112,8 +112,8 @@ class AsyncOpAbstract(object):
|
||||
self._is_completed = True
|
||||
self._exception = _convert_dbus_ex(ex)
|
||||
|
||||
def _wait_for_async_op(self):
|
||||
ctx.non_block_wait(lambda s: s._is_completed, 30, self, exception=None)
|
||||
def _wait_for_async_op(self, timeout=50):
|
||||
ctx.non_block_wait(lambda s: s._is_completed, timeout, self, exception=None)
|
||||
|
||||
self._is_completed = False
|
||||
if self._exception is not None:
|
||||
@ -280,8 +280,15 @@ class StationDebug(IWDDBusAbstract):
|
||||
def autoconnect(self):
|
||||
return self._properties['AutoConnect']
|
||||
|
||||
def connect_bssid(self, address):
|
||||
self._iface.ConnectBssid(dbus.ByteArray.fromhex(address.replace(':', '')))
|
||||
def connect_bssid(self, address, wait=True):
|
||||
self._iface.ConnectBssid(
|
||||
dbus.ByteArray.fromhex(address.replace(':', '')),
|
||||
reply_handler=self._success,
|
||||
error_handler=self._failure
|
||||
)
|
||||
|
||||
if wait:
|
||||
self._wait_for_async_op()
|
||||
|
||||
def roam(self, address):
|
||||
self._iface.Roam(dbus.ByteArray.fromhex(address.replace(':', '')))
|
||||
@ -870,8 +877,8 @@ class Device(IWDDBusAbstract):
|
||||
def stop_adhoc(self):
|
||||
self._prop_proxy.Set(IWD_DEVICE_INTERFACE, 'Mode', 'station')
|
||||
|
||||
def connect_bssid(self, address):
|
||||
self._station_debug.connect_bssid(address)
|
||||
def connect_bssid(self, address, wait=True):
|
||||
self._station_debug.connect_bssid(address, wait=wait)
|
||||
|
||||
def roam(self, address):
|
||||
self._station_debug.roam(address)
|
||||
@ -999,7 +1006,7 @@ class Network(IWDDBusAbstract):
|
||||
def extended_service_set(self):
|
||||
return self._properties['ExtendedServiceSet']
|
||||
|
||||
def connect(self, wait=True):
|
||||
def connect(self, wait=True, timeout=50, reply_handler=None, error_handler=None):
|
||||
'''
|
||||
Connect to the network. Request the device implied by the object
|
||||
path to connect to specified network.
|
||||
@ -1014,12 +1021,19 @@ class Network(IWDDBusAbstract):
|
||||
@rtype: void
|
||||
'''
|
||||
|
||||
if not reply_handler:
|
||||
reply_handler = self._success
|
||||
|
||||
if not error_handler:
|
||||
error_handler = self._failure
|
||||
|
||||
self._iface.Connect(dbus_interface=self._iface_name,
|
||||
reply_handler=self._success,
|
||||
error_handler=self._failure)
|
||||
reply_handler=reply_handler,
|
||||
error_handler=error_handler,
|
||||
timeout=timeout)
|
||||
|
||||
if wait:
|
||||
self._wait_for_async_op()
|
||||
self._wait_for_async_op(timeout=timeout)
|
||||
|
||||
def __str__(self, prefix = ''):
|
||||
return prefix + 'Network:\n' \
|
||||
|
@ -1,5 +1,5 @@
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT([iwd],[3.8])
|
||||
AC_INIT([iwd],[3.9])
|
||||
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
AC_CONFIG_AUX_DIR(build-aux)
|
||||
|
@ -11,6 +11,12 @@ Methods void Connect()
|
||||
the object path to connect to specified network.
|
||||
Connecting to WEP networks is not supported.
|
||||
|
||||
Note: When [General].EnableNetworkConfiguration is set
|
||||
to true a call to Connect() has the potential to take
|
||||
a significant amount of time. Specifically if DHCP is
|
||||
either slow, or is unable to complete. The timeout for
|
||||
DHCP is roughly 30 seconds per BSS.
|
||||
|
||||
Possible errors: net.connman.iwd.Aborted
|
||||
net.connman.iwd.Busy
|
||||
net.connman.iwd.Failed
|
||||
|
86
src/ap.c
86
src/ap.c
@ -109,6 +109,8 @@ struct ap_state {
|
||||
struct l_timeout *rekey_timeout;
|
||||
unsigned int rekey_time;
|
||||
|
||||
uint32_t pre_scan_cmd_id;
|
||||
|
||||
bool started : 1;
|
||||
bool gtk_set : 1;
|
||||
bool netconfig_set_addr4 : 1;
|
||||
@ -354,6 +356,12 @@ static void ap_reset(struct ap_state *ap)
|
||||
l_timeout_remove(ap->rekey_timeout);
|
||||
ap->rekey_timeout = NULL;
|
||||
}
|
||||
|
||||
if (ap->pre_scan_cmd_id) {
|
||||
scan_cancel(netdev_get_wdev_id(ap->netdev),
|
||||
ap->pre_scan_cmd_id);
|
||||
ap->pre_scan_cmd_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ap_event_done(struct ap_state *ap, bool prev_in_event)
|
||||
@ -3852,6 +3860,70 @@ static int ap_load_config(struct ap_state *ap, const struct l_settings *config,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ap_pre_scan_trigger(int err, void *user_data)
|
||||
{
|
||||
struct ap_state *ap = user_data;
|
||||
|
||||
if (err < 0) {
|
||||
l_error("AP pre-scan failed: %i", err);
|
||||
ap_start_failed(ap, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ap_check_channel(struct ap_state *ap)
|
||||
{
|
||||
const struct band_freq_attrs *freq_attr;
|
||||
|
||||
freq_attr = wiphy_get_frequency_info(netdev_get_wiphy(ap->netdev),
|
||||
band_channel_to_freq(ap->channel, ap->band));
|
||||
if (L_WARN_ON(!freq_attr))
|
||||
return false;
|
||||
|
||||
/* Check if disabled/no-IR */
|
||||
if (freq_attr->disabled || freq_attr->no_ir)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ap_pre_scan_notify(int err, struct l_queue *bss_list,
|
||||
const struct scan_freq_set *freqs,
|
||||
void *user_data)
|
||||
{
|
||||
struct ap_state *ap = user_data;
|
||||
|
||||
if (!ap_check_channel(ap)) {
|
||||
l_error("Unable to channel %u even after pre-scan",
|
||||
ap->channel);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ap_start_send(ap))
|
||||
return false;
|
||||
|
||||
error:
|
||||
ap_start_failed(ap, -ENOTSUP);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ap_pre_scan_destroy(void *user_data)
|
||||
{
|
||||
struct ap_state *ap = user_data;
|
||||
|
||||
ap->pre_scan_cmd_id = 0;
|
||||
}
|
||||
|
||||
static bool ap_pre_scan(struct ap_state *ap)
|
||||
{
|
||||
ap->pre_scan_cmd_id = scan_passive(netdev_get_wdev_id(ap->netdev),
|
||||
NULL, ap_pre_scan_trigger,
|
||||
ap_pre_scan_notify,
|
||||
ap, ap_pre_scan_destroy);
|
||||
|
||||
return ap->pre_scan_cmd_id != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start a simple independent WPA2 AP on given netdev.
|
||||
*
|
||||
@ -3962,6 +4034,20 @@ struct ap_state *ap_start(struct netdev *netdev, struct l_settings *config,
|
||||
return ap;
|
||||
}
|
||||
|
||||
if (!ap_check_channel(ap)) {
|
||||
l_debug("Channel %u is disabled/no-IR, pre-scanning",
|
||||
ap->channel);
|
||||
|
||||
if (ap_pre_scan(ap)) {
|
||||
if (err_out)
|
||||
*err_out = 0;
|
||||
|
||||
return ap;
|
||||
}
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ap_start_send(ap)) {
|
||||
if (err_out)
|
||||
*err_out = 0;
|
||||
|
@ -45,7 +45,7 @@
|
||||
|
||||
static uint64_t blacklist_multiplier;
|
||||
static uint64_t blacklist_initial_timeout;
|
||||
static uint64_t blacklist_roam_initial_timeout;
|
||||
static uint64_t blacklist_ap_busy_initial_timeout;
|
||||
static uint64_t blacklist_max_timeout;
|
||||
|
||||
struct blacklist_entry {
|
||||
@ -67,8 +67,8 @@ static uint64_t get_reason_timeout(enum blacklist_reason reason)
|
||||
switch (reason) {
|
||||
case BLACKLIST_REASON_CONNECT_FAILED:
|
||||
return blacklist_initial_timeout;
|
||||
case BLACKLIST_REASON_ROAM_REQUESTED:
|
||||
return blacklist_roam_initial_timeout;
|
||||
case BLACKLIST_REASON_AP_BUSY:
|
||||
return blacklist_ap_busy_initial_timeout;
|
||||
default:
|
||||
l_warn("Unhandled blacklist reason: %u", reason);
|
||||
return 0;
|
||||
@ -218,11 +218,19 @@ static int blacklist_init(void)
|
||||
|
||||
if (!l_settings_get_uint64(config, "Blacklist",
|
||||
"InitialRoamRequestedTimeout",
|
||||
&blacklist_roam_initial_timeout))
|
||||
blacklist_roam_initial_timeout = BLACKLIST_DEFAULT_TIMEOUT;
|
||||
&blacklist_ap_busy_initial_timeout))
|
||||
blacklist_ap_busy_initial_timeout = BLACKLIST_DEFAULT_TIMEOUT;
|
||||
else
|
||||
l_warn("[Blacklist].InitialRoamRequestedTimeout is deprecated, "
|
||||
"use [Blacklist].InitialAccessPointBusyTimeout");
|
||||
|
||||
if (!l_settings_get_uint64(config, "Blacklist",
|
||||
"InitialAccessPointBusyTimeout",
|
||||
&blacklist_ap_busy_initial_timeout))
|
||||
blacklist_ap_busy_initial_timeout = BLACKLIST_DEFAULT_TIMEOUT;
|
||||
|
||||
/* For easier user configuration the timeout values are in seconds */
|
||||
blacklist_roam_initial_timeout *= L_USEC_PER_SEC;
|
||||
blacklist_ap_busy_initial_timeout *= L_USEC_PER_SEC;
|
||||
|
||||
if (!l_settings_get_uint64(config, "Blacklist",
|
||||
"Multiplier",
|
||||
|
@ -27,12 +27,14 @@ enum blacklist_reason {
|
||||
*/
|
||||
BLACKLIST_REASON_CONNECT_FAILED,
|
||||
/*
|
||||
* This type of blacklist is added when a BSS requests IWD roams
|
||||
* elsewhere. This is to aid in preventing IWD from roaming/connecting
|
||||
* back to that BSS in the future unless there are no other "good"
|
||||
* candidates to connect to.
|
||||
* This type of blacklist is added when an AP indicates that its unable
|
||||
* to handle more connections. This is done via BSS-TM requests or
|
||||
* denied authentications/associations with certain status codes.
|
||||
*
|
||||
* Once this type of blacklist is applied to a BSS IWD will attempt to
|
||||
* avoid roaming to it for a configured period of time.
|
||||
*/
|
||||
BLACKLIST_REASON_ROAM_REQUESTED,
|
||||
BLACKLIST_REASON_AP_BUSY,
|
||||
};
|
||||
|
||||
void blacklist_add_bss(const uint8_t *addr, enum blacklist_reason reason);
|
||||
|
@ -292,12 +292,22 @@ control how long a misbehaved BSS spends on the blacklist.
|
||||
|
||||
The initial time that a BSS spends on the blacklist. Setting this to zero
|
||||
will disable blacklisting functionality in IWD.
|
||||
* - InitialRoamRequestedTimeout
|
||||
* - InitialRoamRequestedTimeout (**deprecated**)
|
||||
- Values: uint64 value in seconds (default: **30**)
|
||||
|
||||
The initial time that a BSS will be marked after a BSS requests a roam.
|
||||
This is to aid in avoiding roaming back to BSS's which are likely
|
||||
overloaded. Setting this to zero will disabled this form of blacklisting.
|
||||
This setting is deprecated, please use
|
||||
[Blacklist].InitialAccessPointBusyTimeout instead.
|
||||
* - InitialAccessPointBusyTimeout
|
||||
- Values: uint64 value in seconds (default: **30**)
|
||||
|
||||
The initial time that a BSS will be blacklisted after indicating it
|
||||
cannot handle more connections. This is triggered by either a BSS
|
||||
transition management request (telling IWD to roam elsewhere) or by a
|
||||
denied authentication or association with the NO_MORE_STAS status code.
|
||||
|
||||
Once a BSS is blacklisted in this manor IWD will attempt to avoid it for
|
||||
the configured amount of time.
|
||||
|
||||
* - Multiplier
|
||||
- Values: unsigned int value greater than zero, in seconds
|
||||
(default: **30**)
|
||||
|
36
src/netdev.c
36
src/netdev.c
@ -5451,6 +5451,39 @@ static void netdev_michael_mic_failure(struct l_genl_msg *msg,
|
||||
l_debug("ifindex=%u key_idx=%u type=%u", netdev->index, idx, type);
|
||||
}
|
||||
|
||||
#define MAX_COMEBACK_DELAY 1200
|
||||
|
||||
static void netdev_assoc_comeback(struct l_genl_msg *msg,
|
||||
struct netdev *netdev)
|
||||
{
|
||||
const uint8_t *mac;
|
||||
uint32_t timeout;
|
||||
|
||||
if (L_WARN_ON(!netdev->connected))
|
||||
return;
|
||||
|
||||
if (nl80211_parse_attrs(msg, NL80211_ATTR_MAC, &mac,
|
||||
NL80211_ATTR_TIMEOUT, &timeout,
|
||||
NL80211_ATTR_UNSPEC) < 0)
|
||||
return;
|
||||
|
||||
if (L_WARN_ON(memcmp(mac, netdev->handshake->aa, ETH_ALEN)))
|
||||
return;
|
||||
|
||||
if (timeout <= MAX_COMEBACK_DELAY) {
|
||||
l_debug(MAC" requested an association comeback delay of %u TU",
|
||||
MAC_STR(netdev->handshake->aa), timeout);
|
||||
return;
|
||||
}
|
||||
|
||||
l_debug("Comeback delay of %u exceeded maximum of %u, deauthenticating",
|
||||
timeout, MAX_COMEBACK_DELAY);
|
||||
|
||||
netdev_deauth_and_fail_connection(netdev,
|
||||
NETDEV_RESULT_ASSOCIATION_FAILED,
|
||||
MMPDU_STATUS_CODE_REFUSED_TEMPORARILY);
|
||||
}
|
||||
|
||||
static void netdev_mlme_notify(struct l_genl_msg *msg, void *user_data)
|
||||
{
|
||||
struct netdev *netdev = NULL;
|
||||
@ -5504,6 +5537,9 @@ static void netdev_mlme_notify(struct l_genl_msg *msg, void *user_data)
|
||||
case NL80211_CMD_MICHAEL_MIC_FAILURE:
|
||||
netdev_michael_mic_failure(msg, netdev);
|
||||
break;
|
||||
case NL80211_CMD_ASSOC_COMEBACK:
|
||||
netdev_assoc_comeback(msg, netdev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,6 +168,11 @@ static bool network_secret_check_cacheable(void *data, void *user_data)
|
||||
return false;
|
||||
}
|
||||
|
||||
void network_clear_blacklist(struct network *network)
|
||||
{
|
||||
l_queue_clear(network->blacklist, NULL);
|
||||
}
|
||||
|
||||
void network_connected(struct network *network)
|
||||
{
|
||||
enum security security = network_get_security(network);
|
||||
@ -198,8 +203,6 @@ void network_connected(struct network *network)
|
||||
l_queue_foreach_remove(network->secrets,
|
||||
network_secret_check_cacheable, network);
|
||||
|
||||
l_queue_clear(network->blacklist, NULL);
|
||||
|
||||
network->provisioning_hidden = false;
|
||||
}
|
||||
|
||||
@ -207,7 +210,7 @@ void network_disconnected(struct network *network)
|
||||
{
|
||||
network_settings_close(network);
|
||||
|
||||
l_queue_clear(network->blacklist, NULL);
|
||||
network_clear_blacklist(network);
|
||||
|
||||
if (network->provisioning_hidden)
|
||||
station_hide_network(network->station, network);
|
||||
|
@ -74,6 +74,7 @@ bool network_bss_update(struct network *network, struct scan_bss *bss);
|
||||
const char *network_bss_get_path(const struct network *network,
|
||||
const struct scan_bss *bss);
|
||||
bool network_bss_list_isempty(struct network *network);
|
||||
void network_clear_blacklist(struct network *network);
|
||||
|
||||
const char *__network_path_append_bss(const char *network_path,
|
||||
const struct scan_bss *bss);
|
||||
|
@ -177,6 +177,7 @@ static const struct {
|
||||
{ NL80211_CMD_UNPROT_BEACON, "Unprotected Beacon" },
|
||||
{ NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS,
|
||||
"Control Port TX Status" },
|
||||
{ NL80211_CMD_ASSOC_COMEBACK, "Association comeback delay" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -190,6 +190,7 @@ static attr_handler handler_for_nl80211(int type)
|
||||
case NL80211_ATTR_CENTER_FREQ2:
|
||||
case NL80211_ATTR_AKM_SUITES:
|
||||
case NL80211_ATTR_EXTERNAL_AUTH_ACTION:
|
||||
case NL80211_ATTR_TIMEOUT:
|
||||
return extract_uint32;
|
||||
case NL80211_ATTR_FRAME:
|
||||
return extract_iovec;
|
||||
|
22
src/sae.c
22
src/sae.c
@ -169,6 +169,14 @@ static int sae_choose_next_group(struct sae_sm *sm)
|
||||
!sm->handshake->ecc_sae_pts[sm->group_retry])
|
||||
continue;
|
||||
|
||||
/*
|
||||
* TODO: Groups for P192, P224 and P521 are currently
|
||||
* non-functional with SAE. Until this is fixed we need to
|
||||
* avoid these groups from being used.
|
||||
*/
|
||||
if (group == 21 || group == 25 || group == 26)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -994,7 +1002,8 @@ static int sae_process_anti_clogging(struct sae_sm *sm, const uint8_t *ptr,
|
||||
sm->token_len = len;
|
||||
sm->sync = 0;
|
||||
|
||||
sae_send_commit(sm, true);
|
||||
if (L_WARN_ON(!sae_send_commit(sm, true)))
|
||||
return -EPROTO;
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
@ -1074,7 +1083,9 @@ static int sae_verify_committed(struct sae_sm *sm, uint16_t transaction,
|
||||
return -ETIMEDOUT;
|
||||
|
||||
sm->sync++;
|
||||
sae_send_commit(sm, true);
|
||||
|
||||
if (L_WARN_ON(!sae_send_commit(sm, true)))
|
||||
return -EPROTO;
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
@ -1129,7 +1140,9 @@ static int sae_verify_committed(struct sae_sm *sm, uint16_t transaction,
|
||||
sm->group);
|
||||
|
||||
sm->sync = 0;
|
||||
sae_send_commit(sm, false);
|
||||
|
||||
if (L_WARN_ON(!sae_send_commit(sm, false)))
|
||||
return -EPROTO;
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
@ -1294,7 +1307,8 @@ static int sae_verify_confirmed(struct sae_sm *sm, uint16_t trans,
|
||||
sm->sync++;
|
||||
sm->sc++;
|
||||
|
||||
sae_send_commit(sm, true);
|
||||
if (L_WARN_ON(!sae_send_commit(sm, true)))
|
||||
return -EPROTO;
|
||||
|
||||
if (!sae_send_confirm(sm))
|
||||
return -EPROTO;
|
||||
|
139
src/station.c
139
src/station.c
@ -191,8 +191,7 @@ static uint32_t evaluate_bss_group_rank(const uint8_t *addr, uint32_t freq,
|
||||
if (blacklist_contains_bss(addr, BLACKLIST_REASON_CONNECT_FAILED))
|
||||
return 0;
|
||||
|
||||
roam_blacklist = blacklist_contains_bss(addr,
|
||||
BLACKLIST_REASON_ROAM_REQUESTED);
|
||||
roam_blacklist = blacklist_contains_bss(addr, BLACKLIST_REASON_AP_BUSY);
|
||||
good_signal = signal >= netdev_get_low_signal_threshold(freq);
|
||||
|
||||
if (good_signal)
|
||||
@ -1796,6 +1795,15 @@ static void station_enter_state(struct station *station,
|
||||
periodic_scan_stop(station);
|
||||
break;
|
||||
case STATION_STATE_CONNECTED:
|
||||
network_clear_blacklist(station->connected_network);
|
||||
|
||||
if (station->connect_pending) {
|
||||
struct l_dbus_message *reply =
|
||||
l_dbus_message_new_method_return(
|
||||
station->connect_pending);
|
||||
dbus_pending_reply(&station->connect_pending, reply);
|
||||
}
|
||||
|
||||
l_dbus_object_add_interface(dbus,
|
||||
netdev_get_path(station->netdev),
|
||||
IWD_STATION_DIAGNOSTIC_INTERFACE,
|
||||
@ -2215,6 +2223,26 @@ static void station_early_neighbor_report_cb(struct netdev *netdev, int err,
|
||||
&station->roam_freqs);
|
||||
}
|
||||
|
||||
static bool station_try_next_bss(struct station *station)
|
||||
{
|
||||
struct scan_bss *next;
|
||||
int ret;
|
||||
|
||||
next = network_bss_select(station->connected_network, false);
|
||||
|
||||
if (!next)
|
||||
return false;
|
||||
|
||||
ret = __station_connect_network(station, station->connected_network,
|
||||
next, station->state);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
l_debug("Attempting to connect to next BSS "MAC, MAC_STR(next->addr));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool station_can_fast_transition(struct station *station,
|
||||
struct handshake_state *hs,
|
||||
struct scan_bss *bss)
|
||||
@ -2257,28 +2285,26 @@ static bool station_can_fast_transition(struct station *station,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void station_disconnect_on_error_cb(struct netdev *netdev, bool success,
|
||||
static void station_disconnect_on_netconfig_failed(struct netdev *netdev,
|
||||
bool success,
|
||||
void *user_data)
|
||||
{
|
||||
struct station *station = user_data;
|
||||
bool continue_autoconnect;
|
||||
|
||||
if (station_try_next_bss(station))
|
||||
return;
|
||||
|
||||
if (station->connect_pending) {
|
||||
struct l_dbus_message *reply = dbus_error_failed(
|
||||
station->connect_pending);
|
||||
|
||||
dbus_pending_reply(&station->connect_pending, reply);
|
||||
}
|
||||
|
||||
station_reset_connection_state(station);
|
||||
|
||||
station_enter_state(station, STATION_STATE_DISCONNECTED);
|
||||
|
||||
continue_autoconnect = station->state == STATION_STATE_CONNECTING_AUTO;
|
||||
|
||||
if (continue_autoconnect) {
|
||||
if (station_autoconnect_next(station) < 0) {
|
||||
l_debug("Nothing left on autoconnect list");
|
||||
station_enter_state(station,
|
||||
STATION_STATE_AUTOCONNECT_FULL);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (station->autoconnect)
|
||||
station_enter_state(station, STATION_STATE_AUTOCONNECT_QUICK);
|
||||
station_enter_state(station, STATION_STATE_AUTOCONNECT_FULL);
|
||||
}
|
||||
|
||||
static void station_netconfig_event_handler(enum netconfig_event event,
|
||||
@ -2291,23 +2317,20 @@ static void station_netconfig_event_handler(enum netconfig_event event,
|
||||
station_enter_state(station, STATION_STATE_CONNECTED);
|
||||
break;
|
||||
case NETCONFIG_EVENT_FAILED:
|
||||
if (station->connect_pending) {
|
||||
struct l_dbus_message *reply = dbus_error_failed(
|
||||
station->connect_pending);
|
||||
station_debug_event(station, "netconfig-failed");
|
||||
|
||||
dbus_pending_reply(&station->connect_pending, reply);
|
||||
}
|
||||
netconfig_reset(station->netconfig);
|
||||
|
||||
if (station->state == STATION_STATE_NETCONFIG)
|
||||
network_connect_failed(station->connected_network,
|
||||
false);
|
||||
|
||||
netdev_disconnect(station->netdev,
|
||||
station_disconnect_on_error_cb,
|
||||
station);
|
||||
station_reset_connection_state(station);
|
||||
network_blacklist_add(station->connected_network,
|
||||
station->connected_bss);
|
||||
|
||||
station_enter_state(station, STATION_STATE_DISCONNECTING);
|
||||
netdev_disconnect(station->netdev,
|
||||
station_disconnect_on_netconfig_failed,
|
||||
station);
|
||||
break;
|
||||
default:
|
||||
l_error("station: Unsupported netconfig event: %d.", event);
|
||||
@ -3326,7 +3349,7 @@ static void station_ap_directed_roam(struct station *station,
|
||||
}
|
||||
|
||||
blacklist_add_bss(station->connected_bss->addr,
|
||||
BLACKLIST_REASON_ROAM_REQUESTED);
|
||||
BLACKLIST_REASON_AP_BUSY);
|
||||
station_debug_event(station, "ap-roam-blacklist-added");
|
||||
|
||||
/*
|
||||
@ -3410,26 +3433,6 @@ static void station_event_channel_switched(struct station *station,
|
||||
network_bss_update(network, station->connected_bss);
|
||||
}
|
||||
|
||||
static bool station_try_next_bss(struct station *station)
|
||||
{
|
||||
struct scan_bss *next;
|
||||
int ret;
|
||||
|
||||
next = network_bss_select(station->connected_network, false);
|
||||
|
||||
if (!next)
|
||||
return false;
|
||||
|
||||
ret = __station_connect_network(station, station->connected_network,
|
||||
next, station->state);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
l_debug("Attempting to connect to next BSS "MAC, MAC_STR(next->addr));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool station_retry_owe_default_group(struct station *station)
|
||||
{
|
||||
/*
|
||||
@ -3523,13 +3526,6 @@ static bool station_pmksa_fallback(struct station *station, uint16_t status)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* A bit more concise for trying to fit these into 80 characters */
|
||||
#define IS_TEMPORARY_STATUS(code) \
|
||||
((code) == MMPDU_STATUS_CODE_DENIED_UNSUFFICIENT_BANDWIDTH || \
|
||||
(code) == MMPDU_STATUS_CODE_DENIED_POOR_CHAN_CONDITIONS || \
|
||||
(code) == MMPDU_STATUS_CODE_REJECTED_WITH_SUGG_BSS_TRANS || \
|
||||
(code) == MMPDU_STATUS_CODE_DENIED_NO_MORE_STAS)
|
||||
|
||||
static bool station_retry_with_status(struct station *station,
|
||||
uint16_t status_code)
|
||||
{
|
||||
@ -3537,19 +3533,37 @@ static bool station_retry_with_status(struct station *station,
|
||||
if (station_pmksa_fallback(station, status_code))
|
||||
goto try_next;
|
||||
|
||||
switch (status_code) {
|
||||
/*
|
||||
* Certain Auth/Assoc failures should not cause a timeout blacklist.
|
||||
* In these cases we want to only temporarily blacklist the BSS until
|
||||
* the connection is complete.
|
||||
*
|
||||
*/
|
||||
case MMPDU_STATUS_CODE_DENIED_UNSUFFICIENT_BANDWIDTH:
|
||||
case MMPDU_STATUS_CODE_DENIED_POOR_CHAN_CONDITIONS:
|
||||
/*
|
||||
* TODO: The WITH_SUGG_BSS_TRANS case should also include a neighbor
|
||||
* report IE in the frame. This would allow us to target a
|
||||
* specific BSS on our next attempt. There is currently no way to
|
||||
* obtain that IE, but this should be done in the future.
|
||||
*/
|
||||
if (!IS_TEMPORARY_STATUS(status_code))
|
||||
case MMPDU_STATUS_CODE_REJECTED_WITH_SUGG_BSS_TRANS:
|
||||
break;
|
||||
/*
|
||||
* If a BSS is indicating its unable to handle more connections we will
|
||||
* blacklist this the same way we do for BSS's issuing BSS-TM requests
|
||||
* thereby avoiding roams to this BSS for the configured timeout.
|
||||
*/
|
||||
case MMPDU_STATUS_CODE_DENIED_NO_MORE_STAS:
|
||||
blacklist_add_bss(station->connected_bss->addr,
|
||||
BLACKLIST_REASON_AP_BUSY);
|
||||
break;
|
||||
/* For any other status codes, blacklist the BSS */
|
||||
default:
|
||||
blacklist_add_bss(station->connected_bss->addr,
|
||||
BLACKLIST_REASON_CONNECT_FAILED);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unconditionally network blacklist the BSS if we are retrying. This
|
||||
@ -3571,13 +3585,6 @@ static void station_connect_ok(struct station *station)
|
||||
|
||||
l_debug("");
|
||||
|
||||
if (station->connect_pending) {
|
||||
struct l_dbus_message *reply =
|
||||
l_dbus_message_new_method_return(
|
||||
station->connect_pending);
|
||||
dbus_pending_reply(&station->connect_pending, reply);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a neighbor report now so future roams can avoid waiting for
|
||||
* a report at that time
|
||||
|
@ -2581,7 +2581,8 @@ static bool getrandom_precheck(const void *data)
|
||||
|
||||
static bool aes_cbc_precheck(const void *data)
|
||||
{
|
||||
return l_cipher_is_supported(L_CIPHER_AES_CBC);
|
||||
return (l_key_is_supported(L_KEY_FEATURE_DH) &&
|
||||
l_cipher_is_supported(L_CIPHER_AES_CBC));
|
||||
}
|
||||
|
||||
static bool key_crypto_precheck(const void *data)
|
||||
|
Loading…
x
Reference in New Issue
Block a user