1# Dynamic wpa_supplicant interface 2# Copyright (c) 2013, Jouni Malinen <j@w1.fi> 3# 4# This software may be distributed under the terms of the BSD license. 5# See README for more details. 6 7import logging 8logger = logging.getLogger() 9import subprocess 10import time 11 12import hwsim_utils 13import hostapd 14from wpasupplicant import WpaSupplicant 15 16def test_sta_dynamic(dev, apdev): 17 """Dynamically added wpa_supplicant interface""" 18 params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678") 19 hostapd.add_ap(apdev[0], params) 20 21 logger.info("Create a dynamic wpa_supplicant interface and connect") 22 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 23 wpas.interface_add("wlan5") 24 25 wpas.connect("sta-dynamic", psk="12345678", scan_freq="2412") 26 27def test_sta_ap_scan_0(dev, apdev): 28 """Dynamically added wpa_supplicant interface with AP_SCAN 0 connection""" 29 hostapd.add_ap(apdev[0], {"ssid": "test"}) 30 bssid = apdev[0]['bssid'] 31 32 logger.info("Create a dynamic wpa_supplicant interface and connect") 33 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 34 wpas.interface_add("wlan5") 35 36 if "OK" not in wpas.request("AP_SCAN 0"): 37 raise Exception("Failed to set AP_SCAN 2") 38 39 id = wpas.connect("", key_mgmt="NONE", bssid=bssid, 40 only_add_network=True) 41 wpas.request("ENABLE_NETWORK " + str(id) + " no-connect") 42 wpas.request("SCAN") 43 time.sleep(0.5) 44 subprocess.call(['iw', wpas.ifname, 'connect', 'test', '2412']) 45 wpas.wait_connected(timeout=10) 46 wpas.request("SCAN") 47 wpas.wait_connected(timeout=5) 48 49def test_sta_ap_scan_2(dev, apdev): 50 """Dynamically added wpa_supplicant interface with AP_SCAN 2 connection""" 51 hostapd.add_ap(apdev[0], {"ssid": "test"}) 52 bssid = apdev[0]['bssid'] 53 54 logger.info("Create a dynamic wpa_supplicant interface and connect") 55 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 56 wpas.interface_add("wlan5") 57 58 if "FAIL" not in wpas.request("AP_SCAN -1"): 59 raise Exception("Invalid AP_SCAN -1 accepted") 60 if "FAIL" not in wpas.request("AP_SCAN 3"): 61 raise Exception("Invalid AP_SCAN 3 accepted") 62 if "OK" not in wpas.request("AP_SCAN 2"): 63 raise Exception("Failed to set AP_SCAN 2") 64 65 id = wpas.connect("", key_mgmt="NONE", bssid=bssid, 66 only_add_network=True) 67 wpas.request("ENABLE_NETWORK " + str(id) + " no-connect") 68 subprocess.call(['iw', wpas.ifname, 'scan', 'trigger', 'freq', '2412']) 69 time.sleep(1) 70 subprocess.call(['iw', wpas.ifname, 'connect', 'test', '2412']) 71 wpas.wait_connected(timeout=10) 72 73 wpas.request("SET disallow_aps bssid " + bssid) 74 wpas.wait_disconnected(timeout=10) 75 76 subprocess.call(['iw', wpas.ifname, 'connect', 'test', '2412']) 77 ev = wpas.wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) 78 if ev is not None: 79 raise Exception("Unexpected connection reported") 80 81def test_sta_ap_scan_2b(dev, apdev): 82 """Dynamically added wpa_supplicant interface with AP_SCAN 2 operation""" 83 hapd = hostapd.add_ap(apdev[0], {"ssid": "test"}) 84 bssid = apdev[0]['bssid'] 85 86 logger.info("Create a dynamic wpa_supplicant interface and connect") 87 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 88 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") 89 90 if "OK" not in wpas.request("AP_SCAN 2"): 91 raise Exception("Failed to set AP_SCAN 2") 92 93 id = wpas.connect("test", key_mgmt="NONE", bssid=bssid) 94 wpas.request("DISCONNECT") 95 wpas.set_network(id, "disabled", "1") 96 id2 = wpas.add_network() 97 wpas.set_network_quoted(id2, "ssid", "test2") 98 wpas.set_network(id2, "key_mgmt", "NONE") 99 wpas.set_network(id2, "disabled", "0") 100 wpas.request("REASSOCIATE") 101 ev = wpas.wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=15) 102 if ev is None: 103 raise Exception("Association rejection not reported") 104 hapd.disable() 105 wpas.set_network(id, "disabled", "0") 106 wpas.set_network(id2, "disabled", "1") 107 for i in range(3): 108 ev = wpas.wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=15) 109 if ev is None: 110 raise Exception("Association rejection not reported") 111 wpas.request("DISCONNECT") 112 113def test_sta_dynamic_down_up(dev, apdev): 114 """Dynamically added wpa_supplicant interface down/up""" 115 params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678") 116 hapd = hostapd.add_ap(apdev[0], params) 117 118 logger.info("Create a dynamic wpa_supplicant interface and connect") 119 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 120 wpas.interface_add("wlan5") 121 wpas.connect("sta-dynamic", psk="12345678", scan_freq="2412") 122 hapd.wait_sta() 123 hwsim_utils.test_connectivity(wpas, hapd) 124 subprocess.call(['ifconfig', wpas.ifname, 'down']) 125 wpas.wait_disconnected(timeout=10) 126 if wpas.get_status_field("wpa_state") != "INTERFACE_DISABLED": 127 raise Exception("Unexpected wpa_state") 128 subprocess.call(['ifconfig', wpas.ifname, 'up']) 129 wpas.wait_connected(timeout=15, error="Reconnection not reported") 130 hapd.wait_sta() 131 hwsim_utils.test_connectivity(wpas, hapd) 132 133def test_sta_dynamic_ext_mac_addr_change(dev, apdev): 134 """Dynamically added wpa_supplicant interface with external MAC address change""" 135 params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678") 136 hapd = hostapd.add_ap(apdev[0], params) 137 138 logger.info("Create a dynamic wpa_supplicant interface and connect") 139 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 140 wpas.interface_add("wlan5") 141 wpas.connect("sta-dynamic", psk="12345678", scan_freq="2412") 142 hapd.wait_sta() 143 hwsim_utils.test_connectivity(wpas, hapd) 144 subprocess.call(['ifconfig', wpas.ifname, 'down']) 145 wpas.wait_disconnected(timeout=10) 146 if wpas.get_status_field("wpa_state") != "INTERFACE_DISABLED": 147 raise Exception("Unexpected wpa_state") 148 prev_addr = wpas.p2p_interface_addr() 149 new_addr = '02:11:22:33:44:55' 150 try: 151 subprocess.call(['ip', 'link', 'set', 'dev', wpas.ifname, 152 'address', new_addr]) 153 subprocess.call(['ifconfig', wpas.ifname, 'up']) 154 wpas.wait_connected(timeout=15, error="Reconnection not reported") 155 if wpas.get_driver_status_field('addr') != new_addr: 156 raise Exception("Address change not reported") 157 hapd.wait_sta() 158 hwsim_utils.test_connectivity(wpas, hapd) 159 sta = hapd.get_sta(new_addr) 160 if sta['addr'] != new_addr: 161 raise Exception("STA association with new address not found") 162 finally: 163 subprocess.call(['ifconfig', wpas.ifname, 'down']) 164 subprocess.call(['ip', 'link', 'set', 'dev', wpas.ifname, 165 'address', prev_addr]) 166 subprocess.call(['ifconfig', wpas.ifname, 'up']) 167 168def test_sta_dynamic_ext_mac_addr_change_for_connection(dev, apdev): 169 """Dynamically added wpa_supplicant interface with external MAC address change for connection""" 170 params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678") 171 hapd = hostapd.add_ap(apdev[0], params) 172 bssid = apdev[0]['ifname'] 173 174 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 175 wpas.interface_add("wlan5") 176 wpas.scan_for_bss(bssid, freq=2412) 177 subprocess.call(['ifconfig', wpas.ifname, 'down']) 178 if wpas.get_status_field("wpa_state") != "INTERFACE_DISABLED": 179 raise Exception("Unexpected wpa_state") 180 prev_addr = wpas.own_addr() 181 new_addr = '02:11:22:33:44:55' 182 try: 183 subprocess.call(['ip', 'link', 'set', 'dev', wpas.ifname, 184 'address', new_addr]) 185 subprocess.call(['ifconfig', wpas.ifname, 'up']) 186 wpas.connect("sta-dynamic", psk="12345678", scan_freq="2412", 187 wait_connect=False) 188 ev = wpas.wait_event(["CTRL-EVENT-CONNECTED", 189 "CTRL-EVENT-SCAN-RESULTS"], timeout=10) 190 if "CTRL-EVENT-SCAN-RESULTS" in ev: 191 raise Exception("Unexpected scan after MAC address change") 192 hapd.wait_sta() 193 hwsim_utils.test_connectivity(wpas, hapd) 194 sta = hapd.get_sta(new_addr) 195 if sta['addr'] != new_addr: 196 raise Exception("STA association with new address not found") 197 wpas.request("DISCONNECT") 198 wpas.wait_disconnected() 199 wpas.dump_monitor() 200 subprocess.call(['ifconfig', wpas.ifname, 'down']) 201 time.sleep(0.1) 202 res = wpas.get_bss(bssid) 203 if res is None: 204 raise Exception("BSS entry not maintained after interface disabling") 205 ev = wpas.wait_event(["CTRL-EVENT-BSS-REMOVED"], timeout=5.5) 206 if ev is None: 207 raise Exception("BSS entry not removed after interface has been disabled for a while") 208 res2 = wpas.get_bss(bssid) 209 if res2 is not None: 210 raise Exception("Unexpected BSS entry found on a disabled interface") 211 finally: 212 subprocess.call(['ifconfig', wpas.ifname, 'down']) 213 subprocess.call(['ip', 'link', 'set', 'dev', wpas.ifname, 214 'address', prev_addr]) 215 subprocess.call(['ifconfig', wpas.ifname, 'up']) 216 217def test_sta_dynamic_random_mac_addr(dev, apdev): 218 """Dynamically added wpa_supplicant interface and random MAC address""" 219 params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678") 220 hapd = hostapd.add_ap(apdev[0], params) 221 222 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 223 wpas.interface_add("wlan5") 224 addr0 = wpas.get_driver_status_field("addr") 225 wpas.request("SET preassoc_mac_addr 1") 226 wpas.request("SET rand_addr_lifetime 0") 227 228 id = wpas.connect("sta-dynamic", psk="12345678", mac_addr="1", 229 scan_freq="2412") 230 addr1 = wpas.get_driver_status_field("addr") 231 232 if addr0 == addr1: 233 raise Exception("Random MAC address not used") 234 235 sta = hapd.get_sta(addr0) 236 if sta['addr'] != "FAIL": 237 raise Exception("Unexpected STA association with permanent address") 238 sta = hapd.get_sta(addr1) 239 if sta['addr'] != addr1: 240 raise Exception("STA association with random address not found") 241 242 wpas.request("DISCONNECT") 243 wpas.connect_network(id) 244 addr2 = wpas.get_driver_status_field("addr") 245 if addr1 != addr2: 246 raise Exception("Random MAC address changed unexpectedly") 247 248 wpas.remove_network(id) 249 id = wpas.connect("sta-dynamic", psk="12345678", mac_addr="1", 250 scan_freq="2412") 251 addr2 = wpas.get_driver_status_field("addr") 252 if addr1 == addr2: 253 raise Exception("Random MAC address did not change") 254 255def test_sta_dynamic_random_mac_addr_keep_oui(dev, apdev): 256 """Dynamically added wpa_supplicant interface and random MAC address (keep OUI)""" 257 params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678") 258 hapd = hostapd.add_ap(apdev[0], params) 259 260 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 261 wpas.interface_add("wlan5") 262 addr0 = wpas.get_driver_status_field("addr") 263 wpas.request("SET preassoc_mac_addr 2") 264 wpas.request("SET rand_addr_lifetime 0") 265 266 id = wpas.connect("sta-dynamic", psk="12345678", mac_addr="2", 267 scan_freq="2412") 268 addr1 = wpas.get_driver_status_field("addr") 269 270 if addr0 == addr1: 271 raise Exception("Random MAC address not used") 272 if addr1[3:8] != addr0[3:8]: 273 raise Exception("OUI was not kept") 274 275 sta = hapd.get_sta(addr0) 276 if sta['addr'] != "FAIL": 277 raise Exception("Unexpected STA association with permanent address") 278 sta = hapd.get_sta(addr1) 279 if sta['addr'] != addr1: 280 raise Exception("STA association with random address not found") 281 282 wpas.request("DISCONNECT") 283 wpas.connect_network(id) 284 addr2 = wpas.get_driver_status_field("addr") 285 if addr1 != addr2: 286 raise Exception("Random MAC address changed unexpectedly") 287 288 wpas.remove_network(id) 289 id = wpas.connect("sta-dynamic", psk="12345678", mac_addr="2", 290 scan_freq="2412") 291 addr2 = wpas.get_driver_status_field("addr") 292 if addr1 == addr2: 293 raise Exception("Random MAC address did not change") 294 if addr2[3:8] != addr0[3:8]: 295 raise Exception("OUI was not kept") 296 297def test_sta_dynamic_random_mac_addr_scan(dev, apdev): 298 """Dynamically added wpa_supplicant interface and random MAC address for scan""" 299 params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678") 300 hapd = hostapd.add_ap(apdev[0], params) 301 302 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 303 wpas.interface_add("wlan5") 304 addr0 = wpas.get_driver_status_field("addr") 305 wpas.request("SET preassoc_mac_addr 1") 306 wpas.request("SET rand_addr_lifetime 0") 307 308 id = wpas.connect("sta-dynamic", psk="12345678", scan_freq="2412") 309 addr1 = wpas.get_driver_status_field("addr") 310 311 if addr0 != addr1: 312 raise Exception("Random MAC address used unexpectedly") 313 314def test_sta_dynamic_random_mac_addr_scan_keep_oui(dev, apdev): 315 """Dynamically added wpa_supplicant interface and random MAC address for scan (keep OUI)""" 316 params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678") 317 hapd = hostapd.add_ap(apdev[0], params) 318 319 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 320 wpas.interface_add("wlan5") 321 addr0 = wpas.get_driver_status_field("addr") 322 wpas.request("SET preassoc_mac_addr 2") 323 wpas.request("SET rand_addr_lifetime 0") 324 325 id = wpas.connect("sta-dynamic", psk="12345678", scan_freq="2412") 326 addr1 = wpas.get_driver_status_field("addr") 327 328 if addr0 != addr1: 329 raise Exception("Random MAC address used unexpectedly") 330