diff --git a/autotests/testFT-FILS-SHA256/TestFT.8021x b/autotests/testFT-FILS-SHA256/TestFT.8021x new file mode 100644 index 00000000..7d6e1273 --- /dev/null +++ b/autotests/testFT-FILS-SHA256/TestFT.8021x @@ -0,0 +1,5 @@ +[Security] +EAP-Method=PWD + +[Settings] +Autoconnect=False diff --git a/autotests/testFT-FILS-SHA256/ft-eap-ccmp-1.conf b/autotests/testFT-FILS-SHA256/ft-eap-ccmp-1.conf new file mode 100644 index 00000000..a55d90a2 --- /dev/null +++ b/autotests/testFT-FILS-SHA256/ft-eap-ccmp-1.conf @@ -0,0 +1,52 @@ +hw_mode=g +channel=1 +ssid=TestFT +utf8_ssid=1 +ctrl_interface=/var/run/hostapd +r1_key_holder=000000000001 +nas_identifier=dummy1 + +wpa=2 +# Can support WPA-EAP and FT-EAP (space separated list) at the same +# time but we want to force FT +wpa_key_mgmt=FT-EAP FILS-SHA256 FT-FILS-SHA256 +wpa_pairwise=CCMP +ieee8021x=1 +eap_server=0 +eap_server_erp=1 +erp_domain=example.com +fils_realm=example.com +#eap_user_file=/tmp/certs/eap-user-tls.text +eap_user_file=/tmp/pwd.eap_user +pwd_group=19 +#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=1 +# 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 nas1.w1.fi 000102030405060708090a0b0c0d0e0f +r0kh=12:00:00:00:00:02 nas2.w1.fi 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=1 +ft_over_ds=0 +ap_table_expiration_time=36000 +ap_table_max_size=10 +rrm_neighbor_report=1 + +radius_server_clients=/tmp/certs/radius-clients.text +radius_server_auth_port=1812 + +auth_server_addr=127.0.0.1 +auth_server_port=1812 +auth_server_shared_secret=secret +nas_identifier=nas1.w1.fi diff --git a/autotests/testFT-FILS-SHA256/ft-eap-ccmp-2.conf b/autotests/testFT-FILS-SHA256/ft-eap-ccmp-2.conf new file mode 100644 index 00000000..a7878264 --- /dev/null +++ b/autotests/testFT-FILS-SHA256/ft-eap-ccmp-2.conf @@ -0,0 +1,49 @@ +hw_mode=g +channel=2 +ssid=TestFT +utf8_ssid=1 +ctrl_interface=/var/run/hostapd +r1_key_holder=000000000002 +nas_identifier=dummy2 + +wpa=2 +# Can support WPA-EAP and FT-EAP (space separated list) at the same +# time but we want to force FT +wpa_key_mgmt=FT-FILS-SHA256 +wpa_pairwise=CCMP +ieee8021x=1 +eap_server=0 +eap_server_erp=1 +erp_domain=example.com +fils_realm=example.com +#eap_user_file=/tmp/certs/eap-user-tls.text +eap_user_file=/tmp/pwd.eap_user +pwd_group=19 +#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=1 +# 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 nas1.w1.fi 000102030405060708090a0b0c0d0e0f +r0kh=12:00:00:00:00:02 nas2.w1.fi 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=1 +ft_over_ds=0 +ap_table_expiration_time=36000 +ap_table_max_size=10 +rrm_neighbor_report=1 + +auth_server_addr=127.0.0.1 +auth_server_port=1812 +auth_server_shared_secret=secret +nas_identifier=nas2.w1.fi diff --git a/autotests/testFT-FILS-SHA256/hw.conf b/autotests/testFT-FILS-SHA256/hw.conf new file mode 100644 index 00000000..9ea4f110 --- /dev/null +++ b/autotests/testFT-FILS-SHA256/hw.conf @@ -0,0 +1,9 @@ +[SETUP] +num_radios=3 +max_test_exec_interval_sec=45 +tmpfs_extra_stuff=../misc/certs:main.conf:pwd.eap_user +iwd_config_dir=/tmp + +[HOSTAPD] +rad0=ft-eap-ccmp-1.conf +rad1=ft-eap-ccmp-2.conf diff --git a/autotests/testFT-FILS-SHA256/main.conf b/autotests/testFT-FILS-SHA256/main.conf new file mode 100644 index 00000000..c7eaf63a --- /dev/null +++ b/autotests/testFT-FILS-SHA256/main.conf @@ -0,0 +1,2 @@ +[Scan] +disable_mac_address_randomization=true diff --git a/autotests/testFT-FILS-SHA256/pwd.eap_user b/autotests/testFT-FILS-SHA256/pwd.eap_user new file mode 100644 index 00000000..69079c24 --- /dev/null +++ b/autotests/testFT-FILS-SHA256/pwd.eap_user @@ -0,0 +1 @@ +"user@example.com" PWD "secret123" diff --git a/autotests/testFT-FILS-SHA256/test.py b/autotests/testFT-FILS-SHA256/test.py new file mode 100644 index 00000000..09f4bd06 --- /dev/null +++ b/autotests/testFT-FILS-SHA256/test.py @@ -0,0 +1,192 @@ +#! /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, hostapd_map +import testutil + +class Test(unittest.TestCase): + def test_roam_success(self): + hwsim = Hwsim() + + rule0 = hwsim.rules.create() + rule0.source = self.bss_radio[0].addresses[0] + rule0.bidirectional = True + + rule1 = hwsim.rules.create() + rule1.source = self.bss_radio[1].addresses[0] + rule1.bidirectional = True + + wd = IWD() + + psk_agent = PSKAgent('user@example.com', ('user@example.com', + 'secret123')) + wd.register_psk_agent(psk_agent) + + device = wd.list_devices(1)[0] + + # Check that iwd selects BSS 0 first + rule0.signal = -2000 + rule1.signal = -2500 + + 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) + + ordered_network = device.get_ordered_network('TestFT') + + self.assertEqual(ordered_network.type, NetworkType.eap) + self.assertEqual(ordered_network.signal_strength, -2000) + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + self.assertFalse(self.bss_hostapd[0].list_sta()) + self.assertFalse(self.bss_hostapd[1].list_sta()) + + ordered_network.network_object.connect() + + condition = 'obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + self.assertTrue(self.bss_hostapd[0].list_sta()) + self.assertFalse(self.bss_hostapd[1].list_sta()) + + testutil.test_iface_operstate(device.name) + testutil.test_ifaces_connected(self.bss_hostapd[0].ifname, device.name) + self.assertRaises(Exception, testutil.test_ifaces_connected, + (self.bss_hostapd[1].ifname, device.name)) + + device.disconnect() + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + ordered_network = device.get_ordered_network('TestFT') + + self.assertEqual(ordered_network.type, NetworkType.eap) + + 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.assertTrue(self.bss_hostapd[0].list_sta()) + self.assertFalse(self.bss_hostapd[1].list_sta()) + + testutil.test_iface_operstate(device.name) + testutil.test_ifaces_connected(self.bss_hostapd[0].ifname, device.name) + self.assertRaises(Exception, testutil.test_ifaces_connected, + (self.bss_hostapd[1].ifname, device.name)) + + # Check that iwd starts transition to BSS 1 in less than 10 seconds. + # The 10 seconds is longer than needed to scan on just two channels + # but short enough that a full scan on the 2.4 + 5.8 bands supported + # by mac80211_hwsim will not finish. If this times out then, but + # device_roam_trigger_cb has happened, it probably means that + # Neighbor Reports are broken. + rule0.signal = -8000 + + condition = 'obj.state == DeviceState.roaming' + wd.wait_for_object_condition(device, condition, 10) + + # Check that iwd is on BSS 1 once out of roaming state and doesn't + # go through 'disconnected', 'autoconnect', 'connecting' in between + condition = 'obj.state != DeviceState.roaming' + wd.wait_for_object_condition(device, condition, 5) + + self.assertEqual(device.state, iwd.DeviceState.connected) + 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) + self.assertRaises(Exception, testutil.test_ifaces_connected, + (self.bss_hostapd[0].ifname, device.name)) + + def tearDown(self): + os.system('ifconfig "' + self.bss_hostapd[0].ifname + '" down') + os.system('ifconfig "' + self.bss_hostapd[1].ifname + '" down') + os.system('ifconfig "' + self.bss_hostapd[0].ifname + '" up') + os.system('ifconfig "' + self.bss_hostapd[1].ifname + '" up') + + hwsim = Hwsim() + wd = IWD() + device = wd.list_devices(1)[0] + try: + device.disconnect() + except: + pass + + condition = 'obj.state == DeviceState.disconnected' + wd.wait_for_object_condition(device, condition) + + for rule in list(hwsim.rules.keys()): + del hwsim.rules[rule] + + @classmethod + def setUpClass(cls): + os.system('ifconfig lo up') + IWD.copy_to_storage('TestFT.8021x') + + hwsim = Hwsim() + + cls.bss_hostapd = [None, None] + cls.bss_radio = [None, None] + for intf in hostapd_map.values(): + 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 == intf.wiphy.name: + break + + cls.bss_hostapd[bss_idx] = HostapdCLI(intf) + cls.bss_radio[bss_idx] = radio + + # Set interface addresses to those expected by hostapd config files + os.system('ifconfig "' + cls.bss_hostapd[0].ifname + + '" down hw ether 12:00:00:00:00:01 up') + os.system('ifconfig "' + cls.bss_hostapd[1].ifname + + '" down hw ether 12:00:00:00:00:02 up') + + cls.bss_hostapd[0].reload() + cls.bss_hostapd[1].reload() + + # 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): + IWD.clear_storage() + +if __name__ == '__main__': + unittest.main(exit=True) diff --git a/autotests/testFT-FILS-SHA384/TestFT.8021x b/autotests/testFT-FILS-SHA384/TestFT.8021x new file mode 100644 index 00000000..7d6e1273 --- /dev/null +++ b/autotests/testFT-FILS-SHA384/TestFT.8021x @@ -0,0 +1,5 @@ +[Security] +EAP-Method=PWD + +[Settings] +Autoconnect=False diff --git a/autotests/testFT-FILS-SHA384/ft-eap-ccmp-1.conf b/autotests/testFT-FILS-SHA384/ft-eap-ccmp-1.conf new file mode 100644 index 00000000..ae1d4bfe --- /dev/null +++ b/autotests/testFT-FILS-SHA384/ft-eap-ccmp-1.conf @@ -0,0 +1,52 @@ +hw_mode=g +channel=1 +ssid=TestFT +utf8_ssid=1 +ctrl_interface=/var/run/hostapd +r1_key_holder=000000000001 +nas_identifier=dummy1 + +wpa=2 +# Can support WPA-EAP and FT-EAP (space separated list) at the same +# time but we want to force FT +wpa_key_mgmt=FT-EAP FILS-SHA384 FT-FILS-SHA384 +wpa_pairwise=CCMP +ieee8021x=1 +eap_server=0 +eap_server_erp=1 +erp_domain=example.com +fils_realm=example.com +#eap_user_file=/tmp/certs/eap-user-tls.text +eap_user_file=/tmp/pwd.eap_user +pwd_group=19 +#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=1 +# 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 nas1.w1.fi 000102030405060708090a0b0c0d0e0f +r0kh=12:00:00:00:00:02 nas2.w1.fi 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=1 +ft_over_ds=0 +ap_table_expiration_time=36000 +ap_table_max_size=10 +rrm_neighbor_report=1 + +radius_server_clients=/tmp/certs/radius-clients.text +radius_server_auth_port=1812 + +auth_server_addr=127.0.0.1 +auth_server_port=1812 +auth_server_shared_secret=secret +nas_identifier=nas1.w1.fi diff --git a/autotests/testFT-FILS-SHA384/ft-eap-ccmp-2.conf b/autotests/testFT-FILS-SHA384/ft-eap-ccmp-2.conf new file mode 100644 index 00000000..0c4deee8 --- /dev/null +++ b/autotests/testFT-FILS-SHA384/ft-eap-ccmp-2.conf @@ -0,0 +1,49 @@ +hw_mode=g +channel=2 +ssid=TestFT +utf8_ssid=1 +ctrl_interface=/var/run/hostapd +r1_key_holder=000000000002 +nas_identifier=dummy2 + +wpa=2 +# Can support WPA-EAP and FT-EAP (space separated list) at the same +# time but we want to force FT +wpa_key_mgmt=FT-FILS-SHA384 +wpa_pairwise=CCMP +ieee8021x=1 +eap_server=0 +eap_server_erp=1 +erp_domain=example.com +fils_realm=example.com +#eap_user_file=/tmp/certs/eap-user-tls.text +eap_user_file=/tmp/pwd.eap_user +pwd_group=19 +#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=1 +# 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 nas1.w1.fi 000102030405060708090a0b0c0d0e0f +r0kh=12:00:00:00:00:02 nas2.w1.fi 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=1 +ft_over_ds=0 +ap_table_expiration_time=36000 +ap_table_max_size=10 +rrm_neighbor_report=1 + +auth_server_addr=127.0.0.1 +auth_server_port=1812 +auth_server_shared_secret=secret +nas_identifier=nas2.w1.fi diff --git a/autotests/testFT-FILS-SHA384/hw.conf b/autotests/testFT-FILS-SHA384/hw.conf new file mode 100644 index 00000000..9ea4f110 --- /dev/null +++ b/autotests/testFT-FILS-SHA384/hw.conf @@ -0,0 +1,9 @@ +[SETUP] +num_radios=3 +max_test_exec_interval_sec=45 +tmpfs_extra_stuff=../misc/certs:main.conf:pwd.eap_user +iwd_config_dir=/tmp + +[HOSTAPD] +rad0=ft-eap-ccmp-1.conf +rad1=ft-eap-ccmp-2.conf diff --git a/autotests/testFT-FILS-SHA384/main.conf b/autotests/testFT-FILS-SHA384/main.conf new file mode 100644 index 00000000..c7eaf63a --- /dev/null +++ b/autotests/testFT-FILS-SHA384/main.conf @@ -0,0 +1,2 @@ +[Scan] +disable_mac_address_randomization=true diff --git a/autotests/testFT-FILS-SHA384/pwd.eap_user b/autotests/testFT-FILS-SHA384/pwd.eap_user new file mode 100644 index 00000000..69079c24 --- /dev/null +++ b/autotests/testFT-FILS-SHA384/pwd.eap_user @@ -0,0 +1 @@ +"user@example.com" PWD "secret123" diff --git a/autotests/testFT-FILS-SHA384/test.py b/autotests/testFT-FILS-SHA384/test.py new file mode 100644 index 00000000..09f4bd06 --- /dev/null +++ b/autotests/testFT-FILS-SHA384/test.py @@ -0,0 +1,192 @@ +#! /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, hostapd_map +import testutil + +class Test(unittest.TestCase): + def test_roam_success(self): + hwsim = Hwsim() + + rule0 = hwsim.rules.create() + rule0.source = self.bss_radio[0].addresses[0] + rule0.bidirectional = True + + rule1 = hwsim.rules.create() + rule1.source = self.bss_radio[1].addresses[0] + rule1.bidirectional = True + + wd = IWD() + + psk_agent = PSKAgent('user@example.com', ('user@example.com', + 'secret123')) + wd.register_psk_agent(psk_agent) + + device = wd.list_devices(1)[0] + + # Check that iwd selects BSS 0 first + rule0.signal = -2000 + rule1.signal = -2500 + + 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) + + ordered_network = device.get_ordered_network('TestFT') + + self.assertEqual(ordered_network.type, NetworkType.eap) + self.assertEqual(ordered_network.signal_strength, -2000) + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + self.assertFalse(self.bss_hostapd[0].list_sta()) + self.assertFalse(self.bss_hostapd[1].list_sta()) + + ordered_network.network_object.connect() + + condition = 'obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + self.assertTrue(self.bss_hostapd[0].list_sta()) + self.assertFalse(self.bss_hostapd[1].list_sta()) + + testutil.test_iface_operstate(device.name) + testutil.test_ifaces_connected(self.bss_hostapd[0].ifname, device.name) + self.assertRaises(Exception, testutil.test_ifaces_connected, + (self.bss_hostapd[1].ifname, device.name)) + + device.disconnect() + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + ordered_network = device.get_ordered_network('TestFT') + + self.assertEqual(ordered_network.type, NetworkType.eap) + + 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.assertTrue(self.bss_hostapd[0].list_sta()) + self.assertFalse(self.bss_hostapd[1].list_sta()) + + testutil.test_iface_operstate(device.name) + testutil.test_ifaces_connected(self.bss_hostapd[0].ifname, device.name) + self.assertRaises(Exception, testutil.test_ifaces_connected, + (self.bss_hostapd[1].ifname, device.name)) + + # Check that iwd starts transition to BSS 1 in less than 10 seconds. + # The 10 seconds is longer than needed to scan on just two channels + # but short enough that a full scan on the 2.4 + 5.8 bands supported + # by mac80211_hwsim will not finish. If this times out then, but + # device_roam_trigger_cb has happened, it probably means that + # Neighbor Reports are broken. + rule0.signal = -8000 + + condition = 'obj.state == DeviceState.roaming' + wd.wait_for_object_condition(device, condition, 10) + + # Check that iwd is on BSS 1 once out of roaming state and doesn't + # go through 'disconnected', 'autoconnect', 'connecting' in between + condition = 'obj.state != DeviceState.roaming' + wd.wait_for_object_condition(device, condition, 5) + + self.assertEqual(device.state, iwd.DeviceState.connected) + 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) + self.assertRaises(Exception, testutil.test_ifaces_connected, + (self.bss_hostapd[0].ifname, device.name)) + + def tearDown(self): + os.system('ifconfig "' + self.bss_hostapd[0].ifname + '" down') + os.system('ifconfig "' + self.bss_hostapd[1].ifname + '" down') + os.system('ifconfig "' + self.bss_hostapd[0].ifname + '" up') + os.system('ifconfig "' + self.bss_hostapd[1].ifname + '" up') + + hwsim = Hwsim() + wd = IWD() + device = wd.list_devices(1)[0] + try: + device.disconnect() + except: + pass + + condition = 'obj.state == DeviceState.disconnected' + wd.wait_for_object_condition(device, condition) + + for rule in list(hwsim.rules.keys()): + del hwsim.rules[rule] + + @classmethod + def setUpClass(cls): + os.system('ifconfig lo up') + IWD.copy_to_storage('TestFT.8021x') + + hwsim = Hwsim() + + cls.bss_hostapd = [None, None] + cls.bss_radio = [None, None] + for intf in hostapd_map.values(): + 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 == intf.wiphy.name: + break + + cls.bss_hostapd[bss_idx] = HostapdCLI(intf) + cls.bss_radio[bss_idx] = radio + + # Set interface addresses to those expected by hostapd config files + os.system('ifconfig "' + cls.bss_hostapd[0].ifname + + '" down hw ether 12:00:00:00:00:01 up') + os.system('ifconfig "' + cls.bss_hostapd[1].ifname + + '" down hw ether 12:00:00:00:00:02 up') + + cls.bss_hostapd[0].reload() + cls.bss_hostapd[1].reload() + + # 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): + IWD.clear_storage() + +if __name__ == '__main__': + unittest.main(exit=True)