3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2025-07-15 16:27:26 +02:00

Compare commits

..

No commits in common. "master" and "3.3" have entirely different histories.
master ... 3.3

55 changed files with 478 additions and 1517 deletions

1
.gitignore vendored
View File

@ -68,7 +68,6 @@ unit/test-dpp
unit/test-json unit/test-json
unit/test-nl80211util unit/test-nl80211util
unit/test-pmksa unit/test-pmksa
unit/test-storage
unit/cert-*.pem unit/cert-*.pem
unit/cert-*.csr unit/cert-*.csr
unit/cert-*.srl unit/cert-*.srl

View File

@ -1,30 +1,3 @@
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.
ver 3.7:
Fix issue with handling length of EncryptedSecurity.
Fix issue with handling empty affinities lists.
Fix issue with handling survey scanning results.
Fix issue with handling duplicate values in DPP URI.
ver 3.6:
Fix issue with handling blacklisting and roaming requests.
Fix issue with handling CQM thresholds for FullMAC devices.
Add support for PMKSA when using FullMAC devices.
ver 3.5:
Add support for option to disable blacklist handling.
Add support for option to disable SAE for broken drivers.
ver 3.4:
Add support for the Test Anything Protocol.
ver 3.3: ver 3.3:
Fix issue with handling External Authentication. Fix issue with handling External Authentication.

View File

@ -71,9 +71,7 @@ ell_headers = ell/util.h \
ell_sources = ell/private.h \ ell_sources = ell/private.h \
ell/missing.h \ ell/missing.h \
ell/util.c \ ell/util.c \
ell/test-private.h \
ell/test.c \ ell/test.c \
ell/test-dbus.c \
ell/strv.c \ ell/strv.c \
ell/utf8.c \ ell/utf8.c \
ell/queue.c \ ell/queue.c \
@ -441,7 +439,7 @@ unit_tests += unit/test-cmac-aes \
unit/test-arc4 unit/test-wsc unit/test-eap-mschapv2 \ unit/test-arc4 unit/test-wsc unit/test-eap-mschapv2 \
unit/test-eap-sim unit/test-sae unit/test-p2p unit/test-band \ unit/test-eap-sim unit/test-sae unit/test-p2p unit/test-band \
unit/test-dpp unit/test-json unit/test-nl80211util \ unit/test-dpp unit/test-json unit/test-nl80211util \
unit/test-pmksa unit/test-storage unit/test-pmksa
endif endif
if CLIENT if CLIENT
@ -605,11 +603,6 @@ unit_test_nl80211util_LDADD = $(ell_ldadd)
unit_test_pmksa_SOURCES = unit/test-pmksa.c src/pmksa.c src/pmksa.h \ unit_test_pmksa_SOURCES = unit/test-pmksa.c src/pmksa.c src/pmksa.h \
src/module.h src/util.h src/module.h src/util.h
unit_test_pmksa_LDADD = $(ell_ldadd) unit_test_pmksa_LDADD = $(ell_ldadd)
unit_test_storage_SOURCES = unit/test-storage.c src/storage.c src/storage.h \
src/crypto.c src/crypto.h \
src/common.c src/common.h
unit_test_storage_LDADD = $(ell_ldadd)
endif endif
if CLIENT if CLIENT
@ -625,9 +618,6 @@ unit_test_client_SOURCES = unit/test-client.c \
unit_test_client_LDADD = $(ell_ldadd) $(client_ldadd) unit_test_client_LDADD = $(ell_ldadd) $(client_ldadd)
endif endif
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
$(top_srcdir)/build-aux/tap-driver.sh
TESTS = $(unit_tests) TESTS = $(unit_tests)
EXTRA_DIST = src/genbuiltin src/iwd.service.in src/net.connman.iwd.service \ EXTRA_DIST = src/genbuiltin src/iwd.service.in src/net.connman.iwd.service \

View File

@ -11,58 +11,52 @@ from iwd import NetworkType
from hostapd import HostapdCLI from hostapd import HostapdCLI
class Test(unittest.TestCase): class Test(unittest.TestCase):
def initial_connection(self):
ordered_network = self.device.get_ordered_network('TestAPRoam') def validate(self, expect_roam=True):
wd = IWD()
devices = wd.list_devices(1)
device = devices[0]
ordered_network = device.get_ordered_network('TestAPRoam')
self.assertEqual(ordered_network.type, NetworkType.psk) self.assertEqual(ordered_network.type, NetworkType.psk)
condition = 'not obj.connected' condition = 'not obj.connected'
self.wd.wait_for_object_condition(ordered_network.network_object, condition) wd.wait_for_object_condition(ordered_network.network_object, condition)
self.device.connect_bssid(self.bss_hostapd[0].bssid) device.connect_bssid(self.bss_hostapd[0].bssid)
condition = 'obj.state == DeviceState.connected' condition = 'obj.state == DeviceState.connected'
self.wd.wait_for_object_condition(self.device, condition) wd.wait_for_object_condition(device, condition)
self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED') self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED')
self.assertFalse(self.bss_hostapd[1].list_sta()) self.assertFalse(self.bss_hostapd[1].list_sta())
def validate_roam(self, from_bss, to_bss, expect_roam=True): self.bss_hostapd[0].send_bss_transition(device.address,
from_bss.send_bss_transition(self.device.address, [(self.bss_hostapd[1].bssid, '8f0000005102060603000000')],
self.neighbor_list,
disassoc_imminent=expect_roam) disassoc_imminent=expect_roam)
if expect_roam: if expect_roam:
from_condition = 'obj.state == DeviceState.roaming' from_condition = 'obj.state == DeviceState.roaming'
to_condition = 'obj.state == DeviceState.connected' to_condition = 'obj.state == DeviceState.connected'
self.wd.wait_for_object_change(self.device, from_condition, to_condition) wd.wait_for_object_change(device, from_condition, to_condition)
to_bss.wait_for_event('AP-STA-CONNECTED %s' % self.device.address) self.bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % device.address)
else: else:
self.device.wait_for_event("no-roam-candidates") device.wait_for_event("no-roam-candidates")
device.disconnect()
condition = 'not obj.connected'
wd.wait_for_object_condition(ordered_network.network_object, condition)
def test_disassoc_imminent(self): def test_disassoc_imminent(self):
self.initial_connection() self.validate(expect_roam=True)
self.validate_roam(self.bss_hostapd[0], self.bss_hostapd[1])
def test_no_candidates(self): def test_no_candidates(self):
self.initial_connection() self.validate(expect_roam=False)
# We now have BSS0 roam blacklisted
self.validate_roam(self.bss_hostapd[0], self.bss_hostapd[1])
# Try and trigger another roam back, which shouldn't happen since now
# both BSS's are roam blacklisted
self.validate_roam(self.bss_hostapd[1], self.bss_hostapd[0], expect_roam=False)
def setUp(self):
self.wd = IWD(True)
devices = self.wd.list_devices(1)
self.device = devices[0]
def tearDown(self):
self.wd = None
self.device = None
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
@ -71,10 +65,6 @@ class Test(unittest.TestCase):
cls.bss_hostapd = [ HostapdCLI(config='ssid1.conf'), cls.bss_hostapd = [ HostapdCLI(config='ssid1.conf'),
HostapdCLI(config='ssid2.conf'), HostapdCLI(config='ssid2.conf'),
HostapdCLI(config='ssid3.conf') ] HostapdCLI(config='ssid3.conf') ]
cls.neighbor_list = [
(cls.bss_hostapd[0].bssid, "8f0000005101060603000000"),
(cls.bss_hostapd[1].bssid, "8f0000005102060603000000"),
]
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):

View File

@ -1,7 +1,5 @@
[SETUP] [SETUP]
num_radios=4 num_radios=4
hwsim_medium=true
start_iwd=false
[HOSTAPD] [HOSTAPD]
rad0=ssid1.conf rad0=ssid1.conf

View File

@ -1,6 +0,0 @@
[General]
RoamThreshold=-72
CriticalRoamThreshold=-72
[Blacklist]
InitialAccessPointBusyTimeout=20

View File

@ -1,183 +0,0 @@
#!/usr/bin/python3
import unittest
import sys
sys.path.append('../util')
import iwd
from iwd import IWD, IWD_CONFIG_DIR
from iwd import NetworkType
from hostapd import HostapdCLI
from hwsim import Hwsim
class Test(unittest.TestCase):
def validate_connected(self, hostapd):
ordered_network = self.device.get_ordered_network('TestAPRoam')
self.assertEqual(ordered_network.type, NetworkType.psk)
condition = 'not obj.connected'
self.wd.wait_for_object_condition(ordered_network.network_object, condition)
self.device.connect_bssid(hostapd.bssid)
condition = 'obj.state == DeviceState.connected'
self.wd.wait_for_object_condition(self.device, condition)
hostapd.wait_for_event('AP-STA-CONNECTED')
def validate_ap_roamed(self, from_hostapd, to_hostapd):
from_hostapd.send_bss_transition(
self.device.address, self.neighbor_list, disassoc_imminent=True
)
from_condition = 'obj.state == DeviceState.roaming'
to_condition = 'obj.state == DeviceState.connected'
self.wd.wait_for_object_change(self.device, from_condition, to_condition)
to_hostapd.wait_for_event('AP-STA-CONNECTED %s' % self.device.address)
self.device.wait_for_event("ap-roam-blacklist-added")
def test_roam_to_optimal_candidates(self):
# In this test IWD will naturally transition down the list after each
# BSS gets roam blacklisted. All BSS's are above the RSSI thresholds.
self.rule_ssid1.signal = -5000
self.rule_ssid2.signal = -6500
self.rule_ssid3.signal = -6900
# Connect to BSS0
self.validate_connected(self.bss_hostapd[0])
# AP directed roam to BSS1
self.validate_ap_roamed(self.bss_hostapd[0], self.bss_hostapd[1])
# AP directed roam to BSS2
self.validate_ap_roamed(self.bss_hostapd[1], self.bss_hostapd[2])
def test_avoiding_under_threshold_bss(self):
# In this test IWD will blacklist BSS0, then roam the BSS1. BSS1 will
# then tell IWD to roam, but it should go back to BSS0 since the only
# non-blacklisted BSS is under the roam threshold.
self.rule_ssid1.signal = -5000
self.rule_ssid2.signal = -6500
self.rule_ssid3.signal = -7300
# Connect to BSS0
self.validate_connected(self.bss_hostapd[0])
# AP directed roam to BSS1
self.validate_ap_roamed(self.bss_hostapd[0], self.bss_hostapd[1])
# AP directed roam, but IWD should choose BSS0 since BSS2 is -73dB
self.validate_ap_roamed(self.bss_hostapd[1], self.bss_hostapd[0])
def test_connect_to_roam_blacklisted_bss(self):
# In this test a BSS will be roam blacklisted, but all other options are
# below the RSSI threshold so IWD should roam back to the blacklisted
# BSS.
self.rule_ssid1.signal = -5000
self.rule_ssid2.signal = -8000
self.rule_ssid3.signal = -8500
# Connect to BSS0
self.validate_connected(self.bss_hostapd[0])
# AP directed roam, should connect to BSS1 as its the next best
self.validate_ap_roamed(self.bss_hostapd[0], self.bss_hostapd[1])
# Connected to BSS1, but the signal is bad, so IWD should try to roam
# again. BSS0 is still blacklisted, but its the only reasonable option
# since both BSS1 and BSS2 are below the set RSSI threshold (-72dB)
from_condition = 'obj.state == DeviceState.roaming'
to_condition = 'obj.state == DeviceState.connected'
self.wd.wait_for_object_change(self.device, from_condition, to_condition)
# IWD should have connected to BSS0, even though its roam blacklisted
self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED %s' % self.device.address)
def test_blacklist_during_roam_scan(self):
# Tests that an AP roam request mid-roam results in the AP still being
# blacklisted even though the request itself doesn't directly trigger
# a roam.
self.rule_ssid1.signal = -7300
self.rule_ssid2.signal = -7500
self.rule_ssid3.signal = -8500
# Connect to BSS0 under the roam threshold so IWD will immediately try
# roaming elsewhere
self.validate_connected(self.bss_hostapd[0])
self.device.wait_for_event("roam-scan-triggered")
self.bss_hostapd[0].send_bss_transition(
self.device.address, self.neighbor_list, disassoc_imminent=True
)
self.device.wait_for_event("ap-roam-blacklist-added")
# BSS0 should have gotten blacklisted even though IWD was mid-roam,
# causing IWD to choose BSS1 when it gets is results.
from_condition = 'obj.state == DeviceState.roaming'
to_condition = 'obj.state == DeviceState.connected'
self.wd.wait_for_object_change(self.device, from_condition, to_condition)
self.bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % self.device.address)
def setUp(self):
self.wd = IWD(True)
devices = self.wd.list_devices(1)
self.device = devices[0]
def tearDown(self):
self.wd = None
self.device = None
@classmethod
def setUpClass(cls):
IWD.copy_to_storage("main.conf.roaming", IWD_CONFIG_DIR, "main.conf")
IWD.copy_to_storage('TestAPRoam.psk')
hwsim = Hwsim()
cls.bss_hostapd = [ HostapdCLI(config='ssid1.conf'),
HostapdCLI(config='ssid2.conf'),
HostapdCLI(config='ssid3.conf') ]
HostapdCLI.group_neighbors(*cls.bss_hostapd)
rad0 = hwsim.get_radio('rad0')
rad1 = hwsim.get_radio('rad1')
rad2 = hwsim.get_radio('rad2')
cls.neighbor_list = [
(cls.bss_hostapd[0].bssid, "8f0000005101060603000000"),
(cls.bss_hostapd[1].bssid, "8f0000005102060603000000"),
(cls.bss_hostapd[2].bssid, "8f0000005103060603000000"),
]
cls.rule_ssid1 = hwsim.rules.create()
cls.rule_ssid1.source = rad0.addresses[0]
cls.rule_ssid1.bidirectional = True
cls.rule_ssid1.enabled = True
cls.rule_ssid2 = hwsim.rules.create()
cls.rule_ssid2.source = rad1.addresses[0]
cls.rule_ssid2.bidirectional = True
cls.rule_ssid2.enabled = True
cls.rule_ssid3 = hwsim.rules.create()
cls.rule_ssid3.source = rad2.addresses[0]
cls.rule_ssid3.bidirectional = True
cls.rule_ssid3.enabled = True
@classmethod
def tearDownClass(cls):
IWD.clear_storage()
if __name__ == '__main__':
unittest.main(exit=True)

