mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2025-12-21 10:38:16 +01:00
Compare commits
No commits in common. "master" and "2.7" have entirely different histories.
@ -1,3 +0,0 @@
|
|||||||
[codespell]
|
|
||||||
ignore-words-list = fils, FILS, SME, assertIn, OCE, clen, aci, ELL, sav, ths
|
|
||||||
skip = build-aux, linux, autom4te.cache, aclocal.m4, AUTHORS, libtool, configure*, *.5, ell
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -66,9 +66,6 @@ unit/test-p2p
|
|||||||
unit/test-band
|
unit/test-band
|
||||||
unit/test-dpp
|
unit/test-dpp
|
||||||
unit/test-json
|
unit/test-json
|
||||||
unit/test-nl80211util
|
|
||||||
unit/test-pmksa
|
|
||||||
unit/test-storage
|
|
||||||
unit/cert-*.pem
|
unit/cert-*.pem
|
||||||
unit/cert-*.csr
|
unit/cert-*.csr
|
||||||
unit/cert-*.srl
|
unit/cert-*.srl
|
||||||
|
|||||||
133
ChangeLog
133
ChangeLog
@ -1,136 +1,3 @@
|
|||||||
ver 3.10:
|
|
||||||
Fix issue with handling neighbor report on BSS TM request.
|
|
||||||
Fix issue with handling deauth and FT association failure.
|
|
||||||
Fix issue with handling roaming and old frequencies.
|
|
||||||
|
|
||||||
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.
|
|
||||||
Add support for HighUtilization/StationCount thresholds.
|
|
||||||
Add support for disabling Multicast RX option.
|
|
||||||
|
|
||||||
ver 3.1:
|
|
||||||
Fix issue with handling OWE transition BSS selection.
|
|
||||||
Fix issue with handling oper class 136 starting frequency.
|
|
||||||
|
|
||||||
ver 3.0:
|
|
||||||
Fix issue with handling alpha2 code for United Kingdom.
|
|
||||||
Fix issue with handling empty TX/RX bitrate attributes.
|
|
||||||
Fix issue with handling RSSI polling fallback workaround.
|
|
||||||
Fix issue with handling harmless cloned information elements.
|
|
||||||
Add experimental support for External Authentication feature.
|
|
||||||
|
|
||||||
ver 2.22:
|
|
||||||
Fix issue with handling the Affinities property.
|
|
||||||
Fix issue with handling ConnectedAccessPoint signal when roaming.
|
|
||||||
|
|
||||||
ver 2.21:
|
|
||||||
Fix issue with pending scan requests after regdom update.
|
|
||||||
Fix issue with handling the rearming of the roaming timeout.
|
|
||||||
Fix issue with survey request and externally triggered scans.
|
|
||||||
Fix issue with RSSI fallback when setting CQM threshold fails.
|
|
||||||
Fix issue with FT-over-Air without offchannel support.
|
|
||||||
Add support for per station Affinities property.
|
|
||||||
|
|
||||||
ver 2.20:
|
|
||||||
Fix issue with PKEX timeout and number of frequencies used.
|
|
||||||
Fix issue with handling logic for handshake failures.
|
|
||||||
Fix issue with handling ConnectedAccessPoint signal.
|
|
||||||
|
|
||||||
ver 2.19:
|
|
||||||
Fix issue with handling flush flag for external scans.
|
|
||||||
Fix issue with handling SNR calculation in ranking.
|
|
||||||
|
|
||||||
ver 2.18:
|
|
||||||
Fix issue with handling BSS with invalid HE capabilities.
|
|
||||||
Fix issue with neighbor reports with invalid country codes.
|
|
||||||
Fix issue with EAP-TTLS Start packets with L flag set.
|
|
||||||
Add support for enabling SAE for AP mode operation.
|
|
||||||
|
|
||||||
ver 2.17:
|
|
||||||
Fix issue with handling deauthenticate on disconnect.
|
|
||||||
Fix issue with handling of rate estimation errors.
|
|
||||||
Fix issue with handling EAPOL frame listeners.
|
|
||||||
|
|
||||||
ver 2.16:
|
|
||||||
Fix issue with uninitialized variable and DPP encrypt.
|
|
||||||
Fix issue with Access Point mode and ATTR_MAC validation.
|
|
||||||
Fix issue with Access Point mode and frequency attributes.
|
|
||||||
Fix issue with P2P and handling client info description.
|
|
||||||
Fix issue with P2P and handling parsing of service info.
|
|
||||||
Fix issue with netconfig and handling domain list.
|
|
||||||
Add support for forcing a default ECC group.
|
|
||||||
|
|
||||||
ver 2.15:
|
|
||||||
Fix issue with notice events for connection timeouts.
|
|
||||||
Fix issue with reason code and deauthenticate event.
|
|
||||||
Fix issue with handling basename() functionality.
|
|
||||||
|
|
||||||
ver 2.14:
|
|
||||||
Fix issue with accepting PTK 4/4 after receiving PTK 2/4.
|
|
||||||
Fix issue with frequency limit for quick scans.
|
|
||||||
Fix issue with limiting DHCPv4 attempts.
|
|
||||||
|
|
||||||
ver 2.13:
|
|
||||||
Fix issue with handling netconfig and roaming conditions.
|
|
||||||
Fix issue with logging requirement for CMD_EXTERNAL_AUTH.
|
|
||||||
Fix issue with using OpenSSL 3.2 installations.
|
|
||||||
|
|
||||||
ver 2.12:
|
|
||||||
Fix issue with DPP extra settings not being used.
|
|
||||||
Fix issue with DPP and PRF+ handling on AARCH64.
|
|
||||||
Add support for SAE password identifiers.
|
|
||||||
|
|
||||||
ver 2.11:
|
|
||||||
Fix issue with handling iovecs with multiple IEs.
|
|
||||||
Fix issue with handling SAE password identifiers.
|
|
||||||
Fix issue with handling agent release method call.
|
|
||||||
|
|
||||||
ver 2.10:
|
|
||||||
Fix issue with buffer overflow for 32 byte SSIDs.
|
|
||||||
Fix issue with deauthentication before FT work completes.
|
|
||||||
Fix issue with power save disabling procedure.
|
|
||||||
|
|
||||||
ver 2.9:
|
|
||||||
Fix issue with handling certain FT failures.
|
|
||||||
Fix issue with handling user-disabled bands.
|
|
||||||
Fix issue with handling roam on beacon loss event.
|
|
||||||
Add support for PKEX configurator.
|
|
||||||
Add support for PKEX enrollee.
|
|
||||||
|
|
||||||
ver 2.8:
|
|
||||||
Fix issue with handling OWE AKM in association reply.
|
|
||||||
|
|
||||||
ver 2.7:
|
ver 2.7:
|
||||||
Fix issue with handling FT-8021X and SHA256 PMKID derivation.
|
Fix issue with handling FT-8021X and SHA256 PMKID derivation.
|
||||||
|
|
||||||
|
|||||||
51
Makefile.am
51
Makefile.am
@ -63,17 +63,12 @@ ell_headers = ell/util.h \
|
|||||||
ell/dhcp6.h \
|
ell/dhcp6.h \
|
||||||
ell/acd.h \
|
ell/acd.h \
|
||||||
ell/cleanup.h \
|
ell/cleanup.h \
|
||||||
ell/netconfig.h \
|
ell/netconfig.h
|
||||||
ell/sysctl.h \
|
|
||||||
ell/notifylist.h \
|
|
||||||
ell/minheap.h
|
|
||||||
|
|
||||||
ell_sources = ell/private.h \
|
ell_sources = ell/private.h \
|
||||||
ell/missing.h \
|
ell/missing.h \
|
||||||
ell/util.c \
|
ell/util.c \
|
||||||
ell/test-private.h \
|
|
||||||
ell/test.c \
|
ell/test.c \
|
||||||
ell/test-dbus.c \
|
|
||||||
ell/strv.c \
|
ell/strv.c \
|
||||||
ell/utf8.c \
|
ell/utf8.c \
|
||||||
ell/queue.c \
|
ell/queue.c \
|
||||||
@ -148,10 +143,7 @@ ell_sources = ell/private.h \
|
|||||||
ell/dhcp6-lease.c \
|
ell/dhcp6-lease.c \
|
||||||
ell/dhcp6-transport.c \
|
ell/dhcp6-transport.c \
|
||||||
ell/acd.c \
|
ell/acd.c \
|
||||||
ell/netconfig.c \
|
ell/netconfig.c
|
||||||
ell/sysctl.c \
|
|
||||||
ell/notifylist.c \
|
|
||||||
ell/minheap.c
|
|
||||||
|
|
||||||
ell_shared = ell/useful.h ell/asn1-private.h
|
ell_shared = ell/useful.h ell/asn1-private.h
|
||||||
|
|
||||||
@ -218,8 +210,7 @@ eap_sources = src/eap.c src/eap.h src/eap-private.h \
|
|||||||
if DAEMON
|
if DAEMON
|
||||||
libexec_PROGRAMS += src/iwd
|
libexec_PROGRAMS += src/iwd
|
||||||
|
|
||||||
src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h \
|
src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h src/missing.h \
|
||||||
src/missing.h src/defs.h \
|
|
||||||
src/netdev.h src/netdev.c \
|
src/netdev.h src/netdev.c \
|
||||||
src/wiphy.h src/wiphy.c \
|
src/wiphy.h src/wiphy.c \
|
||||||
src/device.c \
|
src/device.c \
|
||||||
@ -272,10 +263,6 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h \
|
|||||||
src/dpp-util.h src/dpp-util.c \
|
src/dpp-util.h src/dpp-util.c \
|
||||||
src/json.h src/json.c \
|
src/json.h src/json.c \
|
||||||
src/dpp.c \
|
src/dpp.c \
|
||||||
src/udev.c \
|
|
||||||
src/pmksa.h src/pmksa.c \
|
|
||||||
src/vendor_quirks.h \
|
|
||||||
src/vendor_quirks.c \
|
|
||||||
$(eap_sources) \
|
$(eap_sources) \
|
||||||
$(builtin_sources)
|
$(builtin_sources)
|
||||||
|
|
||||||
@ -325,9 +312,7 @@ client_iwctl_SOURCES = client/main.c \
|
|||||||
client/wsc.c client/station.c \
|
client/wsc.c client/station.c \
|
||||||
client/diagnostic.c client/diagnostic.h \
|
client/diagnostic.c client/diagnostic.h \
|
||||||
client/daemon.c client/daemon.h \
|
client/daemon.c client/daemon.h \
|
||||||
client/dpp.c client/dpp-pkex.c \
|
client/dpp.c client/station-debug.c \
|
||||||
client/station-debug.c \
|
|
||||||
client/bss.c \
|
|
||||||
src/util.c src/util.h \
|
src/util.c src/util.h \
|
||||||
src/band.c src/band.h
|
src/band.c src/band.h
|
||||||
|
|
||||||
@ -419,7 +404,6 @@ tools_hwsim_SOURCES = tools/hwsim.c src/mpdu.h \
|
|||||||
src/storage.h src/storage.c \
|
src/storage.h src/storage.c \
|
||||||
src/common.h src/common.c \
|
src/common.h src/common.c \
|
||||||
src/band.h src/band.c \
|
src/band.h src/band.c \
|
||||||
src/ie.h src/ie.c \
|
|
||||||
src/crypto.h src/crypto.c
|
src/crypto.h src/crypto.c
|
||||||
tools_hwsim_LDADD = $(ell_ldadd)
|
tools_hwsim_LDADD = $(ell_ldadd)
|
||||||
|
|
||||||
@ -442,8 +426,7 @@ unit_tests += unit/test-cmac-aes \
|
|||||||
unit/test-ie unit/test-util unit/test-ssid-security \
|
unit/test-ie unit/test-util unit/test-ssid-security \
|
||||||
unit/test-arc4 unit/test-wsc unit/test-eap-mschapv2 \
|
unit/test-arc4 unit/test-wsc unit/test-eap-mschapv2 \
|
||||||
unit/test-eap-sim unit/test-sae unit/test-p2p unit/test-band \
|
unit/test-eap-sim unit/test-sae unit/test-p2p unit/test-band \
|
||||||
unit/test-dpp unit/test-json unit/test-nl80211util \
|
unit/test-dpp unit/test-json
|
||||||
unit/test-pmksa unit/test-storage
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if CLIENT
|
if CLIENT
|
||||||
@ -462,7 +445,6 @@ unit_test_eap_sim_SOURCES = unit/test-eap-sim.c \
|
|||||||
src/eapol.h src/eapol.c \
|
src/eapol.h src/eapol.c \
|
||||||
src/eapolutil.h src/eapolutil.c \
|
src/eapolutil.h src/eapolutil.c \
|
||||||
src/handshake.h src/handshake.c \
|
src/handshake.h src/handshake.c \
|
||||||
src/pmksa.h src/pmksa.c \
|
|
||||||
src/eap.h src/eap.c src/eap-private.h \
|
src/eap.h src/eap.c src/eap-private.h \
|
||||||
src/util.h src/util.c \
|
src/util.h src/util.c \
|
||||||
src/simauth.h src/simauth.c \
|
src/simauth.h src/simauth.c \
|
||||||
@ -522,7 +504,6 @@ unit_test_eapol_SOURCES = unit/test-eapol.c \
|
|||||||
src/eapol.h src/eapol.c \
|
src/eapol.h src/eapol.c \
|
||||||
src/eapolutil.h src/eapolutil.c \
|
src/eapolutil.h src/eapolutil.c \
|
||||||
src/handshake.h src/handshake.c \
|
src/handshake.h src/handshake.c \
|
||||||
src/pmksa.h src/pmksa.c \
|
|
||||||
src/eap.h src/eap.c src/eap-private.h \
|
src/eap.h src/eap.c src/eap-private.h \
|
||||||
src/eap-tls.c src/eap-ttls.c \
|
src/eap-tls.c src/eap-ttls.c \
|
||||||
src/eap-md5.c src/util.c \
|
src/eap-md5.c src/util.c \
|
||||||
@ -553,7 +534,6 @@ unit_test_wsc_SOURCES = unit/test-wsc.c src/wscutil.h src/wscutil.c \
|
|||||||
src/eapol.h src/eapol.c \
|
src/eapol.h src/eapol.c \
|
||||||
src/eapolutil.h src/eapolutil.c \
|
src/eapolutil.h src/eapolutil.c \
|
||||||
src/handshake.h src/handshake.c \
|
src/handshake.h src/handshake.c \
|
||||||
src/pmksa.h src/pmksa.c \
|
|
||||||
src/eap.h src/eap.c src/eap-private.h \
|
src/eap.h src/eap.c src/eap-private.h \
|
||||||
src/util.h src/util.c \
|
src/util.h src/util.c \
|
||||||
src/erp.h src/erp.c \
|
src/erp.h src/erp.c \
|
||||||
@ -572,7 +552,6 @@ unit_test_sae_SOURCES = unit/test-sae.c \
|
|||||||
src/crypto.h src/crypto.c \
|
src/crypto.h src/crypto.c \
|
||||||
src/ie.h src/ie.c \
|
src/ie.h src/ie.c \
|
||||||
src/handshake.h src/handshake.c \
|
src/handshake.h src/handshake.c \
|
||||||
src/pmksa.h src/pmksa.c \
|
|
||||||
src/erp.h src/erp.c \
|
src/erp.h src/erp.c \
|
||||||
src/band.h src/band.c \
|
src/band.h src/band.c \
|
||||||
src/util.h src/util.c \
|
src/util.h src/util.c \
|
||||||
@ -596,22 +575,6 @@ unit_test_dpp_LDADD = $(ell_ldadd)
|
|||||||
|
|
||||||
unit_test_json_SOURCES = unit/test-json.c src/json.h src/json.c shared/jsmn.h
|
unit_test_json_SOURCES = unit/test-json.c src/json.h src/json.c shared/jsmn.h
|
||||||
unit_test_json_LDADD = $(ell_ldadd)
|
unit_test_json_LDADD = $(ell_ldadd)
|
||||||
|
|
||||||
unit_test_nl80211util_SOURCES = unit/test-nl80211util.c \
|
|
||||||
src/nl80211util.h src/nl80211util.c \
|
|
||||||
src/band.h src/band.c \
|
|
||||||
src/ie.h src/ie.c \
|
|
||||||
src/util.h src/util.c
|
|
||||||
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
|
endif
|
||||||
|
|
||||||
if CLIENT
|
if CLIENT
|
||||||
@ -627,9 +590,6 @@ unit_test_client_SOURCES = unit/test-client.c \
|
|||||||
unit_test_client_LDADD = $(ell_ldadd) $(client_ldadd)
|
unit_test_client_LDADD = $(ell_ldadd) $(client_ldadd)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
|
|
||||||
$(top_srcdir)/build-aux/tap-driver.sh
|
|
||||||
|
|
||||||
TESTS = $(unit_tests)
|
TESTS = $(unit_tests)
|
||||||
|
|
||||||
EXTRA_DIST = src/genbuiltin src/iwd.service.in src/net.connman.iwd.service \
|
EXTRA_DIST = src/genbuiltin src/iwd.service.in src/net.connman.iwd.service \
|
||||||
@ -746,7 +706,6 @@ ell/internal: Makefile
|
|||||||
done > $@
|
done > $@
|
||||||
|
|
||||||
ell/ell.h: Makefile
|
ell/ell.h: Makefile
|
||||||
$(AM_V_at)$(MKDIR_P) ell
|
|
||||||
$(AM_V_at)echo -n > $@
|
$(AM_V_at)echo -n > $@
|
||||||
$(AM_V_GEN)for f in $(ell_headers) ; do \
|
$(AM_V_GEN)for f in $(ell_headers) ; do \
|
||||||
echo "#include <$$f>" >> $@ ; \
|
echo "#include <$$f>" >> $@ ; \
|
||||||
|
|||||||
6
TODO
6
TODO
@ -110,7 +110,7 @@ Wireless monitor
|
|||||||
|
|
||||||
- Subscribe to all nl80211 multicast groups at startup
|
- Subscribe to all nl80211 multicast groups at startup
|
||||||
|
|
||||||
It seems the nlmon packets are limited to actual subscribed multicast
|
It seems the nlmon packets are limited to actual subscribed mutlicast
|
||||||
groups. To get a complete picture of all the nl80211 commands and
|
groups. To get a complete picture of all the nl80211 commands and
|
||||||
events, it is required that iwmon adds membership to all multicast
|
events, it is required that iwmon adds membership to all multicast
|
||||||
groups that the nl80211 lists.
|
groups that the nl80211 lists.
|
||||||
@ -234,7 +234,7 @@ Wireless daemon
|
|||||||
|
|
||||||
- Implement Enrollee Session Overlap Detection after WSC Protocol Run
|
- Implement Enrollee Session Overlap Detection after WSC Protocol Run
|
||||||
|
|
||||||
WSC Best Practices v2.0.1, Section 3.15 describes an enhancement to detect
|
WSC Best Practices v2.0.1, Section 3.15 describes an enhacement to detect
|
||||||
PBC session overlaps. The Enrollee is asked to perform an extra scan without
|
PBC session overlaps. The Enrollee is asked to perform an extra scan without
|
||||||
the PBC request in the ProbeRequest frames after EAP-WSC completes
|
the PBC request in the ProbeRequest frames after EAP-WSC completes
|
||||||
successfully. If another AP in PBC mode is found, then a SessionOverlap
|
successfully. If another AP in PBC mode is found, then a SessionOverlap
|
||||||
@ -286,7 +286,7 @@ Wireless daemon
|
|||||||
- Support OCE mutually non-overlapping channels optimization.
|
- Support OCE mutually non-overlapping channels optimization.
|
||||||
|
|
||||||
OCE Section 3.10 mandates that the STA should scan channels 1, 6 and 11 in
|
OCE Section 3.10 mandates that the STA should scan channels 1, 6 and 11 in
|
||||||
the 2.4GHz band first, unless it expects to find an AP on a different
|
the 2.4Ghz band first, unless it expects to find an AP on a different
|
||||||
channel.
|
channel.
|
||||||
|
|
||||||
Priority: Low
|
Priority: Low
|
||||||
|
|||||||
@ -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)
|
|
||||||
@ -11,58 +11,52 @@ from iwd import NetworkType
|
|||||||
from hostapd import HostapdCLI
|
from hostapd import HostapdCLI
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
def initial_connection(self):
|
|
||||||
ordered_network = self.device.get_ordered_network('TestAPRoam')
|
def validate(self, expect_roam=True):
|
||||||
|
wd = IWD()
|
||||||
|
|
||||||
|
devices = wd.list_devices(1)
|
||||||
|
device = devices[0]
|
||||||
|
|
||||||
|
ordered_network = device.get_ordered_network('TestAPRoam')
|
||||||
|
|
||||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
self.assertEqual(ordered_network.type, NetworkType.psk)
|
||||||
|
|
||||||
condition = 'not obj.connected'
|
condition = 'not obj.connected'
|
||||||
self.wd.wait_for_object_condition(ordered_network.network_object, condition)
|
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
||||||
|
|
||||||
self.device.connect_bssid(self.bss_hostapd[0].bssid)
|
device.connect_bssid(self.bss_hostapd[0].bssid)
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
condition = 'obj.state == DeviceState.connected'
|
||||||
self.wd.wait_for_object_condition(self.device, condition)
|
wd.wait_for_object_condition(device, condition)
|
||||||
|
|
||||||
self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED')
|
self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED')
|
||||||
|
|
||||||
self.assertFalse(self.bss_hostapd[1].list_sta())
|
self.assertFalse(self.bss_hostapd[1].list_sta())
|
||||||
|
|
||||||
def validate_roam(self, from_bss, to_bss, expect_roam=True):
|
self.bss_hostapd[0].send_bss_transition(device.address,
|
||||||
from_bss.send_bss_transition(self.device.address,
|
[(self.bss_hostapd[1].bssid, '8f0000005102060603000000')],
|
||||||
self.neighbor_list,
|
|
||||||
disassoc_imminent=expect_roam)
|
disassoc_imminent=expect_roam)
|
||||||
|
|
||||||
if expect_roam:
|
if expect_roam:
|
||||||
from_condition = 'obj.state == DeviceState.roaming'
|
from_condition = 'obj.state == DeviceState.roaming'
|
||||||
to_condition = 'obj.state == DeviceState.connected'
|
to_condition = 'obj.state == DeviceState.connected'
|
||||||
self.wd.wait_for_object_change(self.device, from_condition, to_condition)
|
wd.wait_for_object_change(device, from_condition, to_condition)
|
||||||
|
|
||||||
to_bss.wait_for_event('AP-STA-CONNECTED %s' % self.device.address)
|
self.bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % device.address)
|
||||||
else:
|
else:
|
||||||
self.device.wait_for_event("no-roam-candidates")
|
device.wait_for_event("no-roam-candidates")
|
||||||
|
|
||||||
|
device.disconnect()
|
||||||
|
|
||||||
|
condition = 'not obj.connected'
|
||||||
|
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
||||||
|
|
||||||
def test_disassoc_imminent(self):
|
def test_disassoc_imminent(self):
|
||||||
self.initial_connection()
|
self.validate(expect_roam=True)
|
||||||
self.validate_roam(self.bss_hostapd[0], self.bss_hostapd[1])
|
|
||||||
|
|
||||||
def test_no_candidates(self):
|
def test_no_candidates(self):
|
||||||
self.initial_connection()
|
self.validate(expect_roam=False)
|
||||||
# We now have BSS0 roam blacklisted
|
|
||||||
self.validate_roam(self.bss_hostapd[0], self.bss_hostapd[1])
|
|
||||||
# Try and trigger another roam back, which shouldn't happen since now
|
|
||||||
# both BSS's are roam blacklisted
|
|
||||||
self.validate_roam(self.bss_hostapd[1], self.bss_hostapd[0], expect_roam=False)
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.wd = IWD(True)
|
|
||||||
|
|
||||||
devices = self.wd.list_devices(1)
|
|
||||||
self.device = devices[0]
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.wd = None
|
|
||||||
self.device = None
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
@ -71,10 +65,6 @@ class Test(unittest.TestCase):
|
|||||||
cls.bss_hostapd = [ HostapdCLI(config='ssid1.conf'),
|
cls.bss_hostapd = [ HostapdCLI(config='ssid1.conf'),
|
||||||
HostapdCLI(config='ssid2.conf'),
|
HostapdCLI(config='ssid2.conf'),
|
||||||
HostapdCLI(config='ssid3.conf') ]
|
HostapdCLI(config='ssid3.conf') ]
|
||||||
cls.neighbor_list = [
|
|
||||||
(cls.bss_hostapd[0].bssid, "8f0000005101060603000000"),
|
|
||||||
(cls.bss_hostapd[1].bssid, "8f0000005102060603000000"),
|
|
||||||
]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
[SETUP]
|
[SETUP]
|
||||||
num_radios=4
|
num_radios=4
|
||||||
hwsim_medium=true
|
|
||||||
start_iwd=false
|
|
||||||
|
|
||||||
[HOSTAPD]
|
[HOSTAPD]
|
||||||
rad0=ssid1.conf
|
rad0=ssid1.conf
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
[General]
|
|
||||||
RoamThreshold=-72
|
|
||||||
CriticalRoamThreshold=-72
|
|
||||||
|
|
||||||
[Blacklist]
|
|
||||||
InitialAccessPointBusyTimeout=20
|
|
||||||
@ -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)
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
[Security]
|
|
||||||
Passphrase=EasilyGuessedPassword
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
hw_mode=g
|
|
||||||
channel=1
|
|
||||||
ssid=TestFT
|
|
||||||
utf8_ssid=1
|
|
||||||
ctrl_interface=/var/run/hostapd
|
|
||||||
|
|
||||||
r1_key_holder=120000000001
|
|
||||||
nas_identifier=dummy1
|
|
||||||
|
|
||||||
wpa=2
|
|
||||||
# Can support WPA-PSK and FT-PSK (space separated list) and/or EAP at the same
|
|
||||||
# time but we want to force FT
|
|
||||||
wpa_key_mgmt=FT-PSK
|
|
||||||
wpa_pairwise=CCMP
|
|
||||||
wpa_passphrase=EasilyGuessedPassword
|
|
||||||
ieee80211w=0
|
|
||||||
rsn_preauth=1
|
|
||||||
rsn_preauth_interfaces=lo
|
|
||||||
disable_pmksa_caching=0
|
|
||||||
# Allow PMK cache to be shared opportunistically among configured interfaces
|
|
||||||
# and BSSes (i.e., all configurations within a single hostapd process).
|
|
||||||
okc=1
|
|
||||||
mobility_domain=1234
|
|
||||||
reassociation_deadline=60000
|
|
||||||
r0kh=12:00:00:00:00:01 dummy1 000102030405060708090a0b0c0d0e0f
|
|
||||||
r0kh=12:00:00:00:00:02 dummy2 000102030405060708090a0b0c0d0e0f
|
|
||||||
r1kh=12:00:00:00:00:01 00:00:00:00:00:01 000102030405060708090a0b0c0d0e0f
|
|
||||||
r1kh=12:00:00:00:00:02 00:00:00:00:00:02 000102030405060708090a0b0c0d0e0f
|
|
||||||
# Push mode only needed for 8021x, not PSK mode since msk already known
|
|
||||||
pmk_r1_push=0
|
|
||||||
# Allow locally generated FT response so we don't have to configure push/pull
|
|
||||||
# between BSSes running as separate hostapd processes as in the test-runner
|
|
||||||
# case. Only works with FT-PSK, otherwise brctl needs to be installed and
|
|
||||||
# CONFIG_BRIDGE enabled in the kernel.
|
|
||||||
ft_psk_generate_local=1
|
|
||||||
rkh_pull_timeout=50
|
|
||||||
ft_over_ds=0
|
|
||||||
ap_table_expiration_time=36000
|
|
||||||
ap_table_max_size=10
|
|
||||||
rrm_neighbor_report=1
|
|
||||||
ocv=1
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
hw_mode=g
|
|
||||||
channel=2
|
|
||||||
ssid=TestFT
|
|
||||||
utf8_ssid=1
|
|
||||||
ctrl_interface=/var/run/hostapd
|
|
||||||
|
|
||||||
r1_key_holder=120000000002
|
|
||||||
nas_identifier=dummy2
|
|
||||||
|
|
||||||
wpa=2
|
|
||||||
# Can support WPA-PSK and FT-PSK (space separated list) and/or EAP at the same
|
|
||||||
# time but we want to force FT
|
|
||||||
wpa_key_mgmt=FT-PSK
|
|
||||||
wpa_pairwise=CCMP
|
|
||||||
wpa_passphrase=EasilyGuessedPassword
|
|
||||||
ieee80211w=0
|
|
||||||
rsn_preauth=1
|
|
||||||
rsn_preauth_interfaces=lo
|
|
||||||
disable_pmksa_caching=0
|
|
||||||
# Allow PMK cache to be shared opportunistically among configured interfaces
|
|
||||||
# and BSSes (i.e., all configurations within a single hostapd process).
|
|
||||||
okc=1
|
|
||||||
mobility_domain=1234
|
|
||||||
reassociation_deadline=60000
|
|
||||||
r0kh=12:00:00:00:00:01 dummy1 000102030405060708090a0b0c0d0e0f
|
|
||||||
r0kh=12:00:00:00:00:02 dummy2 000102030405060708090a0b0c0d0e0f
|
|
||||||
r1kh=12:00:00:00:00:01 00:00:00:00:00:01 000102030405060708090a0b0c0d0e0f
|
|
||||||
r1kh=12:00:00:00:00:02 00:00:00:00:00:02 000102030405060708090a0b0c0d0e0f
|
|
||||||
# Push mode only needed for 8021x, not PSK mode since msk already known
|
|
||||||
pmk_r1_push=0
|
|
||||||
# Allow locally generated FT response so we don't have to configure push/pull
|
|
||||||
# between BSSes running as separate hostapd processes as in the test-runner
|
|
||||||
# case. Only works with FT-PSK, otherwise brctl needs to be installed and
|
|
||||||
# CONFIG_BRIDGE enabled in the kernel.
|
|
||||||
ft_psk_generate_local=1
|
|
||||||
rkh_pull_timeout=50
|
|
||||||
ft_over_ds=0
|
|
||||||
ap_table_expiration_time=36000
|
|
||||||
ap_table_max_size=10
|
|
||||||
rrm_neighbor_report=1
|
|
||||||
ocv=1
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
[SETUP]
|
|
||||||
num_radios=3
|
|
||||||
start_iwd=0
|
|
||||||
hwsim_medium=yes
|
|
||||||
|
|
||||||
[HOSTAPD]
|
|
||||||
rad0=ft-psk-ccmp-1.conf
|
|
||||||
rad1=ft-psk-ccmp-2.conf
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
[Scan]
|
|
||||||
DisableMacAddressRandomization=true
|
|
||||||
|
|
||||||
[General]
|
|
||||||
RoamRetryInterval=1
|
|
||||||
@ -1,216 +0,0 @@
|
|||||||
#! /usr/bin/python3
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import sys, os
|
|
||||||
import dbus
|
|
||||||
|
|
||||||
sys.path.append('../util')
|
|
||||||
from config import ctx
|
|
||||||
import iwd
|
|
||||||
from iwd import IWD, IWDDBusAbstract
|
|
||||||
from iwd import NetworkType
|
|
||||||
from hwsim import Hwsim
|
|
||||||
from hostapd import HostapdCLI
|
|
||||||
|
|
||||||
#
|
|
||||||
# Separate client used to test DBus disconnects so we don't bring down the
|
|
||||||
# entire IWD python library
|
|
||||||
#
|
|
||||||
class AffinityClient(IWDDBusAbstract):
|
|
||||||
def __init__(self, device_path):
|
|
||||||
self._bus = dbus.bus.BusConnection(address_or_type=ctx.dbus_address)
|
|
||||||
self._station_prop_if = dbus.Interface(
|
|
||||||
self._bus.get_object(iwd.IWD_SERVICE, device_path),
|
|
||||||
iwd.DBUS_PROPERTIES)
|
|
||||||
|
|
||||||
def set(self, values):
|
|
||||||
self._station_prop_if.Set(iwd.IWD_STATION_INTERFACE, 'Affinities', dbus.Array([dbus.ObjectPath(v) for v in values], signature="o"))
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
self._bus.close()
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
|
||||||
def connect(self, device, hapd):
|
|
||||||
ordered_network = device.get_ordered_network('TestFT', full_scan=True)
|
|
||||||
|
|
||||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
|
||||||
|
|
||||||
condition = 'not obj.connected'
|
|
||||||
self.wd.wait_for_object_condition(ordered_network.network_object, condition)
|
|
||||||
|
|
||||||
device.connect_bssid(hapd.bssid)
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
self.wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
def test_set_affinity(self):
|
|
||||||
device = self.wd.list_devices(1)[0]
|
|
||||||
|
|
||||||
self.connect(device, self.bss_hostapd[0])
|
|
||||||
|
|
||||||
print(device.connected_bss)
|
|
||||||
|
|
||||||
device.affinities = [device.connected_bss]
|
|
||||||
|
|
||||||
# IWD should not attempt to roam
|
|
||||||
with self.assertRaises(TimeoutError):
|
|
||||||
device.wait_for_event("roam-scan-triggered")
|
|
||||||
|
|
||||||
device.affinities = []
|
|
||||||
device.wait_for_event("roam-scan-triggered")
|
|
||||||
|
|
||||||
def test_roam_below_critical(self):
|
|
||||||
device = self.wd.list_devices(1)[0]
|
|
||||||
|
|
||||||
self.connect(device, self.bss_hostapd[0])
|
|
||||||
|
|
||||||
device.affinities = [device.connected_bss]
|
|
||||||
|
|
||||||
# IWD should not attempt to roam
|
|
||||||
with self.assertRaises(TimeoutError):
|
|
||||||
device.wait_for_event("roam-scan-triggered")
|
|
||||||
|
|
||||||
# Lower signal past critical level
|
|
||||||
self.bss0_rule.signal = -9000
|
|
||||||
|
|
||||||
device.wait_for_event("roam-scan-triggered")
|
|
||||||
|
|
||||||
def test_error_conditions(self):
|
|
||||||
device = self.wd.list_devices(1)[0]
|
|
||||||
|
|
||||||
# Calling set while disconnected should fail
|
|
||||||
with self.assertRaises(iwd.NotConnectedEx):
|
|
||||||
device.affinities = ["/some/path"]
|
|
||||||
|
|
||||||
self.connect(device, self.bss_hostapd[0])
|
|
||||||
|
|
||||||
device.affinities = [device.connected_bss]
|
|
||||||
|
|
||||||
# An invalid path should fail
|
|
||||||
with self.assertRaises(iwd.InvalidArgumentsEx):
|
|
||||||
device.affinities = [device.connected_bss, "/an/invalid/path"]
|
|
||||||
|
|
||||||
def test_affinity_client_disconnect(self):
|
|
||||||
device = self.wd.list_devices(1)[0]
|
|
||||||
|
|
||||||
client = AffinityClient(device.device_path)
|
|
||||||
|
|
||||||
self.connect(device, self.bss_hostapd[0])
|
|
||||||
|
|
||||||
client.set([device.connected_bss])
|
|
||||||
|
|
||||||
with self.assertRaises(TimeoutError):
|
|
||||||
device.wait_for_event("roam-scan-triggered")
|
|
||||||
|
|
||||||
client._bus.close()
|
|
||||||
|
|
||||||
device.wait_for_event("roam-scan-triggered")
|
|
||||||
|
|
||||||
def test_affinity_client_reconnect_during_roam(self):
|
|
||||||
device = self.wd.list_devices(1)[0]
|
|
||||||
|
|
||||||
client = AffinityClient(device.device_path)
|
|
||||||
|
|
||||||
self.connect(device, self.bss_hostapd[0])
|
|
||||||
|
|
||||||
client.set([device.connected_bss])
|
|
||||||
|
|
||||||
# Lower signal past critical level
|
|
||||||
self.bss0_rule.signal = -9000
|
|
||||||
|
|
||||||
device.wait_for_event("roam-scan-triggered")
|
|
||||||
|
|
||||||
client.close()
|
|
||||||
del client
|
|
||||||
client = AffinityClient(device.device_path)
|
|
||||||
# setting here should get cleared after connecting
|
|
||||||
client.set([device.connected_bss])
|
|
||||||
|
|
||||||
device.wait_for_event("ft-authenticating")
|
|
||||||
device.wait_for_event("associating")
|
|
||||||
device.wait_for_event("connected")
|
|
||||||
|
|
||||||
# Affinity should be reset, and IWD should be trying to roam
|
|
||||||
device.wait_for_event("roam-scan-triggered")
|
|
||||||
|
|
||||||
def test_cleanup_with_connected_client(self):
|
|
||||||
device = self.wd.list_devices(1)[0]
|
|
||||||
|
|
||||||
client = AffinityClient(device.device_path)
|
|
||||||
|
|
||||||
self.connect(device, self.bss_hostapd[0])
|
|
||||||
|
|
||||||
client.set([device.connected_bss])
|
|
||||||
self.wd.stop()
|
|
||||||
|
|
||||||
def test_affinity_removed_after_roam(self):
|
|
||||||
device = self.wd.list_devices(1)[0]
|
|
||||||
|
|
||||||
self.connect(device, self.bss_hostapd[0])
|
|
||||||
|
|
||||||
device.affinities = [device.connected_bss]
|
|
||||||
|
|
||||||
# Lower signal past critical level
|
|
||||||
self.bss0_rule.signal = -9000
|
|
||||||
|
|
||||||
device.wait_for_event("roam-scan-triggered")
|
|
||||||
|
|
||||||
device.wait_for_event("ft-authenticating")
|
|
||||||
device.wait_for_event("associating")
|
|
||||||
device.wait_for_event("connected")
|
|
||||||
|
|
||||||
self.assertEqual(device.affinities, [])
|
|
||||||
|
|
||||||
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')
|
|
||||||
|
|
||||||
self.wd.stop()
|
|
||||||
self.wd = None
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.bss0_rule.signal = -8000
|
|
||||||
self.bss1_rule.signal = -8000
|
|
||||||
|
|
||||||
self.wd = IWD(True)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
hwsim = Hwsim()
|
|
||||||
|
|
||||||
IWD.copy_to_storage('TestFT.psk')
|
|
||||||
|
|
||||||
cls.bss_hostapd = [ HostapdCLI(config='ft-psk-ccmp-1.conf'),
|
|
||||||
HostapdCLI(config='ft-psk-ccmp-2.conf') ]
|
|
||||||
|
|
||||||
rad0 = hwsim.get_radio('rad0')
|
|
||||||
rad1 = hwsim.get_radio('rad1')
|
|
||||||
|
|
||||||
cls.bss0_rule = hwsim.rules.create()
|
|
||||||
cls.bss0_rule.source = rad0.addresses[0]
|
|
||||||
cls.bss0_rule.bidirectional = True
|
|
||||||
cls.bss0_rule.signal = -8000
|
|
||||||
cls.bss0_rule.enabled = True
|
|
||||||
|
|
||||||
cls.bss1_rule = hwsim.rules.create()
|
|
||||||
cls.bss1_rule.source = rad1.addresses[0]
|
|
||||||
cls.bss1_rule.bidirectional = True
|
|
||||||
cls.bss1_rule.signal = -8000
|
|
||||||
cls.bss1_rule.enabled = True
|
|
||||||
|
|
||||||
cls.bss_hostapd[0].set_address('12:00:00:00:00:01')
|
|
||||||
cls.bss_hostapd[1].set_address('12:00:00:00:00:02')
|
|
||||||
|
|
||||||
HostapdCLI.group_neighbors(*cls.bss_hostapd)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
IWD.clear_storage()
|
|
||||||
cls.bss_hostapd = None
|
|
||||||
cls.bss0_rule.remove()
|
|
||||||
cls.bss1_rule.remove()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main(exit=True)
|
|
||||||
@ -260,69 +260,12 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
self.wd.unregister_psk_agent(psk_agent)
|
self.wd.unregister_psk_agent(psk_agent)
|
||||||
|
|
||||||
def test_blacklist_disabled(self):
|
|
||||||
wd = self.wd
|
|
||||||
bss_hostapd = self.bss_hostapd
|
|
||||||
|
|
||||||
rule0 = self.rule0
|
|
||||||
rule1 = self.rule1
|
|
||||||
rule2 = self.rule2
|
|
||||||
|
|
||||||
psk_agent = PSKAgent(["secret123", 'secret123'])
|
|
||||||
wd.register_psk_agent(psk_agent)
|
|
||||||
|
|
||||||
devices = wd.list_devices(1)
|
|
||||||
device = devices[0]
|
|
||||||
|
|
||||||
rule0.drop = True
|
|
||||||
rule0.enabled = True
|
|
||||||
|
|
||||||
device.autoconnect = True
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
ordered_network = device.get_ordered_network("TestBlacklist", full_scan=True)
|
|
||||||
|
|
||||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
|
||||||
|
|
||||||
# The first BSS should fail, and we should connect to the second. This
|
|
||||||
# should not result in a connection blacklist though since its disabled.
|
|
||||||
bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % device.address)
|
|
||||||
|
|
||||||
device.disconnect()
|
|
||||||
|
|
||||||
rule0.drop = False
|
|
||||||
device.autoconnect = True
|
|
||||||
|
|
||||||
# Verify the first BSS wasn't blacklisted.
|
|
||||||
bss_hostapd[0].wait_for_event('AP-STA-CONNECTED %s' % device.address)
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
_, _, name = self.id().split(".")
|
|
||||||
|
|
||||||
# TODO: If we have this pattern elsewhere it might be nice to turn this
|
|
||||||
# into a decorator e.g.
|
|
||||||
#
|
|
||||||
# @config("main.conf.disabled")
|
|
||||||
# @profile("TestBlacklist.psk")
|
|
||||||
# def test_blacklist_disabled(self)
|
|
||||||
# ...
|
|
||||||
#
|
|
||||||
if name == "test_blacklist_disabled":
|
|
||||||
IWD.copy_to_storage("main.conf.disabled", IWD_CONFIG_DIR, "main.conf")
|
|
||||||
IWD.copy_to_storage("TestBlacklist.psk")
|
|
||||||
else:
|
|
||||||
IWD.copy_to_storage("main.conf.default", IWD_CONFIG_DIR, "main.conf")
|
|
||||||
|
|
||||||
self.wd = IWD(True)
|
self.wd = IWD(True)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
IWD.clear_storage()
|
IWD.clear_storage()
|
||||||
self.wd = None
|
self.wd = None
|
||||||
self.rule0.drop = False
|
|
||||||
self.rule1.drop = False
|
|
||||||
self.rule2.drop = False
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
[Blacklist]
|
|
||||||
InitialTimeout=0
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
#! /usr/bin/python3
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import sys, os
|
|
||||||
|
|
||||||
sys.path.append('../util')
|
|
||||||
import iwd
|
|
||||||
from iwd import IWD
|
|
||||||
from iwd import PSKAgent
|
|
||||||
from iwd import NetworkType
|
|
||||||
from hwsim import Hwsim
|
|
||||||
from hostapd import HostapdCLI
|
|
||||||
import testutil
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
|
||||||
def test_bss_unregister(self):
|
|
||||||
device = self.wd.list_devices(1)[0]
|
|
||||||
|
|
||||||
ordered_network = device.get_ordered_network('ssidTKIP', full_scan=True)
|
|
||||||
network = ordered_network.network_object
|
|
||||||
|
|
||||||
self.assertEqual(len(network.extended_service_set), 2)
|
|
||||||
|
|
||||||
ends = [parts.split('/')[-1] for parts in network.extended_service_set]
|
|
||||||
|
|
||||||
self.assertIn(self.bss_hostapd[0].bssid.replace(':', ''), ends)
|
|
||||||
self.assertIn(self.bss_hostapd[1].bssid.replace(':', ''), ends)
|
|
||||||
|
|
||||||
self.rule_bss1.enabled = True
|
|
||||||
|
|
||||||
# Even with flushing, the kernel still seems to return the scan
|
|
||||||
# results
|
|
||||||
self.wd.wait(40)
|
|
||||||
ordered_network = device.get_ordered_network('ssidTKIP', full_scan=True)
|
|
||||||
network = ordered_network.network_object
|
|
||||||
|
|
||||||
ends = [parts.split('/')[-1] for parts in network.extended_service_set]
|
|
||||||
|
|
||||||
self.assertIn(self.bss_hostapd[0].bssid.replace(':', ''), ends)
|
|
||||||
self.assertNotIn(self.bss_hostapd[1].bssid.replace(':', ''), ends)
|
|
||||||
|
|
||||||
self.rule_bss0.enabled = True
|
|
||||||
|
|
||||||
self.wd.wait(40)
|
|
||||||
ordered_networks = device.get_ordered_networks('ssidTKIP', full_scan=True)
|
|
||||||
self.assertIsNone(ordered_networks)
|
|
||||||
|
|
||||||
self.rule_bss0.enabled = False
|
|
||||||
|
|
||||||
ordered_networks = device.get_ordered_networks('ssidTKIP', full_scan=True)
|
|
||||||
ends = [parts.split('/')[-1] for parts in network.extended_service_set]
|
|
||||||
|
|
||||||
self.assertIn(self.bss_hostapd[0].bssid.replace(':', ''), ends)
|
|
||||||
self.assertNotIn(self.bss_hostapd[1].bssid.replace(':', ''), ends)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.rule_bss0.enabled = False
|
|
||||||
self.rule_bss1.enabled = False
|
|
||||||
|
|
||||||
self.wd.stop()
|
|
||||||
self.wd.wait(10)
|
|
||||||
self.wd = None
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.wd = IWD(True)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
hwsim = Hwsim()
|
|
||||||
|
|
||||||
IWD.copy_to_storage('ssidTKIP.psk')
|
|
||||||
|
|
||||||
cls.bss_hostapd = [ HostapdCLI(config='ssidTKIP-1.conf'),
|
|
||||||
HostapdCLI(config='ssidTKIP-2.conf') ]
|
|
||||||
|
|
||||||
|
|
||||||
rad0 = hwsim.get_radio('rad0')
|
|
||||||
rad1 = hwsim.get_radio('rad1')
|
|
||||||
|
|
||||||
cls.rule_bss0 = hwsim.rules.create()
|
|
||||||
cls.rule_bss0.source = rad0.addresses[0]
|
|
||||||
cls.rule_bss0.bidirectional = True
|
|
||||||
cls.rule_bss0.drop = True
|
|
||||||
|
|
||||||
cls.rule_bss1 = hwsim.rules.create()
|
|
||||||
cls.rule_bss1.source = rad1.addresses[0]
|
|
||||||
cls.rule_bss1.bidirectional = True
|
|
||||||
cls.rule_bss1.drop = True
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
IWD.clear_storage()
|
|
||||||
cls.bss_hostapd = None
|
|
||||||
cls.rule_bss0.remove()
|
|
||||||
cls.rule_bss1.remove()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main(exit=True)
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
[SETUP]
|
|
||||||
num_radios=3
|
|
||||||
hwsim_medium=yes
|
|
||||||
start_iwd=no
|
|
||||||
|
|
||||||
[HOSTAPD]
|
|
||||||
rad0=ssidTKIP-1.conf
|
|
||||||
rad1=ssidTKIP-2.conf
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
hw_mode=g
|
|
||||||
channel=1
|
|
||||||
ssid=ssidTKIP
|
|
||||||
|
|
||||||
wpa=1
|
|
||||||
wpa_pairwise=TKIP
|
|
||||||
wpa_passphrase=secret123
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
hw_mode=g
|
|
||||||
channel=2
|
|
||||||
ssid=ssidTKIP
|
|
||||||
|
|
||||||
wpa=1
|
|
||||||
wpa_pairwise=TKIP
|
|
||||||
wpa_passphrase=secret123
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
[Security]
|
|
||||||
Passphrase=secret123
|
|
||||||
|
|
||||||
[Settings]
|
|
||||||
AutoConnect=False
|
|
||||||
@ -11,7 +11,7 @@ from iwd import IWD
|
|||||||
|
|
||||||
class Test8021xNetwork(unittest.TestCase):
|
class Test8021xNetwork(unittest.TestCase):
|
||||||
'''
|
'''
|
||||||
The below test cases excesise the following connection scenarios:
|
The bellow test cases excesise the following connection scenarios:
|
||||||
|
|
||||||
Network config is
|
Network config is
|
||||||
present at start time: Connect: AutoConnect: Result:
|
present at start time: Connect: AutoConnect: Result:
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from iwd import IWD
|
|||||||
|
|
||||||
class TestOpenNetwork(unittest.TestCase):
|
class TestOpenNetwork(unittest.TestCase):
|
||||||
'''
|
'''
|
||||||
The below test cases excesise the following connection scenarios:
|
The bellow test cases excesise the following connection scenarios:
|
||||||
|
|
||||||
Network config is
|
Network config is
|
||||||
present at start time: Connect: AutoConnect: Result:
|
present at start time: Connect: AutoConnect: Result:
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from iwd import IWD
|
|||||||
|
|
||||||
class TestWpaNetwork(unittest.TestCase):
|
class TestWpaNetwork(unittest.TestCase):
|
||||||
'''
|
'''
|
||||||
The below test cases exercise the following connection scenarios:
|
The bellow test cases exercise the following connection scenarios:
|
||||||
|
|
||||||
Network config is
|
Network config is
|
||||||
present at start time: Connect: AutoConnect: Result:
|
present at start time: Connect: AutoConnect: Result:
|
||||||
|
|||||||
@ -38,18 +38,20 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
def test_iwd_as_enrollee_scan_after(self):
|
def test_iwd_as_enrollee_scan_after(self):
|
||||||
self.wpas.disconnect()
|
self.wpas.disconnect()
|
||||||
self.device.autoconnect = True
|
|
||||||
uri = self.device.dpp_start_enrollee()
|
uri = self.device.dpp_start_enrollee()
|
||||||
|
|
||||||
self.wpas.dpp_configurator_create(uri)
|
self.wpas.dpp_configurator_create(uri)
|
||||||
self.wpas.dpp_configurator_start('ssidCCMP', 'secret123')
|
self.wpas.dpp_configurator_start('ssidCCMP', 'secret123')
|
||||||
|
|
||||||
|
self.hapd.reload()
|
||||||
|
|
||||||
with self.assertRaises(Exception):
|
with self.assertRaises(Exception):
|
||||||
self.device.get_ordered_network('ssidCCMP', scan_if_needed=False)
|
self.device.get_ordered_network('ssidCCMP', scan_if_needed=False)
|
||||||
|
|
||||||
self.hapd.reload()
|
|
||||||
self.hapd.wait_for_event('AP-ENABLED')
|
self.hapd.wait_for_event('AP-ENABLED')
|
||||||
|
|
||||||
|
self.device.autoconnect = True
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
condition = 'obj.state == DeviceState.connected'
|
||||||
self.wd.wait_for_object_condition(self.device, condition)
|
self.wd.wait_for_object_condition(self.device, condition)
|
||||||
|
|
||||||
@ -146,13 +148,8 @@ class Test(unittest.TestCase):
|
|||||||
self.rule0.drop = True
|
self.rule0.drop = True
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
# Tests end in various states, don't fail when tearing down.
|
|
||||||
try:
|
|
||||||
self.device.disconnect()
|
self.device.disconnect()
|
||||||
self.device.dpp_stop()
|
self.device.dpp_stop()
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.wpas.dpp_configurator_remove()
|
self.wpas.dpp_configurator_remove()
|
||||||
self.wpas.clean_up()
|
self.wpas.clean_up()
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
[Security]
|
|
||||||
Passphrase=IncorrectPassphrase
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
hw_mode=g
|
hw_mode=g
|
||||||
channel=6
|
channel=1
|
||||||
ssid=ssidCCMP
|
ssid=ssidCCMP
|
||||||
|
|
||||||
wpa=2
|
wpa=2
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
[SETUP]
|
[SETUP]
|
||||||
num_radios=5
|
num_radios=3
|
||||||
start_iwd=0
|
start_iwd=0
|
||||||
hwsim_medium=yes
|
hwsim_medium=yes
|
||||||
|
|
||||||
@ -8,7 +8,3 @@ rad0=wpas.conf
|
|||||||
|
|
||||||
[HOSTAPD]
|
[HOSTAPD]
|
||||||
rad1=hostapd.conf
|
rad1=hostapd.conf
|
||||||
rad2=ssidHidden.conf
|
|
||||||
|
|
||||||
[NameSpaces]
|
|
||||||
ns0=rad3
|
|
||||||
|
|||||||
@ -1,336 +0,0 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import sys
|
|
||||||
|
|
||||||
sys.path.append('../util')
|
|
||||||
from iwd import IWD, SharedCodeAgent, DeviceState
|
|
||||||
from iwd import DeviceProvisioning
|
|
||||||
from wpas import Wpas
|
|
||||||
from hostapd import HostapdCLI
|
|
||||||
from hwsim import Hwsim
|
|
||||||
from config import ctx
|
|
||||||
from time import time
|
|
||||||
import os
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
|
||||||
def start_wpas_pkex(self, code, curve=None, **kwargs):
|
|
||||||
self.wpas.dpp_bootstrap_gen(type='pkex', curve=curve)
|
|
||||||
self.wpas.dpp_pkex_add(code=code, **kwargs)
|
|
||||||
if kwargs.get('role', 'configurator') == 'configurator':
|
|
||||||
self.wpas.dpp_configurator_create()
|
|
||||||
self.wpas.dpp_listen(2437)
|
|
||||||
|
|
||||||
def stop_wpas_pkex(self):
|
|
||||||
self.wpas.dpp_pkex_remove()
|
|
||||||
self.wpas.dpp_stop_listen()
|
|
||||||
self.wpas.dpp_configurator_remove()
|
|
||||||
|
|
||||||
def start_iwd_pkex_configurator(self, device, agent=False, profile='ssidCCMP.psk'):
|
|
||||||
self.hapd.reload()
|
|
||||||
self.hapd.wait_for_event('AP-ENABLED')
|
|
||||||
|
|
||||||
IWD.copy_to_storage(profile)
|
|
||||||
device.autoconnect = True
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
self.wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
if agent:
|
|
||||||
self.agent = SharedCodeAgent(codes = {"test": "secret123"})
|
|
||||||
|
|
||||||
device.dpp_pkex_start_configurator(self.agent.path)
|
|
||||||
else:
|
|
||||||
device.dpp_pkex_configure_enrollee('secret123', identifier="test")
|
|
||||||
|
|
||||||
#
|
|
||||||
# WPA Supplicant has awful handling of retransmissions and no-ACK
|
|
||||||
# conditions. It only handles retransmitting the exchange request when
|
|
||||||
# there is no-ACK, which makes zero sense since its a broadcast...
|
|
||||||
#
|
|
||||||
# So, really, testing against wpa_supplicant is fragile and dependent on
|
|
||||||
# how the scheduling works out. If IWD doesn't ACK due to being on the
|
|
||||||
# next frequency or in between offchannel requests wpa_supplicant gets
|
|
||||||
# into a state where it thinks a PKEX session has been started (having
|
|
||||||
# received the exchange request) but will only accept commit-reveal
|
|
||||||
# frames. IWD is unaware because it never got a response so it keeps
|
|
||||||
# sending exchange requests which are ignored.
|
|
||||||
#
|
|
||||||
# Nevertheless we should still test against wpa_supplicant for
|
|
||||||
# compatibility so attempt to detect this case and restart the
|
|
||||||
# wpa_supplicant configurator.
|
|
||||||
#
|
|
||||||
def restart_wpas_if_needed(self):
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
while i < 10:
|
|
||||||
data = self.wpas.wait_for_event("DPP-RX")
|
|
||||||
self.assertIn("type=7", data)
|
|
||||||
|
|
||||||
data = self.wpas.wait_for_event("DPP-TX")
|
|
||||||
self.assertIn("type=8", data)
|
|
||||||
|
|
||||||
data = self.wpas.wait_for_event("DPP-TX-STATUS")
|
|
||||||
if "result=no-ACK" in data:
|
|
||||||
self.stop_wpas_pkex()
|
|
||||||
self.start_wpas_pkex('secret123', identifier="test")
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
raise Exception("wpa_supplicant could not complete PKEX after 10 retries")
|
|
||||||
|
|
||||||
def test_pkex_iwd_as_enrollee(self):
|
|
||||||
self.start_wpas_pkex('secret123', identifier="test")
|
|
||||||
|
|
||||||
self.device[0].dpp_pkex_enroll('secret123', identifier="test")
|
|
||||||
|
|
||||||
self.restart_wpas_if_needed()
|
|
||||||
|
|
||||||
self.wpas.wait_for_event("DPP-AUTH-SUCCESS")
|
|
||||||
|
|
||||||
def test_pkex_iwd_as_enrollee_retransmit(self):
|
|
||||||
self.rule_reveal_req.enabled = True
|
|
||||||
|
|
||||||
self.start_wpas_pkex('secret123', identifier="test")
|
|
||||||
|
|
||||||
self.device[0].dpp_pkex_enroll('secret123', identifier="test")
|
|
||||||
|
|
||||||
self.restart_wpas_if_needed()
|
|
||||||
|
|
||||||
self.wpas.wait_for_event("DPP-AUTH-SUCCESS")
|
|
||||||
|
|
||||||
def test_pkex_unsupported_version(self):
|
|
||||||
self.start_wpas_pkex('secret123', identifier="test", version=2)
|
|
||||||
|
|
||||||
now = time()
|
|
||||||
self.device[0].dpp_pkex_enroll('secret123', identifier="test")
|
|
||||||
|
|
||||||
condition = "obj.started == False"
|
|
||||||
self.wd.wait_for_object_condition(self.device[0]._sc_device_provisioning,
|
|
||||||
condition, max_wait=125)
|
|
||||||
|
|
||||||
# Check the enrollee stopped after 2 minutes
|
|
||||||
elapsed = time() - now
|
|
||||||
self.assertLess(elapsed, 125)
|
|
||||||
|
|
||||||
def test_pkex_configurator_timeout(self):
|
|
||||||
self.start_iwd_pkex_configurator(self.device[0])
|
|
||||||
|
|
||||||
now = time()
|
|
||||||
|
|
||||||
condition = "obj.started == False"
|
|
||||||
self.wd.wait_for_object_condition(self.device[0]._sc_device_provisioning,
|
|
||||||
condition, max_wait=125)
|
|
||||||
|
|
||||||
# Check the enrollee stopped after 2 minutes
|
|
||||||
elapsed = time() - now
|
|
||||||
self.assertLess(elapsed, 125)
|
|
||||||
|
|
||||||
def test_pkex_iwd_as_configurator(self):
|
|
||||||
self.start_iwd_pkex_configurator(self.device[0])
|
|
||||||
|
|
||||||
self.start_wpas_pkex('secret123', identifier="test", initiator=True,
|
|
||||||
role='enrollee')
|
|
||||||
|
|
||||||
self.wpas.wait_for_event("DPP-AUTH-SUCCESS")
|
|
||||||
self.wpas.wait_for_event("DPP-CONF-RECEIVED")
|
|
||||||
|
|
||||||
def test_pkex_iwd_as_configurator_retransmit(self):
|
|
||||||
self.rule_xchg_resp.enabled = True
|
|
||||||
self.rule_reveal_resp.enabled = True
|
|
||||||
|
|
||||||
self.start_iwd_pkex_configurator(self.device[0])
|
|
||||||
|
|
||||||
self.start_wpas_pkex('secret123', identifier="test", initiator=True,
|
|
||||||
role='enrollee')
|
|
||||||
|
|
||||||
self.wpas.wait_for_event("DPP-AUTH-SUCCESS")
|
|
||||||
self.wpas.wait_for_event("DPP-CONF-RECEIVED")
|
|
||||||
|
|
||||||
def test_pkex_iwd_as_configurator_bad_group(self):
|
|
||||||
self.start_iwd_pkex_configurator(self.device[0])
|
|
||||||
|
|
||||||
self.start_wpas_pkex('secret123', identifier="test", initiator=True,
|
|
||||||
role='enrollee', curve='P-384')
|
|
||||||
|
|
||||||
self.wpas.wait_for_event(f"DPP-RX src={self.device[0].address} freq=2437 type=8")
|
|
||||||
self.wpas.wait_for_event("DPP-FAIL")
|
|
||||||
|
|
||||||
def test_pkex_iwd_to_iwd(self):
|
|
||||||
self.start_iwd_pkex_configurator(self.device[0])
|
|
||||||
self.device[1].autoconnect = True
|
|
||||||
self.device[1].dpp_pkex_enroll('secret123', identifier="test")
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
self.wd.wait_for_object_condition(self.device[1], condition)
|
|
||||||
|
|
||||||
# Check additional settings were carried over
|
|
||||||
with open('/tmp/ns0/ssidCCMP.psk', 'r') as f:
|
|
||||||
settings = f.read()
|
|
||||||
|
|
||||||
self.assertIn("SendHostname=true", settings)
|
|
||||||
|
|
||||||
def test_pkex_configurator_with_agent(self):
|
|
||||||
self.start_iwd_pkex_configurator(self.device[0], agent=True)
|
|
||||||
self.device[1].autoconnect = True
|
|
||||||
self.device[1].dpp_pkex_enroll('secret123', identifier="test")
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
self.wd.wait_for_object_condition(self.device[1], condition)
|
|
||||||
|
|
||||||
self.agent = None
|
|
||||||
|
|
||||||
def test_existing_network(self):
|
|
||||||
self.hapd.reload()
|
|
||||||
self.hapd.wait_for_event('AP-ENABLED')
|
|
||||||
IWD.copy_to_storage("existingProfile.psk", "/tmp/ns0/", "ssidCCMP.psk")
|
|
||||||
|
|
||||||
# Scan first so a network object exists, and its a known network
|
|
||||||
self.device[1].scan()
|
|
||||||
self.wd.wait_for_object_condition(self.device[1], 'obj.scanning == True')
|
|
||||||
self.wd.wait_for_object_condition(self.device[1], 'obj.scanning == False')
|
|
||||||
|
|
||||||
self.start_iwd_pkex_configurator(self.device[0])
|
|
||||||
|
|
||||||
self.device[1].autoconnect = False
|
|
||||||
self.device[1].dpp_pkex_enroll('secret123', identifier="test")
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
self.wd.wait_for_object_condition(self.device[1], condition)
|
|
||||||
|
|
||||||
# Check additional settings were carried over
|
|
||||||
with open('/tmp/ns0/ssidCCMP.psk', 'r') as f:
|
|
||||||
settings = f.read()
|
|
||||||
|
|
||||||
self.assertIn("SendHostname=true", settings)
|
|
||||||
|
|
||||||
def test_existing_incorrect_profile(self):
|
|
||||||
self.hapd.reload()
|
|
||||||
self.hapd.wait_for_event('AP-ENABLED')
|
|
||||||
IWD.copy_to_storage("existingProfile.psk", "/tmp/ns0/", "ssidCCMP.psk")
|
|
||||||
|
|
||||||
# Start connecting
|
|
||||||
self.device[1].autoconnect = True
|
|
||||||
self.wd.wait_for_object_condition(self.device[1], 'obj.state == DeviceState.connecting')
|
|
||||||
|
|
||||||
# We should be able to start DPP despite the connecting state
|
|
||||||
self.device[1].dpp_pkex_enroll('secret123', identifier="test")
|
|
||||||
|
|
||||||
self.start_iwd_pkex_configurator(self.device[0])
|
|
||||||
self.assertEqual(self.device[1].state, DeviceState.disconnected)
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
self.wd.wait_for_object_condition(self.device[1], condition)
|
|
||||||
|
|
||||||
def test_existing_hidden_network(self):
|
|
||||||
self.hapd_hidden.reload()
|
|
||||||
self.hapd_hidden.wait_for_event('AP-ENABLED')
|
|
||||||
IWD.copy_to_storage("existingProfile.psk", "/tmp/ns0/", "ssidHidden.psk")
|
|
||||||
|
|
||||||
# Scan first so a network object exists, and its a known network
|
|
||||||
self.device[1].scan()
|
|
||||||
self.wd.wait_for_object_condition(self.device[1], 'obj.scanning == True')
|
|
||||||
self.wd.wait_for_object_condition(self.device[1], 'obj.scanning == False')
|
|
||||||
|
|
||||||
self.start_iwd_pkex_configurator(self.device[0], profile='ssidHidden.psk')
|
|
||||||
|
|
||||||
self.device[1].autoconnect = False
|
|
||||||
self.device[1].dpp_pkex_enroll('secret123', identifier="test")
|
|
||||||
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
self.wd.wait_for_object_condition(self.device[1], condition)
|
|
||||||
|
|
||||||
# Check additional settings were carried over
|
|
||||||
with open('/tmp/ns0/ssidHidden.psk', 'r') as f:
|
|
||||||
settings = f.read()
|
|
||||||
|
|
||||||
self.assertIn("Hidden=true", settings)
|
|
||||||
|
|
||||||
def test_hidden_network(self):
|
|
||||||
self.hapd_hidden.reload()
|
|
||||||
self.hapd_hidden.wait_for_event('AP-ENABLED')
|
|
||||||
self.start_iwd_pkex_configurator(self.device[0], profile='ssidHidden.psk')
|
|
||||||
|
|
||||||
self.device[1].autoconnect = False
|
|
||||||
self.device[1].dpp_pkex_enroll('secret123', identifier="test")
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
self.wd.wait_for_object_condition(self.device[1], condition)
|
|
||||||
|
|
||||||
# Check additional settings were carried over
|
|
||||||
with open('/tmp/ns0/ssidHidden.psk', 'r') as f:
|
|
||||||
settings = f.read()
|
|
||||||
|
|
||||||
self.assertIn("Hidden=true", settings)
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
ns0 = ctx.get_namespace('ns0')
|
|
||||||
self.wpas = Wpas('wpas.conf')
|
|
||||||
|
|
||||||
self.wd = IWD(True)
|
|
||||||
self.wd_ns0 = IWD(True, iwd_storage_dir='/tmp/ns0', namespace=ns0)
|
|
||||||
self.device = []
|
|
||||||
self.device.append(self.wd.list_devices(1)[0])
|
|
||||||
self.device.append(self.wd_ns0.list_devices(1)[0])
|
|
||||||
self.hapd = HostapdCLI('hostapd.conf')
|
|
||||||
self.hapd.disable()
|
|
||||||
self.hapd_hidden = HostapdCLI('ssidHidden.conf')
|
|
||||||
self.hapd_hidden.disable()
|
|
||||||
self.hwsim = Hwsim()
|
|
||||||
|
|
||||||
self.rule_xchg_resp = self.hwsim.rules.create()
|
|
||||||
self.rule_xchg_resp.prefix = 'd0'
|
|
||||||
self.rule_xchg_resp.match_offset = 24
|
|
||||||
self.rule_xchg_resp.match = '04 09 50 6f 9a 1a 01 08'
|
|
||||||
self.rule_xchg_resp.match_times = 1
|
|
||||||
self.rule_xchg_resp.drop = True
|
|
||||||
|
|
||||||
self.rule_reveal_resp = self.hwsim.rules.create()
|
|
||||||
self.rule_reveal_resp.prefix = 'd0'
|
|
||||||
self.rule_reveal_resp.match_offset = 24
|
|
||||||
self.rule_reveal_resp.match = '04 09 50 6f 9a 1a 01 0a'
|
|
||||||
self.rule_reveal_resp.match_times = 1
|
|
||||||
self.rule_reveal_resp.drop = True
|
|
||||||
|
|
||||||
self.rule_reveal_req = self.hwsim.rules.create()
|
|
||||||
self.rule_reveal_req.prefix = 'd0'
|
|
||||||
self.rule_reveal_req.match_offset = 24
|
|
||||||
self.rule_reveal_req.match = '04 09 50 6f 9a 1a 01 09'
|
|
||||||
self.rule_reveal_req.match_times = 1
|
|
||||||
self.rule_reveal_req.drop = True
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
# Tests end in various states, don't fail when tearing down.
|
|
||||||
try:
|
|
||||||
self.device[0].disconnect()
|
|
||||||
self.device[0].dpp_pkex_stop()
|
|
||||||
self.device[1].disconnect()
|
|
||||||
self.device[1].dpp_pkex_stop()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.wpas.dpp_configurator_remove()
|
|
||||||
self.wpas.clean_up()
|
|
||||||
|
|
||||||
self.wd = None
|
|
||||||
self.wd_ns0 = None
|
|
||||||
self.device = None
|
|
||||||
self.wpas = None
|
|
||||||
self.hapd = None
|
|
||||||
self.rule_xchg_resp = None
|
|
||||||
IWD.clear_storage()
|
|
||||||
IWD.clear_storage('/tmp/ns0')
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
pass
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main(exit=True)
|
|
||||||
@ -1,5 +1,2 @@
|
|||||||
[Security]
|
[Security]
|
||||||
Passphrase=secret123
|
Passphrase=secret123
|
||||||
|
|
||||||
[IPv4]
|
|
||||||
SendHostname=true
|
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
hw_mode=g
|
|
||||||
channel=6
|
|
||||||
ssid=ssidHidden
|
|
||||||
|
|
||||||
wpa=1
|
|
||||||
wpa_pairwise=TKIP
|
|
||||||
wpa_passphrase=secret123
|
|
||||||
|
|
||||||
ignore_broadcast_ssid=1
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
[Security]
|
|
||||||
Passphrase=secret123
|
|
||||||
|
|
||||||
[Settings]
|
|
||||||
Hidden=true
|
|
||||||
@ -1,107 +0,0 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import sys
|
|
||||||
|
|
||||||
sys.path.append('../util')
|
|
||||||
from iwd import IWD, SharedCodeAgent, DeviceState
|
|
||||||
from iwd import DeviceProvisioning
|
|
||||||
from wpas import Wpas
|
|
||||||
from hostapd import HostapdCLI
|
|
||||||
from hwsim import Hwsim
|
|
||||||
from config import ctx
|
|
||||||
from time import time
|
|
||||||
import os
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
|
||||||
def auto_connect(self):
|
|
||||||
IWD.copy_to_storage('ssidCCMP.psk')
|
|
||||||
self.device.autoconnect = True
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
self.wd.wait_for_object_condition(self.device, condition)
|
|
||||||
|
|
||||||
def test_configurator_stops_on_disconnect(self):
|
|
||||||
self.auto_connect()
|
|
||||||
|
|
||||||
self.device.dpp_start_configurator()
|
|
||||||
|
|
||||||
self.device.disconnect()
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.disconnected'
|
|
||||||
self.wd.wait_for_object_condition(self.device, condition)
|
|
||||||
|
|
||||||
self.assertEqual(self.device._device_provisioning.started, False)
|
|
||||||
|
|
||||||
def test_enrollee_stops_on_connect(self):
|
|
||||||
# Scan to get a list of networks
|
|
||||||
self.device.scan()
|
|
||||||
self.wd.wait_for_object_condition(self.device, 'obj.scanning == True')
|
|
||||||
self.wd.wait_for_object_condition(self.device, 'obj.scanning == False')
|
|
||||||
|
|
||||||
self.device.dpp_start_enrollee()
|
|
||||||
|
|
||||||
network = self.device.get_ordered_network("ssidCCMP")
|
|
||||||
network.network_object.connect()
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
self.wd.wait_for_object_condition(self.device, condition)
|
|
||||||
|
|
||||||
self.assertEqual(self.device._device_provisioning.started, False)
|
|
||||||
|
|
||||||
def test_enrollee_disconnects_automatically(self):
|
|
||||||
self.auto_connect()
|
|
||||||
|
|
||||||
self.device.dpp_start_enrollee()
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.disconnected'
|
|
||||||
self.wd.wait_for_object_condition(self.device, condition)
|
|
||||||
|
|
||||||
def test_enrollee_autoconnect_stays_on(self):
|
|
||||||
# Put in an autoconnecting state, no saved profile though
|
|
||||||
self.device.autoconnect = True
|
|
||||||
|
|
||||||
self.device.dpp_start_enrollee()
|
|
||||||
|
|
||||||
# DPP should set autoconnect false, but then re-enable after it stops
|
|
||||||
self.wd.wait_for_object_condition(self.device, "obj.autoconnect == False")
|
|
||||||
self.wd.wait_for_object_condition(self.device._device_provisioning, "obj.started == True")
|
|
||||||
|
|
||||||
# Stop DPP
|
|
||||||
self.device.dpp_stop()
|
|
||||||
self.wd.wait_for_object_condition(self.device, "obj.autoconnect == True")
|
|
||||||
|
|
||||||
def test_enrollee_autoconnect_stays_off(self):
|
|
||||||
# Autoconnect should be off by default
|
|
||||||
|
|
||||||
self.device.dpp_start_enrollee()
|
|
||||||
|
|
||||||
# DPP should set autoconnect false, but stay off after it stops
|
|
||||||
self.wd.wait_for_object_condition(self.device, "obj.autoconnect == False")
|
|
||||||
self.wd.wait_for_object_condition(self.device._device_provisioning, "obj.started == True")
|
|
||||||
|
|
||||||
# Stop DPP
|
|
||||||
self.device.dpp_stop()
|
|
||||||
self.wd.wait_for_object_condition(self.device, "obj.autoconnect == False")
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.wd = IWD(True)
|
|
||||||
self.device = self.wd.list_devices(1)[0]
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.wd.stop()
|
|
||||||
self.wd = None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
hapd = HostapdCLI(config="hostapd.conf")
|
|
||||||
hapd.reload()
|
|
||||||
|
|
||||||
hapd.wait_for_event("AP-ENABLED")
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
pass
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main(exit=True)
|
|
||||||
@ -3,4 +3,3 @@ ctrl_interface=/tmp/rad1-p2p-wpas
|
|||||||
update_config=0
|
update_config=0
|
||||||
pmf=2
|
pmf=2
|
||||||
dpp_config_processing=2
|
dpp_config_processing=2
|
||||||
p2p_disabled=1
|
|
||||||
|
|||||||
@ -104,7 +104,7 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertTrue(self.profile_is_encrypted('ssidCCMP.psk'))
|
self.assertTrue(self.profile_is_encrypted('ssidCCMP.psk'))
|
||||||
|
|
||||||
# Tests that a profile that doesn't decrypt won't become a known network
|
# Tests that a profile that doesn't decrypt wont become a known network
|
||||||
def test_decryption_failure(self):
|
def test_decryption_failure(self):
|
||||||
bad_config = \
|
bad_config = \
|
||||||
'''
|
'''
|
||||||
|
|||||||
@ -1,5 +1,2 @@
|
|||||||
[Security]
|
[Security]
|
||||||
Passphrase=secret123
|
Passphrase=secret123
|
||||||
|
|
||||||
[General]
|
|
||||||
AutoConnect=false
|
|
||||||
|
|||||||
@ -1,76 +0,0 @@
|
|||||||
import unittest
|
|
||||||
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 time import time, sleep
|
|
||||||
from threading import Thread
|
|
||||||
|
|
||||||
def if_hwaddr(iff):
|
|
||||||
return str2mac(get_if_raw_hwaddr(iff)[1])
|
|
||||||
|
|
||||||
def config_mon(iface, channel):
|
|
||||||
"""set the interface in monitor mode and then change channel using iw"""
|
|
||||||
os.system("ip link set dev %s down" % iface)
|
|
||||||
os.system("iw dev %s set type monitor" % iface)
|
|
||||||
os.system("ip link set dev %s up" % iface)
|
|
||||||
os.system("iw dev %s set channel %d" % (iface, channel))
|
|
||||||
|
|
||||||
class AP:
|
|
||||||
def __init__(self, ssid, psk, mac=None, mode="stdio", iface="wlan0", channel=1):
|
|
||||||
self.channel = channel
|
|
||||||
self.iface = iface
|
|
||||||
self.mode = mode
|
|
||||||
if self.mode == "iface":
|
|
||||||
if not mac:
|
|
||||||
mac = if_hwaddr(iface)
|
|
||||||
config_mon(iface, channel)
|
|
||||||
if not mac:
|
|
||||||
raise Exception("Need a mac")
|
|
||||||
else:
|
|
||||||
self.mac = mac
|
|
||||||
self.boottime = time()
|
|
||||||
|
|
||||||
def get_radiotap_header(self):
|
|
||||||
return RadioTap()
|
|
||||||
|
|
||||||
def dot11_beacon(self, contents):
|
|
||||||
evil_packet = (
|
|
||||||
self.get_radiotap_header()
|
|
||||||
/ Dot11(
|
|
||||||
subtype=8, addr1="ff:ff:ff:ff:ff:ff", addr2=self.mac, addr3=self.mac
|
|
||||||
)
|
|
||||||
/ Dot11Beacon(cap=0x3101)
|
|
||||||
/ contents
|
|
||||||
)
|
|
||||||
self.sendp(evil_packet)
|
|
||||||
|
|
||||||
def run(self, contents):
|
|
||||||
interval = 0.05
|
|
||||||
num_beacons = 100
|
|
||||||
|
|
||||||
while num_beacons:
|
|
||||||
self.dot11_beacon(contents)
|
|
||||||
sleep(interval)
|
|
||||||
num_beacons -= 1
|
|
||||||
|
|
||||||
def start(self, contents):
|
|
||||||
self.thread = Thread(target=self.run, args=(contents,))
|
|
||||||
self.thread.start()
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
self.thread.join()
|
|
||||||
|
|
||||||
def sendp(self, packet, verbose=False):
|
|
||||||
if self.mode == "stdio":
|
|
||||||
x = packet.build()
|
|
||||||
sys.stdout.buffer.write(struct.pack("<L", len(x)) + x)
|
|
||||||
sys.stdout.buffer.flush()
|
|
||||||
return
|
|
||||||
assert self.mode == "iface"
|
|
||||||
sendp(packet, iface=self.iface, verbose=False)
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
[SETUP]
|
|
||||||
num_radios=2
|
|
||||||
start_iwd=0
|
|
||||||
hwsim_medium=yes
|
|
||||||
|
|
||||||
[rad1]
|
|
||||||
reserve=true
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
#! /usr/bin/python3
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import sys
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
from fake_ap import AP
|
|
||||||
|
|
||||||
sys.path.append('../util')
|
|
||||||
from iwd import IWD
|
|
||||||
|
|
||||||
# Probe frame that causes IWD to crash
|
|
||||||
beacon=b'\xdd\nPo\x9a\t\x0e\x00\x00\x19\x10\x00\xdd/Po\x9a\t\x0c\x02\x00\x00\xdd\x05\x03\x03\x03Po\x9a\x10\x00\x0b\x05\x0e\x00\x00\x00\x00\x0b\x05\x00\x00\x00\xdd\x05\x00\x03\x03\x03\x03\x00\x00\x00\xdd\x05\x03\x03\x03\x03\x03'
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
|
||||||
def test_beacon_crash(self):
|
|
||||||
wd = IWD(True)
|
|
||||||
|
|
||||||
devs = wd.list_devices()
|
|
||||||
|
|
||||||
self.assertEqual(len(devs), 1)
|
|
||||||
|
|
||||||
devs[0].autoconnect = True
|
|
||||||
|
|
||||||
os.system("iw phy rad1 interface add wlan1 type managed")
|
|
||||||
|
|
||||||
ap = AP("evilAP", "password1234", mode="iface", iface="wlan1", channel=4)
|
|
||||||
ap.start(beacon)
|
|
||||||
|
|
||||||
condition = "obj.scanning == True"
|
|
||||||
wd.wait_for_object_condition(devs[0], condition)
|
|
||||||
|
|
||||||
condition = "obj.scanning == False"
|
|
||||||
wd.wait_for_object_condition(devs[0], condition)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main(exit=True)
|
|
||||||
@ -12,7 +12,7 @@ from hostapd import HostapdCLI
|
|||||||
|
|
||||||
class TestWpaNetwork(unittest.TestCase):
|
class TestWpaNetwork(unittest.TestCase):
|
||||||
'''
|
'''
|
||||||
The below test cases excesise the following connection scenarios:
|
The bellow test cases excesise the following connection scenarios:
|
||||||
|
|
||||||
Network config is
|
Network config is
|
||||||
present at start time: Connect: AutoConnect: Result:
|
present at start time: Connect: AutoConnect: Result:
|
||||||
|
|||||||
@ -12,7 +12,7 @@ from hostapd import HostapdCLI
|
|||||||
|
|
||||||
class TestOpenNetwork(unittest.TestCase):
|
class TestOpenNetwork(unittest.TestCase):
|
||||||
'''
|
'''
|
||||||
The below test cases excesise the following connection scenarios:
|
The bellow test cases excesise the following connection scenarios:
|
||||||
|
|
||||||
Network config is
|
Network config is
|
||||||
present at start time: Connect: AutoConnect: Result:
|
present at start time: Connect: AutoConnect: Result:
|
||||||
|
|||||||
@ -12,7 +12,7 @@ from hostapd import HostapdCLI
|
|||||||
|
|
||||||
class TestWpaNetwork(unittest.TestCase):
|
class TestWpaNetwork(unittest.TestCase):
|
||||||
'''
|
'''
|
||||||
The below test cases excesise the following connection scenarios:
|
The bellow test cases excesise the following connection scenarios:
|
||||||
|
|
||||||
Network config is
|
Network config is
|
||||||
present at start time: Connect: AutoConnect: Result:
|
present at start time: Connect: AutoConnect: Result:
|
||||||
|
|||||||
@ -4,15 +4,17 @@ import unittest
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
sys.path.append('../util')
|
sys.path.append('../util')
|
||||||
|
import iwd
|
||||||
from iwd import IWD
|
from iwd import IWD
|
||||||
from iwd import PSKAgent
|
from iwd import PSKAgent
|
||||||
from hwsim import Hwsim
|
from iwd import NetworkType
|
||||||
|
import testutil
|
||||||
import os
|
import os
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
def connect_network(self, wd, device, network):
|
def connect_network(self, wd, device, network):
|
||||||
ordered_network = device.get_ordered_network(network, full_scan=True)
|
ordered_network = device.get_ordered_network(network)
|
||||||
|
|
||||||
condition = 'not obj.connected'
|
condition = 'not obj.connected'
|
||||||
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
||||||
@ -28,7 +30,7 @@ class Test(unittest.TestCase):
|
|||||||
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
||||||
|
|
||||||
def test_connection_success(self):
|
def test_connection_success(self):
|
||||||
wd = self.wd
|
wd = IWD(True, '/tmp')
|
||||||
|
|
||||||
psk_agent = PSKAgent("secret123")
|
psk_agent = PSKAgent("secret123")
|
||||||
wd.register_psk_agent(psk_agent)
|
wd.register_psk_agent(psk_agent)
|
||||||
@ -36,11 +38,6 @@ class Test(unittest.TestCase):
|
|||||||
devices = wd.list_devices(1)
|
devices = wd.list_devices(1)
|
||||||
device = devices[0]
|
device = devices[0]
|
||||||
|
|
||||||
|
|
||||||
# Set the signals so that the 2.4GHz ranking will be higher
|
|
||||||
self.ssidccmp_2g_rule.signal = -2000
|
|
||||||
self.ssidccmp_5g_rule.signal = -8000
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Connect to the PSK network, then Hotspot so IWD creates 2 entries in
|
# Connect to the PSK network, then Hotspot so IWD creates 2 entries in
|
||||||
# the known frequency file.
|
# the known frequency file.
|
||||||
@ -78,10 +75,8 @@ class Test(unittest.TestCase):
|
|||||||
#
|
#
|
||||||
self.assertIsNotNone(psk_freqs)
|
self.assertIsNotNone(psk_freqs)
|
||||||
self.assertIsNotNone(psk_uuid)
|
self.assertIsNotNone(psk_uuid)
|
||||||
|
self.assertIn('5180', psk_freqs)
|
||||||
# The 2.4GHz frequency should come first, as it was ranked higher
|
self.assertIn('2412', psk_freqs)
|
||||||
self.assertEqual('2412', psk_freqs[0])
|
|
||||||
self.assertEqual('5180', psk_freqs[1])
|
|
||||||
|
|
||||||
self.assertIsNotNone(hs20_freqs)
|
self.assertIsNotNone(hs20_freqs)
|
||||||
self.assertIsNotNone(hs20_uuid)
|
self.assertIsNotNone(hs20_uuid)
|
||||||
@ -97,10 +92,6 @@ class Test(unittest.TestCase):
|
|||||||
psk_agent = PSKAgent("secret123")
|
psk_agent = PSKAgent("secret123")
|
||||||
wd.register_psk_agent(psk_agent)
|
wd.register_psk_agent(psk_agent)
|
||||||
|
|
||||||
# Now set the signals so that the 5GHz ranking will be higher
|
|
||||||
self.ssidccmp_2g_rule.signal = -8000
|
|
||||||
self.ssidccmp_5g_rule.signal = -2000
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Reconnect, this should generate a completely new UUID since we
|
# Reconnect, this should generate a completely new UUID since we
|
||||||
# previously forgot the network.
|
# previously forgot the network.
|
||||||
@ -129,78 +120,8 @@ class Test(unittest.TestCase):
|
|||||||
self.assertIsNotNone(psk_freqs)
|
self.assertIsNotNone(psk_freqs)
|
||||||
self.assertIsNotNone(psk_uuid2)
|
self.assertIsNotNone(psk_uuid2)
|
||||||
self.assertNotEqual(psk_uuid, psk_uuid2)
|
self.assertNotEqual(psk_uuid, psk_uuid2)
|
||||||
# Now the 5GHz frequency should be first
|
self.assertIn('5180', psk_freqs)
|
||||||
self.assertEqual('5180', psk_freqs[0])
|
self.assertIn('2412', psk_freqs)
|
||||||
self.assertEqual('2412', psk_freqs[1])
|
|
||||||
|
|
||||||
def test_maximum_frequencies(self):
|
|
||||||
psk_agent = PSKAgent("secret123")
|
|
||||||
self.wd.register_psk_agent(psk_agent)
|
|
||||||
|
|
||||||
devices = self.wd.list_devices(1)
|
|
||||||
device = devices[0]
|
|
||||||
|
|
||||||
# Connect and generate a known frequencies file
|
|
||||||
self.connect_network(self.wd, device, 'ssidCCMP')
|
|
||||||
|
|
||||||
self.wd.unregister_psk_agent(psk_agent)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Rewrite the known frequencies file to move the valid network
|
|
||||||
# frequencies to the end, past the maximum for a quick scan
|
|
||||||
#
|
|
||||||
config = ConfigParser()
|
|
||||||
config.read('/tmp/iwd/.known_network.freq')
|
|
||||||
for s in config.sections():
|
|
||||||
if os.path.basename(config[s]['name']) == 'ssidCCMP.psk':
|
|
||||||
config.set(s, 'list', "2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484 2412 5180")
|
|
||||||
break
|
|
||||||
|
|
||||||
self.wd.stop()
|
|
||||||
|
|
||||||
with open('/tmp/iwd/.known_network.freq', 'w') as f:
|
|
||||||
config.write(f)
|
|
||||||
|
|
||||||
self.wd = IWD(True)
|
|
||||||
|
|
||||||
devices = self.wd.list_devices(1)
|
|
||||||
device = devices[0]
|
|
||||||
|
|
||||||
device.autoconnect = True
|
|
||||||
|
|
||||||
device.wait_for_event("autoconnect_quick")
|
|
||||||
|
|
||||||
condition = "obj.scanning == True"
|
|
||||||
self.wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
condition = "obj.scanning == False"
|
|
||||||
self.wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Check that the quick scan didn't return any results
|
|
||||||
#
|
|
||||||
with self.assertRaises(Exception):
|
|
||||||
device.get_ordered_network("ssidCCMP", scan_if_needed=False)
|
|
||||||
|
|
||||||
device.wait_for_event("autoconnect_full")
|
|
||||||
|
|
||||||
condition = "obj.scanning == True"
|
|
||||||
self.wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
condition = "obj.scanning == False"
|
|
||||||
self.wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
#
|
|
||||||
# The full scan should now see the network
|
|
||||||
#
|
|
||||||
device.get_ordered_network("ssidCCMP", scan_if_needed=False)
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.wd = IWD(True)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.wd.stop()
|
|
||||||
self.wd = None
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
@ -208,23 +129,10 @@ class Test(unittest.TestCase):
|
|||||||
conf = '[General]\nDisableANQP=0\n'
|
conf = '[General]\nDisableANQP=0\n'
|
||||||
os.system('echo "%s" > /tmp/main.conf' % conf)
|
os.system('echo "%s" > /tmp/main.conf' % conf)
|
||||||
|
|
||||||
hwsim = Hwsim()
|
|
||||||
|
|
||||||
cls.ssidccmp_2g_rule = hwsim.rules.create()
|
|
||||||
cls.ssidccmp_2g_rule.source = hwsim.get_radio('rad1').addresses[0]
|
|
||||||
cls.ssidccmp_2g_rule.enabled = True
|
|
||||||
|
|
||||||
cls.ssidccmp_5g_rule = hwsim.rules.create()
|
|
||||||
cls.ssidccmp_5g_rule.source = hwsim.get_radio('rad2').addresses[0]
|
|
||||||
cls.ssidccmp_5g_rule.enabled = True
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
IWD.clear_storage()
|
IWD.clear_storage()
|
||||||
os.remove('/tmp/main.conf')
|
os.remove('/tmp/main.conf')
|
||||||
|
|
||||||
cls.ssidccmp_2g_rule.remove()
|
|
||||||
cls.ssidccmp_5g_rule.remove()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(exit=True)
|
unittest.main(exit=True)
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
num_radios=5
|
num_radios=5
|
||||||
start_iwd=0
|
start_iwd=0
|
||||||
reg_domain=US
|
reg_domain=US
|
||||||
hwsim_medium=yes
|
|
||||||
|
|
||||||
[HOSTAPD]
|
[HOSTAPD]
|
||||||
rad0=ssidNew.conf
|
rad0=ssidNew.conf
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from iwd import NetworkType
|
|||||||
|
|
||||||
class TestMFP(unittest.TestCase):
|
class TestMFP(unittest.TestCase):
|
||||||
'''
|
'''
|
||||||
The below test cases excesise the following MFP option setting scenarios:
|
The bellow test cases excesise the following MFP option setting scenarios:
|
||||||
|
|
||||||
IWD_MFP: AP_MFP: Result:
|
IWD_MFP: AP_MFP: Result:
|
||||||
0 0 No MFP, connection succeeds
|
0 0 No MFP, connection succeeds
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
[IPv4]
|
|
||||||
SendHostname=true
|
|
||||||
@ -137,7 +137,7 @@ class Test(unittest.TestCase):
|
|||||||
# since (T2 - T1) / 2 is shorter than 60s. It is now about 10s since the last
|
# since (T2 - T1) / 2 is shorter than 60s. It is now about 10s since the last
|
||||||
# renewal or 5s before the next DHCPREQUEST frame that is going to be lost. We'll
|
# renewal or 5s before the next DHCPREQUEST frame that is going to be lost. We'll
|
||||||
# wait T1 seconds, so until about 10s after the failed attempt, we'll check that
|
# wait T1 seconds, so until about 10s after the failed attempt, we'll check that
|
||||||
# there was no renewal by that time, just in case, and we'll re-enable frame delivery.
|
# there was no renewal by that time, just in case, and we'll reenable frame delivery.
|
||||||
# We'll then wait another 60s and we should see the lease has been successfully
|
# We'll then wait another 60s and we should see the lease has been successfully
|
||||||
# renewed some 10 seconds earlier on the 1st DHCPREQUEST retransmission.
|
# renewed some 10 seconds earlier on the 1st DHCPREQUEST retransmission.
|
||||||
#
|
#
|
||||||
|
|||||||
@ -81,21 +81,14 @@ class Test(unittest.TestCase):
|
|||||||
self.assertEqual(expected_routes6, set(testutil.get_routes6(ifname)))
|
self.assertEqual(expected_routes6, set(testutil.get_routes6(ifname)))
|
||||||
|
|
||||||
rclog = open('/tmp/resolvconf.log', 'r')
|
rclog = open('/tmp/resolvconf.log', 'r')
|
||||||
entries = [l.strip() for l in rclog.readlines()[-7:]]
|
entries = rclog.readlines()
|
||||||
rclog.close()
|
rclog.close()
|
||||||
expected_rclog = [
|
expected_rclog = ['-a %s.dns\n' % (ifname,), 'nameserver 192.168.1.2\n',
|
||||||
'-a %s.dns' % (ifname,),
|
'nameserver 3ffe:501:ffff:100::10\n', 'nameserver 3ffe:501:ffff:100::50\n',
|
||||||
'nameserver 192.168.1.2',
|
'-a %s.domain\n' % (ifname,), 'search test1\n', 'search test2\n']
|
||||||
'nameserver 3ffe:501:ffff:100::10',
|
# Every resolvconf -a run overwrites the previous settings. Check the last seven lines
|
||||||
'nameserver 3ffe:501:ffff:100::50',
|
# of our log since we care about the end result here.
|
||||||
'-a %s.domain' % (ifname,),
|
self.assertEqual(expected_rclog, entries[-7:])
|
||||||
'search test1',
|
|
||||||
'search test2'
|
|
||||||
]
|
|
||||||
|
|
||||||
for line in expected_rclog:
|
|
||||||
self.assertIn(line, entries)
|
|
||||||
expected_rclog.remove(line)
|
|
||||||
|
|
||||||
device.disconnect()
|
device.disconnect()
|
||||||
condition = 'not obj.connected'
|
condition = 'not obj.connected'
|
||||||
|
|||||||
@ -91,11 +91,16 @@ class Test(unittest.TestCase):
|
|||||||
# using the same static config. The new client's ACD client should
|
# using the same static config. The new client's ACD client should
|
||||||
# detect an IP conflict and not allow the device to reach the
|
# detect an IP conflict and not allow the device to reach the
|
||||||
# "connected" state although the DBus .Connect call will succeed.
|
# "connected" state although the DBus .Connect call will succeed.
|
||||||
with self.assertRaises(iwd.FailedEx):
|
ordered_network.network_object.connect()
|
||||||
ordered_network.network_object.connect(timeout=500)
|
self.assertEqual(dev2.state, iwd.DeviceState.connecting)
|
||||||
|
try:
|
||||||
condition = 'obj.state == DeviceState.disconnected'
|
# We should either stay in "connecting" indefinitely or move to
|
||||||
|
# "disconnecting"
|
||||||
|
condition = 'obj.state != DeviceState.connecting'
|
||||||
iwd_ns0_1.wait_for_object_condition(dev2, condition, max_wait=21)
|
iwd_ns0_1.wait_for_object_condition(dev2, condition, max_wait=21)
|
||||||
|
self.assertEqual(dev2.state, iwd.DeviceState.disconnecting)
|
||||||
|
except TimeoutError:
|
||||||
|
dev2.disconnect()
|
||||||
|
|
||||||
iwd_ns0_1.unregister_psk_agent(psk_agent_ns0_1)
|
iwd_ns0_1.unregister_psk_agent(psk_agent_ns0_1)
|
||||||
del dev2
|
del dev2
|
||||||
|
|||||||
@ -1,78 +0,0 @@
|
|||||||
import unittest
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
|
|
||||||
sys.path.append('../util')
|
|
||||||
from iwd import IWD
|
|
||||||
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')
|
|
||||||
|
|
||||||
wd = IWD(True)
|
|
||||||
|
|
||||||
psk_agent = PSKAgent("secret123")
|
|
||||||
wd.register_psk_agent(psk_agent)
|
|
||||||
|
|
||||||
devices = wd.list_devices(1)
|
|
||||||
device = devices[0]
|
|
||||||
|
|
||||||
ordered_network = device.get_ordered_network('ap-ns1')
|
|
||||||
|
|
||||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
|
||||||
|
|
||||||
condition = 'not obj.connected'
|
|
||||||
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
|
||||||
|
|
||||||
self.failure_triggered = False
|
|
||||||
|
|
||||||
# Set our error handler here so we can check if it fails
|
|
||||||
ordered_network.network_object.connect(
|
|
||||||
wait=False,
|
|
||||||
timeout=1000,
|
|
||||||
error_handler=self.connect_failure
|
|
||||||
)
|
|
||||||
|
|
||||||
# IWD should attempt to try both BSS's with both failing netconfig.
|
|
||||||
# Then the autoconnect list should be exhausted, and IWD should
|
|
||||||
# transition to a disconnected state, then proceed to full autoconnect.
|
|
||||||
device.wait_for_event("netconfig-failed", timeout=1000)
|
|
||||||
device.wait_for_event("netconfig-failed", timeout=1000)
|
|
||||||
device.wait_for_event("disconnected")
|
|
||||||
|
|
||||||
device.wait_for_event("autoconnect_full")
|
|
||||||
|
|
||||||
# The connect call should have failed
|
|
||||||
self.assertTrue(self.failure_triggered)
|
|
||||||
|
|
||||||
condition = "obj.scanning"
|
|
||||||
wd.wait_for_object_condition(device, condition)
|
|
||||||
condition = "not obj.scanning"
|
|
||||||
wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
# IWD should attempt to connect, but it will of course fail again.
|
|
||||||
device.wait_for_event("netconfig-failed", timeout=1000)
|
|
||||||
|
|
||||||
device.disconnect()
|
|
||||||
condition = 'obj.state == DeviceState.disconnected'
|
|
||||||
wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
cls.orig_path = os.environ['PATH']
|
|
||||||
os.environ['PATH'] = '/tmp/test-bin:' + os.environ['PATH']
|
|
||||||
IWD.copy_to_storage('resolvconf', '/tmp/test-bin')
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
IWD.clear_storage()
|
|
||||||
os.system('rm -rf /tmp/radvd.conf /tmp/resolvconf.log /tmp/test-bin')
|
|
||||||
os.environ['PATH'] = cls.orig_path
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main(exit=True)
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
[Security]
|
|
||||||
Passphrase=EasilyGuessedPassword
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
hw_mode=g
|
|
||||||
channel=1
|
|
||||||
ssid=TestFT
|
|
||||||
utf8_ssid=1
|
|
||||||
ctrl_interface=/var/run/hostapd
|
|
||||||
|
|
||||||
r1_key_holder=120000000001
|
|
||||||
nas_identifier=dummy1
|
|
||||||
|
|
||||||
wpa=2
|
|
||||||
# Can support WPA-PSK and FT-PSK (space separated list) and/or EAP at the same
|
|
||||||
# time but we want to force FT
|
|
||||||
wpa_key_mgmt=FT-PSK
|
|
||||||
wpa_pairwise=CCMP
|
|
||||||
wpa_passphrase=EasilyGuessedPassword
|
|
||||||
ieee80211w=1
|
|
||||||
rsn_preauth=1
|
|
||||||
rsn_preauth_interfaces=lo
|
|
||||||
disable_pmksa_caching=0
|
|
||||||
# Allow PMK cache to be shared opportunistically among configured interfaces
|
|
||||||
# and BSSes (i.e., all configurations within a single hostapd process).
|
|
||||||
okc=1
|
|
||||||
mobility_domain=1234
|
|
||||||
reassociation_deadline=60000
|
|
||||||
r0kh=12:00:00:00:00:01 dummy1 000102030405060708090a0b0c0d0e0f
|
|
||||||
r0kh=12:00:00:00:00:02 dummy2 000102030405060708090a0b0c0d0e0f
|
|
||||||
r1kh=12:00:00:00:00:01 00:00:00:00:00:01 000102030405060708090a0b0c0d0e0f
|
|
||||||
r1kh=12:00:00:00:00:02 00:00:00:00:00:02 000102030405060708090a0b0c0d0e0f
|
|
||||||
# Push mode only needed for 8021x, not PSK mode since msk already known
|
|
||||||
pmk_r1_push=0
|
|
||||||
# Allow locally generated FT response so we don't have to configure push/pull
|
|
||||||
# between BSSes running as separate hostapd processes as in the test-runner
|
|
||||||
# case. Only works with FT-PSK, otherwise brctl needs to be installed and
|
|
||||||
# CONFIG_BRIDGE enabled in the kernel.
|
|
||||||
ft_psk_generate_local=1
|
|
||||||
rkh_pull_timeout=50
|
|
||||||
ft_over_ds=0
|
|
||||||
ap_table_expiration_time=36000
|
|
||||||
ap_table_max_size=10
|
|
||||||
rrm_neighbor_report=1
|
|
||||||
ocv=1
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
hw_mode=g
|
|
||||||
channel=2
|
|
||||||
ssid=TestFT
|
|
||||||
utf8_ssid=1
|
|
||||||
ctrl_interface=/var/run/hostapd
|
|
||||||
|
|
||||||
r1_key_holder=120000000002
|
|
||||||
nas_identifier=dummy2
|
|
||||||
|
|
||||||
wpa=2
|
|
||||||
# Can support WPA-PSK and FT-PSK (space separated list) and/or EAP at the same
|
|
||||||
# time but we want to force FT
|
|
||||||
wpa_key_mgmt=FT-PSK
|
|
||||||
wpa_pairwise=CCMP
|
|
||||||
wpa_passphrase=EasilyGuessedPassword
|
|
||||||
ieee80211w=1
|
|
||||||
rsn_preauth=1
|
|
||||||
rsn_preauth_interfaces=lo
|
|
||||||
disable_pmksa_caching=0
|
|
||||||
# Allow PMK cache to be shared opportunistically among configured interfaces
|
|
||||||
# and BSSes (i.e., all configurations within a single hostapd process).
|
|
||||||
okc=1
|
|
||||||
mobility_domain=1234
|
|
||||||
reassociation_deadline=60000
|
|
||||||
r0kh=12:00:00:00:00:01 dummy1 000102030405060708090a0b0c0d0e0f
|
|
||||||
r0kh=12:00:00:00:00:02 dummy2 000102030405060708090a0b0c0d0e0f
|
|
||||||
r1kh=12:00:00:00:00:01 00:00:00:00:00:01 000102030405060708090a0b0c0d0e0f
|
|
||||||
r1kh=12:00:00:00:00:02 00:00:00:00:00:02 000102030405060708090a0b0c0d0e0f
|
|
||||||
# Push mode only needed for 8021x, not PSK mode since msk already known
|
|
||||||
pmk_r1_push=0
|
|
||||||
# Allow locally generated FT response so we don't have to configure push/pull
|
|
||||||
# between BSSes running as separate hostapd processes as in the test-runner
|
|
||||||
# case. Only works with FT-PSK, otherwise brctl needs to be installed and
|
|
||||||
# CONFIG_BRIDGE enabled in the kernel.
|
|
||||||
ft_psk_generate_local=1
|
|
||||||
rkh_pull_timeout=50
|
|
||||||
ft_over_ds=0
|
|
||||||
ap_table_expiration_time=36000
|
|
||||||
ap_table_max_size=10
|
|
||||||
rrm_neighbor_report=1
|
|
||||||
ocv=1
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
[SETUP]
|
|
||||||
num_radios=3
|
|
||||||
start_iwd=0
|
|
||||||
hwsim_medium=yes
|
|
||||||
|
|
||||||
[HOSTAPD]
|
|
||||||
rad0=ft-psk-ccmp-1.conf
|
|
||||||
rad1=ft-psk-ccmp-2.conf
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
[General]
|
|
||||||
EnableNetworkConfiguration=true
|
|
||||||
RoamRetryInterval=1
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
#! /usr/bin/python3
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import sys, os
|
|
||||||
|
|
||||||
sys.path.append('../util')
|
|
||||||
import iwd
|
|
||||||
from iwd import IWD
|
|
||||||
from iwd import PSKAgent
|
|
||||||
from iwd import NetworkType
|
|
||||||
from iwd import DeviceState
|
|
||||||
from hwsim import Hwsim
|
|
||||||
from hostapd import HostapdCLI
|
|
||||||
import testutil
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
|
||||||
def test_roam_before_netconfig(self):
|
|
||||||
wd = IWD(True)
|
|
||||||
|
|
||||||
device = wd.list_devices(1)[0]
|
|
||||||
device.get_ordered_network('TestFT', full_scan=True)
|
|
||||||
device.connect_bssid(self.bss_hostapd[1].bssid, wait=False)
|
|
||||||
|
|
||||||
self.bss_hostapd[1].wait_for_event(f'AP-STA-CONNECTED {device.address}')
|
|
||||||
device.wait_for_event("connecting (netconfig)")
|
|
||||||
|
|
||||||
roam_to = 0
|
|
||||||
roam_from = 1
|
|
||||||
|
|
||||||
# Roam back and forth, ensuring that the state transitions between
|
|
||||||
# roaming and connecting (netconfig).
|
|
||||||
for _ in range(0, 5):
|
|
||||||
self.rules[roam_to].signal = -2000
|
|
||||||
self.rules[roam_from].signal = -8000
|
|
||||||
|
|
||||||
# Station should internally transition to roaming, but remain in a
|
|
||||||
# connecting state on DBus
|
|
||||||
device.wait_for_event("ft-roaming")
|
|
||||||
self.assertEqual(device.state, DeviceState.connecting)
|
|
||||||
|
|
||||||
self.bss_hostapd[roam_to].wait_for_event(f'AP-STA-CONNECTED {device.address}')
|
|
||||||
device.wait_for_event("connecting (netconfig)")
|
|
||||||
|
|
||||||
tmp = roam_from
|
|
||||||
roam_from = roam_to
|
|
||||||
roam_to = tmp
|
|
||||||
|
|
||||||
self.bss_hostapd[roam_from].deauthenticate(device.address)
|
|
||||||
condition = 'obj.state == DeviceState.disconnected'
|
|
||||||
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')
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
hwsim = Hwsim()
|
|
||||||
|
|
||||||
IWD.copy_to_storage('TestFT.psk')
|
|
||||||
|
|
||||||
cls.bss_hostapd = [ HostapdCLI(config='ft-psk-ccmp-1.conf'),
|
|
||||||
HostapdCLI(config='ft-psk-ccmp-2.conf') ]
|
|
||||||
|
|
||||||
rule0 = hwsim.rules.create()
|
|
||||||
rule0.source = cls.bss_hostapd[0].bssid
|
|
||||||
rule0.signal = -6000
|
|
||||||
rule0.enabled = True
|
|
||||||
|
|
||||||
rule1 = hwsim.rules.create()
|
|
||||||
rule1.source = cls.bss_hostapd[1].bssid
|
|
||||||
rule1.signal = -2000
|
|
||||||
rule1.enabled = True
|
|
||||||
|
|
||||||
cls.rules = [rule0, rule1]
|
|
||||||
|
|
||||||
cls.bss_hostapd[0].set_address('12:00:00:00:00:01')
|
|
||||||
cls.bss_hostapd[1].set_address('12:00:00:00:00:02')
|
|
||||||
|
|
||||||
HostapdCLI.group_neighbors(*cls.bss_hostapd)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
IWD.clear_storage()
|
|
||||||
cls.bss_hostapd = None
|
|
||||||
cls.rules = None
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main(exit=True)
|
|
||||||
@ -47,6 +47,11 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
# Normal success case
|
# Normal success case
|
||||||
def test_owe_transition(self):
|
def test_owe_transition(self):
|
||||||
|
self.hapd_open.set_value('vendor_elements', 'dd15506f9a1c02000000f1000a6f77652d68696464656e')
|
||||||
|
self.hapd_open.reload()
|
||||||
|
self.hapd_owe.set_value('vendor_elements', 'dd15506f9a1c02000000f0000a7472616e736974696f6e')
|
||||||
|
self.hapd_owe.reload()
|
||||||
|
|
||||||
self.hapd_owe2.disable()
|
self.hapd_owe2.disable()
|
||||||
self.hapd_open2.disable()
|
self.hapd_open2.disable()
|
||||||
|
|
||||||
@ -54,8 +59,15 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
# Normal success case
|
# Normal success case
|
||||||
def test_owe_transition_multi_network(self):
|
def test_owe_transition_multi_network(self):
|
||||||
|
self.hapd_open.set_value('vendor_elements', 'dd15506f9a1c02000000f1000a6f77652d68696464656e')
|
||||||
|
self.hapd_open.reload()
|
||||||
|
self.hapd_owe.set_value('vendor_elements', 'dd15506f9a1c02000000f0000a7472616e736974696f6e')
|
||||||
|
self.hapd_owe.reload()
|
||||||
|
|
||||||
|
self.hapd_open2.set_value('vendor_elements', 'dd17506f9a1c02000000f1000c6f77652d68696464656e2d32')
|
||||||
self.hapd_open2.set_value('ssid', 'transition-2')
|
self.hapd_open2.set_value('ssid', 'transition-2')
|
||||||
self.hapd_open2.reload()
|
self.hapd_open2.reload()
|
||||||
|
self.hapd_owe2.set_value('vendor_elements', 'dd17506f9a1c02000000f0000c7472616e736974696f6e2d32')
|
||||||
self.hapd_owe2.set_value('ssid', 'owe-hidden-2')
|
self.hapd_owe2.set_value('ssid', 'owe-hidden-2')
|
||||||
self.hapd_owe2.reload()
|
self.hapd_owe2.reload()
|
||||||
|
|
||||||
@ -63,6 +75,11 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
# Two pairs of open/OWE BSS's (OWE BSS's have different SSIDs) */
|
# Two pairs of open/OWE BSS's (OWE BSS's have different SSIDs) */
|
||||||
def test_owe_transition_multi_bss(self):
|
def test_owe_transition_multi_bss(self):
|
||||||
|
self.hapd_open.set_value('vendor_elements', 'dd15506f9a1c02000000f1000a6f77652d68696464656e')
|
||||||
|
self.hapd_open.reload()
|
||||||
|
self.hapd_owe.set_value('vendor_elements', 'dd15506f9a1c02000000f0000a7472616e736974696f6e')
|
||||||
|
self.hapd_owe.reload()
|
||||||
|
|
||||||
self.hapd_open2.set_value('vendor_elements', 'dd17506f9a1c02000000f3000c6f77652d68696464656e2d32')
|
self.hapd_open2.set_value('vendor_elements', 'dd17506f9a1c02000000f3000c6f77652d68696464656e2d32')
|
||||||
self.hapd_open2.set_value('ssid', 'transition')
|
self.hapd_open2.set_value('ssid', 'transition')
|
||||||
self.hapd_open2.reload()
|
self.hapd_open2.reload()
|
||||||
@ -74,6 +91,11 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
# Two pairs of open/OWE BSS's (OWE BSS's have same SSID) */
|
# Two pairs of open/OWE BSS's (OWE BSS's have same SSID) */
|
||||||
def test_owe_transition_multi_bss_same_ssid(self):
|
def test_owe_transition_multi_bss_same_ssid(self):
|
||||||
|
self.hapd_open.set_value('vendor_elements', 'dd15506f9a1c02000000f1000a6f77652d68696464656e')
|
||||||
|
self.hapd_open.reload()
|
||||||
|
self.hapd_owe.set_value('vendor_elements', 'dd15506f9a1c02000000f0000a7472616e736974696f6e')
|
||||||
|
self.hapd_owe.reload()
|
||||||
|
|
||||||
self.hapd_open2.set_value('vendor_elements', 'dd15506f9a1c02000000f3000a6f77652d68696464656e')
|
self.hapd_open2.set_value('vendor_elements', 'dd15506f9a1c02000000f3000a6f77652d68696464656e')
|
||||||
self.hapd_open2.set_value('ssid', 'transition')
|
self.hapd_open2.set_value('ssid', 'transition')
|
||||||
self.hapd_open2.reload()
|
self.hapd_open2.reload()
|
||||||
@ -85,6 +107,11 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
# Normal success autoconnect case
|
# Normal success autoconnect case
|
||||||
def test_owe_transition_autoconnect(self):
|
def test_owe_transition_autoconnect(self):
|
||||||
|
self.hapd_open.set_value('vendor_elements', 'dd15506f9a1c02000000f1000a6f77652d68696464656e')
|
||||||
|
self.hapd_open.reload()
|
||||||
|
self.hapd_owe.set_value('vendor_elements', 'dd15506f9a1c02000000f0000a7472616e736974696f6e')
|
||||||
|
self.hapd_owe.reload()
|
||||||
|
|
||||||
self.hapd_owe2.disable()
|
self.hapd_owe2.disable()
|
||||||
self.hapd_open2.disable()
|
self.hapd_open2.disable()
|
||||||
|
|
||||||
@ -97,6 +124,8 @@ class Test(unittest.TestCase):
|
|||||||
def test_owe_transition_invalid_open_bssid(self):
|
def test_owe_transition_invalid_open_bssid(self):
|
||||||
self.hapd_open.set_value('vendor_elements', 'dd15506f9a1c02000000ff000a6f77652d68696464656e')
|
self.hapd_open.set_value('vendor_elements', 'dd15506f9a1c02000000ff000a6f77652d68696464656e')
|
||||||
self.hapd_open.reload()
|
self.hapd_open.reload()
|
||||||
|
self.hapd_owe.set_value('vendor_elements', 'dd15506f9a1c02000000f0000a7472616e736974696f6e')
|
||||||
|
self.hapd_owe.reload()
|
||||||
|
|
||||||
self.hapd_owe2.disable()
|
self.hapd_owe2.disable()
|
||||||
self.hapd_open2.disable()
|
self.hapd_open2.disable()
|
||||||
@ -106,6 +135,8 @@ class Test(unittest.TestCase):
|
|||||||
# OWE BSS has invalid BSSID in OWE transition element
|
# OWE BSS has invalid BSSID in OWE transition element
|
||||||
# Expected connection to Open BSS
|
# Expected connection to Open BSS
|
||||||
def test_owe_transition_invalid_owe_bssid(self):
|
def test_owe_transition_invalid_owe_bssid(self):
|
||||||
|
self.hapd_open.set_value('vendor_elements', 'dd15506f9a1c02000000f1000a6f77652d68696464656e')
|
||||||
|
self.hapd_open.reload()
|
||||||
self.hapd_owe.set_value('vendor_elements', 'dd15506f9a1c02000000ff000a7472616e736974696f6e')
|
self.hapd_owe.set_value('vendor_elements', 'dd15506f9a1c02000000ff000a7472616e736974696f6e')
|
||||||
self.hapd_owe.reload()
|
self.hapd_owe.reload()
|
||||||
|
|
||||||
@ -117,6 +148,8 @@ class Test(unittest.TestCase):
|
|||||||
# No OWE hidden network exists
|
# No OWE hidden network exists
|
||||||
# Expected connection to Open BSS
|
# Expected connection to Open BSS
|
||||||
def test_owe_transition_no_hidden_found(self):
|
def test_owe_transition_no_hidden_found(self):
|
||||||
|
self.hapd_open.set_value('vendor_elements', 'dd15506f9a1c02000000f1000a6f77652d68696464656e')
|
||||||
|
self.hapd_open.reload()
|
||||||
self.hapd_owe.disable()
|
self.hapd_owe.disable()
|
||||||
|
|
||||||
self.hapd_owe2.disable()
|
self.hapd_owe2.disable()
|
||||||
@ -127,6 +160,11 @@ class Test(unittest.TestCase):
|
|||||||
# Directly connect to valid OWE hidden network
|
# Directly connect to valid OWE hidden network
|
||||||
# Expected connection failure
|
# Expected connection failure
|
||||||
def test_owe_transition_connect_hidden_valid(self):
|
def test_owe_transition_connect_hidden_valid(self):
|
||||||
|
self.hapd_open.set_value('vendor_elements', 'dd15506f9a1c02000000f1000a6f77652d68696464656e')
|
||||||
|
self.hapd_open.reload()
|
||||||
|
self.hapd_owe.set_value('vendor_elements', 'dd15506f9a1c02000000f0000a7472616e736974696f6e')
|
||||||
|
self.hapd_owe.reload()
|
||||||
|
|
||||||
self.hapd_owe2.disable()
|
self.hapd_owe2.disable()
|
||||||
self.hapd_open2.disable()
|
self.hapd_open2.disable()
|
||||||
|
|
||||||
@ -151,6 +189,7 @@ class Test(unittest.TestCase):
|
|||||||
def test_owe_transition_band_info(self):
|
def test_owe_transition_band_info(self):
|
||||||
self.hapd_open.set_value('vendor_elements', 'dd17506f9a1c02000000f1000a6f77652d68696464656e5103')
|
self.hapd_open.set_value('vendor_elements', 'dd17506f9a1c02000000f1000a6f77652d68696464656e5103')
|
||||||
self.hapd_open.reload()
|
self.hapd_open.reload()
|
||||||
|
self.hapd_owe.set_value('vendor_elements', 'dd15506f9a1c02000000f0000a7472616e736974696f6e')
|
||||||
self.hapd_owe.set_value('channel', '3')
|
self.hapd_owe.set_value('channel', '3')
|
||||||
self.hapd_owe.reload()
|
self.hapd_owe.reload()
|
||||||
|
|
||||||
@ -162,6 +201,7 @@ class Test(unittest.TestCase):
|
|||||||
def test_owe_transition_wrong_band_info(self):
|
def test_owe_transition_wrong_band_info(self):
|
||||||
self.hapd_open.set_value('vendor_elements', 'dd17506f9a1c02000000f1000a6f77652d68696464656e5102')
|
self.hapd_open.set_value('vendor_elements', 'dd17506f9a1c02000000f1000a6f77652d68696464656e5102')
|
||||||
self.hapd_open.reload()
|
self.hapd_open.reload()
|
||||||
|
self.hapd_owe.set_value('vendor_elements', 'dd15506f9a1c02000000f0000a7472616e736974696f6e')
|
||||||
self.hapd_owe.set_value('channel', '3')
|
self.hapd_owe.set_value('channel', '3')
|
||||||
self.hapd_owe.reload()
|
self.hapd_owe.reload()
|
||||||
|
|
||||||
@ -172,6 +212,11 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
# OWE Transition pair + additional open network with the same SSID
|
# OWE Transition pair + additional open network with the same SSID
|
||||||
def test_owe_transition_extra_open(self):
|
def test_owe_transition_extra_open(self):
|
||||||
|
self.hapd_open.set_value('vendor_elements', 'dd15506f9a1c02000000f1000a6f77652d68696464656e')
|
||||||
|
self.hapd_open.reload()
|
||||||
|
self.hapd_owe.set_value('vendor_elements', 'dd15506f9a1c02000000f0000a7472616e736974696f6e')
|
||||||
|
self.hapd_owe.reload()
|
||||||
|
|
||||||
self.hapd_open2.set_value('ssid', 'transition')
|
self.hapd_open2.set_value('ssid', 'transition')
|
||||||
self.hapd_open2.reload()
|
self.hapd_open2.reload()
|
||||||
|
|
||||||
@ -190,19 +235,17 @@ class Test(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.wd = IWD(True)
|
self.wd = IWD(True)
|
||||||
self.hapd_owe = HostapdCLI(config='ssidOWE.conf')
|
self.hapd_owe = HostapdCLI(config='ssidOWE.conf')
|
||||||
self.hapd_owe.default()
|
|
||||||
self.hapd_open = HostapdCLI(config='ssidOpen.conf')
|
self.hapd_open = HostapdCLI(config='ssidOpen.conf')
|
||||||
self.hapd_open.default()
|
|
||||||
self.hapd_owe2 = HostapdCLI(config='ssidOWE-2.conf')
|
self.hapd_owe2 = HostapdCLI(config='ssidOWE-2.conf')
|
||||||
self.hapd_owe2.default()
|
|
||||||
self.hapd_open2 = HostapdCLI(config='ssidOpen-2.conf')
|
self.hapd_open2 = HostapdCLI(config='ssidOpen-2.conf')
|
||||||
self.hapd_open2.default()
|
|
||||||
|
|
||||||
self.hwsim = Hwsim()
|
self.hwsim = Hwsim()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
IWD.clear_storage()
|
IWD.clear_storage()
|
||||||
|
|
||||||
|
self.hapd_owe.set_value('channel', '1')
|
||||||
|
|
||||||
self.wd = None
|
self.wd = None
|
||||||
self.hapd_open = None
|
self.hapd_open = None
|
||||||
self.hapd_owe = None
|
self.hapd_owe = None
|
||||||
|
|||||||
@ -7,5 +7,3 @@ ieee80211w=1
|
|||||||
wpa=2
|
wpa=2
|
||||||
wpa_key_mgmt=OWE
|
wpa_key_mgmt=OWE
|
||||||
rsn_pairwise=CCMP
|
rsn_pairwise=CCMP
|
||||||
|
|
||||||
vendor_elements=dd17506f9a1c02000000f0000c7472616e736974696f6e2d32
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@ ieee80211w=1
|
|||||||
wpa=2
|
wpa=2
|
||||||
wpa_key_mgmt=OWE
|
wpa_key_mgmt=OWE
|
||||||
rsn_pairwise=CCMP
|
rsn_pairwise=CCMP
|
||||||
vendor_elements=dd15506f9a1c02000000f0000a7472616e736974696f6e
|
|
||||||
|
|
||||||
# You would conventionally use these options but hostapd does not include an
|
# You would conventionally use these options but hostapd does not include an
|
||||||
# IE for the OWE network, hence vendor_elements must be used directly
|
# IE for the OWE network, hence vendor_elements must be used directly
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
channel=1
|
channel=1
|
||||||
ssid=transition-2
|
ssid=transition-2
|
||||||
bssid=02:00:00:00:f2:00
|
bssid=02:00:00:00:f2:00
|
||||||
vendor_elements=dd17506f9a1c02000000f1000c6f77652d68696464656e2d32
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
channel=1
|
channel=1
|
||||||
ssid=transition
|
ssid=transition
|
||||||
bssid=02:00:00:00:f0:00
|
bssid=02:00:00:00:f0:00
|
||||||
vendor_elements=dd15506f9a1c02000000f1000a6f77652d68696464656e
|
|
||||||
|
|
||||||
# You would conventionally use these options but hostapd does not include an
|
# You would conventionally use these options but hostapd does not include an
|
||||||
# IE for the OWE network, hence vendor_elements must be used directly
|
# IE for the OWE network, hence vendor_elements must be used directly
|
||||||
|
|||||||
@ -64,39 +64,6 @@ class Test(unittest.TestCase):
|
|||||||
self.assertRaises(Exception, testutil.test_ifaces_connected,
|
self.assertRaises(Exception, testutil.test_ifaces_connected,
|
||||||
(hapd0.ifname, device.name, True, True))
|
(hapd0.ifname, device.name, True, True))
|
||||||
|
|
||||||
def test_auto_default_group(self):
|
|
||||||
wd = IWD()
|
|
||||||
hapd = HostapdCLI(config='ssidOWE-1.conf')
|
|
||||||
|
|
||||||
devices = wd.list_devices(1)
|
|
||||||
device = devices[0]
|
|
||||||
|
|
||||||
device.get_ordered_network('ssidOWE')
|
|
||||||
|
|
||||||
device.connect_bssid(hapd.bssid)
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
# Should have rejected group 20, but still connected on 19
|
|
||||||
self.assertEqual(device.event_ocurred("ecc-group-rejected"), True)
|
|
||||||
|
|
||||||
testutil.test_iface_operstate()
|
|
||||||
testutil.test_ifaces_connected(device.name, hapd.ifname)
|
|
||||||
|
|
||||||
device.disconnect()
|
|
||||||
|
|
||||||
device.connect_bssid(hapd.bssid)
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
# IWD should have used the default group, no rejection
|
|
||||||
self.assertEqual(device.event_ocurred("ecc-group-rejected"), False)
|
|
||||||
|
|
||||||
testutil.test_iface_operstate()
|
|
||||||
testutil.test_ifaces_connected(device.name, hapd.ifname)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@ -1,114 +0,0 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import sys
|
|
||||||
|
|
||||||
sys.path.append('../util')
|
|
||||||
from iwd import IWD
|
|
||||||
from iwd import PSKAgent
|
|
||||||
from iwd import NetworkType
|
|
||||||
from hostapd import HostapdCLI
|
|
||||||
import testutil
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
|
||||||
|
|
||||||
def validate_connection(self, wd, ssid, hostapd, expected_group):
|
|
||||||
psk_agent = PSKAgent("secret123")
|
|
||||||
wd.register_psk_agent(psk_agent)
|
|
||||||
|
|
||||||
devices = wd.list_devices(1)
|
|
||||||
self.assertIsNotNone(devices)
|
|
||||||
device = devices[0]
|
|
||||||
|
|
||||||
device.disconnect()
|
|
||||||
|
|
||||||
network = device.get_ordered_network(ssid, full_scan=True)
|
|
||||||
|
|
||||||
self.assertEqual(network.type, NetworkType.psk)
|
|
||||||
|
|
||||||
network.network_object.connect()
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
wd.wait(2)
|
|
||||||
|
|
||||||
testutil.test_iface_operstate(intf=device.name)
|
|
||||||
testutil.test_ifaces_connected(if0=device.name, if1=hostapd.ifname)
|
|
||||||
|
|
||||||
# Initial connection PMKSA should not be used. So we should see the
|
|
||||||
# SAE group set.
|
|
||||||
sta_status = hostapd.sta_status(device.address)
|
|
||||||
self.assertEqual(int(sta_status["sae_group"]), expected_group)
|
|
||||||
|
|
||||||
device.disconnect()
|
|
||||||
|
|
||||||
condition = 'not obj.connected'
|
|
||||||
wd.wait_for_object_condition(network.network_object, condition)
|
|
||||||
|
|
||||||
wd.unregister_psk_agent(psk_agent)
|
|
||||||
|
|
||||||
network.network_object.connect(wait=False)
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
wd.wait(2)
|
|
||||||
|
|
||||||
testutil.test_iface_operstate(intf=device.name)
|
|
||||||
testutil.test_ifaces_connected(if0=device.name, if1=hostapd.ifname)
|
|
||||||
|
|
||||||
# Having connected once prior we should have a PMKSA and SAE should not
|
|
||||||
# have been used.
|
|
||||||
sta_status = hostapd.sta_status(device.address)
|
|
||||||
self.assertNotIn("sae_group", sta_status.keys())
|
|
||||||
|
|
||||||
device.disconnect()
|
|
||||||
|
|
||||||
condition = 'not obj.connected'
|
|
||||||
wd.wait_for_object_condition(network.network_object, condition)
|
|
||||||
|
|
||||||
hostapd.pmksa_flush()
|
|
||||||
|
|
||||||
wd.wait(5)
|
|
||||||
|
|
||||||
network.network_object.connect()
|
|
||||||
|
|
||||||
device.wait_for_event("pmksa-invalid-pmkid")
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
wd.wait(2)
|
|
||||||
|
|
||||||
testutil.test_iface_operstate(intf=device.name)
|
|
||||||
testutil.test_ifaces_connected(if0=device.name, if1=hostapd.ifname)
|
|
||||||
|
|
||||||
# Manually flushing the PMKSA from the AP then reconnecting we should
|
|
||||||
# have failed (INVALID_PMKID) then retried the same BSS with SAE, not
|
|
||||||
# PMKSA.
|
|
||||||
sta_status = hostapd.sta_status(device.address)
|
|
||||||
self.assertEqual(int(sta_status["sae_group"]), expected_group)
|
|
||||||
|
|
||||||
def test_pmksa_sae(self):
|
|
||||||
self.hostapd.wait_for_event("AP-ENABLED")
|
|
||||||
self.validate_connection(self.wd, "ssidSAE", self.hostapd, 19)
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.hostapd.default()
|
|
||||||
self.wd = IWD(True)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.wd.clear_storage()
|
|
||||||
self.wd = None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
cls.hostapd = HostapdCLI(config='ssidSAE.conf')
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
pass
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main(exit=True)
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
[SETUP]
|
|
||||||
num_radios=2
|
|
||||||
start_iwd=0
|
|
||||||
hwsim_medium=yes
|
|
||||||
|
|
||||||
[HOSTAPD]
|
|
||||||
rad0=ssidSAE.conf
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
hw_mode=g
|
|
||||||
channel=1
|
|
||||||
ssid=ssidSAE
|
|
||||||
|
|
||||||
wpa=2
|
|
||||||
wpa_key_mgmt=SAE
|
|
||||||
wpa_pairwise=CCMP
|
|
||||||
sae_password=secret123
|
|
||||||
sae_groups=19
|
|
||||||
ieee80211w=2
|
|
||||||
sae_pwe=0
|
|
||||||
rsn_preauth=1
|
|
||||||
@ -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
|
|
||||||
@ -91,32 +91,70 @@ class Test(unittest.TestCase):
|
|||||||
wd.wait_for_object_condition(device, condition)
|
wd.wait_for_object_condition(device, condition)
|
||||||
|
|
||||||
def test_ft_psk(self):
|
def test_ft_psk(self):
|
||||||
self.validate_connection(self.wd)
|
wd = IWD(True)
|
||||||
|
|
||||||
def test_ft_psk_over_ds(self):
|
self.bss_hostapd[0].set_value('wpa_key_mgmt', 'FT-PSK')
|
||||||
self.bss_hostapd[0].set_value('ft_over_ds', '1')
|
self.bss_hostapd[0].set_value('ft_over_ds', '0')
|
||||||
|
self.bss_hostapd[0].set_value('ocv', '1')
|
||||||
self.bss_hostapd[0].reload()
|
self.bss_hostapd[0].reload()
|
||||||
self.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
self.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
||||||
|
|
||||||
self.bss_hostapd[1].set_value('ft_over_ds', '1')
|
self.bss_hostapd[1].set_value('wpa_key_mgmt', 'FT-PSK')
|
||||||
|
self.bss_hostapd[1].set_value('ft_over_ds', '0')
|
||||||
|
self.bss_hostapd[0].set_value('ocv', '1')
|
||||||
self.bss_hostapd[1].reload()
|
self.bss_hostapd[1].reload()
|
||||||
self.bss_hostapd[1].wait_for_event("AP-ENABLED")
|
self.bss_hostapd[1].wait_for_event("AP-ENABLED")
|
||||||
|
|
||||||
self.validate_connection(self.wd, over_ds=True)
|
self.validate_connection(wd)
|
||||||
|
|
||||||
|
def test_ft_psk_over_ds(self):
|
||||||
|
wd = IWD(True)
|
||||||
|
|
||||||
|
self.bss_hostapd[0].set_value('wpa_key_mgmt', 'FT-PSK')
|
||||||
|
self.bss_hostapd[0].set_value('ft_over_ds', '1')
|
||||||
|
self.bss_hostapd[0].set_value('ocv', '1')
|
||||||
|
self.bss_hostapd[0].reload()
|
||||||
|
self.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
||||||
|
|
||||||
|
self.bss_hostapd[1].set_value('wpa_key_mgmt', 'FT-PSK')
|
||||||
|
self.bss_hostapd[1].set_value('ft_over_ds', '1')
|
||||||
|
self.bss_hostapd[1].set_value('ocv', '1')
|
||||||
|
self.bss_hostapd[1].reload()
|
||||||
|
self.bss_hostapd[1].wait_for_event("AP-ENABLED")
|
||||||
|
|
||||||
|
self.validate_connection(wd, over_ds=True)
|
||||||
|
|
||||||
def test_reassociate_psk(self):
|
def test_reassociate_psk(self):
|
||||||
|
wd = IWD(True)
|
||||||
|
|
||||||
self.bss_hostapd[0].set_value('wpa_key_mgmt', 'WPA-PSK')
|
self.bss_hostapd[0].set_value('wpa_key_mgmt', 'WPA-PSK')
|
||||||
|
self.bss_hostapd[0].set_value('ft_over_ds', '0')
|
||||||
self.bss_hostapd[0].reload()
|
self.bss_hostapd[0].reload()
|
||||||
self.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
self.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
||||||
|
|
||||||
self.bss_hostapd[1].set_value('wpa_key_mgmt', 'WPA-PSK')
|
self.bss_hostapd[1].set_value('wpa_key_mgmt', 'WPA-PSK')
|
||||||
|
self.bss_hostapd[1].set_value('ft_over_ds', '0')
|
||||||
self.bss_hostapd[1].reload()
|
self.bss_hostapd[1].reload()
|
||||||
self.bss_hostapd[1].wait_for_event("AP-ENABLED")
|
self.bss_hostapd[1].wait_for_event("AP-ENABLED")
|
||||||
|
|
||||||
self.validate_connection(self.wd)
|
self.validate_connection(wd)
|
||||||
|
|
||||||
def test_roam_packet_loss(self):
|
def test_roam_packet_loss(self):
|
||||||
self.validate_connection(self.wd, pkt_loss=True)
|
wd = IWD(True)
|
||||||
|
|
||||||
|
self.bss_hostapd[0].set_value('wpa_key_mgmt', 'FT-PSK')
|
||||||
|
self.bss_hostapd[0].set_value('ft_over_ds', '0')
|
||||||
|
self.bss_hostapd[0].set_value('ocv', '1')
|
||||||
|
self.bss_hostapd[0].reload()
|
||||||
|
self.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
||||||
|
|
||||||
|
self.bss_hostapd[1].set_value('wpa_key_mgmt', 'FT-PSK')
|
||||||
|
self.bss_hostapd[1].set_value('ft_over_ds', '0')
|
||||||
|
self.bss_hostapd[0].set_value('ocv', '1')
|
||||||
|
self.bss_hostapd[1].reload()
|
||||||
|
self.bss_hostapd[1].wait_for_event("AP-ENABLED")
|
||||||
|
|
||||||
|
self.validate_connection(wd, pkt_loss=True)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
os.system('ip link set "' + self.bss_hostapd[0].ifname + '" down')
|
os.system('ip link set "' + self.bss_hostapd[0].ifname + '" down')
|
||||||
@ -128,15 +166,6 @@ class Test(unittest.TestCase):
|
|||||||
self.rule1.enabled = False
|
self.rule1.enabled = False
|
||||||
self.rule2.enabled = False
|
self.rule2.enabled = False
|
||||||
|
|
||||||
for hapd in self.bss_hostapd:
|
|
||||||
hapd.default()
|
|
||||||
|
|
||||||
self.wd.stop()
|
|
||||||
self.wd = None
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.wd = IWD(True)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
hwsim = Hwsim()
|
hwsim = Hwsim()
|
||||||
@ -144,10 +173,9 @@ class Test(unittest.TestCase):
|
|||||||
IWD.copy_to_storage('TestFT.psk')
|
IWD.copy_to_storage('TestFT.psk')
|
||||||
|
|
||||||
cls.bss_hostapd = [ HostapdCLI(config='ft-psk-ccmp-1.conf'),
|
cls.bss_hostapd = [ HostapdCLI(config='ft-psk-ccmp-1.conf'),
|
||||||
HostapdCLI(config='ft-psk-ccmp-2.conf') ]
|
HostapdCLI(config='ft-psk-ccmp-2.conf'),
|
||||||
|
HostapdCLI(config='ft-psk-ccmp-3.conf') ]
|
||||||
unused = HostapdCLI(config='ft-psk-ccmp-3.conf')
|
cls.bss_hostapd[2].disable()
|
||||||
unused.disable()
|
|
||||||
|
|
||||||
rad0 = hwsim.get_radio('rad0')
|
rad0 = hwsim.get_radio('rad0')
|
||||||
rad3 = hwsim.get_radio('rad3')
|
rad3 = hwsim.get_radio('rad3')
|
||||||
@ -177,9 +205,8 @@ class Test(unittest.TestCase):
|
|||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
IWD.clear_storage()
|
IWD.clear_storage()
|
||||||
cls.bss_hostapd = None
|
cls.bss_hostapd = None
|
||||||
|
cls.rule0.enabled = False
|
||||||
cls.rule0.remove()
|
cls.rule0.remove()
|
||||||
cls.rule1.remove()
|
|
||||||
cls.rule2.remove()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(exit=True)
|
unittest.main(exit=True)
|
||||||
|
|||||||
@ -1,112 +0,0 @@
|
|||||||
#! /usr/bin/python3
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import sys, os
|
|
||||||
|
|
||||||
sys.path.append('../util')
|
|
||||||
import iwd
|
|
||||||
from iwd import IWD
|
|
||||||
from iwd import PSKAgent
|
|
||||||
from iwd import NetworkType
|
|
||||||
from hwsim import Hwsim
|
|
||||||
from hostapd import HostapdCLI
|
|
||||||
import testutil
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
|
||||||
def validate_connection(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))
|
|
||||||
|
|
||||||
self.rule0.enabled = True
|
|
||||||
|
|
||||||
device.roam(self.bss_hostapd[1].bssid)
|
|
||||||
|
|
||||||
device.clear_events()
|
|
||||||
device.wait_for_event("handshake-started")
|
|
||||||
self.bss_hostapd[1].deauthenticate(device.address, reason=15, test=1)
|
|
||||||
|
|
||||||
# Check that iwd is on BSS 1 once out of roaming state and doesn't
|
|
||||||
# go through 'disconnected', 'autoconnect', 'connecting' in between
|
|
||||||
from_condition = 'obj.state == DeviceState.roaming'
|
|
||||||
to_condition = 'obj.state == DeviceState.disconnected'
|
|
||||||
wd.wait_for_object_change(device, from_condition, to_condition)
|
|
||||||
|
|
||||||
def test_disconnect_during_handshake(self):
|
|
||||||
self.bss_hostapd[0].set_value('wpa_key_mgmt', 'WPA-PSK')
|
|
||||||
self.bss_hostapd[0].reload()
|
|
||||||
self.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
|
||||||
|
|
||||||
self.bss_hostapd[1].set_value('wpa_key_mgmt', 'WPA-PSK')
|
|
||||||
self.bss_hostapd[1].reload()
|
|
||||||
self.bss_hostapd[1].wait_for_event("AP-ENABLED")
|
|
||||||
|
|
||||||
self.validate_connection(self.wd)
|
|
||||||
|
|
||||||
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):
|
|
||||||
hwsim = Hwsim()
|
|
||||||
|
|
||||||
IWD.copy_to_storage('TestFT.psk')
|
|
||||||
|
|
||||||
cls.bss_hostapd = [ HostapdCLI(config='ft-psk-ccmp-1.conf'),
|
|
||||||
HostapdCLI(config='ft-psk-ccmp-2.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')
|
|
||||||
|
|
||||||
rad1 = hwsim.get_radio('rad1')
|
|
||||||
|
|
||||||
cls.rule0 = hwsim.rules.create()
|
|
||||||
cls.rule0.destination = rad1.addresses[0]
|
|
||||||
cls.rule0.prefix = '08'
|
|
||||||
cls.rule0.drop = True
|
|
||||||
|
|
||||||
HostapdCLI.group_neighbors(*cls.bss_hostapd)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
IWD.clear_storage()
|
|
||||||
cls.bss_hostapd = None
|
|
||||||
cls.rule0.remove()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main(exit=True)
|
|
||||||
@ -41,14 +41,24 @@ class Test(unittest.TestCase):
|
|||||||
self.assertRaises(Exception, testutil.test_ifaces_connected,
|
self.assertRaises(Exception, testutil.test_ifaces_connected,
|
||||||
(prev.ifname, device.name, True, True))
|
(prev.ifname, device.name, True, True))
|
||||||
|
|
||||||
|
|
||||||
# FT-over-Air failure, should stay connected
|
# FT-over-Air failure, should stay connected
|
||||||
def test_ft_over_air_failure(self):
|
def test_ft_over_air_failure(self):
|
||||||
self.rule2.enabled = True
|
self.bss_hostapd[0].set_value('wpa_key_mgmt', 'FT-PSK')
|
||||||
self.rule3.enabled = True
|
self.bss_hostapd[0].set_value('ft_over_ds', '0')
|
||||||
|
self.bss_hostapd[0].reload()
|
||||||
|
self.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
||||||
|
|
||||||
device = self.wd.list_devices(1)[0]
|
self.bss_hostapd[1].set_value('wpa_key_mgmt', 'FT-PSK')
|
||||||
|
self.bss_hostapd[1].set_value('ft_over_ds', '0')
|
||||||
|
self.bss_hostapd[1].reload()
|
||||||
|
self.bss_hostapd[1].wait_for_event("AP-ENABLED")
|
||||||
|
|
||||||
self.connect(self.wd, device, self.bss_hostapd[0])
|
wd = IWD(True)
|
||||||
|
|
||||||
|
device = wd.list_devices(1)[0]
|
||||||
|
|
||||||
|
self.connect(wd, device, self.bss_hostapd[0])
|
||||||
|
|
||||||
self.rule0.enabled = True
|
self.rule0.enabled = True
|
||||||
|
|
||||||
@ -60,112 +70,11 @@ class Test(unittest.TestCase):
|
|||||||
self.rule0.enabled = False
|
self.rule0.enabled = False
|
||||||
|
|
||||||
# IWD should then try BSS 2, and succeed
|
# IWD should then try BSS 2, and succeed
|
||||||
device.wait_for_event('ft-roaming', timeout=60)
|
self.verify_roam(wd, device, self.bss_hostapd[0], self.bss_hostapd[2])
|
||||||
self.verify_roam(self.wd, device, self.bss_hostapd[0], self.bss_hostapd[2])
|
|
||||||
|
|
||||||
self.bss_hostapd[2].deauthenticate(device.address)
|
self.bss_hostapd[2].deauthenticate(device.address)
|
||||||
|
|
||||||
# Tests that an associate even should cause a disconnect
|
|
||||||
def test_ft_over_air_assoc_timeout(self):
|
|
||||||
self.rule2.enabled = True
|
|
||||||
self.rule3.enabled = True
|
|
||||||
self.assoc_rule.enabled = True
|
|
||||||
|
|
||||||
device = self.wd.list_devices(1)[0]
|
|
||||||
|
|
||||||
self.connect(self.wd, device, self.bss_hostapd[0])
|
|
||||||
|
|
||||||
device.wait_for_event('ft-roaming', timeout=60)
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.disconnected'
|
condition = 'obj.state == DeviceState.disconnected'
|
||||||
self.wd.wait_for_object_condition(device, condition)
|
wd.wait_for_object_condition(device, condition)
|
||||||
|
|
||||||
# FT-over-Air failure with Invalid PMKID, should reassociate
|
|
||||||
def test_ft_over_air_fallback(self):
|
|
||||||
self.rule_bss0.signal = -8000
|
|
||||||
self.rule_bss0.enabled = True
|
|
||||||
self.rule_bss1.signal = -7500
|
|
||||||
self.rule_bss1.enabled = True
|
|
||||||
self.rule_bss2.signal = -6000
|
|
||||||
self.rule_bss2.enabled = True
|
|
||||||
|
|
||||||
# This will cause this BSS to reject any FT roams as its unable to
|
|
||||||
# get keys from other APs
|
|
||||||
self.bss_hostapd[2].set_value('ft_psk_generate_local', '0')
|
|
||||||
self.bss_hostapd[2].reload()
|
|
||||||
|
|
||||||
device = self.wd.list_devices(1)[0]
|
|
||||||
|
|
||||||
self.connect(self.wd, device, self.bss_hostapd[0])
|
|
||||||
|
|
||||||
# IWD should connect, then attempt a roam to BSS 1, which should
|
|
||||||
# fail and cause a fallback to reassociation
|
|
||||||
device.wait_for_event('ft-fallback-to-reassoc', timeout=60)
|
|
||||||
device.wait_for_event('roaming', timeout=60)
|
|
||||||
|
|
||||||
self.verify_roam(self.wd, device, self.bss_hostapd[0], self.bss_hostapd[2])
|
|
||||||
|
|
||||||
# Trigger another roam
|
|
||||||
self.rule_bss2.signal = -8000
|
|
||||||
|
|
||||||
device.wait_for_event('ft-roaming', timeout=60)
|
|
||||||
|
|
||||||
# Ensure an FT roam back to a properly configured AP works.
|
|
||||||
self.verify_roam(self.wd, device, self.bss_hostapd[2], self.bss_hostapd[1])
|
|
||||||
|
|
||||||
self.bss_hostapd[1].deauthenticate(device.address)
|
|
||||||
condition = 'obj.state == DeviceState.disconnected'
|
|
||||||
self.wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
# FT-over-Air failure with Invalid PMKID. The ranking is such that other
|
|
||||||
# FT candidates are available so it should FT elsewhere rather than
|
|
||||||
# retry with reassociation
|
|
||||||
def test_ft_over_air_fallback_retry_ft(self):
|
|
||||||
self.rule_bss0.signal = -8000
|
|
||||||
self.rule_bss0.enabled = True
|
|
||||||
self.rule_bss1.signal = -7300
|
|
||||||
self.rule_bss1.enabled = True
|
|
||||||
self.rule_bss2.signal = -7100
|
|
||||||
self.rule_bss2.enabled = True
|
|
||||||
|
|
||||||
# This will cause this BSS to reject any FT roams as its unable to
|
|
||||||
# get keys from other APs
|
|
||||||
self.bss_hostapd[2].set_value('ft_psk_generate_local', '0')
|
|
||||||
self.bss_hostapd[2].reload()
|
|
||||||
|
|
||||||
device = self.wd.list_devices(1)[0]
|
|
||||||
|
|
||||||
self.connect(self.wd, device, self.bss_hostapd[0])
|
|
||||||
|
|
||||||
# IWD should connect, then attempt a roam to BSS 1, which should
|
|
||||||
# fail and cause the rank to be re-computed. This should then put
|
|
||||||
# bss 1 as the next candidate (since the FT factor is removed)
|
|
||||||
device.wait_for_event('ft-fallback-to-reassoc', timeout=60)
|
|
||||||
device.wait_for_event('ft-roaming', timeout=60)
|
|
||||||
|
|
||||||
self.verify_roam(self.wd, device, self.bss_hostapd[0], self.bss_hostapd[1])
|
|
||||||
|
|
||||||
self.bss_hostapd[1].deauthenticate(device.address)
|
|
||||||
condition = 'obj.state == DeviceState.disconnected'
|
|
||||||
self.wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
def test_ft_deauth_before_association(self):
|
|
||||||
self.rule2.enabled = True
|
|
||||||
self.rule3.enabled = True
|
|
||||||
|
|
||||||
device = self.wd.list_devices(1)[0]
|
|
||||||
|
|
||||||
self.connect(self.wd, device, self.bss_hostapd[0])
|
|
||||||
|
|
||||||
device.wait_for_event('ft-authenticating', timeout=60)
|
|
||||||
|
|
||||||
self.bss_hostapd[1].deauthenticate(device.address)
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.disconnected'
|
|
||||||
self.wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.wd = IWD(True)
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
os.system('ip link set "' + self.bss_hostapd[0].ifname + '" down')
|
os.system('ip link set "' + self.bss_hostapd[0].ifname + '" down')
|
||||||
@ -176,17 +85,6 @@ class Test(unittest.TestCase):
|
|||||||
self.rule0.enabled = False
|
self.rule0.enabled = False
|
||||||
self.rule1.enabled = False
|
self.rule1.enabled = False
|
||||||
self.rule2.enabled = False
|
self.rule2.enabled = False
|
||||||
self.rule3.enabled = False
|
|
||||||
self.rule_bss0.enabled = False
|
|
||||||
self.rule_bss1.enabled = False
|
|
||||||
self.rule_bss2.enabled = False
|
|
||||||
self.assoc_rule.enabled = False
|
|
||||||
|
|
||||||
for hapd in self.bss_hostapd:
|
|
||||||
hapd.default()
|
|
||||||
|
|
||||||
self.wd.stop()
|
|
||||||
self.wd = None
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
@ -208,11 +106,6 @@ class Test(unittest.TestCase):
|
|||||||
cls.rule0.prefix = 'b0'
|
cls.rule0.prefix = 'b0'
|
||||||
cls.rule0.drop = True
|
cls.rule0.drop = True
|
||||||
|
|
||||||
# Drop Associate frames
|
|
||||||
cls.assoc_rule = hwsim.rules.create()
|
|
||||||
cls.assoc_rule.prefix = '20'
|
|
||||||
cls.assoc_rule.drop = True
|
|
||||||
|
|
||||||
# Drop Action frames
|
# Drop Action frames
|
||||||
cls.rule1 = hwsim.rules.create()
|
cls.rule1 = hwsim.rules.create()
|
||||||
cls.rule1.bidirectional = True
|
cls.rule1.bidirectional = True
|
||||||
@ -223,20 +116,13 @@ class Test(unittest.TestCase):
|
|||||||
cls.rule2 = hwsim.rules.create()
|
cls.rule2 = hwsim.rules.create()
|
||||||
cls.rule2.source = hwsim.get_radio('rad0').addresses[0]
|
cls.rule2.source = hwsim.get_radio('rad0').addresses[0]
|
||||||
cls.rule2.signal = -8000
|
cls.rule2.signal = -8000
|
||||||
|
cls.rule2.enabled = True
|
||||||
|
|
||||||
# Causes IWD to first prefer BSS 1 to roam, then BSS 2.
|
# Causes IWD to first prefer BSS 1 to roam, then BSS 2.
|
||||||
cls.rule3 = hwsim.rules.create()
|
cls.rule3 = hwsim.rules.create()
|
||||||
cls.rule3.source = hwsim.get_radio('rad2').addresses[0]
|
cls.rule3.source = hwsim.get_radio('rad2').addresses[0]
|
||||||
cls.rule3.signal = -7000
|
cls.rule3.signal = -7000
|
||||||
|
cls.rule3.enabled = True
|
||||||
cls.rule_bss0 = hwsim.rules.create()
|
|
||||||
cls.rule_bss0.source = hwsim.get_radio('rad0').addresses[0]
|
|
||||||
cls.rule_bss1 = hwsim.rules.create()
|
|
||||||
cls.rule_bss1.source = hwsim.get_radio('rad1').addresses[0]
|
|
||||||
cls.rule_bss2 = hwsim.rules.create()
|
|
||||||
cls.rule_bss2.source = hwsim.get_radio('rad2').addresses[0]
|
|
||||||
|
|
||||||
HostapdCLI.group_neighbors(*cls.bss_hostapd)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
@ -244,12 +130,6 @@ class Test(unittest.TestCase):
|
|||||||
cls.bss_hostapd = None
|
cls.bss_hostapd = None
|
||||||
cls.rule0.remove()
|
cls.rule0.remove()
|
||||||
cls.rule1.remove()
|
cls.rule1.remove()
|
||||||
cls.rule2.remove()
|
|
||||||
cls.rule3.remove()
|
|
||||||
cls.assoc_rule.remove()
|
|
||||||
cls.rule_bss0.remove()
|
|
||||||
cls.rule_bss1.remove()
|
|
||||||
cls.rule_bss2.remove()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(exit=True)
|
unittest.main(exit=True)
|
||||||
|
|||||||
@ -13,7 +13,7 @@ wpa=2
|
|||||||
wpa_key_mgmt=FT-PSK
|
wpa_key_mgmt=FT-PSK
|
||||||
wpa_pairwise=CCMP
|
wpa_pairwise=CCMP
|
||||||
wpa_passphrase=EasilyGuessedPassword
|
wpa_passphrase=EasilyGuessedPassword
|
||||||
ieee80211w=0
|
ieee80211w=1
|
||||||
rsn_preauth=1
|
rsn_preauth=1
|
||||||
rsn_preauth_interfaces=lo
|
rsn_preauth_interfaces=lo
|
||||||
disable_pmksa_caching=0
|
disable_pmksa_caching=0
|
||||||
@ -33,9 +33,7 @@ pmk_r1_push=0
|
|||||||
# case. Only works with FT-PSK, otherwise brctl needs to be installed and
|
# case. Only works with FT-PSK, otherwise brctl needs to be installed and
|
||||||
# CONFIG_BRIDGE enabled in the kernel.
|
# CONFIG_BRIDGE enabled in the kernel.
|
||||||
ft_psk_generate_local=1
|
ft_psk_generate_local=1
|
||||||
rkh_pull_timeout=50
|
|
||||||
ft_over_ds=0
|
ft_over_ds=0
|
||||||
ap_table_expiration_time=36000
|
ap_table_expiration_time=36000
|
||||||
ap_table_max_size=10
|
ap_table_max_size=10
|
||||||
rrm_neighbor_report=1
|
rrm_neighbor_report=1
|
||||||
ocv=1
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ wpa=2
|
|||||||
wpa_key_mgmt=FT-PSK
|
wpa_key_mgmt=FT-PSK
|
||||||
wpa_pairwise=CCMP
|
wpa_pairwise=CCMP
|
||||||
wpa_passphrase=EasilyGuessedPassword
|
wpa_passphrase=EasilyGuessedPassword
|
||||||
ieee80211w=0
|
ieee80211w=1
|
||||||
rsn_preauth=1
|
rsn_preauth=1
|
||||||
rsn_preauth_interfaces=lo
|
rsn_preauth_interfaces=lo
|
||||||
disable_pmksa_caching=0
|
disable_pmksa_caching=0
|
||||||
@ -33,9 +33,7 @@ pmk_r1_push=0
|
|||||||
# case. Only works with FT-PSK, otherwise brctl needs to be installed and
|
# case. Only works with FT-PSK, otherwise brctl needs to be installed and
|
||||||
# CONFIG_BRIDGE enabled in the kernel.
|
# CONFIG_BRIDGE enabled in the kernel.
|
||||||
ft_psk_generate_local=1
|
ft_psk_generate_local=1
|
||||||
rkh_pull_timeout=50
|
|
||||||
ft_over_ds=0
|
ft_over_ds=0
|
||||||
ap_table_expiration_time=36000
|
ap_table_expiration_time=36000
|
||||||
ap_table_max_size=10
|
ap_table_max_size=10
|
||||||
rrm_neighbor_report=1
|
rrm_neighbor_report=1
|
||||||
ocv=1
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ wpa=2
|
|||||||
wpa_key_mgmt=FT-PSK
|
wpa_key_mgmt=FT-PSK
|
||||||
wpa_pairwise=CCMP
|
wpa_pairwise=CCMP
|
||||||
wpa_passphrase=EasilyGuessedPassword
|
wpa_passphrase=EasilyGuessedPassword
|
||||||
ieee80211w=0
|
ieee80211w=1
|
||||||
rsn_preauth=1
|
rsn_preauth=1
|
||||||
rsn_preauth_interfaces=lo
|
rsn_preauth_interfaces=lo
|
||||||
disable_pmksa_caching=0
|
disable_pmksa_caching=0
|
||||||
@ -33,9 +33,7 @@ pmk_r1_push=0
|
|||||||
# case. Only works with FT-PSK, otherwise brctl needs to be installed and
|
# case. Only works with FT-PSK, otherwise brctl needs to be installed and
|
||||||
# CONFIG_BRIDGE enabled in the kernel.
|
# CONFIG_BRIDGE enabled in the kernel.
|
||||||
ft_psk_generate_local=1
|
ft_psk_generate_local=1
|
||||||
rkh_pull_timeout=50
|
|
||||||
ft_over_ds=0
|
ft_over_ds=0
|
||||||
ap_table_expiration_time=36000
|
ap_table_expiration_time=36000
|
||||||
ap_table_max_size=10
|
ap_table_max_size=10
|
||||||
rrm_neighbor_report=1
|
rrm_neighbor_report=1
|
||||||
ocv=1
|
|
||||||
|
|||||||
@ -3,6 +3,3 @@ DisableMacAddressRandomization=true
|
|||||||
|
|
||||||
[General]
|
[General]
|
||||||
RoamRetryInterval=1
|
RoamRetryInterval=1
|
||||||
|
|
||||||
# For disconnect_during_handshake_test
|
|
||||||
ManagementFrameProtection=0
|
|
||||||
|
|||||||
@ -14,7 +14,8 @@ class Test(unittest.TestCase):
|
|||||||
# Tests a crash reported where multiple roam scans combined with an AP
|
# Tests a crash reported where multiple roam scans combined with an AP
|
||||||
# disconnect result in a crash getting scan results.
|
# disconnect result in a crash getting scan results.
|
||||||
#
|
#
|
||||||
def validate(self, wd):
|
def validate(self):
|
||||||
|
wd = IWD(True)
|
||||||
device = wd.list_devices(1)[0]
|
device = wd.list_devices(1)[0]
|
||||||
|
|
||||||
ordered_network = device.get_ordered_network('TestFT', full_scan=True)
|
ordered_network = device.get_ordered_network('TestFT', full_scan=True)
|
||||||
@ -42,15 +43,14 @@ class Test(unittest.TestCase):
|
|||||||
wd.wait_for_object_condition(device, condition)
|
wd.wait_for_object_condition(device, condition)
|
||||||
|
|
||||||
def test_ap_disconnect_no_neighbors(self):
|
def test_ap_disconnect_no_neighbors(self):
|
||||||
self.validate(self.wd)
|
self.validate()
|
||||||
|
|
||||||
def test_ap_disconnect_neighbors(self):
|
def test_ap_disconnect_neighbors(self):
|
||||||
HostapdCLI.group_neighbors(*self.bss_hostapd)
|
HostapdCLI.group_neighbors(*self.bss_hostapd)
|
||||||
|
|
||||||
self.validate(self.wd)
|
self.validate()
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.wd = IWD(True)
|
|
||||||
self.bss_hostapd[0].reload()
|
self.bss_hostapd[0].reload()
|
||||||
self.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
self.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
||||||
|
|
||||||
@ -63,9 +63,6 @@ class Test(unittest.TestCase):
|
|||||||
self.bss_hostapd[0].remove_neighbor(self.bss_hostapd[1].bssid)
|
self.bss_hostapd[0].remove_neighbor(self.bss_hostapd[1].bssid)
|
||||||
self.bss_hostapd[1].remove_neighbor(self.bss_hostapd[0].bssid)
|
self.bss_hostapd[1].remove_neighbor(self.bss_hostapd[0].bssid)
|
||||||
|
|
||||||
self.wd.stop()
|
|
||||||
self.wd = None
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
hwsim = Hwsim()
|
hwsim = Hwsim()
|
||||||
@ -81,21 +78,12 @@ class Test(unittest.TestCase):
|
|||||||
cls.bss_hostapd[0].set_value('ocv', '0')
|
cls.bss_hostapd[0].set_value('ocv', '0')
|
||||||
cls.bss_hostapd[0].set_value('ieee80211w', '0')
|
cls.bss_hostapd[0].set_value('ieee80211w', '0')
|
||||||
|
|
||||||
rad0 = hwsim.get_radio('rad0')
|
|
||||||
rad1 = hwsim.get_radio('rad1')
|
|
||||||
|
|
||||||
cls.rule0 = hwsim.rules.create()
|
cls.rule0 = hwsim.rules.create()
|
||||||
cls.rule0.source = rad0.addresses[0]
|
cls.rule0.source = 'any'
|
||||||
cls.rule0.bidirectional = True
|
cls.rule0.bidirectional = True
|
||||||
cls.rule0.signal = -8000
|
cls.rule0.signal = -8000
|
||||||
cls.rule0.enabled = True
|
cls.rule0.enabled = True
|
||||||
|
|
||||||
cls.rule1 = hwsim.rules.create()
|
|
||||||
cls.rule1.source = rad1.addresses[0]
|
|
||||||
cls.rule1.bidirectional = True
|
|
||||||
cls.rule1.signal = -8500
|
|
||||||
cls.rule1.enabled = True
|
|
||||||
|
|
||||||
cls.bss_hostapd[0].set_address('12:00:00:00:00:01')
|
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[1].set_address('12:00:00:00:00:02')
|
||||||
|
|
||||||
@ -104,7 +92,6 @@ class Test(unittest.TestCase):
|
|||||||
IWD.clear_storage()
|
IWD.clear_storage()
|
||||||
cls.bss_hostapd = None
|
cls.bss_hostapd = None
|
||||||
cls.rule0.remove()
|
cls.rule0.remove()
|
||||||
cls.rule1.remove()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(exit=True)
|
unittest.main(exit=True)
|
||||||
|
|||||||
@ -17,7 +17,7 @@ from hwsim import Hwsim
|
|||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
# Normally the time between a failed roam attempt and the next roam attempt
|
# Normally the time between a failed roam attempt and the next roam attempt
|
||||||
# is 60 seconds (default RoamRetryInterval). Test that we retry roaming
|
# is 60 seconds (default RoamRetryInterval). Test that we retry roaming
|
||||||
# faster if the transition looks like this: LOW [roam] [same bss] HIGH LOW.
|
# faster if the transision looks like this: LOW [roam] [same bss] HIGH LOW.
|
||||||
def test_fast_retry(self):
|
def test_fast_retry(self):
|
||||||
hwsim = Hwsim()
|
hwsim = Hwsim()
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@ from hostapd import HostapdCLI
|
|||||||
from hwsim import Hwsim
|
from hwsim import Hwsim
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
# Test that we do not periodically retry roaming if the transition looks
|
# Test that we do not periodically retry roaming if the transision looks
|
||||||
# like this: LOW [roam] [new bss] HIGH.
|
# like this: LOW [roam] [new bss] HIGH.
|
||||||
def test_stop_retry(self):
|
def test_stop_retry(self):
|
||||||
hwsim = Hwsim()
|
hwsim = Hwsim()
|
||||||
|
|||||||
@ -55,13 +55,14 @@ class Test(unittest.TestCase):
|
|||||||
wd.clear_storage()
|
wd.clear_storage()
|
||||||
|
|
||||||
def test_SAE(self):
|
def test_SAE(self):
|
||||||
|
self.hostapd.set_value('sae_pwe', '0');
|
||||||
|
self.hostapd.set_value('sae_groups', '19');
|
||||||
|
self.hostapd.reload()
|
||||||
|
self.hostapd.wait_for_event("AP-ENABLED")
|
||||||
wd = IWD(True)
|
wd = IWD(True)
|
||||||
self.validate_connection(wd)
|
self.validate_connection(wd)
|
||||||
wd.clear_storage()
|
wd.clear_storage()
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.hostapd.default()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
cls.hostapd = HostapdCLI(config='ssidSAE-Clogging.conf')
|
cls.hostapd = HostapdCLI(config='ssidSAE-Clogging.conf')
|
||||||
|
|||||||
@ -8,5 +8,3 @@ wpa_pairwise=CCMP
|
|||||||
sae_password=secret123|mac=ff:ff:ff:ff:ff:ff
|
sae_password=secret123|mac=ff:ff:ff:ff:ff:ff
|
||||||
sae_anti_clogging_threshold=2
|
sae_anti_clogging_threshold=2
|
||||||
ieee80211w=2
|
ieee80211w=2
|
||||||
sae_pwe=0
|
|
||||||
sae_groups=19
|
|
||||||
@ -13,7 +13,7 @@ import testutil
|
|||||||
from config import ctx
|
from config import ctx
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
def validate_connection(self, wd, ft=True, check_used_pmksa=False):
|
def validate_connection(self, wd, ft=True):
|
||||||
device = wd.list_devices(1)[0]
|
device = wd.list_devices(1)[0]
|
||||||
|
|
||||||
# This won't guarantee all BSS's are found, but at least ensures that
|
# This won't guarantee all BSS's are found, but at least ensures that
|
||||||
@ -37,14 +37,6 @@ class Test(unittest.TestCase):
|
|||||||
self.assertRaises(Exception, testutil.test_ifaces_connected,
|
self.assertRaises(Exception, testutil.test_ifaces_connected,
|
||||||
(self.bss_hostapd[1].ifname, device.name, True, True))
|
(self.bss_hostapd[1].ifname, device.name, True, True))
|
||||||
|
|
||||||
# If PMKSA was used, hostapd should not include the sae_group key in
|
|
||||||
# its status for the station.
|
|
||||||
sta_status = self.bss_hostapd[0].sta_status(device.address)
|
|
||||||
if check_used_pmksa:
|
|
||||||
self.assertNotIn("sae_group", sta_status.keys())
|
|
||||||
else:
|
|
||||||
self.assertIn("sae_group", sta_status.keys())
|
|
||||||
|
|
||||||
device.roam(self.bss_hostapd[1].bssid)
|
device.roam(self.bss_hostapd[1].bssid)
|
||||||
|
|
||||||
# Check that iwd is on BSS 1 once out of roaming state and doesn't
|
# Check that iwd is on BSS 1 once out of roaming state and doesn't
|
||||||
@ -96,31 +88,6 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
self.validate_connection(wd, True)
|
self.validate_connection(wd, True)
|
||||||
|
|
||||||
def test_ft_roam_pmksa(self):
|
|
||||||
wd = IWD(True)
|
|
||||||
|
|
||||||
self.bss_hostapd[0].set_value('wpa_key_mgmt', 'FT-SAE SAE')
|
|
||||||
self.bss_hostapd[0].reload()
|
|
||||||
self.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
|
||||||
self.bss_hostapd[1].set_value('wpa_key_mgmt', 'FT-SAE SAE')
|
|
||||||
self.bss_hostapd[1].reload()
|
|
||||||
self.bss_hostapd[1].wait_for_event("AP-ENABLED")
|
|
||||||
self.bss_hostapd[2].set_value('wpa_key_mgmt', 'FT-PSK')
|
|
||||||
self.bss_hostapd[2].reload()
|
|
||||||
self.bss_hostapd[2].wait_for_event("AP-ENABLED")
|
|
||||||
|
|
||||||
self.validate_connection(wd, True)
|
|
||||||
|
|
||||||
device = wd.list_devices(1)[0]
|
|
||||||
device.disconnect()
|
|
||||||
|
|
||||||
for hapd in self.bss_hostapd:
|
|
||||||
hapd.deauthenticate(device.address)
|
|
||||||
|
|
||||||
wd.wait(5)
|
|
||||||
|
|
||||||
self.validate_connection(wd, True, check_used_pmksa=True)
|
|
||||||
|
|
||||||
def test_reassociate_roam_success(self):
|
def test_reassociate_roam_success(self):
|
||||||
wd = IWD(True)
|
wd = IWD(True)
|
||||||
|
|
||||||
@ -136,31 +103,6 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
self.validate_connection(wd, False)
|
self.validate_connection(wd, False)
|
||||||
|
|
||||||
def test_reassociate_roam_pmksa(self):
|
|
||||||
wd = IWD(True)
|
|
||||||
|
|
||||||
self.bss_hostapd[0].set_value('wpa_key_mgmt', 'SAE')
|
|
||||||
self.bss_hostapd[0].reload()
|
|
||||||
self.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
|
||||||
self.bss_hostapd[1].set_value('wpa_key_mgmt', 'SAE')
|
|
||||||
self.bss_hostapd[1].reload()
|
|
||||||
self.bss_hostapd[1].wait_for_event("AP-ENABLED")
|
|
||||||
self.bss_hostapd[2].set_value('wpa_key_mgmt', 'WPA-PSK')
|
|
||||||
self.bss_hostapd[2].reload()
|
|
||||||
self.bss_hostapd[2].wait_for_event("AP-ENABLED")
|
|
||||||
|
|
||||||
self.validate_connection(wd, False)
|
|
||||||
|
|
||||||
device = wd.list_devices(1)[0]
|
|
||||||
device.disconnect()
|
|
||||||
|
|
||||||
for hapd in self.bss_hostapd:
|
|
||||||
hapd.deauthenticate(device.address)
|
|
||||||
|
|
||||||
wd.wait(5)
|
|
||||||
|
|
||||||
self.validate_connection(wd, False, check_used_pmksa=True)
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
os.system('ip link set "' + self.bss_hostapd[0].ifname + '" down')
|
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[1].ifname + '" down')
|
||||||
|
|||||||
@ -12,7 +12,8 @@ from hostapd import HostapdCLI
|
|||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
|
|
||||||
def validate_connection(self, wd, ssid):
|
def validate_connection(self, wd):
|
||||||
|
|
||||||
devices = wd.list_devices(1)
|
devices = wd.list_devices(1)
|
||||||
self.assertIsNotNone(devices)
|
self.assertIsNotNone(devices)
|
||||||
device = devices[0]
|
device = devices[0]
|
||||||
@ -24,7 +25,7 @@ class Test(unittest.TestCase):
|
|||||||
condition = 'obj.connected_network is not None'
|
condition = 'obj.connected_network is not None'
|
||||||
wd.wait_for_object_condition(device, condition)
|
wd.wait_for_object_condition(device, condition)
|
||||||
|
|
||||||
ordered_network = device.get_ordered_network(ssid)
|
ordered_network = device.get_ordered_network('ssidSAE')
|
||||||
|
|
||||||
self.assertTrue(ordered_network.network_object.connected)
|
self.assertTrue(ordered_network.network_object.connected)
|
||||||
|
|
||||||
@ -34,38 +35,31 @@ class Test(unittest.TestCase):
|
|||||||
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
||||||
|
|
||||||
def test_SAE(self):
|
def test_SAE(self):
|
||||||
IWD.copy_to_storage("profiles/ssidSAE.psk.default", name="ssidSAE.psk")
|
self.hostapd.set_value('sae_pwe', '0')
|
||||||
|
self.hostapd.set_value('sae_groups', '19')
|
||||||
|
self.hostapd.reload()
|
||||||
self.hostapd.wait_for_event("AP-ENABLED")
|
self.hostapd.wait_for_event("AP-ENABLED")
|
||||||
|
|
||||||
wd = IWD(True)
|
wd = IWD(True)
|
||||||
self.validate_connection(wd, "ssidSAE")
|
self.validate_connection(wd)
|
||||||
|
|
||||||
def test_SAE_H2E(self):
|
def test_SAE_H2E(self):
|
||||||
IWD.copy_to_storage("profiles/ssidSAE.psk.default", name="ssidSAE-H2E.psk")
|
self.hostapd.set_value('sae_pwe', '1')
|
||||||
self.hostapd_h2e.set_value('sae_groups', '20')
|
self.hostapd.set_value('sae_groups', '20')
|
||||||
self.hostapd_h2e.reload()
|
self.hostapd.reload()
|
||||||
self.hostapd_h2e.wait_for_event("AP-ENABLED")
|
self.hostapd.wait_for_event("AP-ENABLED")
|
||||||
wd = IWD(True)
|
wd = IWD(True)
|
||||||
self.validate_connection(wd, "ssidSAE-H2E")
|
self.validate_connection(wd)
|
||||||
|
|
||||||
def test_SAE_H2E_password_identifier(self):
|
|
||||||
IWD.copy_to_storage("profiles/ssidSAE.psk.identifier", name="ssidSAE-H2E.psk")
|
|
||||||
self.hostapd_h2e.set_value('sae_groups', '20')
|
|
||||||
self.hostapd_h2e.reload()
|
|
||||||
self.hostapd_h2e.wait_for_event("AP-ENABLED")
|
|
||||||
wd = IWD(True)
|
|
||||||
self.validate_connection(wd, "ssidSAE-H2E")
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.hostapd.default()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
IWD.clear_storage()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
cls.hostapd = HostapdCLI(config='ssidSAE.conf')
|
cls.hostapd = HostapdCLI(config='ssidSAE.conf')
|
||||||
cls.hostapd_h2e = HostapdCLI(config='ssidSAE-H2E.conf')
|
IWD.copy_to_storage('ssidSAE.psk')
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
IWD.clear_storage()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(exit=True)
|
unittest.main(exit=True)
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import testutil
|
|||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
|
|
||||||
def validate_connection(self, wd, ssid, hostapd, expected_group):
|
def validate_connection(self, wd):
|
||||||
psk_agent = PSKAgent("secret123")
|
psk_agent = PSKAgent("secret123")
|
||||||
wd.register_psk_agent(psk_agent)
|
wd.register_psk_agent(psk_agent)
|
||||||
|
|
||||||
@ -23,11 +23,11 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
device.disconnect()
|
device.disconnect()
|
||||||
|
|
||||||
network = device.get_ordered_network(ssid, full_scan=True)
|
network = device.get_ordered_network('ssidSAE', full_scan=True)
|
||||||
|
|
||||||
self.assertEqual(network.type, NetworkType.psk)
|
self.assertEqual(network.type, NetworkType.psk)
|
||||||
|
|
||||||
network.network_object.connect(wait=False)
|
network.network_object.connect()
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
condition = 'obj.state == DeviceState.connected'
|
||||||
wd.wait_for_object_condition(device, condition)
|
wd.wait_for_object_condition(device, condition)
|
||||||
@ -35,11 +35,7 @@ class Test(unittest.TestCase):
|
|||||||
wd.wait(2)
|
wd.wait(2)
|
||||||
|
|
||||||
testutil.test_iface_operstate(intf=device.name)
|
testutil.test_iface_operstate(intf=device.name)
|
||||||
testutil.test_ifaces_connected(if0=device.name, if1=hostapd.ifname)
|
testutil.test_ifaces_connected(if0=device.name, if1=self.hostapd.ifname)
|
||||||
|
|
||||||
sta_status = hostapd.sta_status(device.address)
|
|
||||||
|
|
||||||
self.assertEqual(int(sta_status["sae_group"]), expected_group)
|
|
||||||
|
|
||||||
device.disconnect()
|
device.disconnect()
|
||||||
|
|
||||||
@ -49,29 +45,48 @@ class Test(unittest.TestCase):
|
|||||||
wd.unregister_psk_agent(psk_agent)
|
wd.unregister_psk_agent(psk_agent)
|
||||||
|
|
||||||
def test_SAE(self):
|
def test_SAE(self):
|
||||||
self.hostapd.wait_for_event("AP-ENABLED")
|
self.hostapd.set_value('sae_pwe', '0')
|
||||||
self.validate_connection(self.wd, "ssidSAE", self.hostapd, 19)
|
self.hostapd.set_value('sae_groups', '19')
|
||||||
|
self.hostapd.set_value('vendor_elements', '')
|
||||||
def test_SAE_Group20(self):
|
|
||||||
self.hostapd.set_value('sae_groups', '20')
|
|
||||||
self.hostapd.reload()
|
self.hostapd.reload()
|
||||||
self.hostapd.wait_for_event("AP-ENABLED")
|
self.hostapd.wait_for_event("AP-ENABLED")
|
||||||
self.validate_connection(self.wd, "ssidSAE", self.hostapd, 20)
|
self.validate_connection(self.wd)
|
||||||
|
|
||||||
|
def test_SAE_force_group_19(self):
|
||||||
|
self.hostapd.set_value('sae_pwe', '0')
|
||||||
|
self.hostapd.set_value('sae_groups', '19')
|
||||||
|
# Vendor data from APs which require group 19 be used first
|
||||||
|
# TODO: (for all tests) verify the expected group was used
|
||||||
|
self.hostapd.set_value('vendor_elements', 'dd0cf4f5e8050500000000000000')
|
||||||
|
self.hostapd.reload()
|
||||||
|
self.hostapd.wait_for_event("AP-ENABLED")
|
||||||
|
self.validate_connection(self.wd)
|
||||||
|
|
||||||
|
def test_SAE_Group20(self):
|
||||||
|
self.hostapd.set_value('sae_pwe', '0')
|
||||||
|
self.hostapd.set_value('sae_groups', '20')
|
||||||
|
self.hostapd.set_value('vendor_elements', '')
|
||||||
|
self.hostapd.reload()
|
||||||
|
self.hostapd.wait_for_event("AP-ENABLED")
|
||||||
|
self.validate_connection(self.wd)
|
||||||
|
|
||||||
def test_SAE_H2E(self):
|
def test_SAE_H2E(self):
|
||||||
self.hostapd_h2e.set_value('sae_groups', '19')
|
self.hostapd.set_value('sae_pwe', '1')
|
||||||
self.hostapd_h2e.reload()
|
self.hostapd.set_value('sae_groups', '19')
|
||||||
self.hostapd_h2e.wait_for_event("AP-ENABLED")
|
self.hostapd.set_value('vendor_elements', '')
|
||||||
self.validate_connection(self.wd, "ssidSAE-H2E", self.hostapd_h2e, 19)
|
self.hostapd.reload()
|
||||||
|
self.hostapd.wait_for_event("AP-ENABLED")
|
||||||
|
self.validate_connection(self.wd)
|
||||||
|
|
||||||
def test_SAE_H2E_Group20(self):
|
def test_SAE_H2E_Group20(self):
|
||||||
self.hostapd_h2e.set_value('sae_groups', '20')
|
self.hostapd.set_value('sae_pwe', '1')
|
||||||
self.hostapd_h2e.reload()
|
self.hostapd.set_value('sae_groups', '20')
|
||||||
self.hostapd_h2e.wait_for_event("AP-ENABLED")
|
self.hostapd.set_value('vendor_elements', '')
|
||||||
self.validate_connection(self.wd, "ssidSAE-H2E", self.hostapd_h2e, 20)
|
self.hostapd.reload()
|
||||||
|
self.hostapd.wait_for_event("AP-ENABLED")
|
||||||
|
self.validate_connection(self.wd)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.hostapd.default()
|
|
||||||
self.wd = IWD(True)
|
self.wd = IWD(True)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
@ -81,7 +96,6 @@ class Test(unittest.TestCase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
cls.hostapd = HostapdCLI(config='ssidSAE.conf')
|
cls.hostapd = HostapdCLI(config='ssidSAE.conf')
|
||||||
cls.hostapd_h2e = HostapdCLI(config='ssidSAE-H2E.conf')
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
|
|||||||
@ -1,104 +0,0 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
sys.path.append('../util')
|
|
||||||
import iwd
|
|
||||||
from iwd import IWD
|
|
||||||
from iwd import PSKAgent
|
|
||||||
from iwd import NetworkType
|
|
||||||
from hostapd import HostapdCLI
|
|
||||||
import testutil
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
|
||||||
|
|
||||||
def validate_connection(self, wd, hostapd, rejected=False):
|
|
||||||
devices = wd.list_devices(1)
|
|
||||||
self.assertIsNotNone(devices)
|
|
||||||
device = devices[0]
|
|
||||||
|
|
||||||
device.autoconnect = True
|
|
||||||
|
|
||||||
if rejected:
|
|
||||||
device.wait_for_event("ecc-group-rejected", timeout=60)
|
|
||||||
|
|
||||||
condition = 'obj.state == DeviceState.connected'
|
|
||||||
wd.wait_for_object_condition(device, condition)
|
|
||||||
|
|
||||||
wd.wait(2)
|
|
||||||
|
|
||||||
testutil.test_iface_operstate(intf=device.name)
|
|
||||||
testutil.test_ifaces_connected(if0=device.name, if1=hostapd.ifname)
|
|
||||||
|
|
||||||
if not rejected:
|
|
||||||
self.assertEqual(device.event_ocurred("ecc-group-rejected"), False)
|
|
||||||
|
|
||||||
print(hostapd._get_status())
|
|
||||||
|
|
||||||
sta_status = hostapd.sta_status(device.address)
|
|
||||||
|
|
||||||
print(sta_status)
|
|
||||||
|
|
||||||
self.assertEqual(int(sta_status["sae_group"]), 19)
|
|
||||||
|
|
||||||
device.disconnect()
|
|
||||||
|
|
||||||
# IWD should:
|
|
||||||
# - Connect, fail with group 20
|
|
||||||
# - Retry, succeed with group 19
|
|
||||||
# - Disconnect
|
|
||||||
# - Connect, try only group 19
|
|
||||||
def test_auto_selection(self):
|
|
||||||
IWD.copy_to_storage("profiles/ssidSAE.psk.default", name="ssidSAE.psk")
|
|
||||||
self.validate_connection(self.wd, self.hostapd, rejected=True)
|
|
||||||
|
|
||||||
self.validate_connection(self.wd, self.hostapd, rejected=False)
|
|
||||||
|
|
||||||
# Try group 19 first
|
|
||||||
def test_default_group_enabled(self):
|
|
||||||
IWD.copy_to_storage("profiles/ssidSAE.psk.default_group", name="ssidSAE.psk")
|
|
||||||
self.validate_connection(self.wd, self.hostapd)
|
|
||||||
|
|
||||||
# Try group 19 first, with H2E
|
|
||||||
def test_default_group_enabled_h2e(self):
|
|
||||||
IWD.copy_to_storage("profiles/ssidSAE-H2E.psk.default_group", name="ssidSAE-H2E.psk")
|
|
||||||
self.validate_connection(self.wd, self.hostapd_h2e)
|
|
||||||
|
|
||||||
# Same as auto-selection but won't retain the default group setting
|
|
||||||
def test_default_group_disabled(self):
|
|
||||||
IWD.copy_to_storage("profiles/ssidSAE.psk.most_secure", name="ssidSAE.psk")
|
|
||||||
self.validate_connection(self.wd, self.hostapd, rejected=True)
|
|
||||||
|
|
||||||
# IWD should then retry but use only group 19
|
|
||||||
self.validate_connection(self.wd, self.hostapd, rejected=True)
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.hostapd.default()
|
|
||||||
self.hostapd.set_value('sae_groups', '19')
|
|
||||||
self.hostapd.set_value('sae_pwe', '0')
|
|
||||||
self.hostapd.reload()
|
|
||||||
self.hostapd.wait_for_event("AP-ENABLED")
|
|
||||||
self.wd = IWD(True)
|
|
||||||
|
|
||||||
self.wd.clear_storage()
|
|
||||||
os.system("ls /tmp/iwd")
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.wd.clear_storage()
|
|
||||||
self.wd = None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
cls.hostapd = HostapdCLI(config='ssidSAE.conf')
|
|
||||||
cls.hostapd.default()
|
|
||||||
|
|
||||||
cls.hostapd_h2e = HostapdCLI(config='ssidSAE-H2E.conf')
|
|
||||||
cls.hostapd_h2e.default()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
pass
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main(exit=True)
|
|
||||||
@ -37,16 +37,13 @@ class Test(unittest.TestCase):
|
|||||||
self.validate_connection(wd, 'InvalidSecret')
|
self.validate_connection(wd, 'InvalidSecret')
|
||||||
|
|
||||||
def test_no_supported_groups(self):
|
def test_no_supported_groups(self):
|
||||||
self.hostapd.set_value('sae_groups', '21')
|
hostapd = HostapdCLI(config='ssidSAE.conf')
|
||||||
self.hostapd.reload()
|
hostapd.set_value('sae_groups', '1')
|
||||||
|
hostapd.reload()
|
||||||
|
|
||||||
wd = IWD(True)
|
wd = IWD(True)
|
||||||
self.validate_connection(wd, 'secret123')
|
self.validate_connection(wd, 'secret123')
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.hostapd = HostapdCLI(config='ssidSAE.conf')
|
|
||||||
self.hostapd.default()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
[SETUP]
|
[SETUP]
|
||||||
num_radios=3
|
num_radios=2
|
||||||
start_iwd=0
|
start_iwd=0
|
||||||
hwsim_medium=yes
|
hwsim_medium=yes
|
||||||
|
|
||||||
[HOSTAPD]
|
[HOSTAPD]
|
||||||
rad0=ssidSAE.conf
|
rad0=ssidSAE.conf
|
||||||
rad1=ssidSAE-H2E.conf
|
|
||||||
|
|||||||
@ -4,6 +4,3 @@
|
|||||||
# hardware, but fails when used in simulated environment with mac80211_hwsim.
|
# hardware, but fails when used in simulated environment with mac80211_hwsim.
|
||||||
# Disable MAC randomization for the tests with hidden networks.
|
# Disable MAC randomization for the tests with hidden networks.
|
||||||
DisableMacAddressRandomization=true
|
DisableMacAddressRandomization=true
|
||||||
|
|
||||||
[General]
|
|
||||||
DisablePMKSA=true
|
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
[Security]
|
|
||||||
Passphrase=secret123
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
[Security]
|
|
||||||
Passphrase=secret123
|
|
||||||
|
|
||||||
[Settings]
|
|
||||||
UseDefaultEccGroup=true
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
[Security]
|
|
||||||
Passphrase=secret123
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
[Security]
|
|
||||||
Passphrase=secret123
|
|
||||||
|
|
||||||
[Settings]
|
|
||||||
UseDefaultEccGroup=true
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
[Security]
|
|
||||||
Passphrase=withidentifier
|
|
||||||
PasswordIdentifier=myidentifier
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
[Security]
|
|
||||||
Passphrase=secret123
|
|
||||||
|
|
||||||
[Settings]
|
|
||||||
UseDefaultEccGroup=false
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
hw_mode=g
|
|
||||||
channel=1
|
|
||||||
ssid=ssidSAE-H2E
|
|
||||||
|
|
||||||
wpa=2
|
|
||||||
wpa_key_mgmt=SAE
|
|
||||||
wpa_pairwise=CCMP
|
|
||||||
sae_password=secret123
|
|
||||||
sae_password=withidentifier|id=myidentifier
|
|
||||||
sae_groups=19
|
|
||||||
ieee80211w=2
|
|
||||||
sae_pwe=1
|
|
||||||
@ -5,7 +5,6 @@ ssid=ssidSAE
|
|||||||
wpa=2
|
wpa=2
|
||||||
wpa_key_mgmt=SAE
|
wpa_key_mgmt=SAE
|
||||||
wpa_pairwise=CCMP
|
wpa_pairwise=CCMP
|
||||||
sae_password=secret123
|
sae_password=secret123|mac=ff:ff:ff:ff:ff:ff
|
||||||
sae_groups=19
|
sae_groups=19
|
||||||
ieee80211w=2
|
ieee80211w=2
|
||||||
sae_pwe=0
|
|
||||||
|
|||||||
@ -40,8 +40,10 @@ class Test(unittest.TestCase):
|
|||||||
# needed because the hwsim rule only matches once and must be matched
|
# needed because the hwsim rule only matches once and must be matched
|
||||||
# on the first commit, not during group negotiation.
|
# on the first commit, not during group negotiation.
|
||||||
#
|
#
|
||||||
self.hostapd.set_value('vendor_elements', 'dd0cf4f5e8050500000000000000')
|
hostapd = HostapdCLI(config='ssidSAE.conf')
|
||||||
self.hostapd.reload()
|
hostapd.set_value('vendor_elements', 'dd0cf4f5e8050500000000000000')
|
||||||
|
hostapd.set_value('sae_groups', '19')
|
||||||
|
hostapd.reload()
|
||||||
|
|
||||||
hwsim = Hwsim()
|
hwsim = Hwsim()
|
||||||
bss_radio = hwsim.get_radio('rad0')
|
bss_radio = hwsim.get_radio('rad0')
|
||||||
@ -62,8 +64,10 @@ class Test(unittest.TestCase):
|
|||||||
rule0.remove()
|
rule0.remove()
|
||||||
|
|
||||||
def test_sta_confirm_not_acked(self):
|
def test_sta_confirm_not_acked(self):
|
||||||
self.hostapd.set_value('vendor_elements', 'dd0cf4f5e8050500000000000000')
|
hostapd = HostapdCLI(config='ssidSAE.conf')
|
||||||
self.hostapd.reload()
|
hostapd.set_value('vendor_elements', 'dd0cf4f5e8050500000000000000')
|
||||||
|
hostapd.set_value('sae_groups', '19')
|
||||||
|
hostapd.reload()
|
||||||
|
|
||||||
hwsim = Hwsim()
|
hwsim = Hwsim()
|
||||||
bss_radio = hwsim.get_radio('rad0')
|
bss_radio = hwsim.get_radio('rad0')
|
||||||
@ -83,10 +87,6 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
rule0.remove()
|
rule0.remove()
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.hostapd = HostapdCLI(config='ssidSAE.conf')
|
|
||||||
self.hostapd.default()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@ -43,6 +43,9 @@ class Test(unittest.TestCase):
|
|||||||
wd.unregister_psk_agent(psk_agent)
|
wd.unregister_psk_agent(psk_agent)
|
||||||
|
|
||||||
def test_ccmp(self):
|
def test_ccmp(self):
|
||||||
|
self.hostapd.set_value('rsn_pairwise', 'CCMP')
|
||||||
|
self.hostapd.reload()
|
||||||
|
self.hostapd.wait_for_event("AP-ENABLED")
|
||||||
self.validate_connection_success(self.wd)
|
self.validate_connection_success(self.wd)
|
||||||
|
|
||||||
def test_gcmp(self):
|
def test_gcmp(self):
|
||||||
@ -64,7 +67,6 @@ class Test(unittest.TestCase):
|
|||||||
self.validate_connection_success(self.wd)
|
self.validate_connection_success(self.wd)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.hostapd.default()
|
|
||||||
self.wd = IWD(True)
|
self.wd = IWD(True)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
|||||||
@ -8,12 +8,11 @@ import iwd
|
|||||||
from iwd import IWD
|
from iwd import IWD
|
||||||
from iwd import PSKAgent
|
from iwd import PSKAgent
|
||||||
from iwd import NetworkType
|
from iwd import NetworkType
|
||||||
from hostapd import HostapdCLI
|
|
||||||
import testutil
|
import testutil
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
|
|
||||||
def test_incorrect_password(self):
|
def test_connection_success(self):
|
||||||
wd = IWD(True)
|
wd = IWD(True)
|
||||||
|
|
||||||
psk_agent = PSKAgent("InvalidPassword")
|
psk_agent = PSKAgent("InvalidPassword")
|
||||||
@ -35,35 +34,6 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
wd.unregister_psk_agent(psk_agent)
|
wd.unregister_psk_agent(psk_agent)
|
||||||
|
|
||||||
def test_deauth_after_connection(self):
|
|
||||||
wd = IWD(True)
|
|
||||||
hostapd = HostapdCLI(config="ssidWPA2.conf")
|
|
||||||
|
|
||||||
psk_agent = PSKAgent("secret123")
|
|
||||||
wd.register_psk_agent(psk_agent)
|
|
||||||
|
|
||||||
devices = wd.list_devices(1)
|
|
||||||
self.assertIsNotNone(devices)
|
|
||||||
device = devices[0]
|
|
||||||
|
|
||||||
ordered_network = device.get_ordered_network('ssidWPA2')
|
|
||||||
|
|
||||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
|
||||||
|
|
||||||
condition = 'not obj.connected'
|
|
||||||
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
|
||||||
|
|
||||||
ordered_network.network_object.connect(wait=False)
|
|
||||||
|
|
||||||
device.wait_for_event("authenticating")
|
|
||||||
|
|
||||||
# Trigger a deauth just after authenticating
|
|
||||||
hostapd.deauthenticate(device.address)
|
|
||||||
|
|
||||||
device.wait_for_event("disconnected")
|
|
||||||
|
|
||||||
wd.unregister_psk_agent(psk_agent)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
pass
|
pass
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user