mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2025-08-02 17:37:22 +02:00
Compare commits
No commits in common. "master" and "1.22" 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
|
13
.gitignore
vendored
13
.gitignore
vendored
@ -1,14 +1,9 @@
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
*.gcno
|
||||
*.gcda
|
||||
.libs
|
||||
.deps
|
||||
.dirstamp
|
||||
.cache
|
||||
.ccls-cache
|
||||
compile_commands.json
|
||||
tags
|
||||
cscope.*
|
||||
Makefile
|
||||
@ -42,8 +37,6 @@ wired/ead.service
|
||||
tools/hwsim
|
||||
tools/hwsim.1
|
||||
tools/probe-req
|
||||
tools/iwd-decrypt-profile
|
||||
tools/iwd-psk
|
||||
unit/test-cmac-aes
|
||||
unit/test-arc4
|
||||
unit/test-hmac-md5
|
||||
@ -66,9 +59,6 @@ unit/test-p2p
|
||||
unit/test-band
|
||||
unit/test-dpp
|
||||
unit/test-json
|
||||
unit/test-nl80211util
|
||||
unit/test-pmksa
|
||||
unit/test-storage
|
||||
unit/cert-*.pem
|
||||
unit/cert-*.csr
|
||||
unit/cert-*.srl
|
||||
@ -77,6 +67,3 @@ unit/*.log
|
||||
unit/*.trs
|
||||
test-suite.log
|
||||
src/builtin.h
|
||||
autotests/*/__pycache__
|
||||
iwd-coverage.info
|
||||
gcov
|
||||
|
7
AUTHORS
7
AUTHORS
@ -34,10 +34,3 @@ Matt Oberle <matt.r.oberle@gmail.com>
|
||||
Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
|
||||
Torsten Schmitz <noreply.torsten@gmail.com>
|
||||
Diederik de Haas <didi.debian@cknow.org>
|
||||
Vladimír Dudr <vladimir@tango-dj.cz>
|
||||
Emmanuel VAUTRIN <Emmanuel.VAUTRIN@cpexterne.org>
|
||||
Jesse Lentz <jesse@twosheds.org>
|
||||
Pinghao Wu <xdavidwuph@gmail.com>
|
||||
Neehar Vijay <env252525@gmail.com>
|
||||
Jiajie Chen <c@jia.je>
|
||||
Ronan Pigott <ronan@rjp.ie>
|
||||
|
234
ChangeLog
234
ChangeLog
@ -1,237 +1,3 @@
|
||||
ver 3.9:
|
||||
Fix issue with Access Point mode and frequency unlocking.
|
||||
Fix issue with network configuration and BSS retry logic.
|
||||
Fix issue with handling busy notification from Access Point.
|
||||
Fix issue with handling P-192, P-224 and P-521 for SAE.
|
||||
|
||||
ver 3.8:
|
||||
Fix issue with handling unit tests and missing kernel features.
|
||||
|
||||
ver 3.7:
|
||||
Fix issue with handling length of EncryptedSecurity.
|
||||
Fix issue with handling empty affinities lists.
|
||||
Fix issue with handling survey scanning results.
|
||||
Fix issue with handling duplicate values in DPP URI.
|
||||
|
||||
ver 3.6:
|
||||
Fix issue with handling blacklisting and roaming requests.
|
||||
Fix issue with handling CQM thresholds for FullMAC devices.
|
||||
Add support for PMKSA when using FullMAC devices.
|
||||
|
||||
ver 3.5:
|
||||
Add support for option to disable blacklist handling.
|
||||
Add support for option to disable SAE for broken drivers.
|
||||
|
||||
ver 3.4:
|
||||
Add support for the Test Anything Protocol.
|
||||
|
||||
ver 3.3:
|
||||
Fix issue with handling External Authentication.
|
||||
|
||||
ver 3.2:
|
||||
Fix issue with GCC 15 and -std=c23 build errors.
|
||||
Add support for using PMKSA over SAE if available.
|
||||
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:
|
||||
Fix issue with handling FT-8021X and SHA256 PMKID derivation.
|
||||
|
||||
ver 2.6:
|
||||
Add support for setting driver specific quirks.
|
||||
Add support for disabling power saving mode.
|
||||
|
||||
ver 2.5:
|
||||
Fix issue with HT40+/- checks when creating chandef.
|
||||
Fix issue with handling support for FT-8021X-SHA384.
|
||||
Fix issue with handling secure bit check in handshake 1/4.
|
||||
Fix issue with allowing roaming before netconfig finishes.
|
||||
Fix issue with double free when disconnecting during FT.
|
||||
|
||||
ver 2.4:
|
||||
Fix issue with FT-over-Air and same channel operation.
|
||||
Fix issue with AP mode and missing support for GTK.
|
||||
Fix issue with AP mode and channel switch event.
|
||||
Fix issue with SSID string conversion handling.
|
||||
|
||||
ver 2.3:
|
||||
Fix issue with length calculation for WMM IE.
|
||||
Fix issue with channel number allocation off-by-one.
|
||||
Fix issue with cached session when TLS phase2 fails.
|
||||
Add support for FastReauthentication setting for EAP-TLS.
|
||||
|
||||
ver 2.2:
|
||||
Fix issue with handling FT and multiple roaming scans.
|
||||
Fix issue with handling multiple wiphy registrations.
|
||||
Fix issue with with EAP-PEAP session resumption.
|
||||
Add support for using PTK rekeying in AP mode.
|
||||
Add support for setting country IE in AP mode.
|
||||
Add support for setting WMM parameter IE in AP mode.
|
||||
|
||||
ver 2.1:
|
||||
Fix issue with handling FT-over-DS action.
|
||||
Fix issue with handling scan and 6 GHz support check.
|
||||
Fix issue with handling when periodic scans get aborted.
|
||||
Add support for using 5 GHz frequencies in AP mode.
|
||||
|
||||
ver 2.0:
|
||||
Fix issue with handling P2P and limiting ciphers to CCMP.
|
||||
Fix issue with scanning before forced roaming action.
|
||||
Fix issue with provided scan frequencies from RRM.
|
||||
Fix issue with handling Michael MIC failure message.
|
||||
Fix issue with handling timestamp size in MPDU frames.
|
||||
Fix issue with handling enablement of OCVC for FT AKMs.
|
||||
Fix issue with handling FT work as highest priority.
|
||||
Fix issue with handling roaming events and Multi-BSS.
|
||||
Add support for utilizing roaming candidates list.
|
||||
Add support for utilizing TLS session caching.
|
||||
Add support for ciphers with 256 bits key size.
|
||||
Add support for Access Point mode with legacy TKIP.
|
||||
Add support for MAC address changes while powered.
|
||||
Add support for IPv4 and IPv6 network configuration.
|
||||
|
||||
ver 1.30:
|
||||
Fix issue with handling OWE if buggy AP is detected.
|
||||
Fix issue with handling quick scan and enabling 6GHz.
|
||||
Fix issue with handling tags for extended IEs.
|
||||
Add support for handling HE capabilities.
|
||||
Add support for handling regulatory domain changes.
|
||||
Add support for handling netdev packet loss events.
|
||||
|
||||
ver 1.29:
|
||||
Fix issue with handling EAP-Success message.
|
||||
Fix issue with handling secure setting and EAPoL.
|
||||
Add support for DeviceProvisioning API properties.
|
||||
|
||||
ver 1.28:
|
||||
Fix issue with handling invalid EAPoL frames.
|
||||
Fix issue with handling unexpectedly unencrypted EAP frames.
|
||||
Fix issue with handling AlwaysRandomizeAddress/AddressOverride.
|
||||
Fix issue with handling initial signal level notification.
|
||||
Fix issue with handling sorting of scan requests.
|
||||
Fix issue with handling frame type check in FT.
|
||||
|
||||
ver 1.27:
|
||||
Fix issue with hidden networks on connection error.
|
||||
Fix issue with directed roams if already trying to roam.
|
||||
Fix issue with checking for connected in FT frame event.
|
||||
|
||||
ver 1.26:
|
||||
Fix issue with handling BSS that changed frequency.
|
||||
Fix issue with handling frequencies in neighbor report.
|
||||
Fix issue with operating classes for 802.11ax standard.
|
||||
Fix issue with enforcing of MFPR for 6 GHz frequencies.
|
||||
Add support for band defined in the WiFi 6E amendment.
|
||||
Add support for scanning while in AP mode.
|
||||
|
||||
ver 1.25:
|
||||
Fix issue with handling abort of periodic scans.
|
||||
Fix issue with handling connection when link goes down.
|
||||
Fix issue with handling operating channel information.
|
||||
Add support for encrypted network profile storage.
|
||||
Add support for DPP initiating as a configurator.
|
||||
|
||||
ver 1.24:
|
||||
Fix issue with handshake and missing rekeying support.
|
||||
Fix issue with BSS ranking and zero signal strength.
|
||||
Fix issue with setting OWE IE length correctly.
|
||||
|
||||
ver 1.23:
|
||||
Fix issue with handling handshake offloading.
|
||||
Fix issue with at_console and D-Bus policy.
|
||||
|
||||
ver 1.22:
|
||||
Fix issue with handling periodic scanning.
|
||||
Fix issue with handling scanning completion.
|
||||
|
2
HACKING
2
HACKING
@ -5,7 +5,7 @@ If you fixed a bug or you want to add support for something, patches are
|
||||
welcome! The preferred method of submitting the patches to the project is by
|
||||
email to the iwd mailing list:
|
||||
|
||||
iwd@lists.linux.dev
|
||||
iwd@lists.01.org
|
||||
|
||||
In order to ease the inclusion of your patch, it's important to follow
|
||||
some rules, otherwise it will likely be rejected by maintainers.
|
||||
|
139
Makefile.am
139
Makefile.am
@ -62,18 +62,12 @@ ell_headers = ell/util.h \
|
||||
ell/icmp6.h \
|
||||
ell/dhcp6.h \
|
||||
ell/acd.h \
|
||||
ell/cleanup.h \
|
||||
ell/netconfig.h \
|
||||
ell/sysctl.h \
|
||||
ell/notifylist.h \
|
||||
ell/minheap.h
|
||||
ell/cleanup.h
|
||||
|
||||
ell_sources = ell/private.h \
|
||||
ell/missing.h \
|
||||
ell/util.c \
|
||||
ell/test-private.h \
|
||||
ell/test.c \
|
||||
ell/test-dbus.c \
|
||||
ell/strv.c \
|
||||
ell/utf8.c \
|
||||
ell/queue.c \
|
||||
@ -92,7 +86,6 @@ ell_sources = ell/private.h \
|
||||
ell/netlink-private.h \
|
||||
ell/netlink.c \
|
||||
ell/genl.c \
|
||||
ell/rtnl-private.h \
|
||||
ell/rtnl.c \
|
||||
ell/dbus-private.h \
|
||||
ell/dbus.c \
|
||||
@ -147,25 +140,13 @@ ell_sources = ell/private.h \
|
||||
ell/icmp6-private.h \
|
||||
ell/dhcp6-lease.c \
|
||||
ell/dhcp6-transport.c \
|
||||
ell/acd.c \
|
||||
ell/netconfig.c \
|
||||
ell/sysctl.c \
|
||||
ell/notifylist.c \
|
||||
ell/minheap.c
|
||||
ell/acd.c
|
||||
|
||||
ell_shared = ell/useful.h ell/asn1-private.h
|
||||
|
||||
ell_libell_internal_la_SOURCES = $(ell_headers) $(ell_sources) $(ell_shared)
|
||||
endif
|
||||
|
||||
if LIBEDIT
|
||||
client_cflags = $(LIBEDIT_CFLAGS)
|
||||
client_ldadd = $(LIBEDIT_LIBS)
|
||||
else
|
||||
client_cflags =
|
||||
client_ldadd = $(READLINE_LIBS)
|
||||
endif
|
||||
|
||||
bin_PROGRAMS =
|
||||
libexec_PROGRAMS =
|
||||
noinst_PROGRAMS =
|
||||
@ -218,8 +199,7 @@ eap_sources = src/eap.c src/eap.h src/eap-private.h \
|
||||
if DAEMON
|
||||
libexec_PROGRAMS += src/iwd
|
||||
|
||||
src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h \
|
||||
src/missing.h src/defs.h \
|
||||
src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h src/missing.h \
|
||||
src/netdev.h src/netdev.c \
|
||||
src/wiphy.h src/wiphy.c \
|
||||
src/device.c \
|
||||
@ -254,8 +234,7 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h \
|
||||
src/anqp.h src/anqp.c \
|
||||
src/anqputil.h src/anqputil.c \
|
||||
src/netconfig.h src/netconfig.c\
|
||||
src/netconfig-commit.c \
|
||||
src/resolve.h src/resolve.c \
|
||||
src/resolve.h src/resolve.c\
|
||||
src/hotspot.c \
|
||||
src/p2p.h src/p2p.c \
|
||||
src/p2putil.h src/p2putil.c \
|
||||
@ -272,8 +251,6 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h \
|
||||
src/dpp-util.h src/dpp-util.c \
|
||||
src/json.h src/json.c \
|
||||
src/dpp.c \
|
||||
src/udev.c \
|
||||
src/pmksa.h src/pmksa.c \
|
||||
$(eap_sources) \
|
||||
$(builtin_sources)
|
||||
|
||||
@ -323,13 +300,9 @@ client_iwctl_SOURCES = client/main.c \
|
||||
client/wsc.c client/station.c \
|
||||
client/diagnostic.c client/diagnostic.h \
|
||||
client/daemon.c client/daemon.h \
|
||||
client/dpp.c client/dpp-pkex.c \
|
||||
client/station-debug.c \
|
||||
client/bss.c \
|
||||
src/util.c src/util.h \
|
||||
src/band.c src/band.h
|
||||
client/dpp.c
|
||||
|
||||
client_iwctl_LDADD = $(ell_ldadd) $(client_ldadd)
|
||||
client_iwctl_LDADD = $(ell_ldadd) $(READLINE_LIBS)
|
||||
|
||||
if MANUAL_PAGES
|
||||
man_MANS += client/iwctl.1
|
||||
@ -389,8 +362,7 @@ man_MANS += wired/ead.8
|
||||
endif
|
||||
endif
|
||||
|
||||
if DAEMON
|
||||
noinst_PROGRAMS += tools/probe-req tools/iwd-decrypt-profile
|
||||
noinst_PROGRAMS += tools/probe-req
|
||||
|
||||
tools_probe_req_SOURCES = tools/probe-req.c src/mpdu.h src/mpdu.c \
|
||||
src/ie.h src/ie.c \
|
||||
@ -400,13 +372,6 @@ tools_probe_req_SOURCES = tools/probe-req.c src/mpdu.h src/mpdu.c \
|
||||
src/band.h src/band.c
|
||||
tools_probe_req_LDADD = $(ell_ldadd)
|
||||
|
||||
tools_iwd_decrypt_profile_SOURCES = tools/iwd-decrypt-profile.c \
|
||||
src/common.h src/common.c \
|
||||
src/crypto.h src/crypto.c \
|
||||
src/storage.h src/storage.c
|
||||
tools_iwd_decrypt_profile_LDADD = ${ell_ldadd}
|
||||
endif
|
||||
|
||||
if HWSIM
|
||||
bin_PROGRAMS += tools/hwsim
|
||||
|
||||
@ -416,9 +381,7 @@ tools_hwsim_SOURCES = tools/hwsim.c src/mpdu.h \
|
||||
src/nl80211util.h src/nl80211util.c \
|
||||
src/storage.h src/storage.c \
|
||||
src/common.h src/common.c \
|
||||
src/band.h src/band.c \
|
||||
src/ie.h src/ie.c \
|
||||
src/crypto.h src/crypto.c
|
||||
src/band.h src/band.c
|
||||
tools_hwsim_LDADD = $(ell_ldadd)
|
||||
|
||||
if DBUS_POLICY
|
||||
@ -430,19 +393,14 @@ man_MANS += tools/hwsim.1
|
||||
endif
|
||||
endif
|
||||
|
||||
unit_tests =
|
||||
|
||||
if DAEMON
|
||||
unit_tests += unit/test-cmac-aes \
|
||||
unit_tests = unit/test-cmac-aes \
|
||||
unit/test-hmac-md5 unit/test-hmac-sha1 unit/test-hmac-sha256 \
|
||||
unit/test-prf-sha1 unit/test-kdf-sha256 \
|
||||
unit/test-crypto unit/test-eapol unit/test-mpdu \
|
||||
unit/test-ie unit/test-util unit/test-ssid-security \
|
||||
unit/test-arc4 unit/test-wsc unit/test-eap-mschapv2 \
|
||||
unit/test-eap-sim unit/test-sae unit/test-p2p unit/test-band \
|
||||
unit/test-dpp unit/test-json unit/test-nl80211util \
|
||||
unit/test-pmksa unit/test-storage
|
||||
endif
|
||||
unit/test-dpp unit/test-json
|
||||
|
||||
if CLIENT
|
||||
unit_tests += unit/test-client
|
||||
@ -452,7 +410,6 @@ if MAINTAINER_MODE
|
||||
noinst_PROGRAMS += $(unit_tests)
|
||||
endif
|
||||
|
||||
if DAEMON
|
||||
unit_test_eap_sim_SOURCES = unit/test-eap-sim.c \
|
||||
src/crypto.h src/crypto.c src/simutil.h src/simutil.c \
|
||||
src/ie.h src/ie.c \
|
||||
@ -460,13 +417,13 @@ unit_test_eap_sim_SOURCES = unit/test-eap-sim.c \
|
||||
src/eapol.h src/eapol.c \
|
||||
src/eapolutil.h src/eapolutil.c \
|
||||
src/handshake.h src/handshake.c \
|
||||
src/pmksa.h src/pmksa.c \
|
||||
src/eap.h src/eap.c src/eap-private.h \
|
||||
src/util.h src/util.c \
|
||||
src/simauth.h src/simauth.c \
|
||||
src/erp.h src/erp.c \
|
||||
src/band.h src/band.c \
|
||||
src/eap-sim.c
|
||||
|
||||
unit_test_eap_sim_LDADD = $(ell_ldadd)
|
||||
|
||||
unit_test_cmac_aes_SOURCES = unit/test-cmac-aes.c \
|
||||
@ -475,6 +432,7 @@ unit_test_cmac_aes_LDADD = $(ell_ldadd)
|
||||
|
||||
unit_test_arc4_SOURCES = unit/test-arc4.c \
|
||||
src/crypto.h src/crypto.c
|
||||
|
||||
unit_test_arc4_LDADD = $(ell_ldadd)
|
||||
|
||||
unit_test_hmac_md5_SOURCES = unit/test-hmac-md5.c \
|
||||
@ -500,8 +458,7 @@ unit_test_kdf_sha256_LDADD = $(ell_ldadd)
|
||||
unit_test_ie_SOURCES = unit/test-ie.c src/ie.h src/ie.c
|
||||
unit_test_ie_LDADD = $(ell_ldadd)
|
||||
|
||||
unit_test_band_SOURCES = unit/test-band.c src/band.h src/band.c src/netdev.h \
|
||||
src/ie.h src/ie.c
|
||||
unit_test_band_SOURCES = unit/test-band.c src/band.h src/band.c
|
||||
unit_test_band_LDADD = $(ell_ldadd)
|
||||
|
||||
unit_test_crypto_SOURCES = unit/test-crypto.c \
|
||||
@ -520,7 +477,6 @@ unit_test_eapol_SOURCES = unit/test-eapol.c \
|
||||
src/eapol.h src/eapol.c \
|
||||
src/eapolutil.h src/eapolutil.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-tls.c src/eap-ttls.c \
|
||||
src/eap-md5.c src/util.c \
|
||||
@ -551,7 +507,6 @@ unit_test_wsc_SOURCES = unit/test-wsc.c src/wscutil.h src/wscutil.c \
|
||||
src/eapol.h src/eapol.c \
|
||||
src/eapolutil.h src/eapolutil.c \
|
||||
src/handshake.h src/handshake.c \
|
||||
src/pmksa.h src/pmksa.c \
|
||||
src/eap.h src/eap.c src/eap-private.h \
|
||||
src/util.h src/util.c \
|
||||
src/erp.h src/erp.c \
|
||||
@ -565,12 +520,24 @@ unit_test_eap_mschapv2_SOURCES = src/eap-mschapv2.h src/eap-mschapv2.c \
|
||||
unit/test-eap-mschapv2.c
|
||||
unit_test_eap_mschapv2_LDADD = $(ell_ldadd)
|
||||
|
||||
if CLIENT
|
||||
unit_test_client_SOURCES = unit/test-client.c \
|
||||
client/adapter.c \
|
||||
client/agent.h client/agent.c \
|
||||
client/agent-manager.h client/agent-manager.c \
|
||||
client/command.h client/command.c \
|
||||
client/dbus-proxy.h client/dbus-proxy.c \
|
||||
client/display.h client/display.c \
|
||||
client/network.h client/network.c \
|
||||
client/properties.h client/properties.c
|
||||
unit_test_client_LDADD = $(ell_ldadd) $(READLINE_LIBS)
|
||||
endif
|
||||
|
||||
unit_test_sae_SOURCES = unit/test-sae.c \
|
||||
src/sae.h src/sae.c \
|
||||
src/crypto.h src/crypto.c \
|
||||
src/ie.h src/ie.c \
|
||||
src/handshake.h src/handshake.c \
|
||||
src/pmksa.h src/pmksa.c \
|
||||
src/erp.h src/erp.c \
|
||||
src/band.h src/band.c \
|
||||
src/util.h src/util.c \
|
||||
@ -595,39 +562,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_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
|
||||
|
||||
if CLIENT
|
||||
unit_test_client_SOURCES = unit/test-client.c \
|
||||
client/adapter.c \
|
||||
client/agent.h client/agent.c \
|
||||
client/agent-manager.h client/agent-manager.c \
|
||||
client/command.h client/command.c \
|
||||
client/dbus-proxy.h client/dbus-proxy.c \
|
||||
client/display.h client/display.c \
|
||||
client/network.h client/network.c \
|
||||
client/properties.h client/properties.c
|
||||
unit_test_client_LDADD = $(ell_ldadd) $(client_ldadd)
|
||||
endif
|
||||
|
||||
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
|
||||
$(top_srcdir)/build-aux/tap-driver.sh
|
||||
|
||||
TESTS = $(unit_tests)
|
||||
|
||||
EXTRA_DIST = src/genbuiltin src/iwd.service.in src/net.connman.iwd.service \
|
||||
@ -638,9 +572,10 @@ EXTRA_DIST = src/genbuiltin src/iwd.service.in src/net.connman.iwd.service \
|
||||
$(patsubst %.5,%.rst, \
|
||||
$(patsubst %.8,%.rst,$(manual_pages))))
|
||||
|
||||
AM_CFLAGS = $(ell_cflags) $(client_cflags) -fvisibility=hidden \
|
||||
AM_CFLAGS = $(ell_cflags) -fvisibility=hidden \
|
||||
-DUNITDIR=\""$(top_srcdir)/unit/"\" \
|
||||
-DCERTDIR=\""$(top_builddir)/unit/"\"
|
||||
-DCERTDIR=\""$(top_builddir)/unit/"\" \
|
||||
-DJSMN_PARENT_LINKS -DJSMN_STRICT
|
||||
|
||||
if MAINTAINER_MODE
|
||||
AM_CFLAGS += -DHAVE_PKCS8_SUPPORT
|
||||
@ -744,7 +679,6 @@ ell/internal: Makefile
|
||||
done > $@
|
||||
|
||||
ell/ell.h: Makefile
|
||||
$(AM_V_at)$(MKDIR_P) ell
|
||||
$(AM_V_at)echo -n > $@
|
||||
$(AM_V_GEN)for f in $(ell_headers) ; do \
|
||||
echo "#include <$$f>" >> $@ ; \
|
||||
@ -788,25 +722,12 @@ if WIRED
|
||||
endif
|
||||
endif
|
||||
|
||||
gcov-clean:
|
||||
if GCOV
|
||||
-$(LCOV) --quiet --directory $(builddir) -z
|
||||
-rm -rf "$(builddir)/iwd-coverage.info" "$(builddir)/gcov"
|
||||
-find . -name "*.gcda" -o -name "*.gcov" -o -name "*.gcno" -delete
|
||||
endif
|
||||
|
||||
clean-local: gcov-clean
|
||||
clean-local:
|
||||
-rm -f unit/cert-*.pem unit/cert-*.csr unit/cert-*.srl unit/*-settings.8021x
|
||||
|
||||
maintainer-clean-local:
|
||||
-rm -rf build-aux ell
|
||||
|
||||
gcov-report:
|
||||
if GCOV
|
||||
$(LCOV) --quiet --directory $(builddir) --capture --output-file "iwd-coverage.info"
|
||||
LANG=C $(GENHTML) --quiet --prefix $(builddir) --output-directory "$(builddir)/gcov" --title "iwd Code Coverage" --legend "$(builddir)/iwd-coverage.info"
|
||||
endif
|
||||
|
||||
src/builtin.h: src/genbuiltin config.status
|
||||
$(AM_V_at)$(MKDIR_P) $(@D)
|
||||
$(AM_V_GEN)$(srcdir)/src/genbuiltin $(builtin_modules) > $@
|
||||
|
3
README
3
README
@ -268,8 +268,7 @@ Information
|
||||
===========
|
||||
|
||||
Mailing list:
|
||||
https://lists.linux.dev/
|
||||
https://lore.kernel.org/iwd/
|
||||
https://lists.01.org/postorius/lists/iwd.lists.01.org/
|
||||
|
||||
IRC:
|
||||
irc://irc.oftc.net/#iwd
|
||||
|
6
TODO
6
TODO
@ -110,7 +110,7 @@ Wireless monitor
|
||||
|
||||
- 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
|
||||
events, it is required that iwmon adds membership to all multicast
|
||||
groups that the nl80211 lists.
|
||||
@ -234,7 +234,7 @@ Wireless daemon
|
||||
|
||||
- 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
|
||||
the PBC request in the ProbeRequest frames after EAP-WSC completes
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
Priority: Low
|
||||
|
30
acinclude.m4
30
acinclude.m4
@ -46,30 +46,10 @@ AC_DEFUN([AC_PROG_CC_UBSAN], [
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([AC_PROG_CC_GCOV], [
|
||||
AC_CACHE_CHECK([whether ${CC-cc} accepts -fprofile-arcs], ac_cv_prog_cc_profile_arcs, [
|
||||
echo 'void f(){}' > conftest.c
|
||||
if test -z "`${CC-cc} -fprofile-arcs -c conftest.c 2>&1`"; then
|
||||
ac_cv_prog_cc_profile_arcs=yes
|
||||
else
|
||||
ac_cv_prog_cc_profile_arcs=no
|
||||
fi
|
||||
rm -rf conftest*
|
||||
])
|
||||
AC_CACHE_CHECK([whether ${CC-cc} accepts -ftest_coverage], ac_cv_prog_cc_test_coverage, [
|
||||
echo 'void f(){}' > conftest.c
|
||||
if test -z "`${CC-cc} -ftest-coverage -c conftest.c 2>&1`"; then
|
||||
ac_cv_prog_cc_test_coverage=yes
|
||||
else
|
||||
ac_cv_prog_cc_test_coverage=no
|
||||
fi
|
||||
rm -rf conftest*
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([COMPILER_FLAGS], [
|
||||
if (test "${CFLAGS}" = ""); then
|
||||
CFLAGS="-Wall -fsigned-char -fno-exceptions"
|
||||
CFLAGS="-Wall -O2 -fsigned-char -fno-exceptions"
|
||||
CFLAGS+=" -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2"
|
||||
fi
|
||||
if (test "$USE_MAINTAINER_MODE" = "yes"); then
|
||||
CFLAGS+=" -Werror -Wextra"
|
||||
@ -78,14 +58,10 @@ AC_DEFUN([COMPILER_FLAGS], [
|
||||
CFLAGS+=" -Wdeclaration-after-statement"
|
||||
CFLAGS+=" -Wmissing-declarations"
|
||||
CFLAGS+=" -Wredundant-decls"
|
||||
CFALGS+=" -Wvariadic-macros"
|
||||
CFLAGS+=" -Wformat -Wformat-security"
|
||||
if ( $CC -v 2>/dev/null | grep "gcc version" ); then
|
||||
CFLAGS+=" -Wcast-align"
|
||||
fi
|
||||
fi
|
||||
|
||||
if (test "$CC" = "clang"); then
|
||||
CFLAGS+=" -Wno-unknown-warning-option"
|
||||
CFLAGS+=" -Wno-unknown-pragmas"
|
||||
fi
|
||||
])
|
||||
|
@ -20,8 +20,3 @@
|
||||
"ttls-mschapv2-phase2@example.com" TTLS-MSCHAPV2 "Password" [2]
|
||||
"ttls-pap-phase2@example.com" TTLS-PAP "Password" [2]
|
||||
"112345678@phonesim.org" SIM [2]
|
||||
|
||||
# TODO: Hostapd is broken with phase1 lookups for reauthentication.
|
||||
# Allowing a wildcard phase1 for PEAP/TTLS is a stop gap until
|
||||
# hostapd is actually fixed.
|
||||
* PEAP,TTLS
|
||||
|
@ -1,3 +0,0 @@
|
||||
[Security]
|
||||
Passphrase=secret123
|
||||
PairwiseCiphers=CCMP
|
@ -5,58 +5,20 @@ import sys
|
||||
|
||||
sys.path.append('../util')
|
||||
import iwd
|
||||
from iwd import IWD, NetworkType, PSKAgent
|
||||
from iwd import IWD
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def test_no_ap_mode(self):
|
||||
wd = IWD(True)
|
||||
def test_connection_success(self):
|
||||
wd = IWD()
|
||||
|
||||
dev = wd.list_devices(1)[0]
|
||||
|
||||
with self.assertRaises(iwd.NotSupportedEx):
|
||||
dev.start_ap('TestAP2', 'Password2')
|
||||
|
||||
def test_only_tkip_support(self):
|
||||
wd = IWD(True)
|
||||
|
||||
devices = wd.list_devices(2)
|
||||
|
||||
dev_sta = devices[0]
|
||||
dev_ap = devices[1]
|
||||
|
||||
dev_ap.start_ap('TestAP2', 'Password2')
|
||||
|
||||
self.assertTrue(dev_ap.group_cipher == 'TKIP')
|
||||
self.assertIn('TKIP', dev_ap.pairwise_ciphers)
|
||||
|
||||
ordered_network = dev_sta.get_ordered_network('TestAP2')
|
||||
|
||||
if ordered_network.type != NetworkType.psk:
|
||||
raise Exception("Network type mismatch")
|
||||
|
||||
psk_agent = PSKAgent('Password2')
|
||||
wd.register_psk_agent(psk_agent)
|
||||
|
||||
ordered_network.network_object.connect()
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(dev_sta, condition)
|
||||
|
||||
wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
def test_no_ccmp_support(self):
|
||||
wd = IWD(True)
|
||||
|
||||
dev = wd.list_devices(2)[1]
|
||||
|
||||
# Should fail to start since the radio doesn't support CCMP but the
|
||||
# profile only lists CCMP as allowed.
|
||||
with self.assertRaises(iwd.NotSupportedEx):
|
||||
dev.start_ap('TestAP2')
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
IWD.copy_to_ap('TestAP2.ap')
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
@ -1,9 +1,6 @@
|
||||
[SETUP]
|
||||
num_radios=2
|
||||
start_iwd=0
|
||||
num_radios=1
|
||||
radio_confs=rad0
|
||||
|
||||
[rad0]
|
||||
iftype_disable=ap
|
||||
|
||||
[rad1]
|
||||
cipher_disable=ccmp,bip_cmac,gcmp,gcmp_256,ccmp_256,bip_gmac,bip_gmac_256,bip_cmac_256
|
||||
|
@ -1,2 +0,0 @@
|
||||
[Security]
|
||||
Passphrase=Password2
|
@ -1,76 +1,105 @@
|
||||
#! /usr/bin/python3
|
||||
|
||||
import unittest
|
||||
import os
|
||||
import sys, os
|
||||
|
||||
import iwd
|
||||
from iwd import IWD
|
||||
from config import ctx
|
||||
from validation import validate, client_connect
|
||||
from iwd import PSKAgent
|
||||
from iwd import NetworkType
|
||||
from hostapd import HostapdCLI
|
||||
import testutil
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def test_connection_success(self):
|
||||
IWD.copy_to_storage('TestAP1.psk')
|
||||
|
||||
def client_connect(self, wd, dev):
|
||||
hostapd = HostapdCLI(config='psk-ccmp.conf')
|
||||
|
||||
ordered_network = dev.get_ordered_network('TestAP1')
|
||||
|
||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
||||
|
||||
psk_agent = PSKAgent('Password1')
|
||||
wd.register_psk_agent(psk_agent)
|
||||
|
||||
ordered_network.network_object.connect()
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(dev, condition)
|
||||
|
||||
wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
testutil.test_iface_operstate(dev.name)
|
||||
testutil.test_ifaces_connected(hostapd.ifname, dev.name)
|
||||
|
||||
dev.disconnect()
|
||||
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
||||
|
||||
def test_connection_success(self):
|
||||
wd = IWD(True)
|
||||
|
||||
dev1, dev2 = wd.list_devices(2)
|
||||
|
||||
client_connect(wd, dev1, 'TestAP1')
|
||||
self.client_connect(wd, dev1)
|
||||
|
||||
dev1.start_ap('TestAP2', 'Password2')
|
||||
|
||||
validate(wd, dev2, dev1, 'TestAP2', 'Password2')
|
||||
try:
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
dev2.scan()
|
||||
condition = 'obj.scanning'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
|
||||
networks = {}
|
||||
networks['TestAP1'] = dev2.get_ordered_network('TestAP1')
|
||||
networks['TestAP2'] = dev2.get_ordered_network('TestAP2', full_scan=True)
|
||||
|
||||
self.assertEqual(networks['TestAP1'].type, NetworkType.psk)
|
||||
self.assertEqual(networks['TestAP2'].type, NetworkType.psk)
|
||||
|
||||
psk_agent = PSKAgent('Password2')
|
||||
wd.register_psk_agent(psk_agent)
|
||||
|
||||
try:
|
||||
dev2.disconnect()
|
||||
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
except:
|
||||
pass
|
||||
|
||||
networks['TestAP2'].network_object.connect()
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
|
||||
testutil.test_iface_operstate(dev2.name)
|
||||
testutil.test_ifaces_connected(dev1.name, dev2.name, group=False)
|
||||
|
||||
wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
dev2.disconnect()
|
||||
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(networks['TestAP2'].network_object,
|
||||
condition)
|
||||
finally:
|
||||
dev1.stop_ap()
|
||||
|
||||
# Finally test dev1 can go to client mode and connect again
|
||||
client_connect(wd, dev1, 'TestAP1')
|
||||
self.client_connect(wd, dev1)
|
||||
|
||||
def test_client_start_ap(self):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
IWD.copy_to_storage('TestAP1.psk')
|
||||
|
||||
wd = IWD(True)
|
||||
|
||||
dev1, dev2 = wd.list_devices(2)
|
||||
|
||||
ctx.start_process(['iwctl', 'device', dev1.name, 'set-property', 'Mode', 'ap'], check=True)
|
||||
ctx.start_process(['iwctl', 'ap', dev1.name, 'start', 'TestAP2', 'Password2'], check=True)
|
||||
|
||||
iwctl = ctx.start_process(['iwctl', 'ap', 'list'], check=True)
|
||||
|
||||
self.assertIn(dev1.name, iwctl.out)
|
||||
|
||||
iwctl = ctx.start_process(['iwctl', 'ap', dev1.name, 'show'], check=True)
|
||||
|
||||
self.assertIn('TestAP2', iwctl.out)
|
||||
|
||||
validate(wd, dev2, dev1, 'TestAP2', 'Password2')
|
||||
|
||||
def test_valid_ciphers(self):
|
||||
ciphers = ['TKIP', 'CCMP-128', 'GCMP-128', 'CCMP-256', 'GCMP-256']
|
||||
|
||||
for group in ciphers:
|
||||
for pairwise in ciphers:
|
||||
IWD.copy_to_ap('TestAP2.ap')
|
||||
os.system('echo "PairwiseCiphers=%s" >> /tmp/iwd/ap/TestAP2.ap' % pairwise)
|
||||
os.system('echo "GroupCipher=%s" >> /tmp/iwd/ap/TestAP2.ap' % group)
|
||||
|
||||
wd = IWD(True)
|
||||
|
||||
dev1, dev2 = wd.list_devices(2)
|
||||
|
||||
dev1.start_ap('TestAP2')
|
||||
|
||||
self.assertTrue(dev1.group_cipher == group)
|
||||
self.assertIn(pairwise, dev1.pairwise_ciphers)
|
||||
|
||||
try:
|
||||
validate(wd, dev2, dev1, 'TestAP2', 'Password2', ip_checks=False)
|
||||
except:
|
||||
raise Exception("Failed with pairwise=%s group=%s" % (pairwise, group))
|
||||
finally:
|
||||
IWD.clear_storage()
|
||||
del wd
|
||||
|
||||
def tearDown(self):
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
IWD.clear_storage()
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -1,10 +1,14 @@
|
||||
#! /usr/bin/python3
|
||||
|
||||
import unittest
|
||||
import sys, os
|
||||
|
||||
import iwd
|
||||
from iwd import IWD
|
||||
from iwd import PSKAgent
|
||||
from iwd import NetworkType
|
||||
from config import ctx
|
||||
from validation import validate
|
||||
import testutil
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def test_connection_success(self):
|
||||
@ -24,8 +28,55 @@ class Test(unittest.TestCase):
|
||||
|
||||
dev1.start_ap('APConfig')
|
||||
|
||||
validate(wd, dev2, dev1, 'APConfig', 'password123',
|
||||
sta_ip_info=('192.168.1.3', ctx), ap_ip_info=('192.168.1.1', ns0))
|
||||
try:
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
dev2.scan()
|
||||
condition = 'obj.scanning'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
|
||||
networks = {}
|
||||
networks['APConfig'] = dev2.get_ordered_network('APConfig', full_scan=True)
|
||||
|
||||
self.assertEqual(networks['APConfig'].type, NetworkType.psk)
|
||||
|
||||
psk_agent = PSKAgent('password123')
|
||||
wd.register_psk_agent(psk_agent)
|
||||
|
||||
try:
|
||||
dev2.disconnect()
|
||||
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
except:
|
||||
pass
|
||||
|
||||
networks['APConfig'].network_object.connect()
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
|
||||
testutil.test_iface_operstate(dev2.name)
|
||||
#
|
||||
# TODO: cannot yet check the AP interface IP since its in a
|
||||
# different namespace.
|
||||
#
|
||||
testutil.test_ip_address_match(dev2.name, "192.168.1.3")
|
||||
|
||||
testutil.test_ip_connected(('192.168.1.3', ctx), ('192.168.1.1', ns0))
|
||||
|
||||
wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
dev2.disconnect()
|
||||
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(networks['APConfig'].network_object,
|
||||
condition)
|
||||
|
||||
finally:
|
||||
dev1.stop_ap()
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
@ -10,8 +10,6 @@ from iwd import NetworkType
|
||||
from config import ctx
|
||||
import testutil
|
||||
|
||||
from validation import validate
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def test_connection_success(self):
|
||||
wd = IWD(True, '/tmp/dhcp')
|
||||
@ -27,36 +25,67 @@ class Test(unittest.TestCase):
|
||||
with self.assertRaises(iwd.AlreadyExistsEx):
|
||||
dev4.start_ap('TestAP4', 'Password4')
|
||||
|
||||
validate(wd, dev2, dev1, 'TestAP2', 'Password2', ip_checks=False)
|
||||
|
||||
network = dev2.get_ordered_network('TestAP2', full_scan=True)
|
||||
|
||||
try:
|
||||
testutil.test_ip_address_match(dev1.name, "192.168.80.1")
|
||||
testutil.test_ip_address_match(dev2.name, "192.168.80.2")
|
||||
ip = "192.168.80.1"
|
||||
except:
|
||||
testutil.test_ip_address_match(dev1.name, "192.168.80.17")
|
||||
testutil.test_ip_address_match(dev2.name, "192.168.80.18")
|
||||
ip = "192.168.80.17"
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
dev2.scan()
|
||||
condition = 'obj.scanning'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
|
||||
dev2.disconnect()
|
||||
networks = {}
|
||||
networks['TestAP2'] = dev2.get_ordered_network('TestAP2', full_scan=True)
|
||||
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(network.network_object, condition)
|
||||
self.assertEqual(networks['TestAP2'].type, NetworkType.psk)
|
||||
|
||||
# This should release the IP */
|
||||
dev1.stop_ap()
|
||||
psk_agent = PSKAgent('Password2')
|
||||
wd.register_psk_agent(psk_agent)
|
||||
|
||||
# This should now succeed and the IP should match the old IP dev1
|
||||
# got initially.
|
||||
dev4.start_ap('TestAP4', 'Password4')
|
||||
try:
|
||||
dev2.disconnect()
|
||||
|
||||
testutil.test_ip_address_match(dev4.name, ip)
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
except:
|
||||
pass
|
||||
|
||||
dev1.stop_ap()
|
||||
dev3.stop_ap()
|
||||
dev4.stop_ap()
|
||||
networks['TestAP2'].network_object.connect()
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
|
||||
testutil.test_iface_operstate(dev2.name)
|
||||
testutil.test_ifaces_connected(dev1.name, dev2.name, group=False)
|
||||
|
||||
try:
|
||||
testutil.test_ip_address_match(dev1.name, "192.168.80.1")
|
||||
testutil.test_ip_address_match(dev2.name, "192.168.80.2")
|
||||
ip = "192.168.80.1"
|
||||
except:
|
||||
testutil.test_ip_address_match(dev1.name, "192.168.80.17")
|
||||
testutil.test_ip_address_match(dev2.name, "192.168.80.18")
|
||||
ip = "192.168.80.17"
|
||||
|
||||
wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
dev2.disconnect()
|
||||
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(networks['TestAP2'].network_object,
|
||||
condition)
|
||||
|
||||
# This should release the IP */
|
||||
dev1.stop_ap()
|
||||
|
||||
# This should now succeed and the IP should match the old IP dev1
|
||||
# got initially.
|
||||
dev4.start_ap('TestAP4', 'Password4')
|
||||
|
||||
testutil.test_ip_address_match(dev4.name, ip)
|
||||
|
||||
finally:
|
||||
dev1.stop_ap()
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
@ -48,8 +48,16 @@ class Test(unittest.TestCase):
|
||||
dev1.start_ap('TestAP2', 'Password2')
|
||||
|
||||
try:
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
dev2.scan()
|
||||
condition = 'obj.scanning'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
|
||||
networks = {}
|
||||
networks['TestAP1'] = dev2.get_ordered_network('TestAP1', full_scan=True)
|
||||
networks['TestAP1'] = dev2.get_ordered_network('TestAP1')
|
||||
networks['TestAP2'] = dev2.get_ordered_network('TestAP2', full_scan=True)
|
||||
|
||||
self.assertEqual(networks['TestAP1'].type, NetworkType.psk)
|
||||
|
@ -1,20 +0,0 @@
|
||||
#! /usr/bin/python3
|
||||
|
||||
import unittest
|
||||
|
||||
from iwd import IWD
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def test_ap_scan(self):
|
||||
wd = IWD(True)
|
||||
|
||||
dev = wd.list_devices(1)[0]
|
||||
|
||||
dev.start_ap('TestAP2', 'Password2')
|
||||
|
||||
dev.scan()
|
||||
|
||||
networks = dev.get_ordered_networks()
|
||||
|
||||
self.assertTrue(len(networks) == 1)
|
||||
self.assertTrue(networks[0]['Name'] == 'TestAP1')
|
@ -1,71 +0,0 @@
|
||||
from iwd import PSKAgent
|
||||
from iwd import NetworkType
|
||||
from hostapd import HostapdCLI
|
||||
import testutil
|
||||
|
||||
def validate(wd, sta_dev, ap_dev, ssid, passphrase,
|
||||
sta_ip_info=None, ap_ip_info=None, ip_checks=True):
|
||||
try:
|
||||
network = sta_dev.get_ordered_network(ssid, full_scan=True)
|
||||
|
||||
if network.type != NetworkType.psk:
|
||||
raise Exception("Network type mismatch")
|
||||
|
||||
psk_agent = PSKAgent(passphrase)
|
||||
wd.register_psk_agent(psk_agent)
|
||||
|
||||
network.network_object.connect()
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(sta_dev, condition)
|
||||
|
||||
testutil.test_iface_operstate(sta_dev.name)
|
||||
|
||||
# This implies separate namespaces so the iface names won't exist
|
||||
if not sta_ip_info or not ap_ip_info:
|
||||
testutil.test_ifaces_connected(ap_dev.name, sta_dev.name, group=False)
|
||||
|
||||
if not ip_checks:
|
||||
return
|
||||
|
||||
if sta_ip_info:
|
||||
testutil.test_ip_address_match(sta_dev.name, sta_ip_info[0])
|
||||
|
||||
if sta_ip_info and ap_ip_info:
|
||||
testutil.test_ip_connected(sta_ip_info, ap_ip_info)
|
||||
|
||||
wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
sta_dev.disconnect()
|
||||
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(network.network_object, condition)
|
||||
finally:
|
||||
if ip_checks:
|
||||
ap_dev.stop_ap()
|
||||
|
||||
def client_connect(wd, dev, ssid):
|
||||
hostapd = HostapdCLI(config='psk-ccmp.conf')
|
||||
|
||||
ordered_network = dev.get_ordered_network(ssid)
|
||||
|
||||
if ordered_network.type != NetworkType.psk:
|
||||
raise Exception("Network type mismatch")
|
||||
|
||||
psk_agent = PSKAgent('Password1')
|
||||
wd.register_psk_agent(psk_agent)
|
||||
|
||||
ordered_network.network_object.connect()
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(dev, condition)
|
||||
|
||||
wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
testutil.test_iface_operstate(dev.name)
|
||||
testutil.test_ifaces_connected(hostapd.ifname, dev.name)
|
||||
|
||||
dev.disconnect()
|
||||
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
@ -11,71 +11,57 @@ from iwd import NetworkType
|
||||
from hostapd import HostapdCLI
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def initial_connection(self):
|
||||
ordered_network = self.device.get_ordered_network('TestAPRoam')
|
||||
|
||||
def test_connection_success(self):
|
||||
bss_hostapd = [ HostapdCLI(config='ssid1.conf'),
|
||||
HostapdCLI(config='ssid2.conf'),
|
||||
HostapdCLI(config='ssid3.conf') ]
|
||||
|
||||
wd = IWD()
|
||||
|
||||
devices = wd.list_devices(1)
|
||||
device = devices[0]
|
||||
|
||||
ordered_network = device.get_ordered_network('TestAPRoam')
|
||||
|
||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
||||
|
||||
condition = 'not obj.connected'
|
||||
self.wd.wait_for_object_condition(ordered_network.network_object, condition)
|
||||
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
||||
|
||||
self.device.connect_bssid(self.bss_hostapd[0].bssid)
|
||||
device.connect_bssid(bss_hostapd[0].bssid)
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
self.wd.wait_for_object_condition(self.device, condition)
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED')
|
||||
bss_hostapd[0].wait_for_event('AP-STA-CONNECTED')
|
||||
|
||||
self.assertFalse(self.bss_hostapd[1].list_sta())
|
||||
self.assertTrue(bss_hostapd[0].list_sta())
|
||||
self.assertFalse(bss_hostapd[1].list_sta())
|
||||
|
||||
def validate_roam(self, from_bss, to_bss, expect_roam=True):
|
||||
from_bss.send_bss_transition(self.device.address,
|
||||
self.neighbor_list,
|
||||
disassoc_imminent=expect_roam)
|
||||
bss_hostapd[0].send_bss_transition(device.address,
|
||||
[(bss_hostapd[1].bssid, '8f0000005102060603000000')])
|
||||
|
||||
if expect_roam:
|
||||
from_condition = 'obj.state == DeviceState.roaming'
|
||||
to_condition = 'obj.state == DeviceState.connected'
|
||||
self.wd.wait_for_object_change(self.device, from_condition, to_condition)
|
||||
condition = 'obj.state == DeviceState.roaming'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
to_bss.wait_for_event('AP-STA-CONNECTED %s' % self.device.address)
|
||||
else:
|
||||
self.device.wait_for_event("no-roam-candidates")
|
||||
condition = 'obj.state != DeviceState.roaming'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
def test_disassoc_imminent(self):
|
||||
self.initial_connection()
|
||||
self.validate_roam(self.bss_hostapd[0], self.bss_hostapd[1])
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
def test_no_candidates(self):
|
||||
self.initial_connection()
|
||||
# We now have BSS0 roam blacklisted
|
||||
self.validate_roam(self.bss_hostapd[0], self.bss_hostapd[1])
|
||||
# Try and trigger another roam back, which shouldn't happen since now
|
||||
# both BSS's are roam blacklisted
|
||||
self.validate_roam(self.bss_hostapd[1], self.bss_hostapd[0], expect_roam=False)
|
||||
self.assertEqual(device.state, iwd.DeviceState.connected)
|
||||
self.assertTrue(bss_hostapd[1].list_sta())
|
||||
device.disconnect()
|
||||
|
||||
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
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
||||
|
||||
@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') ]
|
||||
cls.neighbor_list = [
|
||||
(cls.bss_hostapd[0].bssid, "8f0000005101060603000000"),
|
||||
(cls.bss_hostapd[1].bssid, "8f0000005102060603000000"),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
IWD.clear_storage()
|
||||
|
@ -1,7 +1,5 @@
|
||||
[SETUP]
|
||||
num_radios=4
|
||||
hwsim_medium=true
|
||||
start_iwd=false
|
||||
|
||||
[HOSTAPD]
|
||||
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)
|
@ -2,16 +2,16 @@
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.path.append('../util')
|
||||
import iwd
|
||||
from iwd import IWD
|
||||
from iwd import AdHocDevice
|
||||
from config import ctx
|
||||
import testutil
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
def validate_connection(self, wd, client=False):
|
||||
def validate_connection(self, wd):
|
||||
dev1, dev2 = wd.list_devices(2)
|
||||
|
||||
self.assertIsNotNone(dev1)
|
||||
@ -22,14 +22,7 @@ class Test(unittest.TestCase):
|
||||
condition = 'obj.started == True'
|
||||
wd.wait_for_object_condition(adhoc1, condition)
|
||||
|
||||
if not client:
|
||||
adhoc2 = dev2.start_adhoc("AdHocNetwork", "secret123")
|
||||
else:
|
||||
ctx.start_process(['iwctl', 'device', dev2.name, 'set-property',
|
||||
'Mode', 'ad-hoc'], check=True)
|
||||
ctx.start_process(['iwctl', 'ad-hoc', dev2.name, 'start',
|
||||
'AdHocNetwork', 'secret123'], check=True)
|
||||
adhoc2 = AdHocDevice(dev2.device_path)
|
||||
adhoc2 = dev2.start_adhoc("AdHocNetwork", "secret123")
|
||||
|
||||
condition = 'obj.started == True'
|
||||
wd.wait_for_object_condition(adhoc1, condition)
|
||||
@ -49,10 +42,6 @@ class Test(unittest.TestCase):
|
||||
|
||||
self.validate_connection(wd)
|
||||
|
||||
def test_client_adhoc(self):
|
||||
wd = IWD(True)
|
||||
self.validate_connection(wd, client=True)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
pass
|
||||
|
@ -46,7 +46,7 @@ class Test(unittest.TestCase):
|
||||
perm_addr = device.address
|
||||
|
||||
# 1. Test per-network deterministic MAC generation
|
||||
IWD.copy_to_storage('pernetwork.psk', name='ssidCCMP.psk')
|
||||
os.system('cat pernetwork.psk > /tmp/iwd/ssidCCMP.psk')
|
||||
new_addr = self.try_connection(wd)
|
||||
self.assertNotEqual(perm_addr, new_addr)
|
||||
# try again to ensure the generation was deterministic
|
||||
@ -54,7 +54,7 @@ class Test(unittest.TestCase):
|
||||
self.assertEqual(new_addr, new_addr2)
|
||||
|
||||
# 2. Test FullAddressRandomization
|
||||
IWD.copy_to_storage('full_random.psk', name='ssidCCMP.psk')
|
||||
os.system('cat full_random.psk > /tmp/iwd/ssidCCMP.psk')
|
||||
new_addr = self.try_connection(wd)
|
||||
self.assertNotEqual(perm_addr, new_addr)
|
||||
# try again to make sure the generation was random
|
||||
@ -62,7 +62,7 @@ class Test(unittest.TestCase):
|
||||
self.assertNotEqual(new_addr, new_addr2)
|
||||
|
||||
# 3. Test AddressOverride
|
||||
IWD.copy_to_storage('override.psk', name='ssidCCMP.psk')
|
||||
os.system('cat override.psk > /tmp/iwd/ssidCCMP.psk')
|
||||
new_addr = self.try_connection(wd)
|
||||
self.assertEqual(new_addr, 'e6:f6:38:a9:02:02')
|
||||
|
||||
|
@ -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)
|
@ -2,7 +2,6 @@
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
import dbus
|
||||
|
||||
sys.path.append('../util')
|
||||
import iwd
|
||||
@ -56,19 +55,36 @@ class Test(unittest.TestCase):
|
||||
|
||||
IWD.clear_storage()
|
||||
|
||||
def test_connection_use_first_from_multiple_registered(self):
|
||||
def test_connection_with_other_agent(self):
|
||||
wd = IWD()
|
||||
|
||||
psk_agent = PSKAgent("secret_ssid1")
|
||||
wd.register_psk_agent(psk_agent)
|
||||
iwctl = ctx.start_process(['iwctl', '-P', 'secret_ssid2'])
|
||||
# Let iwctl to start and register its agent.
|
||||
wd.wait(2)
|
||||
|
||||
psk_agent = PSKAgent("secret_ssid2")
|
||||
self.check_connection(wd, 'ssid2')
|
||||
|
||||
iwctl.kill()
|
||||
|
||||
IWD.clear_storage()
|
||||
|
||||
def test_connection_use_own_agent_from_multiple_registered(self):
|
||||
|
||||
wd = IWD()
|
||||
|
||||
iwctl = ctx.start_process(['iwctl', '-P', 'secret_ssid2'])
|
||||
# Let iwctl to start and register its agent.
|
||||
wd.wait(2)
|
||||
|
||||
psk_agent = PSKAgent("secret_ssid1")
|
||||
wd.register_psk_agent(psk_agent)
|
||||
|
||||
self.check_connection(wd, 'ssid1')
|
||||
|
||||
wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
iwctl.kill()
|
||||
|
||||
IWD.clear_storage()
|
||||
|
||||
@classmethod
|
||||
|
@ -33,7 +33,7 @@ class Test(unittest.TestCase):
|
||||
|
||||
dev1, dev2 = wd.list_devices(2)
|
||||
|
||||
ordered_network = dev1.get_ordered_network("TestBlacklist", full_scan=True)
|
||||
ordered_network = dev1.get_ordered_network("TestBlacklist")
|
||||
|
||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
||||
|
||||
@ -45,12 +45,12 @@ class Test(unittest.TestCase):
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(dev1, condition)
|
||||
|
||||
bss_hostapd[2].wait_for_event('AP-STA-CONNECTED %s' % dev1.address)
|
||||
self.assertIn(dev1.address, bss_hostapd[2].list_sta())
|
||||
|
||||
# dev1 now connected, this should max out the first AP, causing the next
|
||||
# connection to fail to this AP.
|
||||
|
||||
ordered_network = dev2.get_ordered_network("TestBlacklist", full_scan=True)
|
||||
ordered_network = dev2.get_ordered_network("TestBlacklist")
|
||||
|
||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
||||
|
||||
@ -64,7 +64,7 @@ class Test(unittest.TestCase):
|
||||
|
||||
# We should have temporarily blacklisted the first BSS, and connected
|
||||
# to this one.
|
||||
bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % dev2.address)
|
||||
self.assertIn(dev2.address, bss_hostapd[1].list_sta())
|
||||
|
||||
# Now check that the first BSS is still not blacklisted. We can
|
||||
# disconnect dev1, opening up the AP for more connections
|
||||
@ -83,7 +83,7 @@ class Test(unittest.TestCase):
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(dev2, condition)
|
||||
|
||||
bss_hostapd[2].wait_for_event('AP-STA-CONNECTED %s' % dev2.address)
|
||||
self.assertIn(dev2.address, bss_hostapd[2].list_sta())
|
||||
|
||||
wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
@ -101,7 +101,7 @@ class Test(unittest.TestCase):
|
||||
devices = wd.list_devices(1)
|
||||
device = devices[0]
|
||||
|
||||
ordered_network = device.get_ordered_network("TestBlacklist", full_scan=True)
|
||||
ordered_network = device.get_ordered_network("TestBlacklist")
|
||||
|
||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
||||
|
||||
@ -110,11 +110,11 @@ class Test(unittest.TestCase):
|
||||
|
||||
# Have both APs drop all packets, both should get blacklisted
|
||||
rule0.drop = True
|
||||
rule0.enabled = True
|
||||
rule0.enable = True
|
||||
rule1.drop = True
|
||||
rule1.enabled = True
|
||||
rule1.enable = True
|
||||
rule2.drop = True
|
||||
rule2.enabled = True
|
||||
rule2.enable = True
|
||||
|
||||
with self.assertRaises(iwd.FailedEx):
|
||||
ordered_network.network_object.connect()
|
||||
@ -134,7 +134,7 @@ class Test(unittest.TestCase):
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
bss_hostapd[0].wait_for_event('AP-STA-CONNECTED %s' % device.address)
|
||||
self.assertIn(device.address, bss_hostapd[0].list_sta())
|
||||
|
||||
wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
@ -148,7 +148,7 @@ class Test(unittest.TestCase):
|
||||
devices = wd.list_devices(1)
|
||||
device = devices[0]
|
||||
|
||||
ordered_network = device.get_ordered_network("TestBlacklist", full_scan=True)
|
||||
ordered_network = device.get_ordered_network("TestBlacklist")
|
||||
|
||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
||||
|
||||
@ -188,7 +188,7 @@ class Test(unittest.TestCase):
|
||||
|
||||
devices[1].disconnect()
|
||||
|
||||
ordered_network = device.get_ordered_network("TestBlacklist", full_scan=True)
|
||||
ordered_network = device.get_ordered_network("TestBlacklist")
|
||||
|
||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
||||
|
||||
@ -214,7 +214,7 @@ class Test(unittest.TestCase):
|
||||
# should automatically try the next BSS in the list, which is
|
||||
# bss_hostapd[1]
|
||||
self.assertNotIn(device.address, bss_hostapd[0].list_sta())
|
||||
bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % device.address)
|
||||
self.assertIn(device.address, bss_hostapd[1].list_sta())
|
||||
|
||||
rule0.drop = False
|
||||
|
||||
@ -234,7 +234,7 @@ class Test(unittest.TestCase):
|
||||
|
||||
# Same as before, make sure we didn't connect to the blacklisted AP.
|
||||
self.assertNotIn(device.address, bss_hostapd[0].list_sta())
|
||||
bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % device.address)
|
||||
self.assertIn(device.address, bss_hostapd[1].list_sta())
|
||||
|
||||
# Wait for the blacklist to expire (10 seconds)
|
||||
elapsed = time.time() - start
|
||||
@ -244,7 +244,15 @@ class Test(unittest.TestCase):
|
||||
|
||||
device.disconnect()
|
||||
|
||||
ordered_network = device.get_ordered_network("TestBlacklist", full_scan=True)
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
device.scan()
|
||||
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
ordered_network = device.get_ordered_network("TestBlacklist")
|
||||
|
||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
||||
|
||||
@ -256,73 +264,16 @@ class Test(unittest.TestCase):
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
bss_hostapd[0].wait_for_event('AP-STA-CONNECTED %s' % device.address)
|
||||
self.assertIn(device.address, bss_hostapd[0].list_sta())
|
||||
|
||||
self.wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
def test_blacklist_disabled(self):
|
||||
wd = self.wd
|
||||
bss_hostapd = self.bss_hostapd
|
||||
|
||||
rule0 = self.rule0
|
||||
rule1 = self.rule1
|
||||
rule2 = self.rule2
|
||||
|
||||
psk_agent = PSKAgent(["secret123", 'secret123'])
|
||||
wd.register_psk_agent(psk_agent)
|
||||
|
||||
devices = wd.list_devices(1)
|
||||
device = devices[0]
|
||||
|
||||
rule0.drop = True
|
||||
rule0.enabled = True
|
||||
|
||||
device.autoconnect = True
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
ordered_network = device.get_ordered_network("TestBlacklist", full_scan=True)
|
||||
|
||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
||||
|
||||
# The first BSS should fail, and we should connect to the second. This
|
||||
# should not result in a connection blacklist though since its disabled.
|
||||
bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % device.address)
|
||||
|
||||
device.disconnect()
|
||||
|
||||
rule0.drop = False
|
||||
device.autoconnect = True
|
||||
|
||||
# Verify the first BSS wasn't blacklisted.
|
||||
bss_hostapd[0].wait_for_event('AP-STA-CONNECTED %s' % device.address)
|
||||
|
||||
def setUp(self):
|
||||
_, _, name = self.id().split(".")
|
||||
|
||||
# TODO: If we have this pattern elsewhere it might be nice to turn this
|
||||
# into a decorator e.g.
|
||||
#
|
||||
# @config("main.conf.disabled")
|
||||
# @profile("TestBlacklist.psk")
|
||||
# def test_blacklist_disabled(self)
|
||||
# ...
|
||||
#
|
||||
if name == "test_blacklist_disabled":
|
||||
IWD.copy_to_storage("main.conf.disabled", IWD_CONFIG_DIR, "main.conf")
|
||||
IWD.copy_to_storage("TestBlacklist.psk")
|
||||
else:
|
||||
IWD.copy_to_storage("main.conf.default", IWD_CONFIG_DIR, "main.conf")
|
||||
|
||||
self.wd = IWD(True)
|
||||
|
||||
def tearDown(self):
|
||||
IWD.clear_storage()
|
||||
self.wd = None
|
||||
self.rule0.drop = False
|
||||
self.rule1.drop = False
|
||||
self.rule2.drop = False
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
@ -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=2
|
||||
ssid=ssidTKIP
|
||||
|
||||
wpa=1
|
||||
wpa_pairwise=TKIP
|
||||
wpa_passphrase=secret123
|
@ -1,5 +0,0 @@
|
||||
[Security]
|
||||
Passphrase=secret123
|
||||
|
||||
[Settings]
|
||||
AutoConnect=False
|
@ -11,9 +11,13 @@ import subprocess
|
||||
from config import ctx
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
def check_connection_success(self, ssid):
|
||||
device = self.wd.list_devices(1)[0]
|
||||
|
||||
condition = 'not obj.scanning'
|
||||
self.wd.wait_for_object_condition(device, condition)
|
||||
|
||||
ordered_network = device.get_ordered_network(ssid)
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
@ -24,14 +28,9 @@ class Test(unittest.TestCase):
|
||||
condition = 'not obj.connected'
|
||||
self.wd.wait_for_object_condition(ordered_network.network_object, condition)
|
||||
|
||||
def establish_network(self, ssid):
|
||||
device = self.wd.list_devices(1)[0]
|
||||
device.get_ordered_network(ssid)
|
||||
|
||||
def test_connection_with_passphrase(self):
|
||||
ssid = 'ssidPassphrase'
|
||||
|
||||
self.establish_network(ssid)
|
||||
device = self.wd.list_devices(1)[0]
|
||||
|
||||
# Use --dontaks cmd-line option
|
||||
@ -46,7 +45,6 @@ class Test(unittest.TestCase):
|
||||
def test_connection_with_username_and_password(self):
|
||||
ssid = 'ssidUNameAndPWord'
|
||||
|
||||
self.establish_network(ssid)
|
||||
device = self.wd.list_devices(1)[0]
|
||||
|
||||
ctx.start_process(['iwctl', '-u', 'user', '-p', 'password', 'station', \
|
||||
@ -56,7 +54,6 @@ class Test(unittest.TestCase):
|
||||
def test_connection_with_password(self):
|
||||
ssid = 'ssidPWord'
|
||||
|
||||
self.establish_network(ssid)
|
||||
device = self.wd.list_devices(1)[0]
|
||||
|
||||
ctx.start_process(['iwctl', '-p', 'password', 'station', device.name, 'connect', ssid],
|
||||
@ -67,7 +64,6 @@ class Test(unittest.TestCase):
|
||||
def test_connection_failure(self):
|
||||
ssid = 'ssidPassphrase'
|
||||
|
||||
self.establish_network(ssid)
|
||||
device = self.wd.list_devices(1)[0]
|
||||
|
||||
with self.assertRaises(subprocess.CalledProcessError):
|
||||
@ -77,13 +73,14 @@ class Test(unittest.TestCase):
|
||||
def test_invalid_command_line_option(self):
|
||||
ssid = 'ssidPassphrase'
|
||||
|
||||
self.establish_network(ssid)
|
||||
device = self.wd.list_devices(1)[0]
|
||||
|
||||
with self.assertRaises(subprocess.CalledProcessError):
|
||||
ctx.start_process(['iwctl', '-z', 'station', device.name, 'connect', ssid], check=True)
|
||||
|
||||
def test_invalid_command(self):
|
||||
device = self.wd.list_devices(1)[0]
|
||||
|
||||
with self.assertRaises(subprocess.CalledProcessError):
|
||||
ctx.start_process(['iwctl', 'inexistent', 'command'], check=True)
|
||||
|
||||
@ -94,6 +91,19 @@ class Test(unittest.TestCase):
|
||||
|
||||
cls.wd = IWD()
|
||||
|
||||
device = cls.wd.list_devices(1)[0]
|
||||
|
||||
condition = 'not obj.scanning'
|
||||
cls.wd.wait_for_object_condition(device, condition)
|
||||
|
||||
device.scan()
|
||||
|
||||
condition = 'obj.scanning'
|
||||
cls.wd.wait_for_object_condition(device, condition)
|
||||
|
||||
condition = 'not obj.scanning'
|
||||
cls.wd.wait_for_object_condition(device, condition)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
IWD.clear_storage()
|
||||
|
@ -11,7 +11,7 @@ from iwd import IWD
|
||||
|
||||
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
|
||||
present at start time: Connect: AutoConnect: Result:
|
||||
|
@ -11,7 +11,7 @@ from iwd import IWD
|
||||
|
||||
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
|
||||
present at start time: Connect: AutoConnect: Result:
|
||||
|
@ -11,7 +11,7 @@ from iwd import IWD
|
||||
|
||||
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
|
||||
present at start time: Connect: AutoConnect: Result:
|
||||
|
@ -5,11 +5,9 @@ import sys
|
||||
|
||||
sys.path.append('../util')
|
||||
from iwd import IWD
|
||||
from iwd import DeviceProvisioning
|
||||
from wpas import Wpas
|
||||
from hostapd import HostapdCLI
|
||||
from hwsim import Hwsim
|
||||
from config import ctx
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def test_iwd_as_enrollee(self):
|
||||
@ -38,18 +36,20 @@ class Test(unittest.TestCase):
|
||||
|
||||
def test_iwd_as_enrollee_scan_after(self):
|
||||
self.wpas.disconnect()
|
||||
self.device.autoconnect = True
|
||||
uri = self.device.dpp_start_enrollee()
|
||||
|
||||
self.wpas.dpp_configurator_create(uri)
|
||||
self.wpas.dpp_configurator_start('ssidCCMP', 'secret123')
|
||||
|
||||
self.hapd.reload()
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
self.device.get_ordered_network('ssidCCMP', scan_if_needed=False)
|
||||
|
||||
self.hapd.reload()
|
||||
self.hapd.wait_for_event('AP-ENABLED')
|
||||
|
||||
self.device.autoconnect = True
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
self.wd.wait_for_object_condition(self.device, condition)
|
||||
|
||||
@ -80,60 +80,12 @@ class Test(unittest.TestCase):
|
||||
|
||||
self.wpas.dpp_enrollee_start(uri)
|
||||
|
||||
self.wpas.wait_for_event('DPP-CONF-RECEIVED', timeout=30)
|
||||
|
||||
def test_iwd_as_configurator_initiator(self):
|
||||
self.hapd.reload()
|
||||
self.hapd.wait_for_event('AP-ENABLED')
|
||||
|
||||
IWD.copy_to_storage('ssidCCMP.psk')
|
||||
self.device.autoconnect = True
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
self.wd.wait_for_object_condition(self.device, condition)
|
||||
|
||||
uri = self.wpas.dpp_enrollee_start(oper_and_channel='81/2')
|
||||
|
||||
self.device.dpp_start_configurator(uri)
|
||||
|
||||
self.wpas.wait_for_event('DPP-CONF-RECEIVED', timeout=30)
|
||||
|
||||
def test_client_as_configurator(self):
|
||||
self.hapd.reload()
|
||||
self.hapd.wait_for_event('AP-ENABLED')
|
||||
|
||||
IWD.copy_to_storage('ssidCCMP.psk')
|
||||
self.device.autoconnect = True
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
self.wd.wait_for_object_condition(self.device, condition)
|
||||
|
||||
ctx.start_process(['iwctl', 'dpp', self.device.name, 'start-configurator'], check=True)
|
||||
|
||||
dpp = DeviceProvisioning(self.device.device_path)
|
||||
|
||||
self.wpas.dpp_enrollee_start(dpp.uri)
|
||||
|
||||
self.wpas.wait_for_event('DPP-CONF-RECEIVED', timeout=30)
|
||||
|
||||
def test_client_as_enrollee(self):
|
||||
self.device.autoconnect = True
|
||||
self.hapd.reload()
|
||||
|
||||
ctx.start_process(['iwctl', 'dpp', self.device.name, 'start-enrollee'], check=True)
|
||||
|
||||
dpp = DeviceProvisioning(self.device.device_path)
|
||||
|
||||
self.wpas.dpp_configurator_create(dpp.uri)
|
||||
self.wpas.dpp_configurator_start('ssidCCMP', 'secret123')
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
self.wd.wait_for_object_condition(self.device, condition)
|
||||
self.hapd.wait_for_event('AP-STA-CONNECTED 42:00:00:00:00:00')
|
||||
|
||||
def setUp(self):
|
||||
self.wpas = Wpas('wpas.conf')
|
||||
self.wd = IWD(True)
|
||||
self.device = self.wd.list_devices(1)[0]
|
||||
self.wpas = Wpas('wpas.conf')
|
||||
self.hapd = HostapdCLI('hostapd.conf')
|
||||
self.hapd.disable()
|
||||
self.hwsim = Hwsim()
|
||||
@ -146,15 +98,10 @@ class Test(unittest.TestCase):
|
||||
self.rule0.drop = True
|
||||
|
||||
def tearDown(self):
|
||||
# Tests end in various states, don't fail when tearing down.
|
||||
try:
|
||||
self.device.disconnect()
|
||||
self.device.dpp_stop()
|
||||
except:
|
||||
pass
|
||||
|
||||
print("calling Disconnect()")
|
||||
self.device.disconnect()
|
||||
self.device.dpp_stop()
|
||||
self.wpas.dpp_configurator_remove()
|
||||
self.wpas.clean_up()
|
||||
|
||||
self.wd = None
|
||||
self.device = None
|
||||
|
@ -1,2 +0,0 @@
|
||||
[Security]
|
||||
Passphrase=IncorrectPassphrase
|
@ -1,5 +1,5 @@
|
||||
hw_mode=g
|
||||
channel=6
|
||||
channel=1
|
||||
ssid=ssidCCMP
|
||||
|
||||
wpa=2
|
||||
|
@ -1,5 +1,5 @@
|
||||
[SETUP]
|
||||
num_radios=5
|
||||
num_radios=3
|
||||
start_iwd=0
|
||||
hwsim_medium=yes
|
||||
|
||||
@ -8,7 +8,3 @@ rad0=wpas.conf
|
||||
|
||||
[HOSTAPD]
|
||||
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]
|
||||
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)
|
@ -1,6 +1,5 @@
|
||||
ctrl_interface=/tmp/rad1-p2p-wpas
|
||||
|
||||
update_config=0
|
||||
update_config=1
|
||||
pmf=2
|
||||
dpp_config_processing=2
|
||||
p2p_disabled=1
|
||||
|
@ -21,7 +21,12 @@ class Test(unittest.TestCase):
|
||||
|
||||
hostapd = HostapdCLI(config='ssidOpen.conf')
|
||||
|
||||
ordered_network = device.get_ordered_network('ssidOpen', full_scan=True)
|
||||
device.scan()
|
||||
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
ordered_network = device.get_ordered_network('ssidOpen')
|
||||
|
||||
ordered_network.network_object.connect()
|
||||
|
||||
|
@ -37,6 +37,9 @@ class Test(unittest.TestCase):
|
||||
|
||||
hostapd.eapol_reauth(device.address)
|
||||
|
||||
hostapd.wait_for_event('CTRL-EVENT-EAP-STARTED')
|
||||
hostapd.wait_for_event('CTRL-EVENT-EAP-SUCCESS')
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
|
@ -4,23 +4,22 @@ import unittest
|
||||
import sys
|
||||
|
||||
sys.path.append('../util')
|
||||
import iwd
|
||||
from iwd import IWD
|
||||
from iwd import DeviceState
|
||||
|
||||
from hostapd import HostapdCLI
|
||||
from config import ctx
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
def four_digit_pin_success(self, wd, client=False):
|
||||
def four_digit_pin_success(self, wd):
|
||||
|
||||
devices = wd.list_devices(1)
|
||||
device = devices[0]
|
||||
pin = '1234'
|
||||
self.hostapd.wps_pin(pin)
|
||||
|
||||
if not client:
|
||||
device.wps_start_pin(pin)
|
||||
else:
|
||||
ctx.start_process(['iwctl', 'wsc', device.name, 'start-user-pin', pin], check=True)
|
||||
device.wps_start_pin(pin)
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
@ -37,11 +36,6 @@ class Test(unittest.TestCase):
|
||||
|
||||
self.four_digit_pin_success(wd)
|
||||
|
||||
def test_client_four_digit_pin(self):
|
||||
wd = IWD(True)
|
||||
|
||||
self.four_digit_pin_success(wd, client=True)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.hostapd = HostapdCLI(config='ssidWPS.conf')
|
||||
|
@ -4,22 +4,20 @@ import unittest
|
||||
import sys
|
||||
|
||||
sys.path.append('../util')
|
||||
import iwd
|
||||
from iwd import IWD
|
||||
from hostapd import HostapdCLI
|
||||
from config import ctx
|
||||
from iwd import DeviceState
|
||||
|
||||
from hostapd import HostapdCLI
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
def push_button_success(self, wd, client=False):
|
||||
def push_button_success(self, wd):
|
||||
self.hostapd.wps_push_button()
|
||||
|
||||
devices = wd.list_devices(1)
|
||||
device = devices[0]
|
||||
|
||||
if not client:
|
||||
device.wps_push_button()
|
||||
else:
|
||||
ctx.start_process(['iwctl', 'wsc', device.name, 'push-button'], check=True)
|
||||
device.wps_push_button()
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
@ -36,11 +34,6 @@ class Test(unittest.TestCase):
|
||||
|
||||
self.push_button_success(wd)
|
||||
|
||||
def test_client_push_button(self):
|
||||
wd = IWD(True)
|
||||
|
||||
self.push_button_success(wd, client=True)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.hostapd = HostapdCLI(config='ssidWPS.conf')
|
||||
|
@ -11,8 +11,6 @@ from iwd import PSKAgent
|
||||
from hlrauc import AuthCenter
|
||||
from ofono import Ofono
|
||||
from config import ctx
|
||||
from hostapd import HostapdCLI
|
||||
|
||||
import testutil
|
||||
import traceback
|
||||
|
||||
@ -52,8 +50,6 @@ class Test(unittest.TestCase):
|
||||
testutil.test_iface_operstate()
|
||||
testutil.test_ifaces_connected()
|
||||
|
||||
self.hostapd.eapol_reauth(device.address)
|
||||
|
||||
if secrets:
|
||||
wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
@ -255,7 +251,6 @@ class Test(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.wd = IWD()
|
||||
cls.hostapd = HostapdCLI()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
@ -1,77 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
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
|
||||
|
||||
from time import sleep
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
def test_connection_success(self):
|
||||
hwsim = Hwsim()
|
||||
|
||||
hostapd = HostapdCLI(config='ssidCCMP.conf')
|
||||
radio = hwsim.get_radio('rad0')
|
||||
|
||||
wd = IWD()
|
||||
|
||||
psk_agent = PSKAgent("secret123")
|
||||
wd.register_psk_agent(psk_agent)
|
||||
|
||||
devices = wd.list_devices(1)
|
||||
device = devices[0]
|
||||
|
||||
ordered_network = device.get_ordered_network('ssidCCMP')
|
||||
|
||||
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()
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
# Ensure IWD is not scanning. This causes problems with mac80211_hwsim
|
||||
# where CMD_FRAME will fail during a scan. This is due to the frame not
|
||||
# having the same frequency as the radio (since hwsim is off-channel)
|
||||
if device.scanning:
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
hwsim.spoof_eap_fail(radio, hostapd.frequency, device.address)
|
||||
hwsim.spoof_invalid_ptk_1_of_4(radio, hostapd.frequency, device.address)
|
||||
|
||||
with self.assertRaises(TimeoutError):
|
||||
condition = 'obj.state == DeviceState.disconnected'
|
||||
wd.wait_for_object_condition(device, condition, 4)
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
device.disconnect()
|
||||
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
||||
|
||||
wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
IWD.clear_storage()
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(exit=True)
|
@ -1,6 +0,0 @@
|
||||
[SETUP]
|
||||
num_radios=2
|
||||
hwsim_medium=yes
|
||||
|
||||
[HOSTAPD]
|
||||
rad0=ssidCCMP.conf
|
@ -1,12 +0,0 @@
|
||||
hw_mode=g
|
||||
channel=1
|
||||
ssid=ssidCCMP
|
||||
|
||||
wpa=2
|
||||
wpa_pairwise=CCMP
|
||||
wpa_passphrase=secret123
|
||||
|
||||
ieee80211w=2
|
||||
wpa_key_mgmt=WPA-PSK-SHA256
|
||||
beacon_int=10
|
||||
ocv=1
|
@ -1,163 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
sys.path.append('../util')
|
||||
import iwd
|
||||
import os
|
||||
from time import sleep
|
||||
from iwd import IWD
|
||||
from iwd import NetworkType
|
||||
from iwd import PSKAgent
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def profile_is_encrypted(self, profile):
|
||||
with open('/tmp/iwd/' + profile) as f:
|
||||
contents = f.read()
|
||||
|
||||
if 'Passphrase' in contents:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def validate(self, wd):
|
||||
devices = wd.list_devices(1)
|
||||
device = devices[0]
|
||||
|
||||
ordered_network = device.get_ordered_network('ssidCCMP')
|
||||
|
||||
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()
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
device.disconnect()
|
||||
|
||||
condition = 'not obj.connected'
|
||||
wd.wait_for_object_condition(ordered_network.network_object, condition)
|
||||
|
||||
# Tests that an existing plaintext profile gets encrypted
|
||||
def test_new_profile(self):
|
||||
IWD.copy_to_storage('ssidCCMP.psk')
|
||||
|
||||
mtime = os.path.getmtime('/tmp/iwd/' + 'ssidCCMP.psk')
|
||||
self.assertFalse(self.profile_is_encrypted('ssidCCMP.psk'))
|
||||
|
||||
sleep(1)
|
||||
|
||||
wd = IWD(True)
|
||||
|
||||
# Make sure profile was accepted
|
||||
condition = 'len(obj.list_known_networks()) == 1'
|
||||
wd.wait_for_object_condition(wd, condition)
|
||||
|
||||
# Check the file was modified (should be encrypted now)
|
||||
self.assertNotEqual(mtime, os.path.getmtime('/tmp/iwd/' + 'ssidCCMP.psk'))
|
||||
|
||||
self.validate(wd)
|
||||
|
||||
self.assertTrue(self.profile_is_encrypted('ssidCCMP.psk'))
|
||||
|
||||
# Tests that a new connection with agent gets written to an encrypted profile
|
||||
def test_agent_profile(self):
|
||||
wd = IWD(True)
|
||||
|
||||
psk_agent = PSKAgent("secret123")
|
||||
wd.register_psk_agent(psk_agent)
|
||||
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
self.profile_is_encrypted('ssidCCMP.psk')
|
||||
|
||||
self.validate(wd)
|
||||
|
||||
self.assertTrue(self.profile_is_encrypted('ssidCCMP.psk'))
|
||||
|
||||
wd.unregister_psk_agent(psk_agent)
|
||||
|
||||
# Tests that an invalid profile gets re-written after an agent request
|
||||
def test_invalid_profile_rewritten(self):
|
||||
bad_config = '[Security]\nPassphrase=incorrect\n'
|
||||
os.system('echo "%s" > /tmp/iwd/ssidCCMP.psk' % bad_config)
|
||||
|
||||
wd = IWD(True)
|
||||
|
||||
condition = 'len(obj.list_known_networks()) == 1'
|
||||
wd.wait_for_object_condition(wd, condition)
|
||||
|
||||
# IWD should still encrypt the profile automatically
|
||||
self.assertTrue(self.profile_is_encrypted('ssidCCMP.psk'))
|
||||
|
||||
# This should fail
|
||||
with self.assertRaises(iwd.FailedEx):
|
||||
self.validate(wd)
|
||||
|
||||
psk_agent = PSKAgent("secret123")
|
||||
wd.register_psk_agent(psk_agent)
|
||||
|
||||
self.validate(wd)
|
||||
|
||||
self.assertTrue(self.profile_is_encrypted('ssidCCMP.psk'))
|
||||
|
||||
# Tests that a profile that doesn't decrypt won't become a known network
|
||||
def test_decryption_failure(self):
|
||||
bad_config = \
|
||||
'''
|
||||
[Security]
|
||||
EncryptedSalt=000102030405060708090a0b0c0d0e0f
|
||||
EncryptedSecurity=aabbccddeeff00112233445566778899
|
||||
'''
|
||||
os.system('echo "%s" > /tmp/iwd/ssidCCMP.psk' % bad_config)
|
||||
|
||||
wd = IWD(True)
|
||||
|
||||
self.assertEqual(wd.list_known_networks(), [])
|
||||
|
||||
# This test starts and stops IWD so quickly the DBus utilities don't
|
||||
# even have a chance to set up the Device interface object which causes
|
||||
# exceptions on the next test as the InterfaceAdded signals arrive. This
|
||||
# allows the device interface to get set up before ending the test.
|
||||
wd.list_devices(1)
|
||||
|
||||
def test_runtime_profile(self):
|
||||
wd = IWD(True)
|
||||
|
||||
self.assertEqual(wd.list_known_networks(), [])
|
||||
|
||||
# Add profile after IWD starts
|
||||
IWD.copy_to_storage('ssidCCMP.psk')
|
||||
|
||||
self.validate(wd)
|
||||
|
||||
# Should now be encrypted
|
||||
self.assertTrue(self.profile_is_encrypted('ssidCCMP.psk'))
|
||||
|
||||
with open('/tmp/iwd/ssidCCMP.psk') as f:
|
||||
profile = f.read()
|
||||
|
||||
# Edit the profile, corrupting it
|
||||
profile.replace('EncryptedSecurity=', 'EncryptedSecurity=00')
|
||||
|
||||
devices = wd.list_devices(1)
|
||||
device = devices[0]
|
||||
condition = 'obj.state == DeviceState.disconnected'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
def tearDown(self):
|
||||
IWD.clear_storage()
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
os.environ['CREDENTIALS_DIRECTORY'] = '/tmp'
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
IWD.clear_storage()
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(exit=True)
|
@ -1,6 +0,0 @@
|
||||
[SETUP]
|
||||
num_radios=2
|
||||
start_iwd=0
|
||||
|
||||
[HOSTAPD]
|
||||
rad0=ssidCCMP.conf
|
@ -1 +0,0 @@
|
||||
secret123
|
@ -1,2 +0,0 @@
|
||||
[General]
|
||||
SystemdEncrypt=iwd-secret
|
@ -1,5 +0,0 @@
|
||||
[Security]
|
||||
Passphrase=secret123
|
||||
|
||||
[General]
|
||||
AutoConnect=false
|
@ -55,10 +55,6 @@ class Test(unittest.TestCase):
|
||||
testutil.test_iface_operstate()
|
||||
testutil.test_ifaces_connected(device.name, hapd.ifname)
|
||||
|
||||
#
|
||||
# TODO: If this is failing its likely due to an older hostapd version
|
||||
# not containing commit 7ee814201b72
|
||||
#
|
||||
hapd.rekey(device.address)
|
||||
|
||||
device.disconnect()
|
||||
@ -66,6 +62,8 @@ class Test(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
IWD.copy_to_storage('ssidFILS-256.8021x')
|
||||
os.system('ip link set lo up')
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
@ -55,10 +55,6 @@ class Test(unittest.TestCase):
|
||||
testutil.test_iface_operstate()
|
||||
testutil.test_ifaces_connected(device.name, hapd.ifname)
|
||||
|
||||
#
|
||||
# TODO: If this is failing its likely due to an older hostapd version
|
||||
# not containing commit 7ee814201b72
|
||||
#
|
||||
hapd.rekey(device.address)
|
||||
|
||||
device.disconnect()
|
||||
@ -66,6 +62,8 @@ class Test(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
IWD.copy_to_storage('ssidFILS-384.8021x')
|
||||
os.system('ip link set lo up')
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
@ -11,3 +11,5 @@ fils_realm=example.com
|
||||
disable_pmksa_caching=1
|
||||
|
||||
pwd_group=19
|
||||
wpa_group_rekey=30
|
||||
wpa_ptk_rekey=30
|
||||
|
@ -17,4 +17,6 @@ nas_identifier=nas.w1.fi
|
||||
fils_realm=example.com
|
||||
disable_pmksa_caching=1
|
||||
|
||||
wpa_group_rekey=30
|
||||
wpa_ptk_rekey=30
|
||||
ocv=1
|
||||
|
@ -17,4 +17,6 @@ nas_identifier=nas.w1.fi
|
||||
fils_realm=example.com
|
||||
disable_pmksa_caching=1
|
||||
|
||||
wpa_group_rekey=30
|
||||
wpa_ptk_rekey=30
|
||||
ocv=1
|
||||
|
@ -27,7 +27,7 @@ class Test(unittest.TestCase):
|
||||
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)
|
||||
self.assertTrue(self.bss_hostapd[0].list_sta())
|
||||
self.assertFalse(self.bss_hostapd[1].list_sta())
|
||||
|
||||
testutil.test_iface_operstate(device.name)
|
||||
@ -37,13 +37,16 @@ class Test(unittest.TestCase):
|
||||
|
||||
device.roam(self.bss_hostapd[1].bssid)
|
||||
|
||||
condition = 'obj.state == DeviceState.roaming'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
# 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.connected'
|
||||
wd.wait_for_object_change(device, from_condition, to_condition)
|
||||
|
||||
self.bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % device.address)
|
||||
self.assertTrue(self.bss_hostapd[1].list_sta())
|
||||
|
||||
testutil.test_iface_operstate(device.name)
|
||||
testutil.test_ifaces_connected(self.bss_hostapd[1].ifname, device.name)
|
||||
@ -63,10 +66,28 @@ class Test(unittest.TestCase):
|
||||
cls.bss_hostapd = [ HostapdCLI(config='ft-eap-ccmp-1.conf'),
|
||||
HostapdCLI(config='ft-eap-ccmp-2.conf') ]
|
||||
|
||||
cls.bss_hostapd[0].set_address('12:00:00:00:00:01')
|
||||
cls.bss_hostapd[1].set_address('12:00:00:00:00:02')
|
||||
# Set interface addresses to those expected by hostapd config files
|
||||
os.system('ip link set dev "' + cls.bss_hostapd[0].ifname + '" down')
|
||||
os.system('ip link set dev "' + cls.bss_hostapd[0].ifname + \
|
||||
'" address 12:00:00:00:00:01 up')
|
||||
os.system('ip link set dev "' + cls.bss_hostapd[1].ifname + '" down')
|
||||
os.system('ip link set dev "' + cls.bss_hostapd[1].ifname + \
|
||||
'" address 12:00:00:00:00:02 up')
|
||||
|
||||
HostapdCLI.group_neighbors(*cls.bss_hostapd)
|
||||
cls.bss_hostapd[0].reload()
|
||||
cls.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
||||
cls.bss_hostapd[1].reload()
|
||||
cls.bss_hostapd[1].wait_for_event("AP-ENABLED")
|
||||
|
||||
# Fill in the neighbor AP tables in both BSSes. By default each
|
||||
# instance knows only about current BSS, even inside one hostapd
|
||||
# process.
|
||||
# FT still works without the neighbor AP table but neighbor reports
|
||||
# have to be disabled in the .conf files
|
||||
cls.bss_hostapd[0].set_neighbor('12:00:00:00:00:02', 'TestFT',
|
||||
'1200000000028f0000005102060603000000')
|
||||
cls.bss_hostapd[1].set_neighbor('12:00:00:00:00:01', 'TestFT',
|
||||
'1200000000018f0000005101060603000000')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
@ -17,6 +17,8 @@ eap_user_file=/tmp/secrets/eap-user.text
|
||||
ca_cert=/tmp/certs/cert-ca.pem
|
||||
server_cert=/tmp/certs/cert-server.pem
|
||||
private_key=/tmp/certs/cert-server-key.pem
|
||||
wpa_ptk_rekey=30
|
||||
wpa_group_rekey=80
|
||||
ieee80211w=1
|
||||
rsn_preauth=1
|
||||
disable_pmksa_caching=0
|
||||
|
@ -17,6 +17,8 @@ eap_user_file=/tmp/secrets/eap-user.text
|
||||
ca_cert=/tmp/certs/cert-ca.pem
|
||||
server_cert=/tmp/certs/cert-server.pem
|
||||
private_key=/tmp/certs/cert-server-key.pem
|
||||
wpa_ptk_rekey=30
|
||||
wpa_group_rekey=80
|
||||
ieee80211w=1
|
||||
rsn_preauth=1
|
||||
disable_pmksa_caching=0
|
||||
|
@ -13,10 +13,21 @@ class Test(unittest.TestCase):
|
||||
def validate_connection(self, wd):
|
||||
device = wd.list_devices(1)[0]
|
||||
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
# Scanning is unavoidable in this case since both FILS-SHA256 and
|
||||
# FILS-SHA384 are tested. Without a new scan the cached scan results
|
||||
# would cause IWD to choose an incorrect AKM for the second test.
|
||||
ordered_network = device.get_ordered_network('TestFT', full_scan=True)
|
||||
device.scan()
|
||||
|
||||
condition = 'obj.scanning'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
ordered_network = device.get_ordered_network('TestFT')
|
||||
|
||||
self.assertEqual(ordered_network.type, NetworkType.eap)
|
||||
|
||||
@ -28,8 +39,7 @@ class Test(unittest.TestCase):
|
||||
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)
|
||||
|
||||
self.assertTrue(self.bss_hostapd[0].list_sta())
|
||||
self.assertFalse(self.bss_hostapd[1].list_sta())
|
||||
|
||||
testutil.test_iface_operstate(device.name)
|
||||
@ -52,8 +62,7 @@ class Test(unittest.TestCase):
|
||||
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)
|
||||
|
||||
self.assertTrue(self.bss_hostapd[0].list_sta())
|
||||
self.assertFalse(self.bss_hostapd[1].list_sta())
|
||||
|
||||
testutil.test_iface_operstate(device.name)
|
||||
@ -70,13 +79,16 @@ class Test(unittest.TestCase):
|
||||
#rule0.signal = -8000
|
||||
device.roam(self.bss_hostapd[1].bssid)
|
||||
|
||||
condition = 'obj.state == DeviceState.roaming'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
# 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.connected'
|
||||
wd.wait_for_object_change(device, from_condition, to_condition)
|
||||
|
||||
self.bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % device.address)
|
||||
self.assertTrue(self.bss_hostapd[1].list_sta())
|
||||
|
||||
testutil.test_iface_operstate(device.name)
|
||||
testutil.test_ifaces_connected(self.bss_hostapd[1].ifname, device.name)
|
||||
@ -119,15 +131,32 @@ class Test(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
os.system('ip link set lo up')
|
||||
IWD.copy_to_storage('TestFT.8021x')
|
||||
|
||||
cls.bss_hostapd = [ HostapdCLI(config='ft-eap-ccmp-1.conf'),
|
||||
HostapdCLI(config='ft-eap-ccmp-2.conf') ]
|
||||
|
||||
cls.bss_hostapd[0].set_address('12:00:00:00:00:01')
|
||||
cls.bss_hostapd[1].set_address('12:00:00:00:00:02')
|
||||
# Set interface addresses to those expected by hostapd config files
|
||||
os.system('ip link set dev "' + cls.bss_hostapd[0].ifname + '" down')
|
||||
os.system('ip link set dev "' + cls.bss_hostapd[0].ifname + '" addr 12:00:00:00:00:01 up')
|
||||
os.system('ip link set dev "' + cls.bss_hostapd[1].ifname + '" down')
|
||||
os.system('ip link set dev "' + cls.bss_hostapd[1].ifname + '" addr 12:00:00:00:00:02 up')
|
||||
|
||||
HostapdCLI.group_neighbors(*cls.bss_hostapd)
|
||||
cls.bss_hostapd[0].reload()
|
||||
cls.bss_hostapd[0].wait_for_event("AP-ENABLED")
|
||||
cls.bss_hostapd[1].reload()
|
||||
cls.bss_hostapd[1].wait_for_event("AP-ENABLED")
|
||||
|
||||
# Fill in the neighbor AP tables in both BSSes. By default each
|
||||
# instance knows only about current BSS, even inside one hostapd
|
||||
# process.
|
||||
# FT still works without the neighbor AP table but neighbor reports
|
||||
# have to be disabled in the .conf files
|
||||
cls.bss_hostapd[0].set_neighbor('12:00:00:00:00:02', 'TestFT',
|
||||
'1200000000028f0000005102060603000000')
|
||||
cls.bss_hostapd[1].set_neighbor('12:00:00:00:00:01', 'TestFT',
|
||||
'1200000000018f0000005101060603000000')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
@ -15,6 +15,8 @@ ieee8021x=1
|
||||
|
||||
fils_realm=example.com
|
||||
|
||||
wpa_ptk_rekey=30
|
||||
wpa_group_rekey=80
|
||||
ieee80211w=1
|
||||
rsn_preauth=1
|
||||
disable_pmksa_caching=1
|
||||
|
@ -15,6 +15,8 @@ ieee8021x=1
|
||||
|
||||
fils_realm=example.com
|
||||
|
||||
wpa_ptk_rekey=30
|
||||
wpa_group_rekey=80
|
||||
ieee80211w=1
|
||||
rsn_preauth=1
|
||||
disable_pmksa_caching=1
|
||||
|
@ -11,3 +11,5 @@ fils_realm=example.com
|
||||
disable_pmksa_caching=1
|
||||
|
||||
pwd_group=19
|
||||
wpa_group_rekey=30
|
||||
wpa_ptk_rekey=30
|
||||
|
@ -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)
|
@ -14,11 +14,22 @@ from hostapd import HostapdCLI
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def do_connect(self, wd, device, hostapd):
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
device.scan()
|
||||
|
||||
condition = 'obj.scanning'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
condition = 'not obj.scanning'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
|
||||
#
|
||||
# Scanning must be explicitly done to get updated RSSI values. Therefore
|
||||
# full_scan is set.
|
||||
# scan_if_needed is set false because of the previous scan.
|
||||
#
|
||||
ordered_network = device.get_ordered_network('testSSID', full_scan=True)
|
||||
ordered_network = device.get_ordered_network('testSSID', scan_if_needed=False)
|
||||
|
||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
||||
|
||||
|
@ -7,7 +7,6 @@ sys.path.append('../util')
|
||||
import iwd
|
||||
from iwd import IWD
|
||||
from iwd import PSKAgent
|
||||
from hostapd import HostapdCLI
|
||||
import testutil
|
||||
import time
|
||||
|
||||
@ -68,20 +67,11 @@ class TestConnectionAfterHiddenNetwork(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.disabled = [HostapdCLI('ssidHiddenOpen.conf'),
|
||||
HostapdCLI('ssidHiddenWPA.conf'),
|
||||
HostapdCLI('ssidOverlap1.conf'),
|
||||
HostapdCLI('ssidOverlap2.conf')]
|
||||
|
||||
for hapd in cls.disabled:
|
||||
hapd.disable()
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
IWD.clear_storage()
|
||||
|
||||
for hapd in cls.disabled:
|
||||
hapd.reload()
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(exit=True)
|
||||
|
@ -6,13 +6,12 @@ import sys
|
||||
sys.path.append('../util')
|
||||
import iwd
|
||||
import validation
|
||||
from validation import TestHiddenNetworks
|
||||
from validation import TestConnectAutoConnect
|
||||
from iwd import IWD
|
||||
from hostapd import HostapdCLI
|
||||
|
||||
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
|
||||
present at start time: Connect: AutoConnect: Result:
|
||||
@ -24,7 +23,7 @@ class TestWpaNetwork(unittest.TestCase):
|
||||
'''
|
||||
|
||||
def test_wpa(self):
|
||||
tca = TestHiddenNetworks()
|
||||
tca = TestConnectAutoConnect()
|
||||
|
||||
tca.validate('UnExistingNetwork', False, iwd.NotFoundEx)
|
||||
tca.validate('ssidOverlap', False, iwd.ServiceSetOverlapEx)
|
||||
@ -35,19 +34,9 @@ class TestWpaNetwork(unittest.TestCase):
|
||||
def setUpClass(cls):
|
||||
IWD.copy_to_storage('ssidAlreadyKnown.open')
|
||||
|
||||
cls.disabled = [HostapdCLI('ssidHiddenOpen.conf'),
|
||||
HostapdCLI('ssidHiddenWPA.conf'),
|
||||
HostapdCLI('ssidSomeHidden.conf')]
|
||||
|
||||
for hapd in cls.disabled:
|
||||
hapd.disable()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
IWD.clear_storage()
|
||||
|
||||
for hapd in cls.disabled:
|
||||
hapd.reload()
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(exit=True)
|
||||
|
@ -6,13 +6,12 @@ import sys
|
||||
sys.path.append('../util')
|
||||
import iwd
|
||||
import validation
|
||||
from validation import TestHiddenNetworks
|
||||
from validation import TestConnectAutoConnect
|
||||
from iwd import IWD
|
||||
from hostapd import HostapdCLI
|
||||
|
||||
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
|
||||
present at start time: Connect: AutoConnect: Result:
|
||||
@ -21,26 +20,13 @@ class TestOpenNetwork(unittest.TestCase):
|
||||
True True Connection succeeds
|
||||
'''
|
||||
def test_open(self):
|
||||
tca = TestHiddenNetworks()
|
||||
tca = TestConnectAutoConnect()
|
||||
tca.validate('ssidHiddenOpen', False)
|
||||
tca.validate('ssidHiddenOpen', True)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.disabled = [HostapdCLI('ssidHiddenWPA.conf'),
|
||||
HostapdCLI('ssidOpen.conf'),
|
||||
HostapdCLI('ssidOverlap1.conf'),
|
||||
HostapdCLI('ssidOverlap2.conf'),
|
||||
HostapdCLI('ssidSomeHidden.conf')]
|
||||
for hapd in cls.disabled:
|
||||
hapd.disable()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
IWD.clear_storage()
|
||||
|
||||
for hapd in cls.disabled:
|
||||
hapd.reload()
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(exit=True)
|
||||
|
@ -9,7 +9,7 @@ from iwd import IWD
|
||||
from iwd import PSKAgent
|
||||
from iwd import NetworkType
|
||||
|
||||
class TestHiddenNetworks(unittest.TestCase):
|
||||
class TestConnectAutoConnect(unittest.TestCase):
|
||||
|
||||
def check_connect_hidden_network(self, wd, device, ssid, throws):
|
||||
if not throws is None:
|
||||
|
@ -6,13 +6,12 @@ import sys
|
||||
sys.path.append('../util')
|
||||
import iwd
|
||||
import validation
|
||||
from validation import TestHiddenNetworks
|
||||
from validation import TestConnectAutoConnect
|
||||
from iwd import IWD
|
||||
from hostapd import HostapdCLI
|
||||
|
||||
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
|
||||
present at start time: Connect: AutoConnect: Result:
|
||||
@ -22,27 +21,13 @@ class TestWpaNetwork(unittest.TestCase):
|
||||
'''
|
||||
|
||||
def test_wpa(self):
|
||||
tca = TestHiddenNetworks()
|
||||
tca = TestConnectAutoConnect()
|
||||
tca.validate('ssidHiddenWPA', False, None, True)
|
||||
tca.validate('ssidHiddenWPA', True, None, True)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.disabled = [HostapdCLI('ssidHiddenOpen.conf'),
|
||||
HostapdCLI('ssidOpen.conf'),
|
||||
HostapdCLI('ssidOverlap1.conf'),
|
||||
HostapdCLI('ssidOverlap2.conf'),
|
||||
HostapdCLI('ssidSomeHidden.conf')]
|
||||
|
||||
for hapd in cls.disabled:
|
||||
hapd.disable()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
IWD.clear_storage()
|
||||
|
||||
for hapd in cls.disabled:
|
||||
hapd.reload()
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(exit=True)
|
||||
|
@ -4,15 +4,17 @@ import unittest
|
||||
import sys
|
||||
|
||||
sys.path.append('../util')
|
||||
import iwd
|
||||
from iwd import IWD
|
||||
from iwd import PSKAgent
|
||||
from hwsim import Hwsim
|
||||
from iwd import NetworkType
|
||||
import testutil
|
||||
import os
|
||||
from configparser import ConfigParser
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
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'
|
||||
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)
|
||||
|
||||
def test_connection_success(self):
|
||||
wd = self.wd
|
||||
wd = IWD(True, '/tmp')
|
||||
|
||||
psk_agent = PSKAgent("secret123")
|
||||
wd.register_psk_agent(psk_agent)
|
||||
@ -36,11 +38,6 @@ class Test(unittest.TestCase):
|
||||
devices = wd.list_devices(1)
|
||||
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
|
||||
# the known frequency file.
|
||||
@ -78,10 +75,8 @@ class Test(unittest.TestCase):
|
||||
#
|
||||
self.assertIsNotNone(psk_freqs)
|
||||
self.assertIsNotNone(psk_uuid)
|
||||
|
||||
# The 2.4GHz frequency should come first, as it was ranked higher
|
||||
self.assertEqual('2412', psk_freqs[0])
|
||||
self.assertEqual('5180', psk_freqs[1])
|
||||
self.assertIn('5180', psk_freqs)
|
||||
self.assertIn('2412', psk_freqs)
|
||||
|
||||
self.assertIsNotNone(hs20_freqs)
|
||||
self.assertIsNotNone(hs20_uuid)
|
||||
@ -97,10 +92,6 @@ class Test(unittest.TestCase):
|
||||
psk_agent = PSKAgent("secret123")
|
||||
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
|
||||
# previously forgot the network.
|
||||
@ -129,78 +120,8 @@ class Test(unittest.TestCase):
|
||||
self.assertIsNotNone(psk_freqs)
|
||||
self.assertIsNotNone(psk_uuid2)
|
||||
self.assertNotEqual(psk_uuid, psk_uuid2)
|
||||
# Now the 5GHz frequency should be first
|
||||
self.assertEqual('5180', psk_freqs[0])
|
||||
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
|
||||
self.assertIn('5180', psk_freqs)
|
||||
self.assertIn('2412', psk_freqs)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
@ -208,23 +129,10 @@ class Test(unittest.TestCase):
|
||||
conf = '[General]\nDisableANQP=0\n'
|
||||
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
|
||||
def tearDownClass(cls):
|
||||
IWD.clear_storage()
|
||||
os.remove('/tmp/main.conf')
|
||||
|
||||
cls.ssidccmp_2g_rule.remove()
|
||||
cls.ssidccmp_5g_rule.remove()
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(exit=True)
|
||||
|
@ -2,7 +2,6 @@
|
||||
num_radios=5
|
||||
start_iwd=0
|
||||
reg_domain=US
|
||||
hwsim_medium=yes
|
||||
|
||||
[HOSTAPD]
|
||||
rad0=ssidNew.conf
|
||||
|
@ -2,11 +2,10 @@
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
sys.path.append('../util')
|
||||
import iwd
|
||||
from iwd import IWD
|
||||
from config import ctx
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
@ -71,26 +70,8 @@ class Test(unittest.TestCase):
|
||||
|
||||
self.list_removal_and_addition(wd)
|
||||
|
||||
def test_client_known_networks(self):
|
||||
networks = ['Hotspot Network', 'ssidOpen', 'ssidTKIP', 'ssidEAP-TLS']
|
||||
wd = IWD(True)
|
||||
|
||||
iwctl = ctx.start_process(['iwctl', 'known-networks', 'list'], check=True)
|
||||
|
||||
for n in networks:
|
||||
self.assertIn(n, iwctl.out)
|
||||
|
||||
for n in networks:
|
||||
ctx.start_process(['iwctl', 'known-networks', n, 'show'], check=True)
|
||||
|
||||
networks.remove('ssidOpen')
|
||||
ctx.start_process(['iwctl', 'known-networks', 'ssidOpen', 'forget'], check=True)
|
||||
|
||||
with self.assertRaises(subprocess.CalledProcessError):
|
||||
ctx.start_process(['iwctl', 'known-networks', 'ssidOpen', 'show'], check=True)
|
||||
|
||||
@classmethod
|
||||
def setUp(self):
|
||||
def setUpClass(cls):
|
||||
IWD.copy_to_storage('known_networks/ssidOpen.open')
|
||||
IWD.copy_to_storage('known_networks/ssidTKIP.psk')
|
||||
IWD.copy_to_storage('known_networks/ssidEAP-TLS.8021x')
|
||||
|
@ -11,7 +11,7 @@ from iwd import NetworkType
|
||||
|
||||
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:
|
||||
0 0 No MFP, connection succeeds
|
||||
|
@ -1,7 +0,0 @@
|
||||
hw_mode=g
|
||||
channel=1
|
||||
ssid=ap-main
|
||||
|
||||
wpa=1
|
||||
wpa_pairwise=TKIP
|
||||
wpa_passphrase=secret123
|
@ -1,7 +0,0 @@
|
||||
hw_mode=g
|
||||
channel=1
|
||||
ssid=ap-ns1
|
||||
|
||||
wpa=1
|
||||
wpa_pairwise=TKIP
|
||||
wpa_passphrase=secret123
|
@ -1,2 +0,0 @@
|
||||
[IPv4]
|
||||
SendHostname=true
|
@ -11,33 +11,11 @@ from iwd import NetworkType
|
||||
from hostapd import HostapdCLI
|
||||
import testutil
|
||||
from config import ctx
|
||||
import os
|
||||
import socket
|
||||
import datetime, time
|
||||
import os, time
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
def test_connection_success(self):
|
||||
def check_addr(device):
|
||||
try:
|
||||
# DHCPv6 addresses always have a prefix length of 128 bits, the actual
|
||||
# subnet's prefix length is in the route.
|
||||
testutil.test_ip_address_match(device.name, '3ffe:501:ffff:100::1', 128, 112)
|
||||
except:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def get_ll_addrs6(ns, ifname):
|
||||
show_ip = ns.start_process(['ip', 'addr', 'show', ifname])
|
||||
show_ip.wait()
|
||||
for l in show_ip.out.split('\n'):
|
||||
if 'inet6 fe80::' in l:
|
||||
return socket.inet_pton(socket.AF_INET6, l.split(None, 1)[1].split('/', 1)[0])
|
||||
return None
|
||||
|
||||
os.system("hostname test-sta")
|
||||
IWD.copy_to_storage('auto.psk', name='ap-ns1.psk')
|
||||
wd = IWD(True)
|
||||
|
||||
psk_agent = PSKAgent("secret123")
|
||||
@ -46,7 +24,7 @@ class Test(unittest.TestCase):
|
||||
devices = wd.list_devices(1)
|
||||
device = devices[0]
|
||||
|
||||
ordered_network = device.get_ordered_network('ap-ns1')
|
||||
ordered_network = device.get_ordered_network('ssidTKIP')
|
||||
|
||||
self.assertEqual(ordered_network.type, NetworkType.psk)
|
||||
|
||||
@ -57,120 +35,13 @@ class Test(unittest.TestCase):
|
||||
|
||||
condition = 'obj.state == DeviceState.connected'
|
||||
wd.wait_for_object_condition(device, condition)
|
||||
connect_time = time.time()
|
||||
|
||||
testutil.test_iface_operstate()
|
||||
testutil.test_ifaces_connected()
|
||||
|
||||
testutil.test_ip_address_match(device.name, '192.168.1.10', 17, 24)
|
||||
ctx.non_block_wait(check_addr, 10, device,
|
||||
exception=Exception("IPv6 address was not set"))
|
||||
|
||||
# Cannot use test_ifaces_connected() across namespaces (implementation details)
|
||||
testutil.test_ip_connected(('192.168.1.10', ctx), ('192.168.1.1', self.ns1))
|
||||
|
||||
ifname = str(device.name)
|
||||
router_ll_addr = get_ll_addrs6(self.ns1, self.hapd.ifname)
|
||||
# Since we're in an isolated VM with freshly created interfaces we know any routes
|
||||
# will have been created by IWD and we don't have to allow for pre-existing routes
|
||||
# in the table.
|
||||
# Flags: 1=RTF_UP, 2=RTF_GATEWAY
|
||||
expected_routes4 = {
|
||||
testutil.RouteInfo(gw=socket.inet_pton(socket.AF_INET, '192.168.1.1'),
|
||||
flags=3, ifname=ifname),
|
||||
testutil.RouteInfo(dst=socket.inet_pton(socket.AF_INET, '192.168.0.0'), plen=17,
|
||||
flags=1, ifname=ifname)
|
||||
}
|
||||
expected_routes6 = {
|
||||
# Default router
|
||||
testutil.RouteInfo(gw=router_ll_addr, flags=3, ifname=ifname),
|
||||
# On-link prefix
|
||||
testutil.RouteInfo(dst=socket.inet_pton(socket.AF_INET6, '3ffe:501:ffff:100::'), plen=72,
|
||||
flags=1, ifname=ifname),
|
||||
# Router for an off-link prefix, medium preference
|
||||
testutil.RouteInfo(dst=socket.inet_pton(socket.AF_INET6, '3ffe:501:ffff:300::'), plen=64,
|
||||
gw=router_ll_addr, flags=3, ifname=ifname),
|
||||
# Router for an off-link prefix, high preference
|
||||
testutil.RouteInfo(dst=socket.inet_pton(socket.AF_INET6, '3ffe:501:ffff:400::'), plen=65,
|
||||
gw=router_ll_addr, flags=3, ifname=ifname),
|
||||
# Router for an off-link prefix, low preference
|
||||
testutil.RouteInfo(dst=socket.inet_pton(socket.AF_INET6, '3ffe:501:ffff:500::'), plen=66,
|
||||
gw=router_ll_addr, flags=3, ifname=ifname)
|
||||
}
|
||||
self.maxDiff = None
|
||||
self.assertEqual(expected_routes4, set(testutil.get_routes4(ifname)))
|
||||
self.assertEqual(expected_routes6, set(testutil.get_routes6(ifname)))
|
||||
|
||||
rclog = open('/tmp/resolvconf.log', 'r')
|
||||
entries = rclog.readlines()
|
||||
rclog.close()
|
||||
expected_rclog = ['-a %s.dns\n' % ifname, 'nameserver 192.168.1.2\n', 'nameserver 3ffe:501:ffff:100::2\n']
|
||||
# Every real resolvconf -a run overwrites the previous settings. Check the last three lines
|
||||
# of our log since we care about the end result here.
|
||||
self.assertEqual(expected_rclog, entries[-3:])
|
||||
|
||||
leases_file = self.parse_lease_file('/tmp/dhcpd.leases', socket.AF_INET)
|
||||
lease = leases_file['leases'][socket.inet_pton(socket.AF_INET, '192.168.1.10')]
|
||||
self.assertEqual(lease['state'], 'active')
|
||||
self.assertEqual(lease['client-hostname'], 'test-sta')
|
||||
self.assertTrue(lease['starts'] < connect_time)
|
||||
self.assertTrue(lease['ends'] > connect_time)
|
||||
# The T1 is 15 seconds per dhcpd.conf. This is the approximate interval between lease
|
||||
# renewals we should see from the client (+/- 1 second + some jitter). Wait a little
|
||||
# less than twice that time (25s) so that we can expect the lease was renewed strictly
|
||||
# once (not 0 or 2 times) by that time, check that the lease timestamps have changed by
|
||||
# at least 10s so as to leave a lot of margin.
|
||||
renew_time = lease['starts'] + 15
|
||||
now = time.time()
|
||||
ctx.non_block_wait(lambda: False, renew_time + 10 - now, exception=False)
|
||||
|
||||
leases_file = self.parse_lease_file('/tmp/dhcpd.leases', socket.AF_INET)
|
||||
new_lease = leases_file['leases'][socket.inet_pton(socket.AF_INET, '192.168.1.10')]
|
||||
self.assertEqual(new_lease['state'], 'active')
|
||||
self.assertEqual(new_lease['client-hostname'], 'test-sta')
|
||||
self.assertTrue(new_lease['starts'] > lease['starts'] + 10)
|
||||
self.assertTrue(new_lease['starts'] < lease['starts'] + 25)
|
||||
self.assertTrue(new_lease['ends'] > lease['ends'] + 10)
|
||||
self.assertTrue(new_lease['ends'] < lease['ends'] + 25)
|
||||
|
||||
# Now wait another T1 seconds but don't let our DHCP client get its REQUEST out this
|
||||
# time so as to test renew timeouts and resends. The retry interval is 60 seconds
|
||||
# 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
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
# We can't use hswim to block the frames from reaching the AP because we'd lose
|
||||
# beacons and get disconnected. We also can't drop our subnet route or IP address
|
||||
# because IWD's sendto() call would synchronously error out and the DHCP client
|
||||
# would just give up. Add a false route to break routing to 192.168.1.1 and delete
|
||||
# it afterwards.
|
||||
os.system('ip route add 192.168.1.1/32 dev ' + ifname + ' via 192.168.1.100 preference 0')
|
||||
|
||||
lease = new_lease
|
||||
renew_time = lease['starts'] + 15
|
||||
now = time.time()
|
||||
ctx.non_block_wait(lambda: False, renew_time + 10 - now, exception=False)
|
||||
|
||||
leases_file = self.parse_lease_file('/tmp/dhcpd.leases', socket.AF_INET)
|
||||
new_lease = leases_file['leases'][socket.inet_pton(socket.AF_INET, '192.168.1.10')]
|
||||
self.assertEqual(new_lease['starts'], lease['starts'])
|
||||
|
||||
os.system('ip route del 192.168.1.1/32 dev ' + ifname + ' via 192.168.1.100 preference 0')
|
||||
|
||||
retry_time = lease['starts'] + 75
|
||||
now = time.time()
|
||||
ctx.non_block_wait(lambda: False, retry_time + 10 - now, exception=False)
|
||||
|
||||
leases_file = self.parse_lease_file('/tmp/dhcpd.leases', socket.AF_INET)
|
||||
new_lease = leases_file['leases'][socket.inet_pton(socket.AF_INET, '192.168.1.10')]
|
||||
self.assertEqual(new_lease['state'], 'active')
|
||||
self.assertEqual(lease['client-hostname'], 'test-sta')
|
||||
self.assertTrue(new_lease['starts'] > lease['starts'] + 70)
|
||||
self.assertTrue(new_lease['starts'] < lease['starts'] + 85)
|
||||
self.assertTrue(new_lease['ends'] > lease['ends'] + 70)
|
||||
self.assertTrue(new_lease['ends'] < lease['ends'] + 85)
|
||||
time.sleep(2)
|
||||
ret = os.system('ip addr show ' + device.name + ' | grep \'inet6 3ffe:501:ffff:100::\'')
|
||||
self.assertEqual(os.waitstatus_to_exitcode(ret), 0)
|
||||
|
||||
device.disconnect()
|
||||
|
||||
@ -194,130 +65,40 @@ class Test(unittest.TestCase):
|
||||
except:
|
||||
pass
|
||||
|
||||
cls.ns1 = ctx.get_namespace('ns1')
|
||||
cls.hapd = HostapdCLI('ap-ns1.conf')
|
||||
hapd = HostapdCLI()
|
||||
# TODO: This could be moved into test-runner itself if other tests ever
|
||||
# require this functionality (p2p, FILS, etc.). Since its simple
|
||||
# enough it can stay here for now.
|
||||
cls.ns1.start_process(['ip', 'addr','add', '192.168.1.1/17',
|
||||
'dev', cls.hapd.ifname]).wait()
|
||||
cls.ns1.start_process(['touch', '/tmp/dhcpd.leases']).wait()
|
||||
cls.dhcpd_pid = cls.ns1.start_process(['dhcpd', '-f', '-d', '-cf', '/tmp/dhcpd.conf',
|
||||
'-lf', '/tmp/dhcpd.leases',
|
||||
cls.hapd.ifname], cleanup=remove_lease4)
|
||||
ctx.start_process(['ip', 'addr','add','dev', hapd.ifname,
|
||||
'192.168.1.1/255.255.255.0']).wait()
|
||||
ctx.start_process(['touch', '/tmp/dhcpd.leases']).wait()
|
||||
cls.dhcpd_pid = ctx.start_process(['dhcpd', '-f', '-cf', '/tmp/dhcpd.conf',
|
||||
'-lf', '/tmp/dhcpd.leases',
|
||||
hapd.ifname], cleanup=remove_lease4)
|
||||
|
||||
cls.ns1.start_process(['ip', 'addr', 'add', '3ffe:501:ffff:100::1/72',
|
||||
'dev', cls.hapd.ifname]).wait()
|
||||
cls.ns1.start_process(['touch', '/tmp/dhcpd6.leases']).wait()
|
||||
cls.dhcpd6_pid = cls.ns1.start_process(['dhcpd', '-6', '-f', '-d',
|
||||
'-cf', '/tmp/dhcpd-v6.conf',
|
||||
'-lf', '/tmp/dhcpd6.leases',
|
||||
cls.hapd.ifname], cleanup=remove_lease6)
|
||||
cls.ns1.start_process(['sysctl',
|
||||
'net.ipv6.conf.' + cls.hapd.ifname + '.forwarding=1']).wait()
|
||||
# Send out Router Advertisements telling clients to use DHCPv6.
|
||||
# Note trying to send the RAs from the router's global IPv6 address by adding a
|
||||
# "AdvRASrcAddress { 3ffe:501:ffff:100::1; };" line will fail because the client
|
||||
# and the router interfaces are in the same namespace and Linux won't allow routes
|
||||
# with a non-link-local gateway address that is present on another interface in the
|
||||
# same namespace.
|
||||
ctx.start_process(['ip', 'addr', 'add', 'dev', hapd.ifname,
|
||||
'3ffe:501:ffff:100::1/64']).wait()
|
||||
ctx.start_process(['touch', '/tmp/dhcpd6.leases']).wait()
|
||||
cls.dhcpd6_pid = ctx.start_process(['dhcpd', '-6', '-f', '-cf', '/tmp/dhcpd-v6.conf',
|
||||
'-lf', '/tmp/dhcpd6.leases',
|
||||
hapd.ifname], cleanup=remove_lease6)
|
||||
ctx.start_process(['sysctl', 'net.ipv6.conf.' + hapd.ifname + '.forwarding=1']).wait()
|
||||
# Tell clients to use DHCPv6
|
||||
config = open('/tmp/radvd.conf', 'w')
|
||||
config.write('interface ' + cls.hapd.ifname + ''' {
|
||||
AdvSendAdvert on;
|
||||
AdvManagedFlag on;
|
||||
prefix 3ffe:501:ffff:100::/72 { AdvAutonomous off; };
|
||||
route 3ffe:501:ffff:300::/64 {};
|
||||
route 3ffe:501:ffff:400::/65 { AdvRoutePreference low; };
|
||||
route 3ffe:501:ffff:500::/66 { AdvRoutePreference high; };
|
||||
};''')
|
||||
config.write('interface ' + hapd.ifname + ' { AdvSendAdvert on; AdvManagedFlag on; };')
|
||||
config.close()
|
||||
cls.radvd_pid = cls.ns1.start_process(['radvd', '-n', '-d5',
|
||||
'-p', '/tmp/radvd.pid', '-C', '/tmp/radvd.conf'])
|
||||
|
||||
cls.orig_path = os.environ['PATH']
|
||||
os.environ['PATH'] = '/tmp/test-bin:' + os.environ['PATH']
|
||||
IWD.copy_to_storage('resolvconf', '/tmp/test-bin')
|
||||
cls.radvd_pid = ctx.start_process(['radvd', '-n', '-d5', '-p', '/tmp/radvd.pid', '-C', '/tmp/radvd.conf'])
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
IWD.clear_storage()
|
||||
cls.ns1.stop_process(cls.dhcpd_pid)
|
||||
ctx.stop_process(cls.dhcpd_pid)
|
||||
cls.dhcpd_pid = None
|
||||
cls.ns1.stop_process(cls.dhcpd6_pid)
|
||||
ctx.stop_process(cls.dhcpd6_pid)
|
||||
cls.dhcpd6_pid = None
|
||||
cls.ns1.stop_process(cls.radvd_pid)
|
||||
ctx.stop_process(cls.radvd_pid)
|
||||
cls.radvd_pid = None
|
||||
os.system('rm -rf /tmp/radvd.conf /tmp/resolvconf.log /tmp/test-bin')
|
||||
os.environ['PATH'] = cls.orig_path
|
||||
|
||||
@staticmethod
|
||||
def parse_lease_file(path, family):
|
||||
file = open(path, 'r')
|
||||
lines = file.readlines()
|
||||
file.close()
|
||||
|
||||
stack = [[]]
|
||||
statement = []
|
||||
token = ''
|
||||
for line in lines:
|
||||
whitespace = False
|
||||
quote = False
|
||||
for ch in line:
|
||||
if not quote and ch in ' \t\r\n;{}=#':
|
||||
if len(token):
|
||||
statement.append(token)
|
||||
token = ''
|
||||
if not quote and ch in ';{}':
|
||||
if len(statement):
|
||||
stack[-1].append(statement)
|
||||
statement = []
|
||||
if ch == '"':
|
||||
quote = not quote
|
||||
elif quote or ch not in ' \t\r\n;{}#':
|
||||
token += ch
|
||||
if ch == '#':
|
||||
continue
|
||||
elif ch == '{':
|
||||
stack.append([])
|
||||
elif ch == '}':
|
||||
statements = stack.pop()
|
||||
stack[-1][-1].append(statements)
|
||||
if len(token):
|
||||
statement.append(token)
|
||||
token = ''
|
||||
if len(statement):
|
||||
stack[-1].append(statement)
|
||||
statements = stack.pop(0)
|
||||
if len(stack):
|
||||
raise Exception('Unclosed block(s)')
|
||||
|
||||
contents = {'leases':{}}
|
||||
for s in statements:
|
||||
if s[0] == 'lease':
|
||||
ip = socket.inet_pton(family, s[1])
|
||||
lease = {}
|
||||
for param in s[2]:
|
||||
if param[0] in ('starts', 'ends', 'tstp', 'tsfp', 'atsfp', 'cltt'):
|
||||
weekday = param[1]
|
||||
year, month, day = param[2].split('/')
|
||||
hour, minute, second = param[3].split(':')
|
||||
dt = datetime.datetime(
|
||||
int(year), int(month), int(day),
|
||||
int(hour), int(minute), int(second),
|
||||
tzinfo=datetime.timezone.utc)
|
||||
lease[param[0]] = dt.timestamp()
|
||||
elif param[0:2] == ['binding', 'state']:
|
||||
lease['state'] = param[2]
|
||||
elif param[0:2] == ['hardware', 'ethernet']:
|
||||
lease['hwaddr'] = bytes([int(v, 16) for v in param[2].split(':')])
|
||||
elif param[0] in ('preferred-life', 'max-life'):
|
||||
lease[param[0]] = int(param[1])
|
||||
elif param[0] in ('client-hostname'):
|
||||
lease[param[0]] = param[1]
|
||||
contents['leases'][ip] = lease # New entries overwrite older ones
|
||||
elif s[0] == 'server-duid':
|
||||
contents[s[0]] = s[1]
|
||||
return contents
|
||||
os.remove('/tmp/radvd.conf')
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(exit=True)
|
||||
|
@ -1,6 +1,6 @@
|
||||
subnet6 3ffe:501:ffff:100::/72
|
||||
subnet6 3ffe:501:ffff:100::/64
|
||||
{
|
||||
option dhcp6.name-servers 3ffe:501:ffff:100::2;
|
||||
option dhcp6.name-servers 3ffe:501:ffff:100::1;
|
||||
range6 3ffe:501:ffff:100::10 3ffe:501:ffff:100::20;
|
||||
range6 3ffe:501:ffff:100::100 3ffe:501:ffff:100::200;
|
||||
}
|
||||
|
@ -1,25 +1,15 @@
|
||||
default-lease-time 120; # 2 minutes
|
||||
min-lease-time 120; # 2 minutes
|
||||
max-lease-time 120; # 2 minutes
|
||||
option dhcp-renewal-time 15; # 15 secs for T1
|
||||
# We set a relatively low lease lifetime of 2 minutes but our renewal interval
|
||||
# (T1) is still unproportionally low to speed the test up -- 12% instead of the
|
||||
# default 50% lifetime value. We need a lifetime in the order of minutes
|
||||
# because minimum lease renewal retry interval is 60s per spec. However by
|
||||
# default dhcpd will not renew leases that are newer than 25% their lifetime.
|
||||
# Set that threshold to 1% so that we can verify that the lease is renewed
|
||||
# without waiting too long.
|
||||
dhcp-cache-threshold 1;
|
||||
default-lease-time 600; # 10 minutes
|
||||
max-lease-time 7200; # 2 hours
|
||||
|
||||
option broadcast-address 192.168.127.255;
|
||||
option broadcast-address 192.168.1.255;
|
||||
option routers 192.168.1.254;
|
||||
option subnet-mask 255.255.128.0;
|
||||
option subnet-mask 255.255.255.0;
|
||||
|
||||
subnet 192.168.0.0 netmask 255.255.128.0
|
||||
subnet 192.168.1.0 netmask 255.255.255.0
|
||||
{
|
||||
option routers 192.168.1.1;
|
||||
option subnet-mask 255.255.128.0;
|
||||
option domain-name-servers 192.168.1.2;
|
||||
option subnet-mask 255.255.255.0;
|
||||
option domain-name-servers 192.168.1.1;
|
||||
range 192.168.1.10 192.168.1.20;
|
||||
range 192.168.1.100 192.168.1.200;
|
||||
}
|
||||
|
@ -1,11 +1,9 @@
|
||||
[SETUP]
|
||||
num_radios=4
|
||||
num_radios=3
|
||||
start_iwd=0
|
||||
|
||||
[HOSTAPD]
|
||||
rad2=ap-main.conf
|
||||
rad3=ap-ns1.conf
|
||||
rad0=ssidTKIP.conf
|
||||
|
||||
[NameSpaces]
|
||||
ns0=rad0
|
||||
ns1=rad3
|
||||
ns0=rad2
|
||||
|
@ -3,4 +3,3 @@ EnableNetworkConfiguration=true
|
||||
|
||||
[Network]
|
||||
EnableIPv6=true
|
||||
NameResolvingService=resolvconf
|
||||
|
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