View File

@ -1,2 +0,0 @@
[Security]
Passphrase=secret123

View File

@ -260,69 +260,12 @@ class Test(unittest.TestCase):
self.wd.unregister_psk_agent(psk_agent) self.wd.unregister_psk_agent(psk_agent)
def test_blacklist_disabled(self):
wd = self.wd
bss_hostapd = self.bss_hostapd
rule0 = self.rule0
rule1 = self.rule1
rule2 = self.rule2
psk_agent = PSKAgent(["secret123", 'secret123'])
wd.register_psk_agent(psk_agent)
devices = wd.list_devices(1)
device = devices[0]
rule0.drop = True
rule0.enabled = True
device.autoconnect = True
condition = 'obj.state == DeviceState.connected'
wd.wait_for_object_condition(device, condition)
ordered_network = device.get_ordered_network("TestBlacklist", full_scan=True)
self.assertEqual(ordered_network.type, NetworkType.psk)
# The first BSS should fail, and we should connect to the second. This
# should not result in a connection blacklist though since its disabled.
bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % device.address)
device.disconnect()
rule0.drop = False
device.autoconnect = True
# Verify the first BSS wasn't blacklisted.
bss_hostapd[0].wait_for_event('AP-STA-CONNECTED %s' % device.address)
def setUp(self): def setUp(self):
_, _, name = self.id().split(".")
# TODO: If we have this pattern elsewhere it might be nice to turn this
# into a decorator e.g.
#
# @config("main.conf.disabled")
# @profile("TestBlacklist.psk")
# def test_blacklist_disabled(self)
# ...
#
if name == "test_blacklist_disabled":
IWD.copy_to_storage("main.conf.disabled", IWD_CONFIG_DIR, "main.conf")
IWD.copy_to_storage("TestBlacklist.psk")
else:
IWD.copy_to_storage("main.conf.default", IWD_CONFIG_DIR, "main.conf")
self.wd = IWD(True) self.wd = IWD(True)
def tearDown(self): def tearDown(self):
IWD.clear_storage() IWD.clear_storage()
self.wd = None self.wd = None
self.rule0.drop = False
self.rule1.drop = False
self.rule2.drop = False
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):

View File

@ -1,2 +0,0 @@
[Blacklist]
InitialTimeout=0

View File

@ -3,11 +3,7 @@ import sys
import sys import sys
import os import os
from scapy.layers.dot11 import * from scapy.layers.dot11 import *
from scapy.arch import str2mac from scapy.arch import str2mac, get_if_raw_hwaddr
try:
from scapy.arch import get_if_raw_hwaddr
except:
from scapy.arch.unix import get_if_raw_hwaddr
from time import time, sleep from time import time, sleep
from threading import Thread from threading import Thread

View File

@ -91,11 +91,16 @@ 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.
with self.assertRaises(iwd.FailedEx): ordered_network.network_object.connect()
ordered_network.network_object.connect(timeout=500) self.assertEqual(dev2.state, iwd.DeviceState.connecting)
try:
condition = 'obj.state == DeviceState.disconnected' # We should either stay in "connecting" indefinitely or move to
# "disconnecting"
condition = 'obj.state != DeviceState.connecting'
iwd_ns0_1.wait_for_object_condition(dev2, condition, max_wait=21) 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

View File

@ -8,8 +8,6 @@ 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')
@ -29,34 +27,23 @@ 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)
self.failure_triggered = False ordered_network.network_object.connect()
# Set our error handler here so we can check if it fails condition = 'obj.state == DeviceState.connecting'
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)
# IWD should attempt to connect, but it will of course fail again. device.wait_for_event("connecting (netconfig)")
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'

View File

@ -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, wait=False) device.connect_bssid(self.bss_hostapd[1].bssid)
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)")

View File

@ -7,10 +7,7 @@ from weakref import WeakValueDictionary
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from enum import Enum from enum import Enum
from scapy.all import * from scapy.all import *
try:
from scapy.contrib.wpa_eapol import WPA_key from scapy.contrib.wpa_eapol import WPA_key
except:
from scapy.layers.eap import EAPOL_KEY
import iwd import iwd
from config import ctx from config import ctx
@ -447,15 +444,9 @@ class Hwsim(iwd.AsyncOpAbstract):
# NOTE: Expected key_info is 0x008a, with the install flag # NOTE: Expected key_info is 0x008a, with the install flag
# this becomes 0x00ca. # this becomes 0x00ca.
try:
eapol = WPA_key( descriptor_type = 2, eapol = WPA_key( descriptor_type = 2,
key_info = 0x00ca, # Includes an invalid install flag! key_info = 0x00ca, # Includes an invalid install flag!
replay_counter = struct.pack(">Q", 100)) replay_counter = struct.pack(">Q", 100))
except:
eapol = EAPOL_KEY( key_descriptor_type = 2,
install = 1,
key_ack = 1,
key_replay_counter = 1)
frame /= LLC()/SNAP()/EAPOL(version="802.1X-2004", type="EAPOL-Key") frame /= LLC()/SNAP()/EAPOL(version="802.1X-2004", type="EAPOL-Key")
frame /= eapol frame /= eapol

View File

@ -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, timeout=50): def _wait_for_async_op(self):
ctx.non_block_wait(lambda s: s._is_completed, timeout, self, exception=None) ctx.non_block_wait(lambda s: s._is_completed, 30, self, exception=None)
self._is_completed = False self._is_completed = False
if self._exception is not None: if self._exception is not None:
@ -280,15 +280,8 @@ class StationDebug(IWDDBusAbstract):
def autoconnect(self): def autoconnect(self):
return self._properties['AutoConnect'] return self._properties['AutoConnect']
def connect_bssid(self, address, wait=True): def connect_bssid(self, address):
self._iface.ConnectBssid( self._iface.ConnectBssid(dbus.ByteArray.fromhex(address.replace(':', '')))
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(':', '')))
@ -877,8 +870,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, wait=True): def connect_bssid(self, address):
self._station_debug.connect_bssid(address, wait=wait) self._station_debug.connect_bssid(address)
def roam(self, address): def roam(self, address):
self._station_debug.roam(address) self._station_debug.roam(address)
@ -1006,7 +999,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, timeout=50, reply_handler=None, error_handler=None): def connect(self, wait=True):
''' '''
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.
@ -1021,19 +1014,12 @@ 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=reply_handler, reply_handler=self._success,
error_handler=error_handler, error_handler=self._failure)
timeout=timeout)
if wait: if wait:
self._wait_for_async_op(timeout=timeout) self._wait_for_async_op()
def __str__(self, prefix = ''): def __str__(self, prefix = ''):
return prefix + 'Network:\n' \ return prefix + 'Network:\n' \

View File

@ -1,12 +1,10 @@
AC_PREREQ([2.69]) AC_PREREQ([2.69])
AC_INIT([iwd],[3.9]) AC_INIT([iwd],[3.3])
AC_CONFIG_HEADERS(config.h) AC_CONFIG_HEADERS(config.h)
AC_CONFIG_AUX_DIR(build-aux) AC_CONFIG_AUX_DIR(build-aux)
AC_CONFIG_MACRO_DIR(build-aux) AC_CONFIG_MACRO_DIR(build-aux)
AC_REQUIRE_AUX_FILE([tap-driver.sh])
AM_INIT_AUTOMAKE([foreign subdir-objects color-tests silent-rules AM_INIT_AUTOMAKE([foreign subdir-objects color-tests silent-rules
tar-pax no-dist-gzip dist-xz]) tar-pax no-dist-gzip dist-xz])
@ -31,7 +29,6 @@ AC_PROG_CC_GCOV
AC_PROG_INSTALL AC_PROG_INSTALL
AC_PROG_MKDIR_P AC_PROG_MKDIR_P
AC_PROG_LN_S AC_PROG_LN_S
AC_PROG_AWK
AC_SYS_LARGEFILE AC_SYS_LARGEFILE
@ -300,7 +297,7 @@ if (test "${enable_external_ell}" = "yes"); then
test "${enable_monitor}" != "no" || test "${enable_monitor}" != "no" ||
test "${enable_wired}" = "yes" || test "${enable_wired}" = "yes" ||
test "${enable_hwsim}" = "yes"); then test "${enable_hwsim}" = "yes"); then
ell_min_version="0.77" ell_min_version="0.69"
else else
ell_min_version="0.5" ell_min_version="0.5"
fi fi

View File

@ -11,12 +11,6 @@ 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

View File

