3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2025-09-18 14:27:23 +02:00

Compare commits

..

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

74 changed files with 530 additions and 2298 deletions

1
.gitignore vendored
View File

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

View File

@ -1,33 +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:
Fix issue with handling External Authentication.
ver 3.2:
Fix issue with GCC 15 and -std=c23 build errors.
Add support for using PMKSA over SAE if available.

View File

@ -71,9 +71,7 @@ ell_headers = ell/util.h \
ell_sources = ell/private.h \
ell/missing.h \
ell/util.c \
ell/test-private.h \
ell/test.c \
ell/test-dbus.c \
ell/strv.c \
ell/utf8.c \
ell/queue.c \
@ -274,8 +272,6 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h \
src/dpp.c \
src/udev.c \
src/pmksa.h src/pmksa.c \
src/vendor_quirks.h \
src/vendor_quirks.c \
$(eap_sources) \
$(builtin_sources)
@ -443,7 +439,7 @@ unit_tests += unit/test-cmac-aes \
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-dpp unit/test-json unit/test-nl80211util \
unit/test-pmksa unit/test-storage
unit/test-pmksa
endif
if CLIENT
@ -607,11 +603,6 @@ unit_test_nl80211util_LDADD = $(ell_ldadd)
unit_test_pmksa_SOURCES = unit/test-pmksa.c src/pmksa.c src/pmksa.h \
src/module.h src/util.h
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
if CLIENT
@ -627,9 +618,6 @@ unit_test_client_SOURCES = unit/test-client.c \
unit_test_client_LDADD = $(ell_ldadd) $(client_ldadd)
endif
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
$(top_srcdir)/build-aux/tap-driver.sh
TESTS = $(unit_tests)
EXTRA_DIST = src/genbuiltin src/iwd.service.in src/net.connman.iwd.service \

View File

@ -1,156 +0,0 @@
#!/usr/bin/python3
import unittest
import sys
sys.path.append('../util')
import iwd
from iwd import IWD
from iwd import NetworkType
from hostapd import HostapdCLI
class Test(unittest.TestCase):
def initial_connection(self):
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(self.bss_hostapd[0].bssid)
condition = 'obj.state == DeviceState.connected'
self.wd.wait_for_object_condition(self.device, condition)
self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED')
self.assertFalse(self.bss_hostapd[1].list_sta())
def test_full_scan(self):
"""
Tests that IWD first tries a limited scan, then a full scan after
an AP directed roam. After the full scan yields no results IWD
should stop trying to roam.
"""
self.initial_connection()
# Disable other APs, so the scans come up empty
self.bss_hostapd[1].disable()
self.bss_hostapd[2].disable()
# Send a bad candidate list with the BSS TM request which contains a
# channel with no AP operating on it.
self.bss_hostapd[0].send_bss_transition(
self.device.address,
[(self.bss_hostapd[1].bssid, "8f0000005105060603000000")]
)
self.device.wait_for_event("roam-scan-triggered")
self.device.wait_for_event("no-roam-candidates")
# IWD should then trigger a full scan
self.device.wait_for_event("full-roam-scan")
self.device.wait_for_event("no-roam-candidates", timeout=30)
# IWD should not trigger a roam again after the above 2 failures.
with self.assertRaises(TimeoutError):
self.device.wait_for_event("roam-scan-triggered", timeout=60)
def test_bad_candidate_list(self):
"""
Tests behavior when the AP sends a candidate list but the scan
finds no BSS's. IWD should fall back to a full scan after.
"""
self.initial_connection()
# Send a bad candidate list with the BSS TM request which contains a
# channel with no AP operating on it.
self.bss_hostapd[0].send_bss_transition(
self.device.address,
[(self.bss_hostapd[1].bssid, "8f0000005105060603000000")]
)
self.device.wait_for_event("roam-scan-triggered")
self.device.wait_for_event("no-roam-candidates")
# IWD should then trigger a full scan
self.device.wait_for_event("full-roam-scan")
self.device.wait_for_event("roaming", timeout=30)
self.device.wait_for_event("connected")
def test_bad_neighbor_report(self):
"""
Tests behavior when the AP sends no candidate list. IWD should
request a neighbor report. If the limited scan yields no BSS's IWD
should fall back to a full scan.
"""
# Set a bad neighbor (channel that no AP is on) to force the limited
# roam scan to fail
self.bss_hostapd[0].set_neighbor(
self.bss_hostapd[1].bssid,
"TestAPRoam",
'%s8f000000%s%s060603000000' % (self.bss_hostapd[1].bssid.replace(':', ''), "51", "0b")
)
self.initial_connection()
self.bss_hostapd[0].send_bss_transition(self.device.address, [])
self.device.wait_for_event("roam-scan-triggered")
# The AP will have sent a neighbor report with a single BSS but on
# channel 11 which no AP is on. This should result in a limited scan
# picking up no candidates.
self.device.wait_for_event("no-roam-candidates", timeout=30)
# IWD should then trigger a full scan
self.device.wait_for_event("full-roam-scan")
self.device.wait_for_event("roaming", timeout=30)
self.device.wait_for_event("connected")
def test_ignore_candidate_list_quirk(self):
"""
Tests that IWD ignores the candidate list sent by the AP since its
OUI indicates it should be ignored.
"""
# Set the OUI so the candidate list should be ignored
for hapd in self.bss_hostapd:
hapd.set_value('vendor_elements', 'dd0400180a01')
self.initial_connection()
# Send with a candidate list (should be ignored)
self.bss_hostapd[0].send_bss_transition(
self.device.address,
[(self.bss_hostapd[1].bssid, "8f0000005105060603000000")]
)
# IWD should ignore the list and trigger a full scan since we have not
# set any neighbors
self.device.wait_for_event("full-roam-scan")
self.device.wait_for_event("roaming", timeout=30)
self.device.wait_for_event("connected")
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
for hapd in self.bss_hostapd:
hapd.reload()
@classmethod
def setUpClass(cls):
IWD.copy_to_storage('TestAPRoam.psk')
cls.bss_hostapd = [ HostapdCLI(config='ssid1.conf'),
HostapdCLI(config='ssid2.conf'),
HostapdCLI(config='ssid3.conf') ]
@classmethod
def tearDownClass(cls):
IWD.clear_storage()
if __name__ == '__main__':
unittest.main(exit=True)

View File

@ -11,58 +11,52 @@ from iwd import NetworkType
from hostapd import HostapdCLI
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)
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'
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.assertFalse(self.bss_hostapd[1].list_sta())
def validate_roam(self, from_bss, to_bss, expect_roam=True):
from_bss.send_bss_transition(self.device.address,
self.neighbor_list,
self.bss_hostapd[0].send_bss_transition(device.address,
[(self.bss_hostapd[1].bssid, '8f0000005102060603000000')],
disassoc_imminent=expect_roam)
if expect_roam:
from_condition = 'obj.state == DeviceState.roaming'
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:
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):
self.initial_connection()
self.validate_roam(self.bss_hostapd[0], self.bss_hostapd[1])
self.validate(expect_roam=True)
def test_no_candidates(self):
self.initial_connection()
# 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
self.validate(expect_roam=False)
@classmethod
def setUpClass(cls):
@ -71,10 +65,6 @@ class Test(unittest.TestCase):
cls.bss_hostapd = [ HostapdCLI(config='ssid1.conf'),
HostapdCLI(config='ssid2.conf'),
HostapdCLI(config='ssid3.conf') ]
cls.neighbor_list = [
(cls.bss_hostapd[0].bssid, "8f0000005101060603000000"),
(cls.bss_hostapd[1].bssid, "8f0000005102060603000000"),
]
@classmethod
def tearDownClass(cls):

View File

@ -1,7 +1,5 @@
[SETUP]
num_radios=4
hwsim_medium=true
start_iwd=false
[HOSTAPD]
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)
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):
_, _, 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)
def tearDown(self):
IWD.clear_storage()
self.wd = None
self.rule0.drop = False
self.rule1.drop = False
self.rule2.drop = False
@classmethod
def setUpClass(cls):

View File

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

View File

@ -3,11 +3,7 @@ import sys
import sys
import os
from scapy.layers.dot11 import *
from scapy.arch import str2mac
try:
from scapy.arch import get_if_raw_hwaddr
except:
from scapy.arch.unix import get_if_raw_hwaddr
from scapy.arch import str2mac, get_if_raw_hwaddr
from time import time, sleep
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
# detect an IP conflict and not allow the device to reach the
# "connected" state although the DBus .Connect call will succeed.
with self.assertRaises(iwd.FailedEx):
ordered_network.network_object.connect(timeout=500)
condition = 'obj.state == DeviceState.disconnected'
iwd_ns0_1.wait_for_object_condition(dev2, condition, max_wait=21)
ordered_network.network_object.connect()
self.assertEqual(dev2.state, iwd.DeviceState.connecting)
try:
# We should either stay in "connecting" indefinitely or move to
# "disconnecting"
condition = 'obj.state != DeviceState.connecting'
iwd_ns0_1.wait_for_object_condition(dev2, condition, max_wait=21)
self.assertEqual(dev2.state, iwd.DeviceState.disconnecting)
except TimeoutError:
dev2.disconnect()
iwd_ns0_1.unregister_psk_agent(psk_agent_ns0_1)
del dev2

View File

@ -8,8 +8,6 @@ from iwd import PSKAgent
from iwd import NetworkType
class Test(unittest.TestCase):
def connect_failure(self, ex):
self.failure_triggered = True
def test_netconfig_timeout(self):
IWD.copy_to_storage('autoconnect.psk', name='ap-ns1.psk')
@ -29,34 +27,23 @@ class Test(unittest.TestCase):
condition = 'not obj.connected'
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
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"
condition = 'obj.state == DeviceState.connecting'
wd.wait_for_object_condition(device, condition)
# IWD should attempt to connect, but it will of course fail again.
device.wait_for_event("netconfig-failed", timeout=1000)
device.wait_for_event("connecting (netconfig)")
# Netconfig should fail, and IWD should disconnect
from_condition = 'obj.state == DeviceState.connecting'
to_condition = 'obj.state == DeviceState.disconnecting'
wd.wait_for_object_change(device, from_condition, to_condition, max_wait=60)
# Autoconnect should then try again
condition = 'obj.state == DeviceState.connecting'
wd.wait_for_object_condition(device, condition)
device.wait_for_event("connecting (netconfig)")
device.disconnect()
condition = 'obj.state == DeviceState.disconnected'

View File

@ -19,7 +19,7 @@ class Test(unittest.TestCase):
device = wd.list_devices(1)[0]
device.get_ordered_network('TestFT', full_scan=True)
device.connect_bssid(self.bss_hostapd[1].bssid, wait=False)
device.connect_bssid(self.bss_hostapd[1].bssid)
self.bss_hostapd[1].wait_for_event(f'AP-STA-CONNECTED {device.address}')
device.wait_for_event("connecting (netconfig)")

View File

