diff --git a/autotests/testBSSBlacklist/all_blacklisted_test.py b/autotests/testBSSBlacklist/all_blacklisted_test.py new file mode 100644 index 00000000..9b2c5555 --- /dev/null +++ b/autotests/testBSSBlacklist/all_blacklisted_test.py @@ -0,0 +1,111 @@ +#!/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 hostapd import HostapdCLI +from hostapd import hostapd_map + +from wiphy import wiphy_map +from hwsim import Hwsim + +import time + +class Test(unittest.TestCase): + + def test_connection_success(self): + hwsim = Hwsim() + + bss_radio = [None, None] + bss_hostapd = [None, None] + + for wname in wiphy_map: + wiphy = wiphy_map[wname] + intf = list(wiphy.values())[0] + + if intf.config and '1' in intf.config: + bss_idx = 0 + elif intf.config and '2' in intf.config: + bss_idx = 1 + else: + continue + + for path in hwsim.radios: + radio = hwsim.radios[path] + if radio.name == wname: + break + + bss_radio[bss_idx] = radio + bss_hostapd[bss_idx] = HostapdCLI(intf) + + rule0 = hwsim.rules.create() + rule0.source = bss_radio[0].addresses[0] + rule0.bidirectional = True + rule0.signal = -2000 + + rule1 = hwsim.rules.create() + rule1.source = bss_radio[1].addresses[0] + rule1.bidirectional = True + rule1.signal = -8000 + + wd = IWD(True) + + psk_agent = PSKAgent(["secret123", 'secret123']) + wd.register_psk_agent(psk_agent) + + devices = wd.list_devices(1) + device = devices[0] + + 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) + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + # Have both APs drop all packets, both should get blacklisted + rule0.drop = True + rule1.drop = True + + with self.assertRaises(iwd.FailedEx): + ordered_network.network_object.connect() + + rule0.drop = False + rule1.drop = False + + # This connect should work + ordered_network.network_object.connect() + + condition = 'obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + self.assertIn(device.address, bss_hostapd[0].list_sta()) + + wd.unregister_psk_agent(psk_agent) + + del wd + + @classmethod + def setUpClass(cls): + pass + + @classmethod + def tearDownClass(cls): + IWD.clear_storage() + +if __name__ == '__main__': + unittest.main(exit=True) diff --git a/autotests/testBSSBlacklist/bad_pass_test.py b/autotests/testBSSBlacklist/bad_pass_test.py new file mode 100644 index 00000000..6194c8c6 --- /dev/null +++ b/autotests/testBSSBlacklist/bad_pass_test.py @@ -0,0 +1,109 @@ +#!/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 hostapd import HostapdCLI +from hostapd import hostapd_map + +from wiphy import wiphy_map +from hwsim import Hwsim + +import time + +class Test(unittest.TestCase): + + def test_connection_success(self): + hwsim = Hwsim() + + bss_radio = [None, None] + bss_hostapd = [None, None] + + for wname in wiphy_map: + wiphy = wiphy_map[wname] + intf = list(wiphy.values())[0] + + if intf.config and '1' in intf.config: + bss_idx = 0 + elif intf.config and '2' in intf.config: + bss_idx = 1 + else: + continue + + for path in hwsim.radios: + radio = hwsim.radios[path] + if radio.name == wname: + break + + bss_radio[bss_idx] = radio + bss_hostapd[bss_idx] = HostapdCLI(intf) + + rule0 = hwsim.rules.create() + rule0.source = bss_radio[0].addresses[0] + rule0.bidirectional = True + rule0.signal = -2000 + + rule1 = hwsim.rules.create() + rule1.source = bss_radio[1].addresses[0] + rule1.bidirectional = True + rule1.signal = -8000 + + wd = IWD(True, '/tmp') + + psk_agent = PSKAgent("wrong_password") + wd.register_psk_agent(psk_agent) + + devices = wd.list_devices(1) + device = devices[0] + + 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) + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + with self.assertRaises(iwd.FailedEx): + ordered_network.network_object.connect() + + wd.unregister_psk_agent(psk_agent) + + psk_agent = PSKAgent("secret123") + wd.register_psk_agent(psk_agent) + + ordered_network.network_object.connect() + + # We failed to connect bss_hostapd[0], but with a bad password. Verify + # that this did not trigger a blacklist and that we did reconnect + # successfully to bss_hostapd[0] + self.assertIn(device.address, bss_hostapd[0].list_sta()) + + condition = 'obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + del wd + + @classmethod + def setUpClass(cls): + pass + + @classmethod + def tearDownClass(cls): + IWD.clear_storage() + +if __name__ == '__main__': + unittest.main(exit=True) diff --git a/autotests/testBSSBlacklist/connection_test.py b/autotests/testBSSBlacklist/connection_test.py new file mode 100644 index 00000000..113faa79 --- /dev/null +++ b/autotests/testBSSBlacklist/connection_test.py @@ -0,0 +1,164 @@ +#!/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 hostapd import HostapdCLI +from hostapd import hostapd_map + +from wiphy import wiphy_map +from hwsim import Hwsim + +import time + +class Test(unittest.TestCase): + + def test_connection_success(self): + hwsim = Hwsim() + + bss_radio = [None, None] + bss_hostapd = [None, None] + + for wname in wiphy_map: + wiphy = wiphy_map[wname] + intf = list(wiphy.values())[0] + + if intf.config and '1' in intf.config: + bss_idx = 0 + elif intf.config and '2' in intf.config: + bss_idx = 1 + else: + continue + + for path in hwsim.radios: + radio = hwsim.radios[path] + if radio.name == wname: + break + + bss_radio[bss_idx] = radio + bss_hostapd[bss_idx] = HostapdCLI(intf) + + rule0 = hwsim.rules.create() + rule0.source = bss_radio[0].addresses[0] + rule0.bidirectional = True + rule0.signal = -2000 + + rule1 = hwsim.rules.create() + rule1.source = bss_radio[1].addresses[0] + rule1.bidirectional = True + rule1.signal = -8000 + + wd = IWD(True, '/tmp') + + psk_agent = PSKAgent("secret123") + wd.register_psk_agent(psk_agent) + + devices = wd.list_devices(1) + device = devices[0] + + 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) + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + ordered_network.network_object.connect(wait=False) + + # Have AP1 drop all packets, should result in a connection timeout + rule0.drop = True + + # Note the time so later we don't sleep any longer than required + start = time.time() + + condition = 'obj.state == DeviceState.connected' + wd.wait_for_object_condition(device, condition) + + # IWD should have attempted to connect to bss_hostapd[0], since its + # signal strength was highest. But since we dropped all packets this + # connect should fail, and the BSS should be blacklisted. Then we + # should automatically try the next BSS in the list, which is + # bss_hostapd[1] + self.assertNotIn(device.address, bss_hostapd[0].list_sta()) + self.assertIn(device.address, bss_hostapd[1].list_sta()) + + rule0.drop = False + + # Next try autoconnecting to a network with a blacklisted BSS. Since an + # explicit disconnect call would disable autoconnect we reset + # hostapd which will disconnect IWD. + bss_hostapd[1].reload() + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + # Now we wait... Autoconnect should take over + + condition = 'obj.state == DeviceState.connecting' + wd.wait_for_object_condition(device, condition, 15) + + condition = 'obj.state == DeviceState.connected' + wd.wait_for_object_condition(device, condition, 15) + + # Same as before, make sure we didn't connect to the blacklisted AP. + self.assertNotIn(device.address, bss_hostapd[0].list_sta()) + self.assertIn(device.address, bss_hostapd[1].list_sta()) + + # Wait for the blacklist to expire (10 seconds) + elapsed = time.time() - start + + if elapsed < 11: + time.sleep(11 - elapsed) + + device.disconnect() + + 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) + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + ordered_network.network_object.connect() + + condition = 'obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + self.assertIn(device.address, bss_hostapd[0].list_sta()) + + wd.unregister_psk_agent(psk_agent) + + del wd + + @classmethod + def setUpClass(cls): + IWD.copy_to_storage('main.conf') + + @classmethod + def tearDownClass(cls): + IWD.clear_storage() + +if __name__ == '__main__': + unittest.main(exit=True) diff --git a/autotests/testBSSBlacklist/hw.conf b/autotests/testBSSBlacklist/hw.conf new file mode 100644 index 00000000..61aeb16e --- /dev/null +++ b/autotests/testBSSBlacklist/hw.conf @@ -0,0 +1,9 @@ +[SETUP] +num_radios=3 +tmpfs_extra_stuff=main.conf +max_test_exec_interval_sec=45 +start_iwd=0 + +[HOSTAPD] +rad0=ssid1.conf +rad1=ssid2.conf diff --git a/autotests/testBSSBlacklist/main.conf b/autotests/testBSSBlacklist/main.conf new file mode 100644 index 00000000..302d9837 --- /dev/null +++ b/autotests/testBSSBlacklist/main.conf @@ -0,0 +1,2 @@ +[Blacklist] +bss_blacklist_time=10 diff --git a/autotests/testBSSBlacklist/ssid1.conf b/autotests/testBSSBlacklist/ssid1.conf new file mode 100644 index 00000000..2db39a8c --- /dev/null +++ b/autotests/testBSSBlacklist/ssid1.conf @@ -0,0 +1,11 @@ +hw_mode=g +channel=1 +ssid=TestBlacklist + +wpa=2 +wpa_pairwise=CCMP +wpa_passphrase=secret123 + +ctrl_interface=/var/run/hostapd + +rrm_neighbor_report=1 diff --git a/autotests/testBSSBlacklist/ssid2.conf b/autotests/testBSSBlacklist/ssid2.conf new file mode 100644 index 00000000..d37c308d --- /dev/null +++ b/autotests/testBSSBlacklist/ssid2.conf @@ -0,0 +1,11 @@ +hw_mode=g +channel=2 +ssid=TestBlacklist + +wpa=2 +wpa_pairwise=CCMP +wpa_passphrase=secret123 + +ctrl_interface=/var/run/hostapd + +rrm_neighbor_report=1