@ -1915,7 +1915,7 @@ static void print_ie_interworking(unsigned int level,
size--; size--;
ptr++; ptr++;
if (size < 2) if (!size)
return; return;
/* /*
@ -7433,7 +7433,7 @@ static bool check_pcap(struct nlmon *nlmon, size_t next_size)
pcap_close(nlmon->pcap); pcap_close(nlmon->pcap);
/* Exhausted the single PCAP file */ /* Exausted the single PCAP file */
if (nlmon->max_files < 2) { if (nlmon->max_files < 2) {
printf("Reached maximum size of PCAP, exiting\n"); printf("Reached maximum size of PCAP, exiting\n");
nlmon->pcap = NULL; nlmon->pcap = NULL;

View File

@ -109,8 +109,6 @@ 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;
@ -356,12 +354,6 @@ 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)
@ -3860,70 +3852,6 @@ 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.
* *
@ -4034,20 +3962,6 @@ 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;

View File

@ -45,42 +45,22 @@
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_ap_busy_initial_timeout;
static uint64_t blacklist_max_timeout; static uint64_t blacklist_max_timeout;
struct blacklist_entry { struct blacklist_entry {
uint8_t addr[6]; uint8_t addr[6];
uint64_t added_time; uint64_t added_time;
uint64_t expire_time; uint64_t expire_time;
enum blacklist_reason reason;
};
struct blacklist_search {
const uint8_t *addr;
enum blacklist_reason reason;
}; };
static struct l_queue *blacklist; static struct l_queue *blacklist;
static uint64_t get_reason_timeout(enum blacklist_reason reason)
{
switch (reason) {
case BLACKLIST_REASON_CONNECT_FAILED:
return blacklist_initial_timeout;
case BLACKLIST_REASON_AP_BUSY:
return blacklist_ap_busy_initial_timeout;
default:
l_warn("Unhandled blacklist reason: %u", reason);
return 0;
}
}
static bool check_if_expired(void *data, void *user_data) static bool check_if_expired(void *data, void *user_data)
{ {
struct blacklist_entry *entry = data; struct blacklist_entry *entry = data;
uint64_t now = l_get_u64(user_data); uint64_t now = l_get_u64(user_data);
if (l_time_after(now, entry->expire_time)) { if (l_time_diff(now, entry->added_time) > blacklist_max_timeout) {
l_debug("Removing entry "MAC" on prune", MAC_STR(entry->addr)); l_debug("Removing entry "MAC" on prune", MAC_STR(entry->addr));
l_free(entry); l_free(entry);
return true; return true;
@ -107,53 +87,17 @@ static bool match_addr(const void *a, const void *b)
return false; return false;
} }
static bool match_addr_and_reason(const void *a, const void *b) void blacklist_add_bss(const uint8_t *addr)
{
const struct blacklist_entry *entry = a;
const struct blacklist_search *search = b;
if (entry->reason != search->reason)
return false;
if (!memcmp(entry->addr, search->addr, 6))
return true;
return false;
}
void blacklist_add_bss(const uint8_t *addr, enum blacklist_reason reason)
{ {
struct blacklist_entry *entry; struct blacklist_entry *entry;
uint64_t timeout;
blacklist_prune(); blacklist_prune();
timeout = get_reason_timeout(reason);
if (!timeout)
return;
entry = l_queue_find(blacklist, match_addr, addr); entry = l_queue_find(blacklist, match_addr, addr);
if (entry) { if (entry) {
uint64_t offset; uint64_t offset = l_time_diff(entry->added_time,
entry->expire_time);
if (reason < entry->reason) {
l_debug("Promoting "MAC" blacklist to reason %u",
MAC_STR(addr), reason);
/* Reset this to the new timeout and reason */
entry->reason = reason;
entry->added_time = l_time_now();
entry->expire_time = l_time_offset(entry->added_time,
timeout);
return;
} else if (reason > entry->reason) {
l_debug("Ignoring blacklist extension of "MAC", "
"current blacklist status is more severe!",
MAC_STR(addr));
return;
}
offset = l_time_diff(entry->added_time, entry->expire_time);
offset *= blacklist_multiplier; offset *= blacklist_multiplier;
@ -168,36 +112,40 @@ void blacklist_add_bss(const uint8_t *addr, enum blacklist_reason reason)
entry = l_new(struct blacklist_entry, 1); entry = l_new(struct blacklist_entry, 1);
entry->added_time = l_time_now(); entry->added_time = l_time_now();
entry->expire_time = l_time_offset(entry->added_time, timeout); entry->expire_time = l_time_offset(entry->added_time,
entry->reason = reason; blacklist_initial_timeout);
memcpy(entry->addr, addr, 6); memcpy(entry->addr, addr, 6);
l_queue_push_tail(blacklist, entry); l_queue_push_tail(blacklist, entry);
} }
bool blacklist_contains_bss(const uint8_t *addr, enum blacklist_reason reason) bool blacklist_contains_bss(const uint8_t *addr)
{ {
struct blacklist_search search = { bool ret;
.addr = addr, uint64_t time_now;
.reason = reason struct blacklist_entry *entry;
};
blacklist_prune(); blacklist_prune();
return l_queue_find(blacklist, match_addr_and_reason, &search) != NULL; entry = l_queue_find(blacklist, match_addr, addr);
if (!entry)
return false;
time_now = l_time_now();
ret = l_time_after(time_now, entry->expire_time) ? false : true;
return ret;
} }
void blacklist_remove_bss(const uint8_t *addr, enum blacklist_reason reason) void blacklist_remove_bss(const uint8_t *addr)
{ {
struct blacklist_entry *entry; struct blacklist_entry *entry;
struct blacklist_search search = {
.addr = addr,
.reason = reason
};
blacklist_prune(); blacklist_prune();
entry = l_queue_remove_if(blacklist, match_addr_and_reason, &search); entry = l_queue_remove_if(blacklist, match_addr, addr);
if (!entry) if (!entry)
return; return;
@ -214,47 +162,19 @@ static int blacklist_init(void)
blacklist_initial_timeout = BLACKLIST_DEFAULT_TIMEOUT; blacklist_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_initial_timeout *= L_USEC_PER_SEC; blacklist_initial_timeout *= 1000000;
if (!l_settings_get_uint64(config, "Blacklist",
"InitialRoamRequestedTimeout",
&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_ap_busy_initial_timeout *= L_USEC_PER_SEC;
if (!l_settings_get_uint64(config, "Blacklist", if (!l_settings_get_uint64(config, "Blacklist",
"Multiplier", "Multiplier",
&blacklist_multiplier)) &blacklist_multiplier))
blacklist_multiplier = BLACKLIST_DEFAULT_MULTIPLIER; blacklist_multiplier = BLACKLIST_DEFAULT_MULTIPLIER;
if (blacklist_multiplier == 0) {
l_warn("[Blacklist].Multiplier cannot be zero, setting to 1");
blacklist_multiplier = 1;
}
if (!l_settings_get_uint64(config, "Blacklist", if (!l_settings_get_uint64(config, "Blacklist",
"MaximumTimeout", "MaximumTimeout",
&blacklist_max_timeout)) &blacklist_max_timeout))
blacklist_max_timeout = BLACKLIST_DEFAULT_MAX_TIMEOUT; blacklist_max_timeout = BLACKLIST_DEFAULT_MAX_TIMEOUT;
blacklist_max_timeout *= L_USEC_PER_SEC; blacklist_max_timeout *= 1000000;
if (blacklist_initial_timeout > blacklist_max_timeout)
l_warn("[Blacklist].InitialTimeout exceeded "
"[Blacklist].MaximumTimeout!");
if (!blacklist_initial_timeout)
l_debug("initial timeout was zero, blacklist will be disabled");
blacklist = l_queue_new(); blacklist = l_queue_new();

View File

@ -20,23 +20,6 @@
* *
*/ */
enum blacklist_reason { void blacklist_add_bss(const uint8_t *addr);
/* bool blacklist_contains_bss(const uint8_t *addr);
* When a BSS is blacklisted using this reason IWD will refuse to void blacklist_remove_bss(const uint8_t *addr);
* connect to it via autoconnect
*/
BLACKLIST_REASON_CONNECT_FAILED,
/*
* 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_AP_BUSY,
};
void blacklist_add_bss(const uint8_t *addr, enum blacklist_reason reason);
bool blacklist_contains_bss(const uint8_t *addr, enum blacklist_reason reason);
void blacklist_remove_bss(const uint8_t *addr, enum blacklist_reason reason);

View File

@ -1166,34 +1166,21 @@ struct dpp_uri_info *dpp_parse_uri(const char *uri)
switch (*pos) { switch (*pos) {
case 'C': case 'C':
if (L_WARN_ON(info->freqs))
goto free_info;
info->freqs = dpp_parse_class_and_channel(pos + 2, len); info->freqs = dpp_parse_class_and_channel(pos + 2, len);
if (!info->freqs) if (!info->freqs)
goto free_info; goto free_info;
break; break;
case 'M': case 'M':
if (L_WARN_ON(!l_memeqzero(info->mac,
sizeof(info->mac))))
goto free_info;
ret = dpp_parse_mac(pos + 2, len, info->mac); ret = dpp_parse_mac(pos + 2, len, info->mac);
if (ret < 0) if (ret < 0)
goto free_info; goto free_info;
break; break;
case 'V': case 'V':
if (L_WARN_ON(info->version != 0))
goto free_info;
ret = dpp_parse_version(pos + 2, len, &info->version); ret = dpp_parse_version(pos + 2, len, &info->version);
if (ret < 0) if (ret < 0)
goto free_info; goto free_info;
break; break;
case 'K': case 'K':
if (L_WARN_ON(info->boot_public))
goto free_info;
info->boot_public = dpp_parse_key(pos + 2, len); info->boot_public = dpp_parse_key(pos + 2, len);
if (!info->boot_public) if (!info->boot_public)
goto free_info; goto free_info;

View File

@ -544,8 +544,7 @@ static bool eap_mschapv2_load_settings(struct eap_state *eap,
return true; return true;
error: error:
l_free(state->user); free(state);
l_free(state);
return false; return false;
} }

View File

@ -425,8 +425,8 @@ static void eap_handle_response(struct eap_state *eap, const uint8_t *pkt,
size_t len) size_t len)
{ {
enum eap_type type; enum eap_type type;
uint32_t vendor_id = 0; uint32_t vendor_id;
uint32_t vendor_type = 0; uint32_t vendor_type;
enum eap_type our_type = eap->method->request_type; enum eap_type our_type = eap->method->request_type;
uint32_t our_vendor_id = (eap->method->vendor_id[0] << 16) | uint32_t our_vendor_id = (eap->method->vendor_id[0] << 16) |
(eap->method->vendor_id[1] << 8) | (eap->method->vendor_id[1] << 8) |

View File

@ -1239,7 +1239,7 @@ static struct pmksa *handshake_state_steal_pmksa(struct handshake_state *s)
s->have_pmksa = false; s->have_pmksa = false;
if (l_time_after(now, pmksa->expiration)) { if (l_time_after(now, pmksa->expiration)) {
pmksa_cache_free(pmksa); l_free(pmksa);
pmksa = NULL; pmksa = NULL;
} }
@ -1272,15 +1272,13 @@ void handshake_state_cache_pmksa(struct handshake_state *s)
{ {
struct pmksa *pmksa = handshake_state_steal_pmksa(s); struct pmksa *pmksa = handshake_state_steal_pmksa(s);
if (!pmksa) { l_debug("%p", pmksa);
l_debug("No PMKSA for "MAC, MAC_STR(s->aa));
return;
}
l_debug("Caching PMKSA for "MAC, MAC_STR(s->aa)); if (!pmksa)
return;
if (L_WARN_ON(pmksa_cache_put(pmksa) < 0)) if (L_WARN_ON(pmksa_cache_put(pmksa) < 0))
pmksa_cache_free(pmksa); l_free(pmksa);
} }
bool handshake_state_remove_pmksa(struct handshake_state *s) bool handshake_state_remove_pmksa(struct handshake_state *s)
@ -1294,7 +1292,7 @@ bool handshake_state_remove_pmksa(struct handshake_state *s)
if (!pmksa) if (!pmksa)
return false; return false;
pmksa_cache_free(pmksa); l_free(pmksa);
return true; return true;
} }

View File

@ -290,27 +290,9 @@ control how long a misbehaved BSS spends on the blacklist.
* - InitialTimeout * - InitialTimeout
- Values: uint64 value in seconds (default: **60**) - Values: uint64 value in seconds (default: **60**)
The initial time that a BSS spends on the blacklist. Setting this to zero The initial time that a BSS spends on the blacklist.
will disable blacklisting functionality in IWD.
* - InitialRoamRequestedTimeout (**deprecated**)
- Values: uint64 value in seconds (default: **30**)
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 * - Multiplier
- Values: unsigned int value greater than zero, in seconds - Values: unsigned int value in seconds (default: **30**)
(default: **30**)
If the BSS was blacklisted previously and another connection attempt If the BSS was blacklisted previously and another connection attempt
has failed after the initial timeout has expired, then the BSS blacklist has failed after the initial timeout has expired, then the BSS blacklist
@ -483,14 +465,6 @@ are buggy or just don't behave similar enough to the majority of other drivers.
If a driver in use matches one in this list, multicast RX will be If a driver in use matches one in this list, multicast RX will be
disabled. disabled.
* - SaeDisable
- Values: comma-separated list of drivers or glob matches
If a driver in use matches one in this list, SAE/WPA3 will be disabled
for connections. This will prevent connections to WPA3-only networks, but
will allow for connections to WPA3/WPA2 hybrid networks by utilizing
WPA2.
SEE ALSO SEE ALSO
======== ========

View File

@ -463,14 +463,6 @@ uint8_t netdev_get_rssi_level_idx(struct netdev *netdev)
return netdev->cur_rssi_level_idx; return netdev->cur_rssi_level_idx;
} }
int netdev_get_low_signal_threshold(uint32_t frequency)
{
if (frequency > 4000)
return LOW_SIGNAL_THRESHOLD_5GHZ;
return LOW_SIGNAL_THRESHOLD;
}
static void netdev_set_powered_result(int error, uint16_t type, static void netdev_set_powered_result(int error, uint16_t type,
const void *data, const void *data,
uint32_t len, void *user_data) uint32_t len, void *user_data)
@ -1109,7 +1101,6 @@ static void netdev_free(void *data)
l_timeout_remove(netdev->rssi_poll_timeout); l_timeout_remove(netdev->rssi_poll_timeout);
scan_wdev_remove(netdev->wdev_id); scan_wdev_remove(netdev->wdev_id);
frame_watch_wdev_remove(netdev->wdev_id);
watchlist_destroy(&netdev->station_watches); watchlist_destroy(&netdev->station_watches);
@ -1507,105 +1498,6 @@ static void netdev_setting_keys_failed(struct netdev_handshake_state *nhs,
handshake_event(&nhs->super, HANDSHAKE_EVENT_SETTING_KEYS_FAILED, &err); handshake_event(&nhs->super, HANDSHAKE_EVENT_SETTING_KEYS_FAILED, &err);
} }
static bool netdev_match_addr(const void *a, const void *b)
{
const struct netdev *netdev = a;
const uint8_t *addr = b;
return memcmp(netdev->addr, addr, ETH_ALEN) == 0;
}
static struct netdev *netdev_find_by_address(const uint8_t *addr)
{
return l_queue_find(netdev_list, netdev_match_addr, addr);
}
static void netdev_pmksa_driver_add(const struct pmksa *pmksa)
{
struct l_genl_msg *msg;
struct netdev *netdev = netdev_find_by_address(pmksa->spa);
uint32_t expiration = (uint32_t)pmksa->expiration;
if (!netdev)
return;
/* Only need to set the PMKSA into the kernel for fullmac drivers */
if (wiphy_supports_cmds_auth_assoc(netdev->wiphy))
return;
l_debug("Adding PMKSA to kernel");
msg = l_genl_msg_new(NL80211_CMD_SET_PMKSA);
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
l_genl_msg_append_attr(msg, NL80211_ATTR_PMKID, 16, pmksa->pmkid);
l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, pmksa->aa);
l_genl_msg_append_attr(msg, NL80211_ATTR_SSID,
pmksa->ssid_len, pmksa->ssid);
l_genl_msg_append_attr(msg, NL80211_ATTR_PMK_LIFETIME, 4, &expiration);
l_genl_msg_append_attr(msg, NL80211_ATTR_PMK,
pmksa->pmk_len, pmksa->pmk);
if (!l_genl_family_send(nl80211, msg, NULL, NULL, NULL))
l_error("error sending SET_PMKSA");
}
static void netdev_pmksa_driver_remove(const struct pmksa *pmksa)
{
struct l_genl_msg *msg;
struct netdev *netdev = netdev_find_by_address(pmksa->spa);
if (!netdev)
return;
/* Only need to set the PMKSA into the kernel for fullmac drivers */
if (wiphy_supports_cmds_auth_assoc(netdev->wiphy))
return;
l_debug("Removing PMKSA from kernel");
msg = l_genl_msg_new(NL80211_CMD_DEL_PMKSA);
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
l_genl_msg_append_attr(msg, NL80211_ATTR_PMKID, 16, pmksa->pmkid);
l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, pmksa->aa);
l_genl_msg_append_attr(msg, NL80211_ATTR_SSID,
pmksa->ssid_len, pmksa->ssid);
if (!l_genl_family_send(nl80211, msg, NULL, NULL, NULL))
l_error("error sending DEL_PMKSA");
}
static void netdev_flush_pmksa(struct netdev *netdev)
{
struct l_genl_msg *msg;
/*
* We only utilize the kernel's PMKSA cache for fullmac cards,
* so no need to flush if this is a softmac.
*/
if (wiphy_supports_cmds_auth_assoc(netdev->wiphy))
return;
msg = l_genl_msg_new(NL80211_CMD_FLUSH_PMKSA);
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
if (!l_genl_family_send(nl80211, msg, NULL, NULL, NULL))
l_error("Failed to flush PMKSA for %u", netdev->index);
}
static void netdev_pmksa_driver_flush(void)
{
const struct l_queue_entry *e;
for (e = l_queue_get_entries(netdev_list); e; e = e->next) {
struct netdev *netdev = e->data;
netdev_flush_pmksa(netdev);
}
}
static void try_handshake_complete(struct netdev_handshake_state *nhs) static void try_handshake_complete(struct netdev_handshake_state *nhs)
{ {
l_debug("ptk_installed: %u, gtk_installed: %u, igtk_installed: %u", l_debug("ptk_installed: %u, gtk_installed: %u, igtk_installed: %u",
@ -3924,15 +3816,6 @@ static void netdev_cmd_set_cqm_cb(struct l_genl_msg *msg, void *user_data)
static int netdev_cqm_rssi_update(struct netdev *netdev) static int netdev_cqm_rssi_update(struct netdev *netdev)
{ {
struct l_genl_msg *msg; struct l_genl_msg *msg;
struct netdev_handshake_state *nhs = l_container_of(netdev->handshake,
struct netdev_handshake_state, super);
/*
* Fullmac cards handle roaming in firmware, there is no need to set
* CQM thresholds
*/
if (nhs->type == CONNECTION_TYPE_FULLMAC)
return 0;
l_debug(""); l_debug("");
@ -5451,39 +5334,6 @@ 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;
@ -5537,9 +5387,6 @@ 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;
} }
} }
@ -5657,18 +5504,23 @@ static void netdev_external_auth_event(struct l_genl_msg *msg,
} }
if (action == NL80211_EXTERNAL_AUTH_ABORT) { if (action == NL80211_EXTERNAL_AUTH_ABORT) {
l_warn("External Auth Aborted"); iwd_notice(IWD_NOTICE_CONNECT_INFO, "External Auth Aborted");
goto error; goto error;
} }
iwd_notice(IWD_NOTICE_CONNECT_INFO,
"External Auth to SSID: %s, bssid: "MAC,
util_ssid_to_utf8(ssid.iov_len, ssid.iov_base),
MAC_STR(bssid));
if (hs->ssid_len != ssid.iov_len || if (hs->ssid_len != ssid.iov_len ||
memcmp(hs->ssid, ssid.iov_base, hs->ssid_len)) { memcmp(hs->ssid, ssid.iov_base, hs->ssid_len)) {
l_warn("Target SSID mismatch"); iwd_notice(IWD_NOTICE_CONNECT_INFO, "Target SSID mismatch");
goto error; goto error;
} }
if (memcmp(hs->aa, bssid, ETH_ALEN)) { if (memcmp(hs->aa, bssid, ETH_ALEN)) {
l_warn("Target BSSID mismatch"); iwd_notice(IWD_NOTICE_CONNECT_INFO, "Target BSSID mismatch");
goto error; goto error;
} }
@ -6677,16 +6529,6 @@ struct netdev *netdev_create_from_genl(struct l_genl_msg *msg,
netdev_get_link(netdev); netdev_get_link(netdev);
/*
* Call the netdev-specific variant to flush only this devices PMKSA
* cache in the kernel. This will make IWD's cache and the kernel's
* cache consistent, i.e. no entries
*
* TODO: If we ever are storing PMKSA's on disk we would first need to
* flush, then add all the PMKSA entries at this time.
*/
netdev_flush_pmksa(netdev);
return netdev; return netdev;
} }
@ -6802,10 +6644,6 @@ static int netdev_init(void)
__ft_set_tx_frame_func(netdev_tx_ft_frame); __ft_set_tx_frame_func(netdev_tx_ft_frame);
__pmksa_set_driver_callbacks(netdev_pmksa_driver_add,
netdev_pmksa_driver_remove,
netdev_pmksa_driver_flush);
unicast_watch = l_genl_add_unicast_watch(genl, NL80211_GENL_NAME, unicast_watch = l_genl_add_unicast_watch(genl, NL80211_GENL_NAME,
netdev_unicast_notify, netdev_unicast_notify,
NULL, NULL); NULL, NULL);

View File

@ -158,7 +158,6 @@ const char *netdev_get_name(struct netdev *netdev);
bool netdev_get_is_up(struct netdev *netdev); bool netdev_get_is_up(struct netdev *netdev);
const char *netdev_get_path(struct netdev *netdev); const char *netdev_get_path(struct netdev *netdev);
uint8_t netdev_get_rssi_level_idx(struct netdev *netdev); uint8_t netdev_get_rssi_level_idx(struct netdev *netdev);
int netdev_get_low_signal_threshold(uint32_t frequency);
struct handshake_state *netdev_handshake_state_new(struct netdev *netdev); struct handshake_state *netdev_handshake_state_new(struct netdev *netdev);
struct handshake_state *netdev_get_handshake(struct netdev *netdev); struct handshake_state *netdev_get_handshake(struct netdev *netdev);

View File

@ -168,11 +168,6 @@ 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);
@ -203,6 +198,8 @@ 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;
} }
@ -210,7 +207,7 @@ void network_disconnected(struct network *network)
{ {
network_settings_close(network); network_settings_close(network);
network_clear_blacklist(network); l_queue_clear(network->blacklist, NULL);
if (network->provisioning_hidden) if (network->provisioning_hidden)
station_hide_network(network->station, network); station_hide_network(network->station, network);
@ -1283,8 +1280,7 @@ struct scan_bss *network_bss_select(struct network *network,
if (l_queue_find(network->blacklist, match_bss, bss)) if (l_queue_find(network->blacklist, match_bss, bss))
continue; continue;
if (blacklist_contains_bss(bss->addr, if (blacklist_contains_bss(bss->addr))
BLACKLIST_REASON_CONNECT_FAILED))
continue; continue;
/* OWE Transition BSS */ /* OWE Transition BSS */

View File

@ -74,7 +74,6 @@ 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);

View File

@ -177,7 +177,6 @@ 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" },
{ } { }
}; };

View File

@ -190,7 +190,6 @@ 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;

View File

@ -40,9 +40,6 @@
static uint64_t dot11RSNAConfigPMKLifetime = 43200ULL * L_USEC_PER_SEC; static uint64_t dot11RSNAConfigPMKLifetime = 43200ULL * L_USEC_PER_SEC;
static uint32_t pmksa_cache_capacity = 255; static uint32_t pmksa_cache_capacity = 255;
static pmksa_cache_add_func_t driver_add;
static pmksa_cache_remove_func_t driver_remove;
static pmksa_cache_flush_func_t driver_flush;
struct min_heap { struct min_heap {
struct pmksa **data; struct pmksa **data;
@ -145,7 +142,7 @@ int pmksa_cache_put(struct pmksa *pmksa)
l_debug("Adding entry with PMKID: "PMKID, PMKID_STR(pmksa->pmkid)); l_debug("Adding entry with PMKID: "PMKID, PMKID_STR(pmksa->pmkid));
if (cache.used == cache.capacity) { if (cache.used == cache.capacity) {
pmksa_cache_free(cache.data[0]); l_free(cache.data[0]);
cache.data[0] = pmksa; cache.data[0] = pmksa;
__minheap_sift_down(cache.data, cache.used, 0, &ops); __minheap_sift_down(cache.data, cache.used, 0, &ops);
return 0; return 0;
@ -155,9 +152,6 @@ int pmksa_cache_put(struct pmksa *pmksa)
__minheap_sift_up(cache.data, cache.used, &ops); __minheap_sift_up(cache.data, cache.used, &ops);
cache.used += 1; cache.used += 1;
if (driver_add)
driver_add(pmksa);
return 0; return 0;
} }
@ -173,7 +167,7 @@ int pmksa_cache_expire(uint64_t cutoff)
for (i = 0; i < used; i++) { for (i = 0; i < used; i++) {
if (cache.data[i]->expiration <= cutoff) { if (cache.data[i]->expiration <= cutoff) {
pmksa_cache_free(cache.data[i]); l_free(cache.data[i]);
continue; continue;
} }
@ -196,30 +190,11 @@ int pmksa_cache_flush(void)
{ {
uint32_t i; uint32_t i;
/*
* The driver flush operation is done via a single kernel API call which
* is why below we use l_free instead of pmksa_cache_free as to not
* induce a DEL_PMKSA kernel call for each entry.
*/
if (driver_flush)
driver_flush();
for (i = 0; i < cache.used; i++) for (i = 0; i < cache.used; i++)
l_free(cache.data[i]); l_free(cache.data[i]);
memset(cache.data, 0, cache.capacity * sizeof(struct pmksa *)); memset(cache.data, 0, cache.capacity * sizeof(struct pmksa *));
cache.used = 0; cache.used = 0;
return 0;
}
int pmksa_cache_free(struct pmksa *pmksa)
{
if (driver_remove)
driver_remove(pmksa);
l_free(pmksa);
return 0; return 0;
} }
@ -242,15 +217,6 @@ void __pmksa_set_config(const struct l_settings *config)
&pmksa_cache_capacity); &pmksa_cache_capacity);
} }
void __pmksa_set_driver_callbacks(pmksa_cache_add_func_t add,
pmksa_cache_remove_func_t remove,
pmksa_cache_flush_func_t flush)
{
driver_add = add;
driver_remove = remove;
driver_flush = flush;
}
static int pmksa_init(void) static int pmksa_init(void)
{ {
cache.capacity = pmksa_cache_capacity; cache.capacity = pmksa_cache_capacity;

View File

@ -32,10 +32,6 @@ struct pmksa {
size_t pmk_len; size_t pmk_len;
}; };
typedef void (*pmksa_cache_add_func_t)(const struct pmksa *pmksa);
typedef void (*pmksa_cache_remove_func_t)(const struct pmksa *pmksa);
typedef void (*pmksa_cache_flush_func_t)(void);
struct pmksa **__pmksa_cache_get_all(uint32_t *out_n_entries); struct pmksa **__pmksa_cache_get_all(uint32_t *out_n_entries);
struct pmksa *pmksa_cache_get(const uint8_t spa[static 6], struct pmksa *pmksa_cache_get(const uint8_t spa[static 6],
@ -45,11 +41,6 @@ struct pmksa *pmksa_cache_get(const uint8_t spa[static 6],
int pmksa_cache_put(struct pmksa *pmksa); int pmksa_cache_put(struct pmksa *pmksa);
int pmksa_cache_expire(uint64_t cutoff); int pmksa_cache_expire(uint64_t cutoff);
int pmksa_cache_flush(void); int pmksa_cache_flush(void);
int pmksa_cache_free(struct pmksa *pmksa);
uint64_t pmksa_lifetime(void); uint64_t pmksa_lifetime(void);
void __pmksa_set_config(const struct l_settings *config); void __pmksa_set_config(const struct l_settings *config);
void __pmksa_set_driver_callbacks(pmksa_cache_add_func_t add,
pmksa_cache_remove_func_t remove,
pmksa_cache_flush_func_t flush);

View File

@ -169,14 +169,6 @@ 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;
} }
@ -1002,8 +994,7 @@ 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;
if (L_WARN_ON(!sae_send_commit(sm, true))) sae_send_commit(sm, true);
return -EPROTO;
return -EAGAIN; return -EAGAIN;
} }
@ -1083,9 +1074,7 @@ 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;
} }
@ -1140,9 +1129,7 @@ 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;
} }
@ -1307,8 +1294,7 @@ static int sae_verify_confirmed(struct sae_sm *sm, uint16_t trans,
sm->sync++; sm->sync++;
sm->sc++; sm->sc++;
if (L_WARN_ON(!sae_send_commit(sm, true))) sae_send_commit(sm, true);
return -EPROTO;
if (!sae_send_confirm(sm)) if (!sae_send_confirm(sm))
return -EPROTO; return -EPROTO;

View File

@ -143,9 +143,9 @@ struct scan_survey {
}; };
struct scan_survey_results { struct scan_survey_results {
struct scan_survey survey_2_4[15]; struct scan_survey survey_2_4[14];
struct scan_survey survey_5[197]; struct scan_survey survey_5[196];
struct scan_survey survey_6[234]; struct scan_survey survey_6[233];
}; };
struct scan_results { struct scan_results {

View File

@ -155,54 +155,6 @@ struct anqp_entry {
uint32_t pending; uint32_t pending;
}; };
/*
* Rather than sorting BSS's purely based on ranking a higher level grouping
* is used. The purpose of this higher order grouping is the consider the BSS's
* roam blacklist status. The roam blacklist is a "soft" blacklist in that we
* still should connect to these BSS's if they are the only "good" option.
* The question here is: what makes a BSS "good" vs "bad".
*
* For an initial (probably naive) approach here we can use the
* RoamThreshold[5G] which indicates the signal level that would not
* be of an acceptable connection quality. BSS can then be sorted either
* above or below this threshold. Within each of these groups a BSS may be
* blacklisted, meaning it should get sorted lower on the list compared to
* others within the same group.
*
* This sorting is achieved by extending rank to a uint32_t where the first 16
* bits are the standard rank calculated by scan.c. Above that bits can be
* reserved for this higher level grouping:
*
* Bit 16 indicates the BSS is not blacklisted
* Bit 17 indicates the BSS is above the critical signal threshold
*/
#define ABOVE_THRESHOLD_BIT 17
#define NOT_BLACKLISTED_BIT 16
static uint32_t evaluate_bss_group_rank(const uint8_t *addr, uint32_t freq,
int16_t signal_strength, uint16_t rank)
{
int signal = signal_strength / 100;
bool roam_blacklist;
bool good_signal;
uint32_t rank_out = (uint32_t) rank;
if (blacklist_contains_bss(addr, BLACKLIST_REASON_CONNECT_FAILED))
return 0;
roam_blacklist = blacklist_contains_bss(addr, BLACKLIST_REASON_AP_BUSY);
good_signal = signal >= netdev_get_low_signal_threshold(freq);
if (good_signal)
set_bit(&rank_out, ABOVE_THRESHOLD_BIT);
if (!roam_blacklist)
set_bit(&rank_out, NOT_BLACKLISTED_BIT);
return rank_out;
}
/* /*
* Used as entries for the roam list since holding scan_bss pointers directly * Used as entries for the roam list since holding scan_bss pointers directly
* from station->bss_list is not 100% safe due to the possibility of the * from station->bss_list is not 100% safe due to the possibility of the
@ -210,13 +162,13 @@ static uint32_t evaluate_bss_group_rank(const uint8_t *addr, uint32_t freq,
*/ */
struct roam_bss { struct roam_bss {
uint8_t addr[6]; uint8_t addr[6];
uint32_t rank; uint16_t rank;
int32_t signal_strength; int32_t signal_strength;
bool ft_failed: 1; bool ft_failed: 1;
}; };
static struct roam_bss *roam_bss_from_scan_bss(const struct scan_bss *bss, static struct roam_bss *roam_bss_from_scan_bss(const struct scan_bss *bss,
uint32_t rank) uint16_t rank)
{ {
struct roam_bss *rbss = l_new(struct roam_bss, 1); struct roam_bss *rbss = l_new(struct roam_bss, 1);
@ -1795,15 +1747,6 @@ 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,
@ -2223,26 +2166,6 @@ 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)
@ -2285,26 +2208,28 @@ static bool station_can_fast_transition(struct station *station,
return true; return true;
} }
static void station_disconnect_on_netconfig_failed(struct netdev *netdev, static void station_disconnect_on_error_cb(struct netdev *netdev, bool success,
bool success,
void *user_data) void *user_data)
{ {
struct station *station = 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); station_enter_state(station, STATION_STATE_DISCONNECTED);
station_enter_state(station, STATION_STATE_AUTOCONNECT_FULL);
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);
} }
static void station_netconfig_event_handler(enum netconfig_event event, static void station_netconfig_event_handler(enum netconfig_event event,
@ -2317,20 +2242,23 @@ 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:
station_debug_event(station, "netconfig-failed"); if (station->connect_pending) {
struct l_dbus_message *reply = dbus_error_failed(
station->connect_pending);
netconfig_reset(station->netconfig); dbus_pending_reply(&station->connect_pending, reply);
}
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);
network_blacklist_add(station->connected_network,
station->connected_bss);
netdev_disconnect(station->netdev, netdev_disconnect(station->netdev,
station_disconnect_on_netconfig_failed, station_disconnect_on_error_cb,
station); station);
station_reset_connection_state(station);
station_enter_state(station, STATION_STATE_DISCONNECTING);
break; break;
default: default:
l_error("station: Unsupported netconfig event: %d.", event); l_error("station: Unsupported netconfig event: %d.", event);
@ -2877,7 +2805,7 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
struct handshake_state *hs = netdev_get_handshake(station->netdev); struct handshake_state *hs = netdev_get_handshake(station->netdev);
struct scan_bss *current_bss = station->connected_bss; struct scan_bss *current_bss = station->connected_bss;
struct scan_bss *bss; struct scan_bss *bss;
uint32_t cur_bss_group_rank = 0; double cur_bss_rank = 0.0;
static const double RANK_FT_FACTOR = 1.3; static const double RANK_FT_FACTOR = 1.3;
uint16_t mdid; uint16_t mdid;
enum security orig_security, security; enum security orig_security, security;
@ -2906,15 +2834,10 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
*/ */
bss = l_queue_find(bss_list, bss_match_bssid, current_bss->addr); bss = l_queue_find(bss_list, bss_match_bssid, current_bss->addr);
if (bss && !station->ap_directed_roaming) { if (bss && !station->ap_directed_roaming) {
double cur_bss_rank = bss->rank; cur_bss_rank = bss->rank;
if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid) if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid)
cur_bss_rank *= RANK_FT_FACTOR; cur_bss_rank *= RANK_FT_FACTOR;
cur_bss_group_rank = evaluate_bss_group_rank(bss->addr,
bss->frequency,
bss->signal_strength,
(uint16_t) cur_bss_rank);
} }
/* /*
@ -2936,7 +2859,6 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
while ((bss = l_queue_pop_head(bss_list))) { while ((bss = l_queue_pop_head(bss_list))) {
double rank; double rank;
struct roam_bss *rbss; struct roam_bss *rbss;
uint32_t group_rank;
station_print_scan_bss(bss); station_print_scan_bss(bss);
@ -2958,8 +2880,7 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
if (network_can_connect_bss(network, bss) < 0) if (network_can_connect_bss(network, bss) < 0)
goto next; goto next;
if (blacklist_contains_bss(bss->addr, if (blacklist_contains_bss(bss->addr))
BLACKLIST_REASON_CONNECT_FAILED))
goto next; goto next;
rank = bss->rank; rank = bss->rank;
@ -2967,11 +2888,7 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid) if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid)
rank *= RANK_FT_FACTOR; rank *= RANK_FT_FACTOR;
group_rank = evaluate_bss_group_rank(bss->addr, bss->frequency, if (rank <= cur_bss_rank)
bss->signal_strength,
(uint16_t) rank);
if (group_rank <= cur_bss_group_rank)
goto next; goto next;
/* /*
@ -2980,7 +2897,7 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
*/ */
station_update_roam_bss(station, bss); station_update_roam_bss(station, bss);
rbss = roam_bss_from_scan_bss(bss, group_rank); rbss = roam_bss_from_scan_bss(bss, rank);
l_queue_insert(station->roam_bss_list, rbss, l_queue_insert(station->roam_bss_list, rbss,
roam_bss_rank_compare, NULL); roam_bss_rank_compare, NULL);
@ -3248,10 +3165,12 @@ static void station_ap_directed_roam(struct station *station,
uint8_t req_mode; uint8_t req_mode;
uint16_t dtimer; uint16_t dtimer;
uint8_t valid_interval; uint8_t valid_interval;
bool can_roam = !station_cannot_roam(station);
l_debug("ifindex: %u", netdev_get_ifindex(station->netdev)); l_debug("ifindex: %u", netdev_get_ifindex(station->netdev));
if (station_cannot_roam(station))
return;
if (station->state != STATION_STATE_CONNECTED) { if (station->state != STATION_STATE_CONNECTED) {
l_debug("roam: unexpected AP directed roam -- ignore"); l_debug("roam: unexpected AP directed roam -- ignore");
return; return;
@ -3315,13 +3234,8 @@ static void station_ap_directed_roam(struct station *station,
* disassociating us. If either of these bits are set, set the * disassociating us. If either of these bits are set, set the
* ap_directed_roaming flag. Otherwise still try roaming but don't * ap_directed_roaming flag. Otherwise still try roaming but don't
* treat it any different than a normal roam. * treat it any different than a normal roam.
*
* The only exception here is if we are in the middle of roaming
* (can_roam == false) since we cannot reliably know if the roam scan
* included frequencies from potential candidates in this request,
* forcing a roam in this case might result in unintended behavior.
*/ */
if (can_roam && req_mode & (WNM_REQUEST_MODE_DISASSOCIATION_IMMINENT | if (req_mode & (WNM_REQUEST_MODE_DISASSOCIATION_IMMINENT |
WNM_REQUEST_MODE_TERMINATION_IMMINENT | WNM_REQUEST_MODE_TERMINATION_IMMINENT |
WNM_REQUEST_MODE_ESS_DISASSOCIATION_IMMINENT)) WNM_REQUEST_MODE_ESS_DISASSOCIATION_IMMINENT))
station->ap_directed_roaming = true; station->ap_directed_roaming = true;
@ -3348,19 +3262,6 @@ static void station_ap_directed_roam(struct station *station,
pos += url_len; pos += url_len;
} }
blacklist_add_bss(station->connected_bss->addr,
BLACKLIST_REASON_AP_BUSY);
station_debug_event(station, "ap-roam-blacklist-added");
/*
* Validating the frame and blacklisting should still be done even if
* we are mid-roam. Its important to track the BSS requesting the
* transition so when the current roam completes IWD will be less likely
* to roam back to the current BSS.
*/
if (!can_roam)
return;
station->preparing_roam = true; station->preparing_roam = true;
l_timeout_remove(station->roam_trigger_timeout); l_timeout_remove(station->roam_trigger_timeout);
@ -3433,6 +3334,26 @@ 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)
{ {
/* /*
@ -3479,15 +3400,7 @@ static bool station_retry_with_reason(struct station *station,
break; break;
} }
blacklist_add_bss(station->connected_bss->addr, blacklist_add_bss(station->connected_bss->addr);
BLACKLIST_REASON_CONNECT_FAILED);
/*
* Network blacklist the BSS as well, since the timeout blacklist could
* be disabled
*/
network_blacklist_add(station->connected_network,
station->connected_bss);
try_next: try_next:
return station_try_next_bss(station); return station_try_next_bss(station);
@ -3526,54 +3439,32 @@ 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)
{ {
/* If PMKSA failed don't blacklist so we can retry this BSS */
if (station_pmksa_fallback(station, status_code))
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: if (IS_TEMPORARY_STATUS(status_code))
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
* will allow network_bss_select to traverse the BSS list and ignore
* BSS's which have previously failed
*/
network_blacklist_add(station->connected_network, network_blacklist_add(station->connected_network,
station->connected_bss); station->connected_bss);
else if (!station_pmksa_fallback(station, status_code))
blacklist_add_bss(station->connected_bss->addr);
try_next:
iwd_notice(IWD_NOTICE_CONNECT_FAILED, "status: %u", status_code); iwd_notice(IWD_NOTICE_CONNECT_FAILED, "status: %u", status_code);
return station_try_next_bss(station); return station_try_next_bss(station);
@ -3585,6 +3476,13 @@ 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
@ -3651,8 +3549,7 @@ static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
switch (result) { switch (result) {
case NETDEV_RESULT_OK: case NETDEV_RESULT_OK:
blacklist_remove_bss(station->connected_bss->addr, blacklist_remove_bss(station->connected_bss->addr);
BLACKLIST_REASON_CONNECT_FAILED);
station_connect_ok(station); station_connect_ok(station);
return; return;
case NETDEV_RESULT_DISCONNECTED: case NETDEV_RESULT_DISCONNECTED:
@ -4822,7 +4719,7 @@ static struct l_dbus_message *station_property_set_affinities(
struct l_dbus_message_iter array; struct l_dbus_message_iter array;
const char *sender = l_dbus_message_get_sender(message); const char *sender = l_dbus_message_get_sender(message);
char *old_path = l_queue_peek_head(station->affinities); char *old_path = l_queue_peek_head(station->affinities);
const char *new_path; const char *new_path = NULL;
struct scan_bss *new_bss = NULL; struct scan_bss *new_bss = NULL;
struct scan_bss *old_bss = NULL; struct scan_bss *old_bss = NULL;
bool lower_threshold = false; bool lower_threshold = false;
@ -4842,15 +4739,10 @@ static struct l_dbus_message *station_property_set_affinities(
if (!l_dbus_message_iter_get_variant(new_value, "ao", &array)) if (!l_dbus_message_iter_get_variant(new_value, "ao", &array))
return dbus_error_invalid_args(message); return dbus_error_invalid_args(message);
/* Get first entry, or if an empty array set the path to NULL */ /* Get first entry, there should be only one */
if (!l_dbus_message_iter_next_entry(&array, &new_path)) l_dbus_message_iter_next_entry(&array, &new_path);
new_path = NULL;
/* if (l_dbus_message_iter_next_entry(&array, &new_path))
* Only allowing single values for now. If there is more than a single
* value, fail
*/
if (new_path && l_dbus_message_iter_next_entry(&array, &new_path))
return dbus_error_invalid_args(message); return dbus_error_invalid_args(message);
old_path = l_queue_peek_head(station->affinities); old_path = l_queue_peek_head(station->affinities);

View File

@ -500,13 +500,6 @@ int __storage_decrypt(struct l_settings *settings, const char *ssid,
return 0; return 0;
} }
/*
* It should likely be far larger than this, but that will get caught
* later when reloading the decrypted data.
*/
if (elen < 16)
return -EBADMSG;
/* /*
* AES-SIV automatically verifies the IV (16 bytes) and returns only * AES-SIV automatically verifies the IV (16 bytes) and returns only
* the decrypted data portion. We add one here for the NULL terminator * the decrypted data portion. We add one here for the NULL terminator

View File

@ -74,7 +74,6 @@ enum driver_flag {
POWER_SAVE_DISABLE = 0x4, POWER_SAVE_DISABLE = 0x4,
OWE_DISABLE = 0x8, OWE_DISABLE = 0x8,
MULTICAST_RX_DISABLE = 0x10, MULTICAST_RX_DISABLE = 0x10,
SAE_DISABLE = 0x20,
}; };
struct driver_flag_name { struct driver_flag_name {
@ -107,8 +106,7 @@ static const struct driver_flag_name driver_flag_names[] = {
{ "ForcePae", FORCE_PAE }, { "ForcePae", FORCE_PAE },
{ "PowerSaveDisable", POWER_SAVE_DISABLE }, { "PowerSaveDisable", POWER_SAVE_DISABLE },
{ "OweDisable", OWE_DISABLE }, { "OweDisable", OWE_DISABLE },
{ "MulticastRxDisable", MULTICAST_RX_DISABLE }, { "MulticastRxDisable", MULTICAST_RX_DISABLE }
{ "SaeDisable", SAE_DISABLE },
}; };
struct wiphy { struct wiphy {
@ -204,9 +202,6 @@ uint16_t wiphy_get_supported_ciphers(struct wiphy *wiphy, uint16_t mask)
static bool wiphy_can_connect_sae(struct wiphy *wiphy) static bool wiphy_can_connect_sae(struct wiphy *wiphy)
{ {
if (wiphy->driver_flags & SAE_DISABLE)
return false;
/* /*
* WPA3 Specification version 3, Section 2.2: * WPA3 Specification version 3, Section 2.2:
* A STA shall not enable WEP and TKIP * A STA shall not enable WEP and TKIP
@ -1379,9 +1374,6 @@ static void wiphy_print_basic_info(struct wiphy *wiphy)
if (wiphy->driver_flags & MULTICAST_RX_DISABLE) if (wiphy->driver_flags & MULTICAST_RX_DISABLE)
flags = l_strv_append(flags, "MulticastRxDisable"); flags = l_strv_append(flags, "MulticastRxDisable");
if (wiphy->driver_flags & SAE_DISABLE)
flags = l_strv_append(flags, "SaeDisable");
joined = l_strjoinv(flags, ' '); joined = l_strjoinv(flags, ' ');
l_info("\tDriver Flags: %s", joined); l_info("\tDriver Flags: %s", joined);

View File

@ -138,22 +138,20 @@ static const struct cmac_data example_4 = {
.tag_len = sizeof(tag_4), .tag_len = sizeof(tag_4),
}; };
static bool test_precheck(const void *data)
{
return l_checksum_cmac_aes_supported();
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
l_test_init(&argc, &argv); l_test_init(&argc, &argv);
add_test("/cmac-aes/Example 1", cmac_test, &example_1); if (!l_checksum_cmac_aes_supported()) {
add_test("/cmac-aes/Example 2", cmac_test, &example_2); printf("AES-CMAC support missing, skipping...\n");
add_test("/cmac-aes/Example 3", cmac_test, &example_3); goto done;
add_test("/cmac-aes/Example 4", cmac_test, &example_4); }
l_test_add("/cmac-aes/Example 1", cmac_test, &example_1);
l_test_add("/cmac-aes/Example 2", cmac_test, &example_2);
l_test_add("/cmac-aes/Example 3", cmac_test, &example_3);
l_test_add("/cmac-aes/Example 4", cmac_test, &example_4);
done:
return l_test_run(); return l_test_run();
} }

View File

@ -403,32 +403,40 @@ static void aes_siv_test(const void *data)
assert(memcmp(decrypted, plaintext, sizeof(decrypted)) == 0); assert(memcmp(decrypted, plaintext, sizeof(decrypted)) == 0);
} }
static bool test_precheck(const void *data)
{
return (l_cipher_is_supported(L_CIPHER_AES) &&
l_checksum_is_supported(L_CHECKSUM_SHA1, true));
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
l_test_init(&argc, &argv); l_test_init(&argc, &argv);
add_test("/Passphrase Generator/PSK Test Case 1", if (!l_checksum_is_supported(L_CHECKSUM_SHA1, true)) {
printf("SHA1 support missing, skipping...\n");
goto done;
}
if (!l_cipher_is_supported(L_CIPHER_AES)) {
printf("AES support missing, skipping...\n");
goto done;
}
l_test_add("/Passphrase Generator/PSK Test Case 1",
psk_test, &psk_test_case_1); psk_test, &psk_test_case_1);
add_test("/Passphrase Generator/PSK Test Case 2", l_test_add("/Passphrase Generator/PSK Test Case 2",
psk_test, &psk_test_case_2); psk_test, &psk_test_case_2);
add_test("/Passphrase Generator/PSK Test Case 3", l_test_add("/Passphrase Generator/PSK Test Case 3",
psk_test, &psk_test_case_3); psk_test, &psk_test_case_3);
add_test("/PTK Derivation/PTK Test Case 1", ptk_test, &ptk_test_1); l_test_add("/PTK Derivation/PTK Test Case 1",
add_test("/PTK Derivation/PTK Test Case 2", ptk_test, &ptk_test_2); ptk_test, &ptk_test_1);
add_test("/PTK Derivation/PTK Test Case 3", ptk_test, &ptk_test_3); l_test_add("/PTK Derivation/PTK Test Case 2",
add_test("/PTK Derivation/PTK Test Case 4", ptk_test, &ptk_test_4); ptk_test, &ptk_test_2);
l_test_add("/PTK Derivation/PTK Test Case 3",
ptk_test, &ptk_test_3);
l_test_add("/PTK Derivation/PTK Test Case 4",
ptk_test, &ptk_test_4);
add_test("/AES Key-wrap/Wrap & unwrap", aes_wrap_test, NULL); l_test_add("/AES Key-wrap/Wrap & unwrap",
add_test("/AES-SIV", aes_siv_test, NULL); aes_wrap_test, NULL);
l_test_add("/AES-SIV", aes_siv_test, NULL);
done:
return l_test_run(); return l_test_run();
} }

View File

@ -116,29 +116,6 @@ struct dpp_test_info bad_channels[] = {
}, },
}; };
struct dpp_test_info duplicates[] = {
/* Duplicate key */
{
.uri = "DPP:K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;;",
.expect_fail = true
},
/* Duplicate frequencies*/
{
.uri = "DPP:C:81/1,115/36;C:81/1,115/36;;",
.expect_fail = true
},
/* Duplicate MACs*/
{
.uri = "DPP:M:5254005828e5;M:5254005828e5;;",
.expect_fail = true
},
/* Duplicate versions */
{
.uri = "DPP:V:2;V:2;;",
.expect_fail = true
},
};
static bool verify_info(const struct dpp_uri_info *parsed, static bool verify_info(const struct dpp_uri_info *parsed,
const struct dpp_test_info *result) const struct dpp_test_info *result)
{ {
@ -181,14 +158,6 @@ static void test_bad_channels(const void *data)
test_uri_parse(&bad_channels[i]); test_uri_parse(&bad_channels[i]);
} }
static void test_duplicate_in_uri(const void *data)
{
unsigned int i;
for (i = 0; i < L_ARRAY_SIZE(duplicates); i++)
test_uri_parse(&duplicates[i]);
}
struct dpp_test_vector { struct dpp_test_vector {
/* Initiator values */ /* Initiator values */
const char *i_proto_public; const char *i_proto_public;
@ -577,25 +546,22 @@ static void test_pkex_key_derivation(const void *user_data)
CHECK_FROM_STR(vector->v, tmp, 32); CHECK_FROM_STR(vector->v, tmp, 32);
} }
static bool test_precheck(const void *data)
{
return (l_getrandom_is_supported() &&
l_checksum_is_supported(L_CHECKSUM_SHA256, true));
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
l_test_init(&argc, &argv); l_test_init(&argc, &argv);
add_test("DPP test responder-only key derivation", test_key_derivation, if (l_checksum_is_supported(L_CHECKSUM_SHA256, true) &&
l_getrandom_is_supported()) {
l_test_add("DPP test responder-only key derivation",
test_key_derivation,
&responder_only_p256); &responder_only_p256);
add_test("DPP test mutual key derivation", test_key_derivation, l_test_add("DPP test mutual key derivation",
test_key_derivation,
&mutual_p256); &mutual_p256);
add_test("DPP test PKEX key derivation", test_pkex_key_derivation, l_test_add("DPP test PKEX key derivation",
test_pkex_key_derivation,
&pkex_vector); &pkex_vector);
}
l_test_add("DPP URI parse", test_uri_parse, &all_values); l_test_add("DPP URI parse", test_uri_parse, &all_values);
l_test_add("DPP URI no type", test_uri_parse, &no_type); l_test_add("DPP URI no type", test_uri_parse, &no_type);
@ -610,7 +576,6 @@ int main(int argc, char *argv[])
l_test_add("DPP URI bad key", test_uri_parse, &bad_key); l_test_add("DPP URI bad key", test_uri_parse, &bad_key);
l_test_add("DPP URI bad channels", test_bad_channels, &bad_channels); l_test_add("DPP URI bad channels", test_bad_channels, &bad_channels);
l_test_add("DPP URI unexpected ID", test_uri_parse, &unexpected_id); l_test_add("DPP URI unexpected ID", test_uri_parse, &unexpected_id);
l_test_add("DPP URI duplicates", test_duplicate_in_uri, &duplicates);
return l_test_run(); return l_test_run();
} }

View File

@ -131,23 +131,27 @@ static void test_get_asym_key(const void *data)
assert(!memcmp(msk, m_session_key, sizeof(m_session_key))); assert(!memcmp(msk, m_session_key, sizeof(m_session_key)));
} }
static bool test_precheck(const void *data)
{
return l_checksum_is_supported(L_CHECKSUM_MD4, false);
}
#define add_test(name, func) l_test_add_func_precheck(name, func, \
test_precheck, 0)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
l_test_init(&argc, &argv); l_test_init(&argc, &argv);
add_test("MSHAPv2 nt_password-hash", test_nt_password_hash); if (!l_checksum_is_supported(L_CHECKSUM_MD4, false)) {
add_test("MSHAPv2 generate_nt_response", test_generate_nt_response); printf("MD4 support missing, skipping...\n");
add_test("MSHAPv2 get_master_key", test_get_master_key); goto done;
add_test("MSHAPv2 get_asym_state_key", test_get_asym_key); }
add_test("MSHAPv2 authenticator_response", test_authenticator_response);
l_test_add("MSHAPv2 nt_password-hash",
test_nt_password_hash, NULL);
l_test_add("MSHAPv2 generate_nt_response",
test_generate_nt_response, NULL);
l_test_add("MSHAPv2 get_master_key",
test_get_master_key, NULL);
l_test_add("MSHAPv2 get_asym_state_key",
test_get_asym_key, NULL);
l_test_add("MSHAPv2 authenticator_response",
test_authenticator_response, NULL);
done:
return l_test_run(); return l_test_run();
} }

View File

@ -3908,38 +3908,6 @@ static void eapol_ap_sta_handshake_ip_alloc_no_req_test(const void *data)
#define _IS_ENABLED2(one_or_two_args) _IS_ENABLED3(one_or_two_args true, false) #define _IS_ENABLED2(one_or_two_args) _IS_ENABLED3(one_or_two_args true, false)
#define _IS_ENABLED3(ignore_this, val, ...) val #define _IS_ENABLED3(ignore_this, val, ...) val
static bool hash_precheck(const void *data)
{
return (l_checksum_is_supported(L_CHECKSUM_MD5, true) &&
l_checksum_is_supported(L_CHECKSUM_SHA1, true));
}
static bool aes_precheck(const void *data)
{
return (l_cipher_is_supported(L_CIPHER_AES) &&
l_checksum_is_supported(L_CHECKSUM_MD5, true) &&
l_checksum_is_supported(L_CHECKSUM_SHA1, true));
}
static bool pkcs8_precheck(const void *data)
{
return (IS_ENABLED(HAVE_PKCS8_SUPPORT) &&
l_cipher_is_supported(L_CIPHER_AES) &&
l_cipher_is_supported(L_CIPHER_AES_CBC) &&
l_cipher_is_supported(L_CIPHER_DES3_EDE_CBC) &&
l_checksum_is_supported(L_CHECKSUM_MD5, true) &&
l_checksum_is_supported(L_CHECKSUM_SHA1, true) &&
l_key_is_supported(L_KEY_FEATURE_CRYPTO) &&
l_key_is_supported(L_KEY_FEATURE_RESTRICT));
}
#define add_hash_test(name, func, data) l_test_add_data_func_precheck(name, \
data, func, hash_precheck, 0)
#define add_aes_test(name, func, data) l_test_add_data_func_precheck(name, \
data, func, aes_precheck, 0)
#define add_pkcs8_test(name, func, data) l_test_add_data_func_precheck(name, \
data, func, pkcs8_precheck, 0)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
l_test_init(&argc, &argv); l_test_init(&argc, &argv);
@ -4009,55 +3977,80 @@ int main(int argc, char *argv[])
l_test_add("/EAPoL Key/Key Frame 32", l_test_add("/EAPoL Key/Key Frame 32",
eapol_key_test, &eapol_key_test_32); eapol_key_test, &eapol_key_test_32);
add_hash_test("/EAPoL Key/MIC Test 1", if (!l_checksum_is_supported(L_CHECKSUM_MD5, true) ||
!l_checksum_is_supported(L_CHECKSUM_SHA1, true))
goto done;
l_test_add("/EAPoL Key/MIC Test 1",
eapol_key_mic_test, &eapol_key_mic_test_1); eapol_key_mic_test, &eapol_key_mic_test_1);
add_hash_test("/EAPoL Key/MIC Test 2", l_test_add("/EAPoL Key/MIC Test 2",
eapol_key_mic_test, &eapol_key_mic_test_2); eapol_key_mic_test, &eapol_key_mic_test_2);
add_hash_test("/EAPoL Key/Calculate MIC Test 1",
l_test_add("/EAPoL Key/Calculate MIC Test 1",
eapol_calculate_mic_test, &eapol_calculate_mic_test_1); eapol_calculate_mic_test, &eapol_calculate_mic_test_1);
add_aes_test("EAPoL/WPA2 4-Way Handshake", if (!l_cipher_is_supported(L_CIPHER_AES))
eapol_4way_test, NULL); goto done;
add_aes_test("EAPoL/WPA2 4-Way & GTK Handshake",
eapol_wpa2_handshake_test, NULL);
add_aes_test("EAPoL/WPA 4-Way & GTK Handshake",
eapol_wpa_handshake_test, NULL);
add_aes_test("EAPoL/WPA2 PTK State Machine",
eapol_sm_test_ptk, NULL);
add_aes_test("EAPoL IGTK & 4-Way Handshake",
eapol_sm_test_igtk, NULL);
add_aes_test("EAPoL/WPA2 PTK & GTK State Machine",
eapol_sm_test_wpa2_ptk_gtk, NULL);
add_aes_test("EAPoL/WPA PTK & GTK State Machine Test 1",
eapol_sm_test_wpa_ptk_gtk, NULL);
add_aes_test("EAPoL/WPA PTK & GTK State Machine Test 2",
eapol_sm_test_wpa_ptk_gtk_2, NULL);
add_aes_test("EAPoL/WPA2 Retransmit Test",
eapol_sm_wpa2_retransmit_test, NULL);
add_pkcs8_test("EAPoL/8021x EAP-TLS & 4-Way Handshake", l_test_add("EAPoL/WPA2 4-Way Handshake",
eapol_sm_test_eap_tls, NULL); &eapol_4way_test, NULL);
add_pkcs8_test("EAPoL/8021x EAP-TTLS+EAP-MD5 & 4-Way Handshake",
eapol_sm_test_eap_ttls_md5, NULL);
add_pkcs8_test("EAPoL/8021x EAP NAK",
eapol_sm_test_eap_nak, NULL);
add_pkcs8_test("EAPoL/8021x EAP-TLS subject name match",
eapol_sm_test_eap_tls_subject_good, NULL);
add_pkcs8_test("EAPoL/8021x EAP-TLS subject name mismatch",
eapol_sm_test_eap_tls_subject_bad, NULL);
add_pkcs8_test("EAPoL/8021x EAP-TLS embedded certs",
eapol_sm_test_eap_tls_embedded, NULL);
add_aes_test("EAPoL/FT-Using-PSK 4-Way Handshake", l_test_add("EAPoL/WPA2 4-Way & GTK Handshake",
eapol_ft_handshake_test, NULL); &eapol_wpa2_handshake_test, NULL);
add_aes_test("EAPoL/Supplicant+Authenticator 4-Way Handshake",
eapol_ap_sta_handshake_test, NULL);
add_aes_test("EAPoL/Supplicant+Authenticator 4-Way Handshake Bad PSK",
eapol_ap_sta_handshake_bad_psk_test, NULL);
add_aes_test("EAPoL/Supplicant+Authenticator IP Allocation OK",
eapol_ap_sta_handshake_ip_alloc_ok_test, NULL);
add_aes_test("EAPoL/Supplicant+Authenticator IP Allocation no request",
eapol_ap_sta_handshake_ip_alloc_no_req_test, NULL);
l_test_add("EAPoL/WPA 4-Way & GTK Handshake",
&eapol_wpa_handshake_test, NULL);
l_test_add("EAPoL/WPA2 PTK State Machine", &eapol_sm_test_ptk, NULL);
l_test_add("EAPoL IGTK & 4-Way Handshake",
&eapol_sm_test_igtk, NULL);
l_test_add("EAPoL/WPA2 PTK & GTK State Machine",
&eapol_sm_test_wpa2_ptk_gtk, NULL);
l_test_add("EAPoL/WPA PTK & GTK State Machine Test 1",
&eapol_sm_test_wpa_ptk_gtk, NULL);
l_test_add("EAPoL/WPA PTK & GTK State Machine Test 2",
&eapol_sm_test_wpa_ptk_gtk_2, NULL);
l_test_add("EAPoL/WPA2 Retransmit Test",
&eapol_sm_wpa2_retransmit_test, NULL);
if (IS_ENABLED(HAVE_PKCS8_SUPPORT) &&
l_cipher_is_supported(L_CIPHER_DES3_EDE_CBC) &&
l_cipher_is_supported(L_CIPHER_AES_CBC) &&
l_key_is_supported(L_KEY_FEATURE_RESTRICT |
L_KEY_FEATURE_CRYPTO)) {
l_test_add("EAPoL/8021x EAP-TLS & 4-Way Handshake",
&eapol_sm_test_eap_tls, NULL);
l_test_add("EAPoL/8021x EAP-TTLS+EAP-MD5 & 4-Way Handshake",
&eapol_sm_test_eap_ttls_md5, NULL);
l_test_add("EAPoL/8021x EAP NAK",
&eapol_sm_test_eap_nak, NULL);
l_test_add("EAPoL/8021x EAP-TLS subject name match",
&eapol_sm_test_eap_tls_subject_good, NULL);
l_test_add("EAPoL/8021x EAP-TLS subject name mismatch",
&eapol_sm_test_eap_tls_subject_bad, NULL);
l_test_add("EAPoL/8021x EAP-TLS embedded certs",
&eapol_sm_test_eap_tls_embedded, NULL);
}
l_test_add("EAPoL/FT-Using-PSK 4-Way Handshake",
&eapol_ft_handshake_test, NULL);
l_test_add("EAPoL/Supplicant+Authenticator 4-Way Handshake",
&eapol_ap_sta_handshake_test, NULL);
l_test_add("EAPoL/Supplicant+Authenticator 4-Way Handshake Bad PSK",
&eapol_ap_sta_handshake_bad_psk_test, NULL);
l_test_add("EAPoL/Supplicant+Authenticator IP Allocation OK",
&eapol_ap_sta_handshake_ip_alloc_ok_test, NULL);
l_test_add("EAPoL/Supplicant+Authenticator IP Allocation no request",
&eapol_ap_sta_handshake_ip_alloc_no_req_test, NULL);
done:
return l_test_run(); return l_test_run();
} }

