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:
|
ver 3.8:
|
||||||
Fix issue with handling unit tests and missing kernel features.
|
Fix issue with handling unit tests and missing kernel features.
|
||||||
|
|
||||||
|
@ -3,4 +3,4 @@ RoamThreshold=-72
|
|||||||
CriticalRoamThreshold=-72
|
CriticalRoamThreshold=-72
|
||||||
|
|
||||||
[Blacklist]
|
[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
|
# using the same static config. The new client's ACD client should
|
||||||
# detect an IP conflict and not allow the device to reach the
|
# detect an IP conflict and not allow the device to reach the
|
||||||
# "connected" state although the DBus .Connect call will succeed.
|
# "connected" state although the DBus .Connect call will succeed.
|
||||||
ordered_network.network_object.connect()
|
with self.assertRaises(iwd.FailedEx):
|
||||||
self.assertEqual(dev2.state, iwd.DeviceState.connecting)
|
ordered_network.network_object.connect(timeout=500)
|
||||||
try:
|
|
||||||
# We should either stay in "connecting" indefinitely or move to
|
condition = 'obj.state == DeviceState.disconnected'
|
||||||
# "disconnecting"
|
iwd_ns0_1.wait_for_object_condition(dev2, condition, max_wait=21)
|
||||||
condition = 'obj.state != DeviceState.connecting'
|
|
||||||
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)
|
iwd_ns0_1.unregister_psk_agent(psk_agent_ns0_1)
|
||||||
del dev2
|
del dev2
|
||||||
|
@ -8,6 +8,8 @@ from iwd import PSKAgent
|
|||||||
from iwd import NetworkType
|
from iwd import NetworkType
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
|
def connect_failure(self, ex):
|
||||||
|
self.failure_triggered = True
|
||||||
|
|
||||||
def test_netconfig_timeout(self):
|
def test_netconfig_timeout(self):
|
||||||
IWD.copy_to_storage('autoconnect.psk', name='ap-ns1.psk')
|
IWD.copy_to_storage('autoconnect.psk', name='ap-ns1.psk')
|
||||||
@ -27,23 +29,34 @@ class Test(unittest.TestCase):
|
|||||||
condition = 'not obj.connected'
|
condition = 'not obj.connected'
|
||||||
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
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)
|
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)
|
||||||
# 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)")
|
|
||||||
|
|
||||||
device.disconnect()
|
device.disconnect()
|
||||||
condition = 'obj.state == DeviceState.disconnected'
|
condition = 'obj.state == DeviceState.disconnected'
|
||||||
|
@ -19,7 +19,7 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
device = wd.list_devices(1)[0]
|
device = wd.list_devices(1)[0]
|
||||||
device.get_ordered_network('TestFT', full_scan=True)
|
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}')
|
self.bss_hostapd[1].wait_for_event(f'AP-STA-CONNECTED {device.address}')
|
||||||
device.wait_for_event("connecting (netconfig)")
|
device.wait_for_event("connecting (netconfig)")
|
||||||
|
@ -112,8 +112,8 @@ class AsyncOpAbstract(object):
|
|||||||
self._is_completed = True
|
self._is_completed = True
|
||||||
self._exception = _convert_dbus_ex(ex)
|
self._exception = _convert_dbus_ex(ex)
|
||||||
|
|
||||||
def _wait_for_async_op(self):
|
def _wait_for_async_op(self, timeout=50):
|
||||||
ctx.non_block_wait(lambda s: s._is_completed, 30, self, exception=None)
|
ctx.non_block_wait(lambda s: s._is_completed, timeout, self, exception=None)
|
||||||
|
|
||||||
self._is_completed = False
|
self._is_completed = False
|
||||||
if self._exception is not None:
|
if self._exception is not None:
|
||||||
@ -280,8 +280,15 @@ class StationDebug(IWDDBusAbstract):
|
|||||||
def autoconnect(self):
|
def autoconnect(self):
|
||||||
return self._properties['AutoConnect']
|
return self._properties['AutoConnect']
|
||||||
|
|
||||||
def connect_bssid(self, address):
|
def connect_bssid(self, address, wait=True):
|
||||||
self._iface.ConnectBssid(dbus.ByteArray.fromhex(address.replace(':', '')))
|
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):
|
def roam(self, address):
|
||||||
self._iface.Roam(dbus.ByteArray.fromhex(address.replace(':', '')))
|
self._iface.Roam(dbus.ByteArray.fromhex(address.replace(':', '')))
|
||||||
@ -870,8 +877,8 @@ class Device(IWDDBusAbstract):
|
|||||||
def stop_adhoc(self):
|
def stop_adhoc(self):
|
||||||
self._prop_proxy.Set(IWD_DEVICE_INTERFACE, 'Mode', 'station')
|
self._prop_proxy.Set(IWD_DEVICE_INTERFACE, 'Mode', 'station')
|
||||||
|
|
||||||
def connect_bssid(self, address):
|
def connect_bssid(self, address, wait=True):
|
||||||
self._station_debug.connect_bssid(address)
|
self._station_debug.connect_bssid(address, wait=wait)
|
||||||
|
|
||||||
def roam(self, address):
|
def roam(self, address):
|
||||||
self._station_debug.roam(address)
|
self._station_debug.roam(address)
|
||||||
@ -999,7 +1006,7 @@ class Network(IWDDBusAbstract):
|
|||||||
def extended_service_set(self):
|
def extended_service_set(self):
|
||||||
return self._properties['ExtendedServiceSet']
|
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
|
Connect to the network. Request the device implied by the object
|
||||||
path to connect to specified network.
|
path to connect to specified network.
|
||||||
@ -1014,12 +1021,19 @@ class Network(IWDDBusAbstract):
|
|||||||
@rtype: void
|
@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,
|
self._iface.Connect(dbus_interface=self._iface_name,
|
||||||
reply_handler=self._success,
|
reply_handler=reply_handler,
|
||||||
error_handler=self._failure)
|
error_handler=error_handler,
|
||||||
|
timeout=timeout)
|
||||||
|
|
||||||
if wait:
|
if wait:
|
||||||
self._wait_for_async_op()
|
self._wait_for_async_op(timeout=timeout)
|
||||||
|
|
||||||
def __str__(self, prefix = ''):
|
def __str__(self, prefix = ''):
|
||||||
return prefix + 'Network:\n' \
|
return prefix + 'Network:\n' \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
AC_PREREQ([2.69])
|
AC_PREREQ([2.69])
|
||||||
AC_INIT([iwd],[3.8])
|
AC_INIT([iwd],[3.9])
|
||||||
|
|
||||||
AC_CONFIG_HEADERS(config.h)
|
AC_CONFIG_HEADERS(config.h)
|
||||||
AC_CONFIG_AUX_DIR(build-aux)
|
AC_CONFIG_AUX_DIR(build-aux)
|
||||||
|
@ -11,6 +11,12 @@ Methods void Connect()
|
|||||||
the object path to connect to specified network.
|
the object path to connect to specified network.
|
||||||
Connecting to WEP networks is not supported.
|
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
|
Possible errors: net.connman.iwd.Aborted
|
||||||
net.connman.iwd.Busy
|
net.connman.iwd.Busy
|
||||||
net.connman.iwd.Failed
|
net.connman.iwd.Failed
|
||||||
|
86
src/ap.c
86
src/ap.c
@ -109,6 +109,8 @@ struct ap_state {
|
|||||||
struct l_timeout *rekey_timeout;
|
struct l_timeout *rekey_timeout;
|
||||||
unsigned int rekey_time;
|
unsigned int rekey_time;
|
||||||
|
|
||||||
|
uint32_t pre_scan_cmd_id;
|
||||||
|
|
||||||
bool started : 1;
|
bool started : 1;
|
||||||
bool gtk_set : 1;
|
bool gtk_set : 1;
|
||||||
bool netconfig_set_addr4 : 1;
|
bool netconfig_set_addr4 : 1;
|
||||||
@ -354,6 +356,12 @@ static void ap_reset(struct ap_state *ap)
|
|||||||
l_timeout_remove(ap->rekey_timeout);
|
l_timeout_remove(ap->rekey_timeout);
|
||||||
ap->rekey_timeout = NULL;
|
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)
|
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;
|
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.
|
* 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;
|
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 (ap_start_send(ap)) {
|
||||||
if (err_out)
|
if (err_out)
|
||||||
*err_out = 0;
|
*err_out = 0;
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
static uint64_t blacklist_multiplier;
|
static uint64_t blacklist_multiplier;
|
||||||
static uint64_t blacklist_initial_timeout;
|
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;
|
static uint64_t blacklist_max_timeout;
|
||||||
|
|
||||||
struct blacklist_entry {
|
struct blacklist_entry {
|
||||||
@ -67,8 +67,8 @@ static uint64_t get_reason_timeout(enum blacklist_reason reason)
|
|||||||
switch (reason) {
|
switch (reason) {
|
||||||
case BLACKLIST_REASON_CONNECT_FAILED:
|
case BLACKLIST_REASON_CONNECT_FAILED:
|
||||||
return blacklist_initial_timeout;
|
return blacklist_initial_timeout;
|
||||||
case BLACKLIST_REASON_ROAM_REQUESTED:
|
case BLACKLIST_REASON_AP_BUSY:
|
||||||
return blacklist_roam_initial_timeout;
|
return blacklist_ap_busy_initial_timeout;
|
||||||
default:
|
default:
|
||||||
l_warn("Unhandled blacklist reason: %u", reason);
|
l_warn("Unhandled blacklist reason: %u", reason);
|
||||||
return 0;
|
return 0;
|
||||||
@ -218,11 +218,19 @@ static int blacklist_init(void)
|
|||||||
|
|
||||||
if (!l_settings_get_uint64(config, "Blacklist",
|
if (!l_settings_get_uint64(config, "Blacklist",
|
||||||
"InitialRoamRequestedTimeout",
|
"InitialRoamRequestedTimeout",
|
||||||
&blacklist_roam_initial_timeout))
|
&blacklist_ap_busy_initial_timeout))
|
||||||
blacklist_roam_initial_timeout = BLACKLIST_DEFAULT_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 */
|
/* 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",
|
if (!l_settings_get_uint64(config, "Blacklist",
|
||||||
"Multiplier",
|
"Multiplier",
|
||||||
|
@ -27,12 +27,14 @@ enum blacklist_reason {
|
|||||||
*/
|
*/
|
||||||
BLACKLIST_REASON_CONNECT_FAILED,
|
BLACKLIST_REASON_CONNECT_FAILED,
|
||||||
/*
|
/*
|
||||||
* This type of blacklist is added when a BSS requests IWD roams
|
* This type of blacklist is added when an AP indicates that its unable
|
||||||
* elsewhere. This is to aid in preventing IWD from roaming/connecting
|
* to handle more connections. This is done via BSS-TM requests or
|
||||||
* back to that BSS in the future unless there are no other "good"
|
* denied authentications/associations with certain status codes.
|
||||||
* candidates to connect to.
|
*
|
||||||
|
* 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);
|
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
|
The initial time that a BSS spends on the blacklist. Setting this to zero
|
||||||
will disable blacklisting functionality in IWD.
|
will disable blacklisting functionality in IWD.
|
||||||
* - InitialRoamRequestedTimeout
|
* - InitialRoamRequestedTimeout (**deprecated**)
|
||||||
- Values: uint64 value in seconds (default: **30**)
|
- Values: uint64 value in seconds (default: **30**)
|
||||||
|
|
||||||
The initial time that a BSS will be marked after a BSS requests a roam.
|
This setting is deprecated, please use
|
||||||
This is to aid in avoiding roaming back to BSS's which are likely
|
[Blacklist].InitialAccessPointBusyTimeout instead.
|
||||||
overloaded. Setting this to zero will disabled this form of blacklisting.
|
* - 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
|
* - Multiplier
|
||||||
- Values: unsigned int value greater than zero, in seconds
|
- Values: unsigned int value greater than zero, in seconds
|
||||||
(default: **30**)
|
(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);
|
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)
|
static void netdev_mlme_notify(struct l_genl_msg *msg, void *user_data)
|
||||||
{
|
{
|
||||||
struct netdev *netdev = NULL;
|
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:
|
case NL80211_CMD_MICHAEL_MIC_FAILURE:
|
||||||
netdev_michael_mic_failure(msg, netdev);
|
netdev_michael_mic_failure(msg, netdev);
|
||||||
break;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void network_clear_blacklist(struct network *network)
|
||||||
|
{
|
||||||
|
l_queue_clear(network->blacklist, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void network_connected(struct network *network)
|
void network_connected(struct network *network)
|
||||||
{
|
{
|
||||||
enum security security = network_get_security(network);
|
enum security security = network_get_security(network);
|
||||||
@ -198,8 +203,6 @@ void network_connected(struct network *network)
|
|||||||
l_queue_foreach_remove(network->secrets,
|
l_queue_foreach_remove(network->secrets,
|
||||||
network_secret_check_cacheable, network);
|
network_secret_check_cacheable, network);
|
||||||
|
|
||||||
l_queue_clear(network->blacklist, NULL);
|
|
||||||
|
|
||||||
network->provisioning_hidden = false;
|
network->provisioning_hidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +210,7 @@ void network_disconnected(struct network *network)
|
|||||||
{
|
{
|
||||||
network_settings_close(network);
|
network_settings_close(network);
|
||||||
|
|
||||||
l_queue_clear(network->blacklist, NULL);
|
network_clear_blacklist(network);
|
||||||
|
|
||||||
if (network->provisioning_hidden)
|
if (network->provisioning_hidden)
|
||||||
station_hide_network(network->station, network);
|
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 char *network_bss_get_path(const struct network *network,
|
||||||
const struct scan_bss *bss);
|
const struct scan_bss *bss);
|
||||||
bool network_bss_list_isempty(struct network *network);
|
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 char *__network_path_append_bss(const char *network_path,
|
||||||
const struct scan_bss *bss);
|
const struct scan_bss *bss);
|
||||||
|
@ -177,6 +177,7 @@ static const struct {
|
|||||||
{ NL80211_CMD_UNPROT_BEACON, "Unprotected Beacon" },
|
{ NL80211_CMD_UNPROT_BEACON, "Unprotected Beacon" },
|
||||||
{ NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS,
|
{ NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS,
|
||||||
"Control Port 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_CENTER_FREQ2:
|
||||||
case NL80211_ATTR_AKM_SUITES:
|
case NL80211_ATTR_AKM_SUITES:
|
||||||
case NL80211_ATTR_EXTERNAL_AUTH_ACTION:
|
case NL80211_ATTR_EXTERNAL_AUTH_ACTION:
|
||||||
|
case NL80211_ATTR_TIMEOUT:
|
||||||
return extract_uint32;
|
return extract_uint32;
|
||||||
case NL80211_ATTR_FRAME:
|
case NL80211_ATTR_FRAME:
|
||||||
return extract_iovec;
|
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])
|
!sm->handshake->ecc_sae_pts[sm->group_retry])
|
||||||
continue;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -994,7 +1002,8 @@ static int sae_process_anti_clogging(struct sae_sm *sm, const uint8_t *ptr,
|
|||||||
sm->token_len = len;
|
sm->token_len = len;
|
||||||
sm->sync = 0;
|
sm->sync = 0;
|
||||||
|
|
||||||
sae_send_commit(sm, true);
|
if (L_WARN_ON(!sae_send_commit(sm, true)))
|
||||||
|
return -EPROTO;
|
||||||
|
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
@ -1074,7 +1083,9 @@ static int sae_verify_committed(struct sae_sm *sm, uint16_t transaction,
|
|||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
|
|
||||||
sm->sync++;
|
sm->sync++;
|
||||||
sae_send_commit(sm, true);
|
|
||||||
|
if (L_WARN_ON(!sae_send_commit(sm, true)))
|
||||||
|
return -EPROTO;
|
||||||
|
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
@ -1129,7 +1140,9 @@ static int sae_verify_committed(struct sae_sm *sm, uint16_t transaction,
|
|||||||
sm->group);
|
sm->group);
|
||||||
|
|
||||||
sm->sync = 0;
|
sm->sync = 0;
|
||||||
sae_send_commit(sm, false);
|
|
||||||
|
if (L_WARN_ON(!sae_send_commit(sm, false)))
|
||||||
|
return -EPROTO;
|
||||||
|
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
@ -1294,7 +1307,8 @@ static int sae_verify_confirmed(struct sae_sm *sm, uint16_t trans,
|
|||||||
sm->sync++;
|
sm->sync++;
|
||||||
sm->sc++;
|
sm->sc++;
|
||||||
|
|
||||||
sae_send_commit(sm, true);
|
if (L_WARN_ON(!sae_send_commit(sm, true)))
|
||||||
|
return -EPROTO;
|
||||||
|
|
||||||
if (!sae_send_confirm(sm))
|
if (!sae_send_confirm(sm))
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
|
137
src/station.c
137
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))
|
if (blacklist_contains_bss(addr, BLACKLIST_REASON_CONNECT_FAILED))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
roam_blacklist = blacklist_contains_bss(addr,
|
roam_blacklist = blacklist_contains_bss(addr, BLACKLIST_REASON_AP_BUSY);
|
||||||
BLACKLIST_REASON_ROAM_REQUESTED);
|
|
||||||
good_signal = signal >= netdev_get_low_signal_threshold(freq);
|
good_signal = signal >= netdev_get_low_signal_threshold(freq);
|
||||||
|
|
||||||
if (good_signal)
|
if (good_signal)
|
||||||
@ -1796,6 +1795,15 @@ static void station_enter_state(struct station *station,
|
|||||||
periodic_scan_stop(station);
|
periodic_scan_stop(station);
|
||||||
break;
|
break;
|
||||||
case STATION_STATE_CONNECTED:
|
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,
|
l_dbus_object_add_interface(dbus,
|
||||||
netdev_get_path(station->netdev),
|
netdev_get_path(station->netdev),
|
||||||
IWD_STATION_DIAGNOSTIC_INTERFACE,
|
IWD_STATION_DIAGNOSTIC_INTERFACE,
|
||||||
@ -2215,6 +2223,26 @@ static void station_early_neighbor_report_cb(struct netdev *netdev, int err,
|
|||||||
&station->roam_freqs);
|
&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,
|
static bool station_can_fast_transition(struct station *station,
|
||||||
struct handshake_state *hs,
|
struct handshake_state *hs,
|
||||||
struct scan_bss *bss)
|
struct scan_bss *bss)
|
||||||
@ -2257,28 +2285,26 @@ static bool station_can_fast_transition(struct station *station,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void station_disconnect_on_error_cb(struct netdev *netdev, bool success,
|
static void station_disconnect_on_netconfig_failed(struct netdev *netdev,
|
||||||
void *user_data)
|
bool success,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct station *station = user_data;
|
struct station *station = user_data;
|
||||||
bool continue_autoconnect;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (station_try_next_bss(station))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (station->connect_pending) {
|
||||||
|
struct l_dbus_message *reply = dbus_error_failed(
|
||||||
|
station->connect_pending);
|
||||||
|
|
||||||
|
dbus_pending_reply(&station->connect_pending, reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (station->autoconnect)
|
station_reset_connection_state(station);
|
||||||
station_enter_state(station, STATION_STATE_AUTOCONNECT_QUICK);
|
|
||||||
|
station_enter_state(station, STATION_STATE_DISCONNECTED);
|
||||||
|
station_enter_state(station, STATION_STATE_AUTOCONNECT_FULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void station_netconfig_event_handler(enum netconfig_event event,
|
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);
|
station_enter_state(station, STATION_STATE_CONNECTED);
|
||||||
break;
|
break;
|
||||||
case NETCONFIG_EVENT_FAILED:
|
case NETCONFIG_EVENT_FAILED:
|
||||||
if (station->connect_pending) {
|
station_debug_event(station, "netconfig-failed");
|
||||||
struct l_dbus_message *reply = dbus_error_failed(
|
|
||||||
station->connect_pending);
|
|
||||||
|
|
||||||
dbus_pending_reply(&station->connect_pending, reply);
|
netconfig_reset(station->netconfig);
|
||||||
}
|
|
||||||
|
|
||||||
if (station->state == STATION_STATE_NETCONFIG)
|
if (station->state == STATION_STATE_NETCONFIG)
|
||||||
network_connect_failed(station->connected_network,
|
network_connect_failed(station->connected_network,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
netdev_disconnect(station->netdev,
|
network_blacklist_add(station->connected_network,
|
||||||
station_disconnect_on_error_cb,
|
station->connected_bss);
|
||||||
station);
|
|
||||||
station_reset_connection_state(station);
|
|
||||||
|
|
||||||
station_enter_state(station, STATION_STATE_DISCONNECTING);
|
netdev_disconnect(station->netdev,
|
||||||
|
station_disconnect_on_netconfig_failed,
|
||||||
|
station);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
l_error("station: Unsupported netconfig event: %d.", event);
|
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_add_bss(station->connected_bss->addr,
|
||||||
BLACKLIST_REASON_ROAM_REQUESTED);
|
BLACKLIST_REASON_AP_BUSY);
|
||||||
station_debug_event(station, "ap-roam-blacklist-added");
|
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);
|
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)
|
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;
|
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,
|
static bool station_retry_with_status(struct station *station,
|
||||||
uint16_t status_code)
|
uint16_t status_code)
|
||||||
{
|
{
|
||||||
@ -3537,19 +3533,37 @@ static bool station_retry_with_status(struct station *station,
|
|||||||
if (station_pmksa_fallback(station, status_code))
|
if (station_pmksa_fallback(station, status_code))
|
||||||
goto try_next;
|
goto try_next;
|
||||||
|
|
||||||
|
switch (status_code) {
|
||||||
/*
|
/*
|
||||||
* Certain Auth/Assoc failures should not cause a timeout blacklist.
|
* Certain Auth/Assoc failures should not cause a timeout blacklist.
|
||||||
* In these cases we want to only temporarily blacklist the BSS until
|
* In these cases we want to only temporarily blacklist the BSS until
|
||||||
* the connection is complete.
|
* 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
|
* TODO: The WITH_SUGG_BSS_TRANS case should also include a neighbor
|
||||||
* report IE in the frame. This would allow us to target a
|
* report IE in the frame. This would allow us to target a
|
||||||
* specific BSS on our next attempt. There is currently no way to
|
* specific BSS on our next attempt. There is currently no way to
|
||||||
* obtain that IE, but this should be done in the future.
|
* obtain that IE, but this should be done in the future.
|
||||||
|
*/
|
||||||
|
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.
|
||||||
*/
|
*/
|
||||||
if (!IS_TEMPORARY_STATUS(status_code))
|
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_add_bss(station->connected_bss->addr,
|
||||||
BLACKLIST_REASON_CONNECT_FAILED);
|
BLACKLIST_REASON_CONNECT_FAILED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unconditionally network blacklist the BSS if we are retrying. This
|
* Unconditionally network blacklist the BSS if we are retrying. This
|
||||||
@ -3571,13 +3585,6 @@ static void station_connect_ok(struct station *station)
|
|||||||
|
|
||||||
l_debug("");
|
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
|
* Get a neighbor report now so future roams can avoid waiting for
|
||||||
* a report at that time
|
* a report at that time
|
||||||
|
@ -2581,7 +2581,8 @@ static bool getrandom_precheck(const void *data)
|
|||||||
|
|
||||||
static bool aes_cbc_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)
|
static bool key_crypto_precheck(const void *data)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user