@ -1,114 +0,0 @@
#! /usr/bin/python3
import unittest
import sys, os
sys.path.append('../util')
from iwd import IWD
from iwd import NetworkType
from hostapd import HostapdCLI
from packaging import version
from subprocess import run
import re
import testutil
#
# The CSA handling was added in kernel 6.8, so for any earlier kernel this test
# won't pass.
#
def kernel_is_newer(min_version="6.8"):
proc = run(["uname", "-r"], capture_output=True)
version_str = proc.stdout.decode("utf-8")
match = re.match(r"(\d+\.\d+)", version_str)
if not match:
return False
return version.parse(match.group(1)) >= version.parse(min_version)
class Test(unittest.TestCase):
def test_channel_switch_during_roam(self):
wd = self.wd
device = wd.list_devices(1)[0]
ordered_network = device.get_ordered_network('TestFT', full_scan=True)
self.assertEqual(ordered_network.type, NetworkType.psk)
condition = 'not obj.connected'
wd.wait_for_object_condition(ordered_network.network_object, condition)
self.assertFalse(self.bss_hostapd[0].list_sta())
self.assertFalse(self.bss_hostapd[1].list_sta())
device.connect_bssid(self.bss_hostapd[0].bssid)
condition = 'obj.state == DeviceState.connected'
wd.wait_for_object_condition(device, condition)
self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED %s' % device.address)
testutil.test_iface_operstate(device.name)
testutil.test_ifaces_connected(self.bss_hostapd[0].ifname, device.name)
self.assertRaises(Exception, testutil.test_ifaces_connected,
(self.bss_hostapd[1].ifname, device.name, True, True))
# Start a channel switch and wait for it to begin
self.bss_hostapd[1].chan_switch(6, wait=False)
self.bss_hostapd[1].wait_for_event("CTRL-EVENT-STARTED-CHANNEL-SWITCH")
# Initiate a roam immediately which should get rejected by the kernel
device.roam(self.bss_hostapd[1].bssid)
# IWD should authenticate, then proceed to association
device.wait_for_event("ft-authenticating")
device.wait_for_event("ft-roaming")
# The kernel should reject the association, which should trigger a
# disconnect
condition = 'obj.state == DeviceState.disconnected'
wd.wait_for_object_condition(device, condition)
condition = 'obj.state == DeviceState.connected'
wd.wait_for_object_condition(device, condition)
def tearDown(self):
os.system('ip link set "' + self.bss_hostapd[0].ifname + '" down')
os.system('ip link set "' + self.bss_hostapd[1].ifname + '" down')
os.system('ip link set "' + self.bss_hostapd[0].ifname + '" up')
os.system('ip link set "' + self.bss_hostapd[1].ifname + '" up')
for hapd in self.bss_hostapd:
hapd.default()
self.wd.stop()
self.wd = None
def setUp(self):
self.wd = IWD(True)
@classmethod
def setUpClass(cls):
if not kernel_is_newer():
raise unittest.SkipTest()
IWD.copy_to_storage('TestFT.psk')
cls.bss_hostapd = [ HostapdCLI(config='ft-psk-ccmp-1.conf'),
HostapdCLI(config='ft-psk-ccmp-2.conf'),
HostapdCLI(config='ft-psk-ccmp-3.conf') ]
unused = HostapdCLI(config='ft-psk-ccmp-3.conf')
unused.disable()
cls.bss_hostapd[0].set_address('12:00:00:00:00:01')
cls.bss_hostapd[1].set_address('12:00:00:00:00:02')
cls.bss_hostapd[2].set_address('12:00:00:00:00:03')
HostapdCLI.group_neighbors(*cls.bss_hostapd)
@classmethod
def tearDownClass(cls):
IWD.clear_storage()
cls.bss_hostapd = None

View File

@ -288,15 +288,13 @@ class HostapdCLI(object):
cmd = 'RESEND_M3 %s' % address
self.ctrl_sock.sendall(cmd.encode('utf-8'))
def chan_switch(self, channel, wait=True):
def chan_switch(self, channel):
if channel > len(chan_freq_map):
raise Exception("Only 2.4GHz channels supported for chan_switch")
cmd = self.cmdline + ['chan_switch', '50', str(chan_freq_map[channel])]
ctx.start_process(cmd).wait()
if wait:
self.wait_for_event('AP-CSA-FINISHED')
self.wait_for_event('AP-CSA-FINISHED')
def _get_status(self):
ret = {}

View File

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

View File