View File

@ -81,20 +81,18 @@ static const struct hmac_data test_case_2 = {
.hmac = "80070713463e7749b90c2dc24911e275", .hmac = "80070713463e7749b90c2dc24911e275",
}; };
static bool test_precheck(const void *data)
{
return l_checksum_is_supported(L_CHECKSUM_MD5, true);
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
l_test_init(&argc, &argv); l_test_init(&argc, &argv);
add_test("/hmac-md5/Test case 1", hmac_test, &test_case_1); if (!l_checksum_is_supported(L_CHECKSUM_MD5, true)) {
add_test("/hmac-md5/Test case 2", hmac_test, &test_case_2); printf("MD5 support missing, skipping...\n");
goto done;
}
l_test_add("/hmac-md5/Test case 1", hmac_test, &test_case_1);
l_test_add("/hmac-md5/Test case 2", hmac_test, &test_case_2);
done:
return l_test_run(); return l_test_run();
} }

View File

@ -81,20 +81,18 @@ static const struct hmac_data test_case_2 = {
.hmac = "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9", .hmac = "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9",
}; };
static bool test_precheck(const void *data)
{
return l_checksum_is_supported(L_CHECKSUM_SHA1, true);
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
l_test_init(&argc, &argv); l_test_init(&argc, &argv);
add_test("/hmac-sha1/Test case 1", hmac_test, &test_case_1); if (!l_checksum_is_supported(L_CHECKSUM_SHA1, true)) {
add_test("/hmac-sha1/Test case 2", hmac_test, &test_case_2); printf("SHA1 support missing, skipping...\n");
goto done;
}
l_test_add("/hmac-sha1/Test case 1", hmac_test, &test_case_1);
l_test_add("/hmac-sha1/Test case 2", hmac_test, &test_case_2);
done:
return l_test_run(); return l_test_run();
} }

View File

@ -83,20 +83,18 @@ static const struct hmac_data test_case_2 = {
"ef4d59a14946175997479dbc2d1a3cd8", "ef4d59a14946175997479dbc2d1a3cd8",
}; };
static bool test_precheck(const void *data)
{
return l_checksum_is_supported(L_CHECKSUM_SHA256, true);
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
l_test_init(&argc, &argv); l_test_init(&argc, &argv);
add_test("/hmac-sha256/Test case 1", hmac_test, &test_case_1); if (!l_checksum_is_supported(L_CHECKSUM_SHA256, true)) {
add_test("/hmac-sha256/Test case 2", hmac_test, &test_case_2); printf("SHA256 support missing, skipping...\n");
goto done;
}
l_test_add("/hmac-sha256/Test case 1", hmac_test, &test_case_1);
l_test_add("/hmac-sha256/Test case 2", hmac_test, &test_case_2);
done:
return l_test_run(); return l_test_run();
} }

View File

@ -81,19 +81,17 @@ static const struct kdf_data test_case_1 = {
"84f7d2291143d4d4", "84f7d2291143d4d4",
}; };
static bool test_precheck(const void *data)
{
return l_checksum_is_supported(L_CHECKSUM_SHA256, true);
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
l_test_init(&argc, &argv); l_test_init(&argc, &argv);
add_test("/kdf-sha256/Test case 1", kdf_test, &test_case_1); if (!l_checksum_is_supported(L_CHECKSUM_SHA256, true)) {
printf("SHA256 support missing, skipping...\n");
goto done;
}
l_test_add("/kdf-sha256/Test case 1", kdf_test, &test_case_1);
done:
return l_test_run(); return l_test_run();
} }