@ -112,8 +112,8 @@ class AsyncOpAbstract(object):
self._is_completed = True
self._exception = _convert_dbus_ex(ex)
def _wait_for_async_op(self, timeout=50):
ctx.non_block_wait(lambda s: s._is_completed, timeout, self, exception=None)
def _wait_for_async_op(self):
ctx.non_block_wait(lambda s: s._is_completed, 30, self, exception=None)
self._is_completed = False
if self._exception is not None:
@ -280,15 +280,8 @@ class StationDebug(IWDDBusAbstract):
def autoconnect(self):
return self._properties['AutoConnect']
def connect_bssid(self, address, wait=True):
self._iface.ConnectBssid(
dbus.ByteArray.fromhex(address.replace(':', '')),
reply_handler=self._success,
error_handler=self._failure
)
if wait:
self._wait_for_async_op()
def connect_bssid(self, address):
self._iface.ConnectBssid(dbus.ByteArray.fromhex(address.replace(':', '')))
def roam(self, address):
self._iface.Roam(dbus.ByteArray.fromhex(address.replace(':', '')))
@ -877,8 +870,8 @@ class Device(IWDDBusAbstract):
def stop_adhoc(self):
self._prop_proxy.Set(IWD_DEVICE_INTERFACE, 'Mode', 'station')
def connect_bssid(self, address, wait=True):
self._station_debug.connect_bssid(address, wait=wait)
def connect_bssid(self, address):
self._station_debug.connect_bssid(address)
def roam(self, address):
self._station_debug.roam(address)
@ -1006,7 +999,7 @@ class Network(IWDDBusAbstract):
def extended_service_set(self):
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
path to connect to specified network.
@ -1021,19 +1014,12 @@ class Network(IWDDBusAbstract):
@rtype: void
'''
if not reply_handler:
reply_handler = self._success
if not error_handler:
error_handler = self._failure
self._iface.Connect(dbus_interface=self._iface_name,
reply_handler=reply_handler,
error_handler=error_handler,
timeout=timeout)
reply_handler=self._success,
error_handler=self._failure)
if wait:
self._wait_for_async_op(timeout=timeout)
self._wait_for_async_op()
def __str__(self, prefix = ''):
return prefix + 'Network:\n' \

View File

@ -95,8 +95,6 @@ static const struct diagnostic_dict_mapping diagnostic_mapping[] = {
{ "Frequency", 'u' },
{ "Channel", 'q' },
{ "Security", 's' },
{ "InactiveTime", 'u', "ms" },
{ "ConnectedTime", 'u', "s" },
{ NULL }
};

View File

@ -1,12 +1,10 @@
AC_PREREQ([2.69])
AC_INIT([iwd],[3.9])
AC_INIT([iwd],[3.2])
AC_CONFIG_HEADERS(config.h)
AC_CONFIG_AUX_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
tar-pax no-dist-gzip dist-xz])
@ -31,7 +29,6 @@ AC_PROG_CC_GCOV
AC_PROG_INSTALL
AC_PROG_MKDIR_P
AC_PROG_LN_S
AC_PROG_AWK
AC_SYS_LARGEFILE
@ -300,7 +297,7 @@ if (test "${enable_external_ell}" = "yes"); then
test "${enable_monitor}" != "no" ||
test "${enable_wired}" = "yes" ||
test "${enable_hwsim}" = "yes"); then
ell_min_version="0.77"
ell_min_version="0.69"
else
ell_min_version="0.5"
fi

View File

@ -31,12 +31,6 @@ Methods array{dict} GetDiagnostics()
TxMCS [optional] - Transmitting MCS index
InactiveTime [optional] - Time duration (in ms) for which the STA
connected to this BSS is currently inactive.
ConnectedTime [optional] - Time duration (in s) for which the STA
remains connected to this BSS.
Possible errors: net.connman.iwd.Failed
net.connman.iwd.NotConnected
net.connman.iwd.NotFound

View File

@ -11,12 +11,6 @@ Methods void Connect()
the object path to connect to specified network.
Connecting to WEP networks is not supported.
Note: When [General].EnableNetworkConfiguration is set
to true a call to Connect() has the potential to take
a significant amount of time. Specifically if DHCP is
either slow, or is unable to complete. The timeout for
DHCP is roughly 30 seconds per BSS.
Possible errors: net.connman.iwd.Aborted
net.connman.iwd.Busy
net.connman.iwd.Failed

View File

@ -53,12 +53,6 @@ Methods dict GetDiagnostics()
- GCMP-256
- CCMP-256
InactiveTime [optional] - Time duration (in ms) for which this STA
is currently inactive.
ConnectedTime [optional] - Time Duration (in s) for which this STA
remains connected to the BSS.
Possible errors: net.connman.iwd.Busy
net.connman.iwd.Failed
net.connman.iwd.NotConnected

View File

@ -718,36 +718,29 @@ static void usage(void)
"Usage:\n");
printf("\tiwmon [options]\n");
printf("Options:\n"
"\t-r, --read <file> Read netlink PCAP trace file\n"
"\t-w, --write <file> Write netlink PCAP trace file\n"
"\t-a, --analyze <file> Analyze netlink PCAP trace file\n"
"\t-i, --interface <dev> Use specified netlink monitor\n"
"\t-n, --nortnl Don't show RTNL output\n"
"\t-y, --nowiphy Don't show 'New Wiphy' output\n"
"\t-s, --noscan Don't show scan result output\n"
"\t-e, --noies Don't show IEs except SSID\n"
"\t-t, --time-format <format> Time format to display. Either\n"
"\t\t\t\t 'delta' or 'utc'.\n"
"\t-W,--pcap-count Maximum number of PCAP files\n"
"\t-C,--pcap-size Maximum size (MB) of PCAP files\n"
"\t-h, --help Show help options\n");
"\t-r, --read <file> Read netlink PCAP trace file\n"
"\t-w, --write <file> Write netlink PCAP trace file\n"
"\t-a, --analyze <file> Analyze netlink PCAP trace file\n"
"\t-i, --interface <dev> Use specified netlink monitor\n"
"\t-n, --nortnl Don't show RTNL output\n"
"\t-y, --nowiphy Don't show 'New Wiphy' output\n"
"\t-s, --noscan Don't show scan result output\n"
"\t-e, --noies Don't show IEs except SSID\n"
"\t-h, --help Show help options\n");
}
static const struct option main_options[] = {
{ "read", required_argument, NULL, 'r' },
{ "write", required_argument, NULL, 'w' },
{ "analyze", required_argument, NULL, 'a' },
{ "nl80211", required_argument, NULL, 'F' },
{ "interface", required_argument, NULL, 'i' },
{ "nortnl", no_argument, NULL, 'n' },
{ "nowiphy", no_argument, NULL, 'y' },
{ "noscan", no_argument, NULL, 's' },
{ "noies", no_argument, NULL, 'e' },
{ "time-format", required_argument, NULL, 't' },
{ "pcap-count", required_argument, NULL, 'W' },
{ "pcap-size", required_argument, NULL, 'C' },
{ "version", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' },
{ "read", required_argument, NULL, 'r' },
{ "write", required_argument, NULL, 'w' },
{ "analyze", required_argument, NULL, 'a' },
{ "nl80211", required_argument, NULL, 'F' },
{ "interface", required_argument, NULL, 'i' },
{ "nortnl", no_argument, NULL, 'n' },
{ "nowiphy", no_argument, NULL, 'y' },
{ "noscan", no_argument, NULL, 's' },
{ "noies", no_argument, NULL, 'e' },
{ "version", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' },
{ }
};
@ -761,7 +754,7 @@ int main(int argc, char *argv[])
for (;;) {
int opt;
opt = getopt_long(argc, argv, "r:w:a:i:t:W:C:nvhyse",
opt = getopt_long(argc, argv, "r:w:a:i:nvhyse",
main_options, NULL);
if (opt < 0)
break;
@ -791,35 +784,6 @@ int main(int argc, char *argv[])
break;
case 'e':
config.noies = true;
break;
case 't':
if (!strcmp(optarg, "delta"))
config.time_format = TIME_FORMAT_DELTA;
else if (!strcmp(optarg, "utc"))
config.time_format = TIME_FORMAT_UTC;
else {
printf("Invalid time format '%s'", optarg);
return EXIT_FAILURE;
}
break;
case 'W':
if (l_safe_atou32(optarg,
&config.pcap_file_count) < 0 ||
config.pcap_file_count == 0) {
printf("Invalid file count '%s'\n", optarg);
return EXIT_FAILURE;
}
break;
case 'C':
if (l_safe_atou32(optarg,
&config.pcap_file_size) < 0 ||
config.pcap_file_size == 0) {
printf("Invalid file size '%s'\n", optarg);
return EXIT_FAILURE;
}
break;
case 'v':
printf("%s\n", VERSION);

View File

@ -29,7 +29,6 @@
#include <errno.h>
#include <ctype.h>
#include <unistd.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
@ -43,7 +42,6 @@
#include <linux/genetlink.h>
#include <linux/rtnetlink.h>
#include <linux/filter.h>
#include <linux/limits.h>
#include <ell/ell.h>
#ifndef ARPHRD_NETLINK
@ -95,8 +93,6 @@
#define BSS_CAPABILITY_APSD (1<<11)
#define BSS_CAPABILITY_DSSS_OFDM (1<<13)
#define BYTES_PER_MB 1000000
struct nlmon *cur_nlmon;
enum msg_type {
@ -117,12 +113,6 @@ struct nlmon {
bool noscan;
bool noies;
bool read;
enum time_format time_format;
char *file_prefix;
unsigned int file_idx;
unsigned int max_files;
unsigned int max_size;
};
struct nlmon_req {
@ -195,15 +185,11 @@ static void nlmon_req_free(void *data)
}
static time_t time_offset = ((time_t) -1);
static enum time_format time_format;
static inline void update_time_offset(const struct timeval *tv,
enum time_format tf)
static inline void update_time_offset(const struct timeval *tv)
{
if (tv && time_offset == ((time_t) -1)) {
if (tv && time_offset == ((time_t) -1))
time_offset = tv->tv_sec;
time_format = tf;
}
}
#define print_indent(indent, color1, prefix, title, color2, fmt, args...) \
@ -239,38 +225,15 @@ static void print_packet(const struct timeval *tv, char ident,
int n, ts_len = 0, ts_pos = 0, len = 0, pos = 0;
if (tv) {
struct tm *tm;
if (use_color()) {
n = sprintf(ts_str + ts_pos, "%s", COLOR_TIMESTAMP);
if (n > 0)
ts_pos += n;
}
switch (time_format) {
case TIME_FORMAT_DELTA:
n = sprintf(ts_str + ts_pos, " %" PRId64 ".%06" PRId64,
n = sprintf(ts_str + ts_pos, " %" PRId64 ".%06" PRId64,
(int64_t)tv->tv_sec - time_offset,
(int64_t)tv->tv_usec);
break;
case TIME_FORMAT_UTC:
tm = gmtime(&tv->tv_sec);
if (!tm) {
n = sprintf(ts_str + ts_pos, "%s",
"Time error");
break;
}
n = strftime(ts_str + ts_pos, sizeof(ts_str) - ts_pos,
"%b %d %H:%M:%S", tm);
break;
default:
/* Should never happen */
printf("Unknown time format");
l_main_quit();
return;
}
if (n > 0) {
ts_pos += n;
ts_len += n;
@ -404,7 +367,6 @@ static const struct {
{ { 0x00, 0x50, 0xf2 }, "Microsoft" },
{ { 0x00, 0x90, 0x4c }, "Epigram" },
{ { 0x50, 0x6f, 0x9a }, "Wi-Fi Alliance" },
{ { 0x00, 0x18, 0x0a }, "Cisco Meraki" },
{ }
};
@ -1916,7 +1878,7 @@ static void print_ie_interworking(unsigned int level,
size--;
ptr++;
if (size < 2)
if (!size)
return;
/*
@ -7402,64 +7364,6 @@ static bool nlmon_req_match(const void *a, const void *b)
return (req->seq == match->seq && req->pid == match->pid);
}
/*
* Ensures that PCAP names are zero padded when needed. This makes the files
* sort correctly.
*/
static void next_pcap_name(char *buf, size_t size, const char *prefix,
unsigned int idx, unsigned int max)
{
unsigned int ndigits = 1;
while (max > 9) {
max /= 10;
ndigits++;
}
snprintf(buf, size, "%s%.*u", prefix, ndigits, idx);
}
static bool check_pcap(struct nlmon *nlmon, size_t next_size)
{
char path[PATH_MAX];
if (!nlmon->pcap)
return false;
if (!nlmon->max_size)
return true;
if (pcap_get_size(nlmon->pcap) + next_size <= nlmon->max_size)
return true;
pcap_close(nlmon->pcap);
/* Exhausted the single PCAP file */
if (nlmon->max_files < 2) {
printf("Reached maximum size of PCAP, exiting\n");
nlmon->pcap = NULL;
l_main_quit();
return false;
}
next_pcap_name(path, sizeof(path), nlmon->file_prefix,
++nlmon->file_idx, nlmon->max_files);
nlmon->pcap = pcap_create(path);
if (nlmon->max_files > nlmon->file_idx)
return true;
/* Remove oldest PCAP file */
next_pcap_name(path, sizeof(path), nlmon->file_prefix,
nlmon->file_idx - nlmon->max_files, nlmon->max_files);
if (remove(path) < 0)
printf("Failed to remove old PCAP file %s\n", path);
return true;
}
static void store_packet(struct nlmon *nlmon, const struct timeval *tv,
uint16_t pkt_type,
uint16_t arphrd_type,
@ -7468,7 +7372,7 @@ static void store_packet(struct nlmon *nlmon, const struct timeval *tv,
{
uint8_t sll_hdr[16], *buf = sll_hdr;
if (!check_pcap(nlmon, sizeof(sll_hdr) + size))
if (!nlmon->pcap)
return;
memset(sll_hdr, 0, sizeof(sll_hdr));
@ -7593,10 +7497,6 @@ struct nlmon *nlmon_create(uint16_t id, const struct nlmon_config *config)
nlmon->noscan = config->noscan;
nlmon->noies = config->noies;
nlmon->read = config->read_only;
nlmon->time_format = config->time_format;
nlmon->max_files = config->pcap_file_count;
/* Command line expects MB, but use bytes internally */
nlmon->max_size = config->pcap_file_size * BYTES_PER_MB;
return nlmon;
}
@ -8433,10 +8333,7 @@ void nlmon_print_rtnl(struct nlmon *nlmon, const struct timeval *tv,
int64_t aligned_size = NLMSG_ALIGN(size);
const struct nlmsghdr *nlmsg;
if (nlmon->nortnl)
return;
update_time_offset(tv, nlmon->time_format);
update_time_offset(tv);
for (nlmsg = data; NLMSG_OK(nlmsg, aligned_size);
nlmsg = NLMSG_NEXT(nlmsg, aligned_size)) {
@ -8474,7 +8371,7 @@ void nlmon_print_genl(struct nlmon *nlmon, const struct timeval *tv,
{
const struct nlmsghdr *nlmsg;
update_time_offset(tv, nlmon->time_format);
update_time_offset(tv);
for (nlmsg = data; NLMSG_OK(nlmsg, size);
nlmsg = NLMSG_NEXT(nlmsg, size)) {
@ -8497,7 +8394,7 @@ void nlmon_print_pae(struct nlmon *nlmon, const struct timeval *tv,
{
char extra_str[16];
update_time_offset(tv, nlmon->time_format);
update_time_offset(tv);
sprintf(extra_str, "len %u", size);
@ -8624,20 +8521,13 @@ struct nlmon *nlmon_open(uint16_t id, const char *pathname,
struct nlmon *nlmon;
struct l_io *pae_io;
struct pcap *pcap;
char path[PATH_MAX];
pae_io = open_pae();
if (!pae_io)
return NULL;
if (pathname) {
if (config->pcap_file_count > 1)
next_pcap_name(path, sizeof(path), pathname,
0, config->pcap_file_count);
else
snprintf(path, sizeof(path), "%s", pathname);
pcap = pcap_create(path);
pcap = pcap_create(pathname);
if (!pcap) {
l_io_destroy(pae_io);
return NULL;
@ -8650,7 +8540,6 @@ struct nlmon *nlmon_open(uint16_t id, const char *pathname,
nlmon->pae_io = pae_io;
nlmon->pcap = pcap;
nlmon->file_prefix = l_strdup(pathname);
l_io_set_read_handler(nlmon->pae_io, pae_receive, nlmon, NULL);
@ -8673,7 +8562,5 @@ void nlmon_close(struct nlmon *nlmon)
if (nlmon->pcap)
pcap_close(nlmon->pcap);
l_free(nlmon->file_prefix);
l_free(nlmon);
}

View File

@ -25,22 +25,12 @@
struct nlmon;
enum time_format {
TIME_FORMAT_DELTA,
TIME_FORMAT_UTC,
};
struct nlmon_config {
bool nortnl;
bool nowiphy;
bool noscan;
bool noies;
bool read_only;
enum time_format time_format;
/* File size in MB */
uint32_t pcap_file_size;
uint32_t pcap_file_count;
};
struct nlmon *nlmon_open(uint16_t id, const char *pathname,

View File

@ -60,7 +60,6 @@ struct pcap {
bool closed;
uint32_t type;
uint32_t snaplen;
size_t size;
};
struct pcap *pcap_open(const char *pathname)
@ -153,8 +152,6 @@ struct pcap *pcap_create(const char *pathname)
goto failed;
}
pcap->size += len;
return pcap;
failed:
@ -191,11 +188,6 @@ uint32_t pcap_get_snaplen(struct pcap *pcap)
return pcap->snaplen;
}
size_t pcap_get_size(struct pcap *pcap)
{
return pcap->size;
}
bool pcap_read(struct pcap *pcap, struct timeval *tv,
void *data, uint32_t size, uint32_t *len, uint32_t *real_len)
{
@ -287,7 +279,5 @@ bool pcap_write(struct pcap *pcap, const struct timeval *tv,
return false;
}
pcap->size += written;
return true;
}

View File

@ -36,7 +36,6 @@ void pcap_close(struct pcap *pcap);
uint32_t pcap_get_type(struct pcap *pcap);
uint32_t pcap_get_snaplen(struct pcap *pcap);
size_t pcap_get_size(struct pcap *pcap);
bool pcap_read(struct pcap *pcap, struct timeval *tv,
void *data, uint32_t size, uint32_t *len, uint32_t *real_len);

View File

@ -109,8 +109,6 @@ struct ap_state {
struct l_timeout *rekey_timeout;
unsigned int rekey_time;
uint32_t pre_scan_cmd_id;
bool started : 1;
bool gtk_set : 1;
bool netconfig_set_addr4 : 1;
@ -356,12 +354,6 @@ static void ap_reset(struct ap_state *ap)
l_timeout_remove(ap->rekey_timeout);
ap->rekey_timeout = NULL;
}
if (ap->pre_scan_cmd_id) {
scan_cancel(netdev_get_wdev_id(ap->netdev),
ap->pre_scan_cmd_id);
ap->pre_scan_cmd_id = 0;
}
}
static bool ap_event_done(struct ap_state *ap, bool prev_in_event)
@ -3860,70 +3852,6 @@ static int ap_load_config(struct ap_state *ap, const struct l_settings *config,
return 0;
}
static void ap_pre_scan_trigger(int err, void *user_data)
{
struct ap_state *ap = user_data;
if (err < 0) {
l_error("AP pre-scan failed: %i", err);
ap_start_failed(ap, err);
return;
}
}
static bool ap_check_channel(struct ap_state *ap)
{
const struct band_freq_attrs *freq_attr;
freq_attr = wiphy_get_frequency_info(netdev_get_wiphy(ap->netdev),
band_channel_to_freq(ap->channel, ap->band));
if (L_WARN_ON(!freq_attr))
return false;
/* Check if disabled/no-IR */
if (freq_attr->disabled || freq_attr->no_ir)
return false;
return true;
}
static bool ap_pre_scan_notify(int err, struct l_queue *bss_list,
const struct scan_freq_set *freqs,
void *user_data)
{
struct ap_state *ap = user_data;
if (!ap_check_channel(ap)) {
l_error("Unable to channel %u even after pre-scan",
ap->channel);
goto error;
}
if (ap_start_send(ap))
return false;
error:
ap_start_failed(ap, -ENOTSUP);
return false;
}
static void ap_pre_scan_destroy(void *user_data)
{
struct ap_state *ap = user_data;
ap->pre_scan_cmd_id = 0;
}
static bool ap_pre_scan(struct ap_state *ap)
{
ap->pre_scan_cmd_id = scan_passive(netdev_get_wdev_id(ap->netdev),
NULL, ap_pre_scan_trigger,
ap_pre_scan_notify,
ap, ap_pre_scan_destroy);
return ap->pre_scan_cmd_id != 0;
}
/*
* Start a simple independent WPA2 AP on given netdev.
*
@ -4034,20 +3962,6 @@ struct ap_state *ap_start(struct netdev *netdev, struct l_settings *config,
return ap;
}
if (!ap_check_channel(ap)) {
l_debug("Channel %u is disabled/no-IR, pre-scanning",
ap->channel);
if (ap_pre_scan(ap)) {
if (err_out)
*err_out = 0;
return ap;
}
goto error;
}
if (ap_start_send(ap)) {
if (err_out)
*err_out = 0;

View File

@ -45,42 +45,22 @@
static uint64_t blacklist_multiplier;
static uint64_t blacklist_initial_timeout;
static uint64_t blacklist_ap_busy_initial_timeout;
static uint64_t blacklist_max_timeout;
struct blacklist_entry {
uint8_t addr[6];
uint64_t added_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 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)
{
struct blacklist_entry *entry = 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_free(entry);
return true;
@ -107,53 +87,17 @@ static bool match_addr(const void *a, const void *b)
return false;
}
static bool match_addr_and_reason(const void *a, const void *b)
{
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)
void blacklist_add_bss(const uint8_t *addr)
{
struct blacklist_entry *entry;
uint64_t timeout;
blacklist_prune();
timeout = get_reason_timeout(reason);
if (!timeout)
return;
entry = l_queue_find(blacklist, match_addr, addr);
if (entry) {
uint64_t offset;
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);
uint64_t offset = l_time_diff(entry->added_time,
entry->expire_time);
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->added_time = l_time_now();
entry->expire_time = l_time_offset(entry->added_time, timeout);
entry->reason = reason;
entry->expire_time = l_time_offset(entry->added_time,
blacklist_initial_timeout);
memcpy(entry->addr, addr, 6);
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 = {
.addr = addr,
.reason = reason
};
bool ret;
uint64_t time_now;
struct blacklist_entry *entry;
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_search search = {
.addr = addr,
.reason = reason
};
blacklist_prune();
entry = l_queue_remove_if(blacklist, match_addr_and_reason, &search);
entry = l_queue_remove_if(blacklist, match_addr, addr);
if (!entry)
return;
@ -214,47 +162,19 @@ static int blacklist_init(void)
blacklist_initial_timeout = BLACKLIST_DEFAULT_TIMEOUT;
/* For easier user configuration the timeout values are in seconds */
blacklist_initial_timeout *= L_USEC_PER_SEC;
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;
blacklist_initial_timeout *= 1000000;
if (!l_settings_get_uint64(config, "Blacklist",
"Multiplier",
&blacklist_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",
"MaximumTimeout",
&blacklist_max_timeout))
blacklist_max_timeout = BLACKLIST_DEFAULT_MAX_TIMEOUT;
blacklist_max_timeout *= L_USEC_PER_SEC;
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_max_timeout *= 1000000;
blacklist = l_queue_new();

View File

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

View File

@ -110,14 +110,6 @@ bool diagnostic_info_to_dict(const struct diagnostic_station_info *info,
dbus_append_dict_basic(builder, "ExpectedThroughput", 'u',
&info->expected_throughput);
if (info->have_inactive_time)
dbus_append_dict_basic(builder, "InactiveTime", 'u',
&info->inactive_time);
if (info->have_connected_time)
dbus_append_dict_basic(builder, "ConnectedTime", 'u',
&info->connected_time);
return true;
}

View File

@ -43,9 +43,6 @@ struct diagnostic_station_info {
uint32_t expected_throughput;
uint32_t inactive_time;
uint32_t connected_time;
bool have_cur_rssi : 1;
bool have_avg_rssi : 1;
bool have_rx_mcs : 1;
@ -53,8 +50,6 @@ struct diagnostic_station_info {
bool have_rx_bitrate : 1;
bool have_tx_bitrate : 1;
bool have_expected_throughput : 1;
bool have_inactive_time : 1;
bool have_connected_time : 1;
};
bool diagnostic_info_to_dict(const struct diagnostic_station_info *info,

View File

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

View File

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

View File

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

View File

@ -1810,7 +1810,7 @@ static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm,
if ((rsne[1] != hs->authenticator_ie[1] ||
memcmp(rsne + 2, hs->authenticator_ie + 2, rsne[1])) &&
!handshake_util_ap_ie_matches(hs, &rsn_info,
!handshake_util_ap_ie_matches(&rsn_info,
hs->authenticator_ie,
hs->wpa_ie))
goto error_ie_different;

View File

@ -223,8 +223,7 @@ static bool ft_parse_associate_resp_frame(const uint8_t *frame, size_t frame_len
return true;
}
static bool ft_verify_rsne(struct handshake_state *hs,
const uint8_t *rsne, const uint8_t *pmk_r0_name,
static bool ft_verify_rsne(const uint8_t *rsne, const uint8_t *pmk_r0_name,
const uint8_t *authenticator_ie)
{
/*
@ -254,7 +253,7 @@ static bool ft_verify_rsne(struct handshake_state *hs,
memcmp(msg2_rsne.pmkids, pmk_r0_name, 16))
return false;
if (!handshake_util_ap_ie_matches(hs, &msg2_rsne, authenticator_ie, false))
if (!handshake_util_ap_ie_matches(&msg2_rsne, authenticator_ie, false))
return false;
return true;
@ -302,8 +301,7 @@ static int parse_ies(struct handshake_state *hs,
is_rsn = hs->supplicant_ie != NULL;
if (is_rsn) {
if (!ft_verify_rsne(hs, rsne, hs->pmk_r0_name,
authenticator_ie))
if (!ft_verify_rsne(rsne, hs->pmk_r0_name, authenticator_ie))
goto ft_error;
} else if (rsne)
goto ft_error;
@ -482,7 +480,7 @@ int __ft_rx_associate(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
memcmp(msg4_rsne.pmkids, hs->pmk_r1_name, 16))
return -EBADMSG;
if (!handshake_util_ap_ie_matches(hs, &msg4_rsne,
if (!handshake_util_ap_ie_matches(&msg4_rsne,
hs->authenticator_ie,
false))
return -EBADMSG;

View File

@ -368,12 +368,6 @@ void handshake_state_set_vendor_ies(struct handshake_state *s,
}
}
void handshake_state_set_vendor_quirks(struct handshake_state *s,
struct vendor_quirk quirks)
{
s->vendor_quirks = quirks;
}
void handshake_state_set_kh_ids(struct handshake_state *s,
const uint8_t *r0khid, size_t r0khid_len,
const uint8_t *r1khid)
@ -883,8 +877,7 @@ void handshake_state_set_igtk(struct handshake_state *s, const uint8_t *key,
* results vs the RSN/WPA IE obtained as part of the 4-way handshake. If they
* don't match, the EAPoL packet must be silently discarded.
*/
bool handshake_util_ap_ie_matches(struct handshake_state *s,
const struct ie_rsn_info *msg_info,
bool handshake_util_ap_ie_matches(const struct ie_rsn_info *msg_info,
const uint8_t *scan_ie, bool is_wpa)
{
struct ie_rsn_info scan_info;
@ -914,15 +907,11 @@ bool handshake_util_ap_ie_matches(struct handshake_state *s,
if (msg_info->no_pairwise != scan_info.no_pairwise)
return false;
if (!(s->vendor_quirks.replay_counter_mismatch)) {
if (msg_info->ptksa_replay_counter !=
scan_info.ptksa_replay_counter)
return false;
if (msg_info->ptksa_replay_counter != scan_info.ptksa_replay_counter)
return false;
if (msg_info->gtksa_replay_counter !=
scan_info.gtksa_replay_counter)
return false;
}
if (msg_info->gtksa_replay_counter != scan_info.gtksa_replay_counter)
return false;
if (msg_info->mfpr != scan_info.mfpr)
return false;
@ -1250,7 +1239,7 @@ static struct pmksa *handshake_state_steal_pmksa(struct handshake_state *s)
s->have_pmksa = false;
if (l_time_after(now, pmksa->expiration)) {
pmksa_cache_free(pmksa);
l_free(pmksa);
pmksa = NULL;
}
@ -1283,15 +1272,13 @@ void handshake_state_cache_pmksa(struct handshake_state *s)
{
struct pmksa *pmksa = handshake_state_steal_pmksa(s);
if (!pmksa) {
l_debug("No PMKSA for "MAC, MAC_STR(s->aa));
return;
}
l_debug("%p", pmksa);
l_debug("Caching PMKSA for "MAC, MAC_STR(s->aa));
if (!pmksa)
return;
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)
@ -1305,7 +1292,7 @@ bool handshake_state_remove_pmksa(struct handshake_state *s)
if (!pmksa)
return false;
pmksa_cache_free(pmksa);
l_free(pmksa);
return true;
}

View File

@ -26,8 +26,6 @@
#include <linux/types.h>
#include <ell/cleanup.h>
#include "src/vendor_quirks.h"
struct handshake_state;
enum crypto_cipher;
struct eapol_frame;
@ -109,7 +107,6 @@ struct handshake_state {
uint8_t *authenticator_fte;
uint8_t *supplicant_fte;
uint8_t *vendor_ies;
struct vendor_quirk vendor_quirks;
size_t vendor_ies_len;
enum ie_rsn_cipher_suite pairwise_cipher;
enum ie_rsn_cipher_suite group_cipher;
@ -240,9 +237,6 @@ void handshake_state_set_vendor_ies(struct handshake_state *s,
const struct iovec *iov,
size_t n_iovs);
void handshake_state_set_vendor_quirks(struct handshake_state *s,
struct vendor_quirk quirks);
void handshake_state_set_kh_ids(struct handshake_state *s,
const uint8_t *r0khid, size_t r0khid_len,
const uint8_t *r1khid);
@ -318,8 +312,7 @@ bool handshake_state_set_pmksa(struct handshake_state *s, struct pmksa *pmksa);
void handshake_state_cache_pmksa(struct handshake_state *s);
bool handshake_state_remove_pmksa(struct handshake_state *s);
bool handshake_util_ap_ie_matches(struct handshake_state *s,
const struct ie_rsn_info *msg_info,
bool handshake_util_ap_ie_matches(const struct ie_rsn_info *msg_info,
const uint8_t *scan_ie, bool is_wpa);
const uint8_t *handshake_util_find_kde(enum handshake_kde selector,

View File

@ -290,27 +290,9 @@ control how long a misbehaved BSS spends on the blacklist.
* - InitialTimeout
- Values: uint64 value in seconds (default: **60**)
The initial time that a BSS spends on the blacklist. Setting this to zero
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.
The initial time that a BSS spends on the blacklist.
* - Multiplier
- Values: unsigned int value greater than zero, in seconds
(default: **30**)
- Values: unsigned int value in seconds (default: **30**)
If the BSS was blacklisted previously and another connection attempt
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
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
========

View File

@ -463,14 +463,6 @@ uint8_t netdev_get_rssi_level_idx(struct netdev *netdev)
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,
const void *data,
uint32_t len, void *user_data)
@ -637,6 +629,7 @@ static bool netdev_parse_sta_info(struct l_genl_attr *attr,
info->have_tx_mcs = true;
break;
case NL80211_STA_INFO_EXPECTED_THROUGHPUT:
if (len != 4)
return false;
@ -644,22 +637,6 @@ static bool netdev_parse_sta_info(struct l_genl_attr *attr,
info->expected_throughput = l_get_u32(data);
info->have_expected_throughput = true;
break;
case NL80211_STA_INFO_INACTIVE_TIME:
if (len != 4)
return false;
info->inactive_time = l_get_u32(data);
info->have_inactive_time = true;
break;
case NL80211_STA_INFO_CONNECTED_TIME:
if (len != 4)
return false;
info->connected_time = l_get_u32(data);
info->have_connected_time = true;
break;
}
}
@ -1124,7 +1101,6 @@ static void netdev_free(void *data)
l_timeout_remove(netdev->rssi_poll_timeout);
scan_wdev_remove(netdev->wdev_id);
frame_watch_wdev_remove(netdev->wdev_id);
watchlist_destroy(&netdev->station_watches);
@ -1522,105 +1498,6 @@ static void netdev_setting_keys_failed(struct netdev_handshake_state *nhs,
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)
{
l_debug("ptk_installed: %u, gtk_installed: %u, igtk_installed: %u",
@ -3008,26 +2885,13 @@ static void netdev_cmd_ft_reassociate_cb(struct l_genl_msg *msg,
void *user_data)
{
struct netdev *netdev = user_data;
int err = l_genl_msg_get_error(msg);
netdev->connect_cmd_id = 0;
l_debug("%d", err);
if (err >= 0)
if (l_genl_msg_get_error(msg) >= 0)
return;
/*
* TODO: It is possible to not trigger a disconnect here and maintain
* the current connection. The issue is that IWD has already
* modified the handshake and we've lost all reference to the old
* BSS keys.
*
* This could be remedied in the future by creating an entirely
* new handshake_state object for the association and only when
* the ack indicates success do we clear out the old object.
*/
netdev_disconnect_and_fail_connection(netdev,
netdev_deauth_and_fail_connection(netdev,
NETDEV_RESULT_ASSOCIATION_FAILED,
MMPDU_STATUS_CODE_UNSPECIFIED);
}
@ -3619,13 +3483,6 @@ static void netdev_external_auth_sae_tx_associate(void *user_data)
netdev_send_external_auth(netdev, MMPDU_STATUS_CODE_SUCCESS);
netdev_ensure_eapol_registered(netdev);
/*
* Free the auth proto now. With external auth there is no associate
* event which is where this normally gets cleaned up.
*/
auth_proto_free(netdev->ap);
netdev->ap = NULL;
}
struct rtnl_data {
@ -3952,15 +3809,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)
{
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("");
@ -5430,9 +5278,6 @@ static void netdev_channel_switch_event(struct l_genl_msg *msg,
if (netdev->type != NL80211_IFTYPE_STATION)
return;
if (L_WARN_ON(!netdev->connected))
return;
chandef = l_new(struct band_chandef, 1);
if (nl80211_parse_chandef(msg, chandef) < 0) {
@ -5482,39 +5327,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);
}
#define MAX_COMEBACK_DELAY 1200
static void netdev_assoc_comeback(struct l_genl_msg *msg,
struct netdev *netdev)
{
const uint8_t *mac;
uint32_t timeout;
if (L_WARN_ON(!netdev->connected))
return;
if (nl80211_parse_attrs(msg, NL80211_ATTR_MAC, &mac,
NL80211_ATTR_TIMEOUT, &timeout,
NL80211_ATTR_UNSPEC) < 0)
return;
if (L_WARN_ON(memcmp(mac, netdev->handshake->aa, ETH_ALEN)))
return;
if (timeout <= MAX_COMEBACK_DELAY) {
l_debug(MAC" requested an association comeback delay of %u TU",
MAC_STR(netdev->handshake->aa), timeout);
return;
}
l_debug("Comeback delay of %u exceeded maximum of %u, deauthenticating",
timeout, MAX_COMEBACK_DELAY);
netdev_deauth_and_fail_connection(netdev,
NETDEV_RESULT_ASSOCIATION_FAILED,
MMPDU_STATUS_CODE_REFUSED_TEMPORARILY);
}
static void netdev_mlme_notify(struct l_genl_msg *msg, void *user_data)
{
struct netdev *netdev = NULL;
@ -5568,9 +5380,6 @@ static void netdev_mlme_notify(struct l_genl_msg *msg, void *user_data)
case NL80211_CMD_MICHAEL_MIC_FAILURE:
netdev_michael_mic_failure(msg, netdev);
break;
case NL80211_CMD_ASSOC_COMEBACK:
netdev_assoc_comeback(msg, netdev);
break;
}
}
@ -5688,18 +5497,23 @@ static void netdev_external_auth_event(struct l_genl_msg *msg,
}
if (action == NL80211_EXTERNAL_AUTH_ABORT) {
l_warn("External Auth Aborted");
iwd_notice(IWD_NOTICE_CONNECT_INFO, "External Auth Aborted");
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 ||
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;
}
if (memcmp(hs->aa, bssid, ETH_ALEN)) {
l_warn("Target BSSID mismatch");
iwd_notice(IWD_NOTICE_CONNECT_INFO, "Target BSSID mismatch");
goto error;
}
@ -6708,16 +6522,6 @@ struct netdev *netdev_create_from_genl(struct l_genl_msg *msg,
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;
}
@ -6833,10 +6637,6 @@ static int netdev_init(void)
__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,
netdev_unicast_notify,
NULL, NULL);

View File

@ -158,7 +158,6 @@ const char *netdev_get_name(struct netdev *netdev);
bool netdev_get_is_up(struct netdev *netdev);
const char *netdev_get_path(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_get_handshake(struct netdev *netdev);

View File

@ -168,11 +168,6 @@ static bool network_secret_check_cacheable(void *data, void *user_data)
return false;
}
void network_clear_blacklist(struct network *network)
{
l_queue_clear(network->blacklist, NULL);
}
void network_connected(struct network *network)
{
enum security security = network_get_security(network);
@ -203,6 +198,8 @@ void network_connected(struct network *network)
l_queue_foreach_remove(network->secrets,
network_secret_check_cacheable, network);
l_queue_clear(network->blacklist, NULL);
network->provisioning_hidden = false;
}
@ -210,7 +207,7 @@ void network_disconnected(struct network *network)
{
network_settings_close(network);
network_clear_blacklist(network);
l_queue_clear(network->blacklist, NULL);
if (network->provisioning_hidden)
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))
continue;
if (blacklist_contains_bss(bss->addr,
BLACKLIST_REASON_CONNECT_FAILED))
if (blacklist_contains_bss(bss->addr))
continue;
/* 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 struct scan_bss *bss);
bool network_bss_list_isempty(struct network *network);
void network_clear_blacklist(struct network *network);
const char *__network_path_append_bss(const char *network_path,
const struct scan_bss *bss);

View File

@ -177,7 +177,6 @@ static const struct {
{ NL80211_CMD_UNPROT_BEACON, "Unprotected Beacon" },
{ NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS,
"Control Port TX Status" },
{ NL80211_CMD_ASSOC_COMEBACK, "Association comeback delay" },
{ }
};

View File

@ -190,7 +190,6 @@ static attr_handler handler_for_nl80211(int type)
case NL80211_ATTR_CENTER_FREQ2:
case NL80211_ATTR_AKM_SUITES:
case NL80211_ATTR_EXTERNAL_AUTH_ACTION:
case NL80211_ATTR_TIMEOUT:
return extract_uint32;
case NL80211_ATTR_FRAME:
return extract_iovec;

View File

@ -40,9 +40,6 @@
static uint64_t dot11RSNAConfigPMKLifetime = 43200ULL * L_USEC_PER_SEC;
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 pmksa **data;
@ -145,7 +142,7 @@ int pmksa_cache_put(struct pmksa *pmksa)
l_debug("Adding entry with PMKID: "PMKID, PMKID_STR(pmksa->pmkid));
if (cache.used == cache.capacity) {
pmksa_cache_free(cache.data[0]);
l_free(cache.data[0]);
cache.data[0] = pmksa;
__minheap_sift_down(cache.data, cache.used, 0, &ops);
return 0;
@ -155,9 +152,6 @@ int pmksa_cache_put(struct pmksa *pmksa)
__minheap_sift_up(cache.data, cache.used, &ops);
cache.used += 1;
if (driver_add)
driver_add(pmksa);
return 0;
}
@ -173,7 +167,7 @@ int pmksa_cache_expire(uint64_t cutoff)
for (i = 0; i < used; i++) {
if (cache.data[i]->expiration <= cutoff) {
pmksa_cache_free(cache.data[i]);
l_free(cache.data[i]);
continue;
}
@ -196,30 +190,11 @@ int pmksa_cache_flush(void)
{
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++)
l_free(cache.data[i]);
memset(cache.data, 0, cache.capacity * sizeof(struct pmksa *));
cache.used = 0;
return 0;
}
int pmksa_cache_free(struct pmksa *pmksa)
{
if (driver_remove)
driver_remove(pmksa);
l_free(pmksa);
return 0;
}
@ -242,15 +217,6 @@ void __pmksa_set_config(const struct l_settings *config)
&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)
{
cache.capacity = pmksa_cache_capacity;

View File

@ -32,10 +32,6 @@ struct pmksa {
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(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_expire(uint64_t cutoff);
int pmksa_cache_flush(void);
int pmksa_cache_free(struct pmksa *pmksa);
uint64_t pmksa_lifetime(void);
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])
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;
}
@ -1002,8 +994,7 @@ static int sae_process_anti_clogging(struct sae_sm *sm, const uint8_t *ptr,
sm->token_len = len;
sm->sync = 0;
if (L_WARN_ON(!sae_send_commit(sm, true)))
return -EPROTO;
sae_send_commit(sm, true);
return -EAGAIN;
}
@ -1083,9 +1074,7 @@ static int sae_verify_committed(struct sae_sm *sm, uint16_t transaction,
return -ETIMEDOUT;
sm->sync++;
if (L_WARN_ON(!sae_send_commit(sm, true)))
return -EPROTO;
sae_send_commit(sm, true);
return -EAGAIN;
}
@ -1140,9 +1129,7 @@ static int sae_verify_committed(struct sae_sm *sm, uint16_t transaction,
sm->group);
sm->sync = 0;
if (L_WARN_ON(!sae_send_commit(sm, false)))
return -EPROTO;
sae_send_commit(sm, false);
return -EAGAIN;
}
@ -1307,8 +1294,7 @@ static int sae_verify_confirmed(struct sae_sm *sm, uint16_t trans,
sm->sync++;
sm->sc++;
if (L_WARN_ON(!sae_send_commit(sm, true)))
return -EPROTO;
sae_send_commit(sm, true);
if (!sae_send_confirm(sm))
return -EPROTO;

View File

@ -51,7 +51,6 @@
#include "src/mpdu.h"
#include "src/band.h"
#include "src/scan.h"
#include "src/vendor_quirks.h"
/* User configurable options */
static double RANK_2G_FACTOR;
@ -144,9 +143,9 @@ struct scan_survey {
};
struct scan_survey_results {
struct scan_survey survey_2_4[15];
struct scan_survey survey_5[197];
struct scan_survey survey_6[234];
struct scan_survey survey_2_4[14];
struct scan_survey survey_5[196];
struct scan_survey survey_6[233];
};
struct scan_results {
@ -415,8 +414,7 @@ static struct l_genl_msg *scan_build_cmd(struct scan_context *sc,
if (params->ap_scan)
flags |= NL80211_SCAN_FLAG_AP;
if (wiphy_supports_colocated_flag(sc->wiphy))
flags |= NL80211_SCAN_FLAG_COLOCATED_6GHZ;
flags |= NL80211_SCAN_FLAG_COLOCATED_6GHZ;
if (flags)
l_genl_msg_append_attr(msg, NL80211_ATTR_SCAN_FLAGS, 4, &flags);
@ -1222,11 +1220,6 @@ static void scan_parse_vendor_specific(struct scan_bss *bss, const void *data,
uint16_t cost_flags;
bool dgaf_disable;
if (L_WARN_ON(len < 3))
return;
vendor_quirks_append_for_oui(data, &bss->vendor_quirks);
if (!bss->wpa && is_ie_wpa_ie(data, len)) {
bss->wpa = l_memdup(data - 2, len + 2);
return;

View File

@ -21,7 +21,6 @@
*/
#include "src/defs.h"
#include "src/vendor_quirks.h"
struct scan_freq_set;
struct ie_rsn_info;
@ -80,7 +79,6 @@ struct scan_bss {
uint8_t *wfd; /* Concatenated WFD IEs */
ssize_t wfd_size; /* Size of Concatenated WFD IEs */
int8_t snr;
struct vendor_quirk vendor_quirks;
bool mde_present : 1;
bool cc_present : 1;
bool cap_rm_neighbor_report : 1;

View File

@ -64,7 +64,6 @@
#include "src/eap-tls-common.h"
#include "src/storage.h"
#include "src/pmksa.h"
#include "src/vendor_quirks.h"
#define STATION_RECENT_NETWORK_LIMIT 5
#define STATION_RECENT_FREQS_LIMIT 5
@ -156,54 +155,6 @@ struct anqp_entry {
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
* from station->bss_list is not 100% safe due to the possibility of the
@ -211,13 +162,13 @@ static uint32_t evaluate_bss_group_rank(const uint8_t *addr, uint32_t freq,
*/
struct roam_bss {
uint8_t addr[6];
uint32_t rank;
uint16_t rank;
int32_t signal_strength;
bool ft_failed: 1;
};
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);
@ -1447,8 +1398,6 @@ static struct handshake_state *station_handshake_setup(struct station *station,
vendor_ies = network_info_get_extra_ies(info, bss, &iov_elems);
handshake_state_set_vendor_ies(hs, vendor_ies, iov_elems);
handshake_state_set_vendor_quirks(hs, bss->vendor_quirks);
/*
* It can't hurt to try the FILS IP Address Assignment independent of
* which auth-proto is actually used.
@ -1798,15 +1747,6 @@ static void station_enter_state(struct station *station,
periodic_scan_stop(station);
break;
case STATION_STATE_CONNECTED:
network_clear_blacklist(station->connected_network);
if (station->connect_pending) {
struct l_dbus_message *reply =
l_dbus_message_new_method_return(
station->connect_pending);
dbus_pending_reply(&station->connect_pending, reply);
}
l_dbus_object_add_interface(dbus,
netdev_get_path(station->netdev),
IWD_STATION_DIAGNOSTIC_INTERFACE,
@ -2226,26 +2166,6 @@ static void station_early_neighbor_report_cb(struct netdev *netdev, int err,
&station->roam_freqs);
}
static bool station_try_next_bss(struct station *station)
{
struct scan_bss *next;
int ret;
next = network_bss_select(station->connected_network, false);
if (!next)
return false;
ret = __station_connect_network(station, station->connected_network,
next, station->state);
if (ret < 0)
return false;
l_debug("Attempting to connect to next BSS "MAC, MAC_STR(next->addr));
return true;
}
static bool station_can_fast_transition(struct station *station,
struct handshake_state *hs,
struct scan_bss *bss)
@ -2288,26 +2208,28 @@ static bool station_can_fast_transition(struct station *station,
return true;
}
static void station_disconnect_on_netconfig_failed(struct netdev *netdev,
bool success,
void *user_data)
static void station_disconnect_on_error_cb(struct netdev *netdev, bool success,
void *user_data)
{
struct station *station = user_data;
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);
bool continue_autoconnect;
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,
@ -2320,20 +2242,23 @@ static void station_netconfig_event_handler(enum netconfig_event event,
station_enter_state(station, STATION_STATE_CONNECTED);
break;
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)
network_connect_failed(station->connected_network,
false);
network_blacklist_add(station->connected_network,
station->connected_bss);
netdev_disconnect(station->netdev,
station_disconnect_on_netconfig_failed,
station_disconnect_on_error_cb,
station);
station_reset_connection_state(station);
station_enter_state(station, STATION_STATE_DISCONNECTING);
break;
default:
l_error("station: Unsupported netconfig event: %d.", event);
@ -2407,11 +2332,6 @@ static void station_roam_retry(struct station *station)
station->roam_scan_full = false;
station->ap_directed_roaming = false;
if (station->roam_freqs) {
scan_freq_set_free(station->roam_freqs);
station->roam_freqs = NULL;
}
if (station->signal_low)
station_roam_timeout_rearm(station, roam_retry_interval);
}
@ -2441,16 +2361,8 @@ static void station_roam_failed(struct station *station)
* We were told by the AP to roam, but failed. Try ourselves or
* wait for the AP to tell us to roam again
*/
if (station->ap_directed_roaming) {
/*
* The candidate list from the AP (or neighbor report) found
* no BSS's. Force a full scan
*/
if (!station->roam_scan_full)
goto full_scan;
if (station->ap_directed_roaming)
goto delayed_retry;
}
/*
* If we tried a limited scan, failed and the signal is still low,
@ -2462,7 +2374,6 @@ static void station_roam_failed(struct station *station)
* the scan here, so that the destroy callback is not called
* after the return of this function
*/
full_scan:
scan_cancel(netdev_get_wdev_id(station->netdev),
station->roam_scan_id);
@ -2750,15 +2661,11 @@ static bool station_try_next_transition(struct station *station,
enum security security = network_get_security(connected);
struct handshake_state *new_hs;
struct ie_rsn_info cur_rsne, target_rsne;
const char *vendor_quirks = vendor_quirks_to_string(bss->vendor_quirks);
iwd_notice(IWD_NOTICE_ROAM_INFO, "bss: "MAC", signal: %d, load: %d/255",
MAC_STR(bss->addr),
bss->signal_strength / 100,
bss->utilization);
if (vendor_quirks)
l_debug("vendor quirks for "MAC": %s",
MAC_STR(bss->addr), vendor_quirks);
/* Reset AP roam flag, at this point the roaming behaves the same */
station->ap_directed_roaming = false;
@ -2898,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 scan_bss *current_bss = station->connected_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;
uint16_t mdid;
enum security orig_security, security;
@ -2927,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);
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)
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);
}
/*
@ -2957,7 +2859,6 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
while ((bss = l_queue_pop_head(bss_list))) {
double rank;
struct roam_bss *rbss;
uint32_t group_rank;
station_print_scan_bss(bss);
@ -2979,8 +2880,7 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
if (network_can_connect_bss(network, bss) < 0)
goto next;
if (blacklist_contains_bss(bss->addr,
BLACKLIST_REASON_CONNECT_FAILED))
if (blacklist_contains_bss(bss->addr))
goto next;
rank = bss->rank;
@ -2988,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)
rank *= RANK_FT_FACTOR;
group_rank = evaluate_bss_group_rank(bss->addr, bss->frequency,
bss->signal_strength,
(uint16_t) rank);
if (group_rank <= cur_bss_group_rank)
if (rank <= cur_bss_rank)
goto next;
/*
@ -3001,7 +2897,7 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
*/
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,
roam_bss_rank_compare, NULL);
@ -3059,7 +2955,6 @@ static int station_roam_scan(struct station *station,
if (!freq_set) {
station->roam_scan_full = true;
params.freqs = allowed;
station_debug_event(station, "full-roam-scan");
} else
scan_freq_set_constrain(freq_set, allowed);
@ -3270,12 +3165,12 @@ static void station_ap_directed_roam(struct station *station,
uint8_t req_mode;
uint16_t dtimer;
uint8_t valid_interval;
bool can_roam = !station_cannot_roam(station);
bool ignore_candidates =
station->connected_bss->vendor_quirks.ignore_bss_tm_candidates;
l_debug("ifindex: %u", netdev_get_ifindex(station->netdev));
if (station_cannot_roam(station))
return;
if (station->state != STATION_STATE_CONNECTED) {
l_debug("roam: unexpected AP directed roam -- ignore");
return;
@ -3339,13 +3234,8 @@ static void station_ap_directed_roam(struct station *station,
* disassociating us. If either of these bits are set, set the
* ap_directed_roaming flag. Otherwise still try roaming but don't
* 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_ESS_DISASSOCIATION_IMMINENT))
station->ap_directed_roaming = true;
@ -3372,39 +3262,17 @@ static void station_ap_directed_roam(struct station *station,
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;
l_timeout_remove(station->roam_trigger_timeout);
station->roam_trigger_timeout = NULL;
if ((req_mode & WNM_REQUEST_MODE_PREFERRED_CANDIDATE_LIST) &&
!ignore_candidates) {
if (req_mode & WNM_REQUEST_MODE_PREFERRED_CANDIDATE_LIST) {
l_debug("roam: AP sent a preferred candidate list");
station_neighbor_report_cb(station->netdev, 0, body + pos,
body_len - pos, station);
} else {
if (station->connected_bss->cap_rm_neighbor_report) {
if (!netdev_neighbor_report_req(station->netdev,
station_neighbor_report_cb))
return;
l_warn("failed to request neighbor report!");
}
l_debug("full scan after BSS transition request");
l_debug("roam: AP did not include a preferred candidate list");
if (station_roam_scan(station, NULL) < 0)
station_roam_failed(station);
}
@ -3466,6 +3334,26 @@ static void station_event_channel_switched(struct station *station,
network_bss_update(network, station->connected_bss);
}
static bool station_try_next_bss(struct station *station)
{
struct scan_bss *next;
int ret;
next = network_bss_select(station->connected_network, false);
if (!next)
return false;
ret = __station_connect_network(station, station->connected_network,
next, station->state);
if (ret < 0)
return false;
l_debug("Attempting to connect to next BSS "MAC, MAC_STR(next->addr));
return true;
}
static bool station_retry_owe_default_group(struct station *station)
{
/*
@ -3512,15 +3400,7 @@ static bool station_retry_with_reason(struct station *station,
break;
}
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);
blacklist_add_bss(station->connected_bss->addr);
try_next:
return station_try_next_bss(station);
@ -3559,54 +3439,32 @@ static bool station_pmksa_fallback(struct station *station, uint16_t status)
return true;
}
/* A bit more concise for trying to fit these into 80 characters */
#define IS_TEMPORARY_STATUS(code) \
((code) == MMPDU_STATUS_CODE_DENIED_UNSUFFICIENT_BANDWIDTH || \
(code) == MMPDU_STATUS_CODE_DENIED_POOR_CHAN_CONDITIONS || \
(code) == MMPDU_STATUS_CODE_REJECTED_WITH_SUGG_BSS_TRANS || \
(code) == MMPDU_STATUS_CODE_DENIED_NO_MORE_STAS)
static bool station_retry_with_status(struct station *station,
uint16_t status_code)
{
/* 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.
* In these cases we want to only temporarily blacklist the BSS until
* the connection is complete.
*/
case MMPDU_STATUS_CODE_DENIED_UNSUFFICIENT_BANDWIDTH:
case MMPDU_STATUS_CODE_DENIED_POOR_CHAN_CONDITIONS:
/*
*
* TODO: The WITH_SUGG_BSS_TRANS case should also include a neighbor
* report IE in the frame. This would allow us to target a
* specific BSS on our next attempt. There is currently no way to
* obtain that IE, but this should be done in the future.
*/
case MMPDU_STATUS_CODE_REJECTED_WITH_SUGG_BSS_TRANS:
break;
/*
* If a BSS is indicating its unable to handle more connections we will
* blacklist this the same way we do for BSS's issuing BSS-TM requests
* thereby avoiding roams to this BSS for the configured timeout.
*/
case MMPDU_STATUS_CODE_DENIED_NO_MORE_STAS:
blacklist_add_bss(station->connected_bss->addr,
BLACKLIST_REASON_AP_BUSY);
break;
/* For any other status codes, blacklist the BSS */
default:
blacklist_add_bss(station->connected_bss->addr,
BLACKLIST_REASON_CONNECT_FAILED);
break;
}
if (IS_TEMPORARY_STATUS(status_code))
network_blacklist_add(station->connected_network,
station->connected_bss);
else if (!station_pmksa_fallback(station, status_code))
blacklist_add_bss(station->connected_bss->addr);
/*
* 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,
station->connected_bss);
try_next:
iwd_notice(IWD_NOTICE_CONNECT_FAILED, "status: %u", status_code);
return station_try_next_bss(station);
@ -3618,6 +3476,13 @@ static void station_connect_ok(struct station *station)
l_debug("");
if (station->connect_pending) {
struct l_dbus_message *reply =
l_dbus_message_new_method_return(
station->connect_pending);
dbus_pending_reply(&station->connect_pending, reply);
}
/*
* Get a neighbor report now so future roams can avoid waiting for
* a report at that time
@ -3684,8 +3549,7 @@ static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
switch (result) {
case NETDEV_RESULT_OK:
blacklist_remove_bss(station->connected_bss->addr,
BLACKLIST_REASON_CONNECT_FAILED);
blacklist_remove_bss(station->connected_bss->addr);
station_connect_ok(station);
return;
case NETDEV_RESULT_DISCONNECTED:
@ -3917,7 +3781,6 @@ int __station_connect_network(struct station *station, struct network *network,
{
struct handshake_state *hs;
int r;
const char *vendor_quirks = vendor_quirks_to_string(bss->vendor_quirks);
/*
* If we already have a handshake_state ref this is due to a retry,
@ -3952,10 +3815,6 @@ int __station_connect_network(struct station *station, struct network *network,
bss->signal_strength / 100,
bss->utilization);
if (vendor_quirks)
l_debug("vendor quirks for "MAC": %s",
MAC_STR(bss->addr), vendor_quirks);
station->connected_bss = bss;
station->connected_network = network;
station->hs = handshake_state_ref(hs);
@ -4860,7 +4719,7 @@ static struct l_dbus_message *station_property_set_affinities(
struct l_dbus_message_iter array;
const char *sender = l_dbus_message_get_sender(message);
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 *old_bss = NULL;
bool lower_threshold = false;
@ -4880,15 +4739,10 @@ static struct l_dbus_message *station_property_set_affinities(
if (!l_dbus_message_iter_get_variant(new_value, "ao", &array))
return dbus_error_invalid_args(message);
/* Get first entry, or if an empty array set the path to NULL */
if (!l_dbus_message_iter_next_entry(&array, &new_path))
new_path = NULL;
/* Get first entry, there should be only one */
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))
if (l_dbus_message_iter_next_entry(&array, &new_path))
return dbus_error_invalid_args(message);
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;
}
/*
* 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
* the decrypted data portion. We add one here for the NULL terminator

View File

@ -1,84 +0,0 @@
/*
*
* Wireless daemon for Linux
*
* Copyright (C) 2025 Locus Robotics Corporation. 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 <string.h>
#include <stdio.h>
#include <ell/ell.h>
#include "src/vendor_quirks.h"
static const struct {
uint8_t oui[3];
struct vendor_quirk quirks;
} oui_quirk_db[] = {
{
/* Cisco Meraki */
{ 0x00, 0x18, 0x0a },
{ .ignore_bss_tm_candidates = true },
},
{
/* Hewlett Packard, owns Aruba */
{ 0x00, 0x0b, 0x86 },
{ .replay_counter_mismatch = true },
},
};
void vendor_quirks_append_for_oui(const uint8_t *oui,
struct vendor_quirk *quirks)
{
size_t i;
for (i = 0; i < L_ARRAY_SIZE(oui_quirk_db); i++) {
const struct vendor_quirk *quirk = &oui_quirk_db[i].quirks;
if (memcmp(oui_quirk_db[i].oui, oui, 3))
continue;
quirks->ignore_bss_tm_candidates |=
quirk->ignore_bss_tm_candidates;
quirks->replay_counter_mismatch |=
quirk->replay_counter_mismatch;
}
}
const char *vendor_quirks_to_string(struct vendor_quirk quirks)
{
static char out[1024];
char *pos = out;
size_t s = 0;
if (quirks.ignore_bss_tm_candidates)
s += snprintf(pos, sizeof(out) - s, "IgnoreBssTmCandidateList");
if (quirks.replay_counter_mismatch)
s += snprintf(pos, sizeof(out) - s, "ReplayCounterMismatch");
if (!s)
return NULL;
return out;
}

View File

@ -1,39 +0,0 @@
/*
*
* Wireless daemon for Linux
*
* Copyright (C) 2025 Locus Robotics Corporation. 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
*
*/
#ifndef __IWD_VENDOR_QUIRKS_H
#define __IWD_VENDOR_QUIRKS_H
#include <stdint.h>
struct vendor_quirk {
bool ignore_bss_tm_candidates : 1;
bool replay_counter_mismatch : 1;
};
void vendor_quirks_append_for_oui(const uint8_t *oui,
struct vendor_quirk *quirks);
const char *vendor_quirks_to_string(struct vendor_quirk quirks);
#endif /* __IWD_VENDOR_QUIRKS_H */

View File

@ -69,26 +69,11 @@ static uint32_t work_ids;
static unsigned int wiphy_dump_id;
enum driver_flag {
/* Force the use of the default interface created by the kernel */
DEFAULT_IF = 0x1,
/*
* Force the use of the PAE socket rather than control port, even if
* control port is supported
*/
FORCE_PAE = 0x2,
/* Disable power save on the adapter during initialization */
POWER_SAVE_DISABLE = 0x4,
/* Don't use OWE when connecting to open networks */
OWE_DISABLE = 0x8,
/* Disables multicast RX frame registration */
MULTICAST_RX_DISABLE = 0x10,
/*
* Don't use SAE (WPA3) when connecting to hybrid networks. This will
* prevent IWD from connecting to WPA3-only networks
*/
SAE_DISABLE = 0x20,
/* Disables use of the NL80211_SCAN_FLAG_COLOCATED_6GHZ flag in scans */
COLOCATED_SCAN_DISABLE = 0x40,
};
struct driver_flag_name {
@ -117,13 +102,11 @@ static const struct driver_info driver_infos[] = {
};
static const struct driver_flag_name driver_flag_names[] = {
{ "DefaultInterface", DEFAULT_IF },
{ "ForcePae", FORCE_PAE },
{ "PowerSaveDisable", POWER_SAVE_DISABLE },
{ "OweDisable", OWE_DISABLE },
{ "MulticastRxDisable", MULTICAST_RX_DISABLE },
{ "SaeDisable", SAE_DISABLE },
{ "ColocatedScanDisable", COLOCATED_SCAN_DISABLE },
{ "DefaultInterface", DEFAULT_IF },
{ "ForcePae", FORCE_PAE },
{ "PowerSaveDisable", POWER_SAVE_DISABLE },
{ "OweDisable", OWE_DISABLE },
{ "MulticastRxDisable", MULTICAST_RX_DISABLE }
};
struct wiphy {
@ -219,9 +202,6 @@ uint16_t wiphy_get_supported_ciphers(struct wiphy *wiphy, uint16_t mask)
static bool wiphy_can_connect_sae(struct wiphy *wiphy)
{
if (wiphy->driver_flags & SAE_DISABLE)
return false;
/*
* WPA3 Specification version 3, Section 2.2:
* A STA shall not enable WEP and TKIP
@ -978,11 +958,6 @@ bool wiphy_supports_multicast_rx(const struct wiphy *wiphy)
!(wiphy->driver_flags & MULTICAST_RX_DISABLE);
}
bool wiphy_supports_colocated_flag(const struct wiphy *wiphy)
{
return !(wiphy->driver_flags & COLOCATED_SCAN_DISABLE);
}
const uint8_t *wiphy_get_ht_capabilities(const struct wiphy *wiphy,
enum band_freq band,
size_t *size)
@ -1396,15 +1371,6 @@ static void wiphy_print_basic_info(struct wiphy *wiphy)
if (wiphy->driver_flags & OWE_DISABLE)
flags = l_strv_append(flags, "OweDisable");
if (wiphy->driver_flags & MULTICAST_RX_DISABLE)
flags = l_strv_append(flags, "MulticastRxDisable");
if (wiphy->driver_flags & SAE_DISABLE)
flags = l_strv_append(flags, "SaeDisable");
if (wiphy->driver_flags & COLOCATED_SCAN_DISABLE)
flags = l_strv_append(flags, "ColocatedScanDisable");
joined = l_strjoinv(flags, ' ');
l_info("\tDriver Flags: %s", joined);

View File

@ -144,7 +144,6 @@ bool wiphy_country_is_unknown(struct wiphy *wiphy);
bool wiphy_supports_uapsd(const struct wiphy *wiphy);
bool wiphy_supports_cmd_offchannel(const struct wiphy *wiphy);
bool wiphy_supports_multicast_rx(const struct wiphy *wiphy);
bool wiphy_supports_colocated_flag(const struct wiphy *wiphy);
const uint8_t *wiphy_get_ht_capabilities(const struct wiphy *wiphy,
enum band_freq band,

View File

@ -138,22 +138,20 @@ static const struct cmac_data example_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[])
{
l_test_init(&argc, &argv);
add_test("/cmac-aes/Example 1", cmac_test, &example_1);
add_test("/cmac-aes/Example 2", cmac_test, &example_2);
add_test("/cmac-aes/Example 3", cmac_test, &example_3);
add_test("/cmac-aes/Example 4", cmac_test, &example_4);
if (!l_checksum_cmac_aes_supported()) {
printf("AES-CMAC support missing, skipping...\n");
goto done;
}
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();
}

View File

@ -403,32 +403,40 @@ static void aes_siv_test(const void *data)
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[])
{
l_test_init(&argc, &argv);
add_test("/Passphrase Generator/PSK Test Case 1",
psk_test, &psk_test_case_1);
add_test("/Passphrase Generator/PSK Test Case 2",
psk_test, &psk_test_case_2);
add_test("/Passphrase Generator/PSK Test Case 3",
psk_test, &psk_test_case_3);
if (!l_checksum_is_supported(L_CHECKSUM_SHA1, true)) {
printf("SHA1 support missing, skipping...\n");
goto done;
}
add_test("/PTK Derivation/PTK Test Case 1", ptk_test, &ptk_test_1);
add_test("/PTK Derivation/PTK Test Case 2", ptk_test, &ptk_test_2);
add_test("/PTK Derivation/PTK Test Case 3", ptk_test, &ptk_test_3);
add_test("/PTK Derivation/PTK Test Case 4", ptk_test, &ptk_test_4);
if (!l_cipher_is_supported(L_CIPHER_AES)) {
printf("AES support missing, skipping...\n");
goto done;
}
add_test("/AES Key-wrap/Wrap & unwrap", aes_wrap_test, NULL);
add_test("/AES-SIV", aes_siv_test, NULL);
l_test_add("/Passphrase Generator/PSK Test Case 1",
psk_test, &psk_test_case_1);
l_test_add("/Passphrase Generator/PSK Test Case 2",
psk_test, &psk_test_case_2);
l_test_add("/Passphrase Generator/PSK Test Case 3",
psk_test, &psk_test_case_3);
l_test_add("/PTK Derivation/PTK Test Case 1",
ptk_test, &ptk_test_1);
l_test_add("/PTK Derivation/PTK Test Case 2",
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);
l_test_add("/AES Key-wrap/Wrap & unwrap",
aes_wrap_test, NULL);
l_test_add("/AES-SIV", aes_siv_test, NULL);
done:
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,
const struct dpp_test_info *result)
{
@ -181,14 +158,6 @@ static void test_bad_channels(const void *data)
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 {
/* Initiator values */
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);
}
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[])
{
l_test_init(&argc, &argv);
add_test("DPP test responder-only key derivation", test_key_derivation,
&responder_only_p256);
add_test("DPP test mutual key derivation", test_key_derivation,
&mutual_p256);
add_test("DPP test PKEX key derivation", test_pkex_key_derivation,
&pkex_vector);
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);
l_test_add("DPP test mutual key derivation",
test_key_derivation,
&mutual_p256);
l_test_add("DPP test PKEX key derivation",
test_pkex_key_derivation,
&pkex_vector);
}
l_test_add("DPP URI parse", test_uri_parse, &all_values);
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 channels", test_bad_channels, &bad_channels);
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();
}

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)));
}
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[])
{
l_test_init(&argc, &argv);
add_test("MSHAPv2 nt_password-hash", test_nt_password_hash);
add_test("MSHAPv2 generate_nt_response", test_generate_nt_response);
add_test("MSHAPv2 get_master_key", test_get_master_key);
add_test("MSHAPv2 get_asym_state_key", test_get_asym_key);
add_test("MSHAPv2 authenticator_response", test_authenticator_response);
if (!l_checksum_is_supported(L_CHECKSUM_MD4, false)) {
printf("MD4 support missing, skipping...\n");
goto done;
}
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();
}

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_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[])
{
l_test_init(&argc, &argv);
@ -4009,55 +3977,80 @@ int main(int argc, char *argv[])
l_test_add("/EAPoL Key/Key Frame 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);
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);
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);
add_aes_test("EAPoL/WPA2 4-Way Handshake",
eapol_4way_test, NULL);
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);
if (!l_cipher_is_supported(L_CIPHER_AES))
goto done;
add_pkcs8_test("EAPoL/8021x EAP-TLS & 4-Way Handshake",
eapol_sm_test_eap_tls, 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);
l_test_add("EAPoL/WPA2 4-Way Handshake",
&eapol_4way_test, NULL);
add_aes_test("EAPoL/FT-Using-PSK 4-Way Handshake",
eapol_ft_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/WPA2 4-Way & GTK Handshake",
&eapol_wpa2_handshake_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();
}

View File

@ -81,20 +81,18 @@ static const struct hmac_data test_case_2 = {
.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[])
{
l_test_init(&argc, &argv);
add_test("/hmac-md5/Test case 1", hmac_test, &test_case_1);
add_test("/hmac-md5/Test case 2", hmac_test, &test_case_2);
if (!l_checksum_is_supported(L_CHECKSUM_MD5, true)) {
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();
}

View File

@ -81,20 +81,18 @@ static const struct hmac_data test_case_2 = {
.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[])
{
l_test_init(&argc, &argv);
add_test("/hmac-sha1/Test case 1", hmac_test, &test_case_1);
add_test("/hmac-sha1/Test case 2", hmac_test, &test_case_2);
if (!l_checksum_is_supported(L_CHECKSUM_SHA1, true)) {
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();
}

View File

@ -83,20 +83,18 @@ static const struct hmac_data test_case_2 = {
"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[])
{
l_test_init(&argc, &argv);
add_test("/hmac-sha256/Test case 1", hmac_test, &test_case_1);
add_test("/hmac-sha256/Test case 2", hmac_test, &test_case_2);
if (!l_checksum_is_supported(L_CHECKSUM_SHA256, true)) {
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();
}

View File

@ -81,19 +81,17 @@ static const struct kdf_data test_case_1 = {
"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[])
{
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();
}

View File

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

View File

@ -113,21 +113,19 @@ static const struct prf_data test_case_3 = {
"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[])
{
l_test_init(&argc, &argv);
add_test("/prf-sha1/Test case 1", prf_test, &test_case_1);
add_test("/prf-sha1/Test case 2", prf_test, &test_case_2);
add_test("/prf-sha1/Test case 3", prf_test, &test_case_3);
if (!l_checksum_is_supported(L_CHECKSUM_SHA1, true)) {
printf("SHA1 support missing, skipping...\n");
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();
}

View File

@ -871,29 +871,32 @@ static void test_pt_pwe(const void *data)
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[])
{
l_test_init(&argc, &argv);
add_test("SAE anti-clogging", test_clogging);
add_test("SAE early confirm", test_early_confirm);
add_test("SAE reflection", test_reflection);
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_getrandom_is_supported()) {
l_info("l_getrandom not supported, skipping...");
goto done;
}
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();
}

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,
};
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[])
{
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 checksum", wsc_test_pin_checksum, NULL);
l_test_add_func_precheck("/wsc/pin/generate", wsc_test_pin_generate,
getrandom_precheck, 0);
if (l_getrandom_is_supported())
l_test_add("/wsc/pin/generate", wsc_test_pin_generate, NULL);
l_test_add("/wsc/gen_uuid/1", wsc_test_uuid_from_addr,
&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 2", wsc_test_build_m1, &m1_data_2);
add_dh_test("/wsc/parse/m2 1", wsc_test_parse_m2, &m2_data_1);
add_dh_test("/wsc/parse/m2 2", wsc_test_parse_m2, &m2_data_2);
if (!l_checksum_is_supported(L_CHECKSUM_SHA256, true)) {
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);
add_crypto_test("/wsc/build/m3 1", wsc_test_build_m3, &m3_data_1);
if (l_key_is_supported(L_KEY_FEATURE_DH)) {
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);
add_crypto_test("/wsc/build/m4 1", wsc_test_build_m4, &m4_data_1);
l_test_add("/wsc/build/m2 1", wsc_test_build_m2, &m2_data_1);
add_crypto_test("/wsc/parse/m4 encrypted settings 1",
wsc_test_parse_m4_encrypted_settings,
&m4_encrypted_settings_data_1);
add_crypto_test("/wsc/build/m4 encrypted settings 1",
wsc_test_build_m4_encrypted_settings,
&m4_encrypted_settings_data_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);
add_crypto_test("/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/parse/m4 1", wsc_test_parse_m4, &m4_data_1);
l_test_add("/wsc/build/m4 1", wsc_test_build_m4, &m4_data_1);
add_crypto_test("/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/parse/m4 encrypted settings 1",
wsc_test_parse_m4_encrypted_settings,
&m4_encrypted_settings_data_1);
l_test_add("/wsc/build/m4 encrypted settings 1",
wsc_test_build_m4_encrypted_settings,
&m4_encrypted_settings_data_1);
add_crypto_test("/wsc/parse/m6 encrypted settings 1",
wsc_test_parse_m6_encrypted_settings,
&m6_encrypted_settings_data_1);
add_crypto_test("/wsc/build/m6 encrypted settings 1",
wsc_test_build_m6_encrypted_settings,
&m6_encrypted_settings_data_1);
l_test_add("/wsc/parse/m5 1", wsc_test_parse_m5, &m5_data_1);
l_test_add("/wsc/build/m5 1", wsc_test_build_m5, &m5_data_1);
add_crypto_test("/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/parse/m6 1", wsc_test_parse_m6, &m6_data_1);
l_test_add("/wsc/build/m6 1", wsc_test_build_m6, &m6_data_1);
add_crypto_test("/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/parse/m6 encrypted settings 1",
wsc_test_parse_m6_encrypted_settings,
&m6_encrypted_settings_data_1);
l_test_add("/wsc/build/m6 encrypted settings 1",
wsc_test_build_m6_encrypted_settings,
&m6_encrypted_settings_data_1);
add_crypto_test("/wsc/parse/m8 encrypted settings 1",
wsc_test_parse_m8_encrypted_settings,
&m8_encrypted_settings_data_1);
add_crypto_test("/wsc/build/m8 encrypted settings 1",
wsc_test_build_m8_encrypted_settings,
&m8_encrypted_settings_data_1);
l_test_add("/wsc/parse/m7 1", wsc_test_parse_m7, &m7_data_1);
l_test_add("/wsc/build/m7 1", wsc_test_build_m7, &m7_data_1);
add_crypto_test("/wsc/parse/wsc_done 1", wsc_test_parse_wsc_done,
l_test_add("/wsc/parse/m8 1", wsc_test_parse_m8, &m8_data_1);
l_test_add("/wsc/build/m8 1", wsc_test_build_m8, &m8_data_1);
l_test_add("/wsc/parse/m8 encrypted settings 1",
wsc_test_parse_m8_encrypted_settings,
&m8_encrypted_settings_data_1);
l_test_add("/wsc/build/m8 encrypted settings 1",
wsc_test_build_m8_encrypted_settings,
&m8_encrypted_settings_data_1);
l_test_add("/wsc/parse/wsc_done 1", wsc_test_parse_wsc_done,
&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);
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,
&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,
&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);
add_aes_cbc_test("/wsc/retransmission/no fragmentation",
l_test_add("/wsc/retransmission/no fragmentation",
wsc_test_retransmission_no_fragmentation, NULL);
add_aes_cbc_test("/wsc-r/handshake/PBC Handshake WPA2 passphrase test",
wsc_r_test_pbc_handshake,
&wsc_r_test_wpa2_cred_passphrase);
add_aes_cbc_test("/wsc-r/handshake/PBC Handshake WPA2 PSK test",
wsc_r_test_pbc_handshake,
&wsc_r_test_wpa2_cred_psk);
add_aes_cbc_test("/wsc-r/handshake/PBC Handshake Open test",
wsc_r_test_pbc_handshake,
&wsc_r_test_open_cred);
l_test_add("/wsc-r/handshake/PBC Handshake WPA2 passphrase test",
wsc_r_test_pbc_handshake,
&wsc_r_test_wpa2_cred_passphrase);
l_test_add("/wsc-r/handshake/PBC Handshake WPA2 PSK test",
wsc_r_test_pbc_handshake,
&wsc_r_test_wpa2_cred_psk);
l_test_add("/wsc-r/handshake/PBC Handshake Open test",
wsc_r_test_pbc_handshake,
&wsc_r_test_open_cred);
done:
return l_test_run();
}