View File

@ -341,7 +341,7 @@ static const struct p2p_probe_req_data p2p_probe_req_data_1 = {
.group_caps = 0, .group_caps = 0,
}, },
.listen_channel = { .listen_channel = {
.country = { 'X', 'X', '\x04' }, .country = "XX\x04",
.oper_class = 81, .oper_class = 81,
.channel_num = 1, .channel_num = 1,
}, },

View File

@ -113,21 +113,19 @@ static const struct prf_data test_case_3 = {
"f7b4abd43d87f0a68f1cbd9e2b6f7607", "f7b4abd43d87f0a68f1cbd9e2b6f7607",
}; };
static bool test_precheck(const void *data)
{
return l_checksum_is_supported(L_CHECKSUM_SHA1, true);
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
l_test_init(&argc, &argv); l_test_init(&argc, &argv);
add_test("/prf-sha1/Test case 1", prf_test, &test_case_1); if (!l_checksum_is_supported(L_CHECKSUM_SHA1, true)) {
add_test("/prf-sha1/Test case 2", prf_test, &test_case_2); printf("SHA1 support missing, skipping...\n");
add_test("/prf-sha1/Test case 3", prf_test, &test_case_3); goto done;
}
l_test_add("/prf-sha1/Test case 1", prf_test, &test_case_1);
l_test_add("/prf-sha1/Test case 2", prf_test, &test_case_2);
l_test_add("/prf-sha1/Test case 3", prf_test, &test_case_3);
done:
return l_test_run(); return l_test_run();
} }

View File

@ -871,29 +871,32 @@ static void test_pt_pwe(const void *data)
l_ecc_point_free(pt); l_ecc_point_free(pt);
} }
static bool test_precheck(const void *data)
{
return (l_getrandom_is_supported() &&
l_checksum_is_supported(L_CHECKSUM_SHA256, true));
}
#define add_test(name, func) l_test_add_func_precheck(name, func, \
test_precheck, 0)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
l_test_init(&argc, &argv); l_test_init(&argc, &argv);
add_test("SAE anti-clogging", test_clogging); if (!l_getrandom_is_supported()) {
add_test("SAE early confirm", test_early_confirm); l_info("l_getrandom not supported, skipping...");
add_test("SAE reflection", test_reflection); goto done;
add_test("SAE malformed commit", test_malformed_commit); }
add_test("SAE malformed confirm", test_malformed_confirm);
add_test("SAE bad group", test_bad_group);
add_test("SAE bad confirm", test_bad_confirm);
add_test("SAE confirm after accept", test_confirm_after_accept);
add_test("SAE end-to-end", test_end_to_end);
add_test("SAE pt-pwe", test_pt_pwe);
if (!l_checksum_is_supported(L_CHECKSUM_SHA256, true)) {
l_info("SHA256/HMAC_SHA256 not supported, skipping...");
goto done;
}
l_test_add("SAE anti-clogging", test_clogging, NULL);
l_test_add("SAE early confirm", test_early_confirm, NULL);
l_test_add("SAE reflection", test_reflection, NULL);
l_test_add("SAE malformed commit", test_malformed_commit, NULL);
l_test_add("SAE malformed confirm", test_malformed_confirm, NULL);
l_test_add("SAE bad group", test_bad_group, NULL);
l_test_add("SAE bad confirm", test_bad_confirm, NULL);
l_test_add("SAE confirm after accept", test_confirm_after_accept, NULL);
l_test_add("SAE end-to-end", test_end_to_end, NULL);
l_test_add("SAE pt-pwe", test_pt_pwe, NULL);
done:
return l_test_run(); return l_test_run();
} }

View File

@ -1,66 +0,0 @@
/*
*
* Wireless daemon for Linux
*
* Copyright (C) 2025 Locus Robotics. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include <ell/ell.h>
#include "src/storage.h"
static bool aes_ctr_supported(const void *data)
{
return l_cipher_is_supported(L_CIPHER_AES_CTR);
}
static void test_short_encrypted_bytes(const void *data)
{
struct l_settings *settings = l_settings_new();
bool changed;
int err;
storage_init((const uint8_t *)"abc123", 6);
l_settings_set_string(settings, "Security", "EncryptedSecurity", "012345");
l_settings_set_string(settings, "Security", "EncryptedSalt", "012345");
err = __storage_decrypt(settings, "mySSID", &changed);
assert(err == -EBADMSG);
l_settings_free(settings);
storage_exit();
}
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
l_test_add_func_precheck("/storage/profile encryption",
test_short_encrypted_bytes,
aes_ctr_supported, 0);
return l_test_run();
}

View File

@ -2574,40 +2574,6 @@ struct wsc_credential wsc_r_test_open_cred = {
.encryption_type = WSC_ENCRYPTION_TYPE_NONE, .encryption_type = WSC_ENCRYPTION_TYPE_NONE,
}; };
static bool getrandom_precheck(const void *data)
{
return l_getrandom_is_supported();
}
static bool aes_cbc_precheck(const void *data)
{
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)
{
return (l_key_is_supported(L_KEY_FEATURE_CRYPTO) &&
l_checksum_is_supported(L_CHECKSUM_SHA256, true));
}
static bool key_dh_precheck(const void *data)
{
return (l_key_is_supported(L_KEY_FEATURE_DH) &&
l_key_is_supported(L_KEY_FEATURE_CRYPTO) &&
l_checksum_is_supported(L_CHECKSUM_SHA256, true));
}
#define add_aes_cbc_test(name, func, data) l_test_add_data_func_precheck(name, \
data, func, \
aes_cbc_precheck, 0)
#define add_crypto_test(name, func, data) l_test_add_data_func_precheck(name, \
data, func, \
key_crypto_precheck, 0)
#define add_dh_test(name, func, data) l_test_add_data_func_precheck(name, \
data, func, \
key_dh_precheck, 0)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
l_test_init(&argc, &argv); l_test_init(&argc, &argv);
@ -2629,8 +2595,8 @@ int main(int argc, char *argv[])
l_test_add("/wsc/pin/valid pin", wsc_test_pin_valid, NULL); l_test_add("/wsc/pin/valid pin", wsc_test_pin_valid, NULL);
l_test_add("/wsc/pin/valid checksum", wsc_test_pin_checksum, NULL); l_test_add("/wsc/pin/valid checksum", wsc_test_pin_checksum, NULL);
l_test_add_func_precheck("/wsc/pin/generate", wsc_test_pin_generate, if (l_getrandom_is_supported())
getrandom_precheck, 0); l_test_add("/wsc/pin/generate", wsc_test_pin_generate, NULL);
l_test_add("/wsc/gen_uuid/1", wsc_test_uuid_from_addr, l_test_add("/wsc/gen_uuid/1", wsc_test_uuid_from_addr,
&uuid_from_addr_data_1); &uuid_from_addr_data_1);
@ -2641,77 +2607,96 @@ int main(int argc, char *argv[])
l_test_add("/wsc/build/m1 1", wsc_test_build_m1, &m1_data_1); l_test_add("/wsc/build/m1 1", wsc_test_build_m1, &m1_data_1);
l_test_add("/wsc/build/m1 2", wsc_test_build_m1, &m1_data_2); l_test_add("/wsc/build/m1 2", wsc_test_build_m1, &m1_data_2);
add_dh_test("/wsc/parse/m2 1", wsc_test_parse_m2, &m2_data_1); if (!l_checksum_is_supported(L_CHECKSUM_SHA256, true)) {
add_dh_test("/wsc/parse/m2 2", wsc_test_parse_m2, &m2_data_2); printf("SHA256 support missing, skipping other tests...\n");
goto done;
}
add_crypto_test("/wsc/build/m2 1", wsc_test_build_m2, &m2_data_1); if (!l_key_is_supported(L_KEY_FEATURE_CRYPTO)) {
printf("Key crypto not supported, skipping other tests...\n");
goto done;
}
add_crypto_test("/wsc/parse/m3 1", wsc_test_parse_m3, &m3_data_1); if (l_key_is_supported(L_KEY_FEATURE_DH)) {
add_crypto_test("/wsc/build/m3 1", wsc_test_build_m3, &m3_data_1); l_test_add("/wsc/parse/m2 1", wsc_test_parse_m2, &m2_data_1);
l_test_add("/wsc/parse/m2 2", wsc_test_parse_m2, &m2_data_2);
}
add_crypto_test("/wsc/parse/m4 1", wsc_test_parse_m4, &m4_data_1); l_test_add("/wsc/build/m2 1", wsc_test_build_m2, &m2_data_1);
add_crypto_test("/wsc/build/m4 1", wsc_test_build_m4, &m4_data_1);
add_crypto_test("/wsc/parse/m4 encrypted settings 1", l_test_add("/wsc/parse/m3 1", wsc_test_parse_m3, &m3_data_1);
l_test_add("/wsc/build/m3 1", wsc_test_build_m3, &m3_data_1);
l_test_add("/wsc/parse/m4 1", wsc_test_parse_m4, &m4_data_1);
l_test_add("/wsc/build/m4 1", wsc_test_build_m4, &m4_data_1);
l_test_add("/wsc/parse/m4 encrypted settings 1",
wsc_test_parse_m4_encrypted_settings, wsc_test_parse_m4_encrypted_settings,
&m4_encrypted_settings_data_1); &m4_encrypted_settings_data_1);
add_crypto_test("/wsc/build/m4 encrypted settings 1", l_test_add("/wsc/build/m4 encrypted settings 1",
wsc_test_build_m4_encrypted_settings, wsc_test_build_m4_encrypted_settings,
&m4_encrypted_settings_data_1); &m4_encrypted_settings_data_1);
add_crypto_test("/wsc/parse/m5 1", wsc_test_parse_m5, &m5_data_1); l_test_add("/wsc/parse/m5 1", wsc_test_parse_m5, &m5_data_1);
add_crypto_test("/wsc/build/m5 1", wsc_test_build_m5, &m5_data_1); l_test_add("/wsc/build/m5 1", wsc_test_build_m5, &m5_data_1);
add_crypto_test("/wsc/parse/m6 1", wsc_test_parse_m6, &m6_data_1); l_test_add("/wsc/parse/m6 1", wsc_test_parse_m6, &m6_data_1);
add_crypto_test("/wsc/build/m6 1", wsc_test_build_m6, &m6_data_1); l_test_add("/wsc/build/m6 1", wsc_test_build_m6, &m6_data_1);
add_crypto_test("/wsc/parse/m6 encrypted settings 1", l_test_add("/wsc/parse/m6 encrypted settings 1",
wsc_test_parse_m6_encrypted_settings, wsc_test_parse_m6_encrypted_settings,
&m6_encrypted_settings_data_1); &m6_encrypted_settings_data_1);
add_crypto_test("/wsc/build/m6 encrypted settings 1", l_test_add("/wsc/build/m6 encrypted settings 1",
wsc_test_build_m6_encrypted_settings, wsc_test_build_m6_encrypted_settings,
&m6_encrypted_settings_data_1); &m6_encrypted_settings_data_1);
add_crypto_test("/wsc/parse/m7 1", wsc_test_parse_m7, &m7_data_1); l_test_add("/wsc/parse/m7 1", wsc_test_parse_m7, &m7_data_1);
add_crypto_test("/wsc/build/m7 1", wsc_test_build_m7, &m7_data_1); l_test_add("/wsc/build/m7 1", wsc_test_build_m7, &m7_data_1);
add_crypto_test("/wsc/parse/m8 1", wsc_test_parse_m8, &m8_data_1); l_test_add("/wsc/parse/m8 1", wsc_test_parse_m8, &m8_data_1);
add_crypto_test("/wsc/build/m8 1", wsc_test_build_m8, &m8_data_1); l_test_add("/wsc/build/m8 1", wsc_test_build_m8, &m8_data_1);
add_crypto_test("/wsc/parse/m8 encrypted settings 1", l_test_add("/wsc/parse/m8 encrypted settings 1",
wsc_test_parse_m8_encrypted_settings, wsc_test_parse_m8_encrypted_settings,
&m8_encrypted_settings_data_1); &m8_encrypted_settings_data_1);
add_crypto_test("/wsc/build/m8 encrypted settings 1", l_test_add("/wsc/build/m8 encrypted settings 1",
wsc_test_build_m8_encrypted_settings, wsc_test_build_m8_encrypted_settings,
&m8_encrypted_settings_data_1); &m8_encrypted_settings_data_1);
add_crypto_test("/wsc/parse/wsc_done 1", wsc_test_parse_wsc_done, l_test_add("/wsc/parse/wsc_done 1", wsc_test_parse_wsc_done,
&wsc_done_data_1); &wsc_done_data_1);
add_crypto_test("/wsc/build/wsc_done 1", wsc_test_build_wsc_done, l_test_add("/wsc/build/wsc_done 1", wsc_test_build_wsc_done,
&wsc_done_data_1); &wsc_done_data_1);
add_dh_test("/wsc/diffie-hellman/generate pubkey 1", if (!l_key_is_supported(L_KEY_FEATURE_DH))
goto done;
l_test_add("/wsc/diffie-hellman/generate pubkey 1",
wsc_test_dh_generate_pubkey, wsc_test_dh_generate_pubkey,
&dh_generate_pubkey_test_data_1); &dh_generate_pubkey_test_data_1);
add_dh_test("/wsc/diffie-hellman/generate pubkey 2", l_test_add("/wsc/diffie-hellman/generate pubkey 2",
wsc_test_dh_generate_pubkey, wsc_test_dh_generate_pubkey,
&dh_generate_pubkey_test_data_2); &dh_generate_pubkey_test_data_2);
add_aes_cbc_test("/wsc/handshake/PBC Handshake Test", if (!l_cipher_is_supported(L_CIPHER_AES_CBC))
goto done;
l_test_add("/wsc/handshake/PBC Handshake Test",
wsc_test_pbc_handshake, NULL); wsc_test_pbc_handshake, NULL);
add_aes_cbc_test("/wsc/retransmission/no fragmentation", l_test_add("/wsc/retransmission/no fragmentation",
wsc_test_retransmission_no_fragmentation, NULL); wsc_test_retransmission_no_fragmentation, NULL);
add_aes_cbc_test("/wsc-r/handshake/PBC Handshake WPA2 passphrase test", l_test_add("/wsc-r/handshake/PBC Handshake WPA2 passphrase test",
wsc_r_test_pbc_handshake, wsc_r_test_pbc_handshake,
&wsc_r_test_wpa2_cred_passphrase); &wsc_r_test_wpa2_cred_passphrase);
add_aes_cbc_test("/wsc-r/handshake/PBC Handshake WPA2 PSK test", l_test_add("/wsc-r/handshake/PBC Handshake WPA2 PSK test",
wsc_r_test_pbc_handshake, wsc_r_test_pbc_handshake,
&wsc_r_test_wpa2_cred_psk); &wsc_r_test_wpa2_cred_psk);
add_aes_cbc_test("/wsc-r/handshake/PBC Handshake Open test", l_test_add("/wsc-r/handshake/PBC Handshake Open test",
wsc_r_test_pbc_handshake, wsc_r_test_pbc_handshake,
&wsc_r_test_open_cred); &wsc_r_test_open_cred);
done:
return l_test_run(); return l_test_run();
} }