1# Test cases for hostapd tracking unconnected stations 2# Copyright (c) 2015, 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 hostapd 13from wpasupplicant import WpaSupplicant 14from utils import parse_ie, disable_hapd, clear_regdom_dev 15 16def test_ap_track_sta(dev, apdev): 17 """Dualband AP tracking unconnected stations""" 18 19 try: 20 params = {"ssid": "track", 21 "country_code": "US", 22 "hw_mode": "g", 23 "channel": "6", 24 "track_sta_max_num": "2"} 25 hapd = hostapd.add_ap(apdev[0], params) 26 27 params = {"ssid": "track", 28 "country_code": "US", 29 "hw_mode": "a", 30 "channel": "40", 31 "track_sta_max_num": "100", 32 "track_sta_max_age": "1"} 33 hapd2 = hostapd.add_ap(apdev[1], params) 34 35 _test_ap_track_sta(dev, hapd, apdev[0]['bssid'], hapd2, 36 apdev[1]['bssid']) 37 finally: 38 disable_hapd(hapd) 39 disable_hapd(hapd2) 40 clear_regdom_dev(dev, 3) 41 42def _test_ap_track_sta(dev, hapd, bssid, hapd2, bssid2): 43 for i in range(2): 44 dev[0].scan_for_bss(bssid, freq=2437, force_scan=True) 45 dev[0].scan_for_bss(bssid2, freq=5200, force_scan=True) 46 dev[1].scan_for_bss(bssid, freq=2437, force_scan=True) 47 dev[2].scan_for_bss(bssid2, freq=5200, force_scan=True) 48 49 addr0 = dev[0].own_addr() 50 addr1 = dev[1].own_addr() 51 addr2 = dev[2].own_addr() 52 53 track = hapd.request("TRACK_STA_LIST") 54 if addr0 not in track or addr1 not in track: 55 raise Exception("Station missing from 2.4 GHz tracking") 56 if addr2 in track: 57 raise Exception("Unexpected station included in 2.4 GHz tracking") 58 59 track = hapd2.request("TRACK_STA_LIST") 60 if addr0 not in track or addr2 not in track: 61 raise Exception("Station missing from 5 GHz tracking") 62 if addr1 in track: 63 raise Exception("Unexpected station included in 5 GHz tracking") 64 65 # Test expiration 66 time.sleep(1.1) 67 track = hapd.request("TRACK_STA_LIST") 68 if addr0 not in track or addr1 not in track: 69 raise Exception("Station missing from 2.4 GHz tracking (expiration)") 70 track = hapd2.request("TRACK_STA_LIST") 71 if addr0 in track or addr2 in track: 72 raise Exception("Station not expired from 5 GHz tracking") 73 74 # Test maximum list length 75 dev[0].scan_for_bss(bssid, freq=2437, force_scan=True) 76 dev[1].scan_for_bss(bssid, freq=2437, force_scan=True) 77 dev[2].scan_for_bss(bssid, freq=2437, force_scan=True) 78 track = hapd.request("TRACK_STA_LIST") 79 if len(track.splitlines()) != 2: 80 raise Exception("Unexpected number of entries: %d" % len(track.splitlines())) 81 if addr1 not in track or addr2 not in track: 82 raise Exception("Station missing from 2.4 GHz tracking (max limit)") 83 84def test_ap_track_sta_no_probe_resp(dev, apdev): 85 """Dualband AP not replying to probes from dualband STA on 2.4 GHz""" 86 try: 87 params = {"ssid": "track", 88 "country_code": "US", 89 "hw_mode": "g", 90 "channel": "6", 91 "beacon_int": "10000", 92 "no_probe_resp_if_seen_on": apdev[1]['ifname']} 93 hapd = hostapd.add_ap(apdev[0], params) 94 95 params = {"ssid": "track", 96 "country_code": "US", 97 "hw_mode": "a", 98 "channel": "40", 99 "track_sta_max_num": "100"} 100 hapd2 = hostapd.add_ap(apdev[1], params) 101 102 _test_ap_track_sta_no_probe_resp(dev, apdev[0]['bssid'], 103 apdev[1]['bssid']) 104 finally: 105 disable_hapd(hapd) 106 disable_hapd(hapd2) 107 clear_regdom_dev(dev, 2) 108 109def _test_ap_track_sta_no_probe_resp(dev, bssid, bssid2): 110 dev[0].flush_scan_cache() 111 112 dev[0].scan_for_bss(bssid2, freq=5200, force_scan=True) 113 dev[1].scan_for_bss(bssid, freq=2437, force_scan=True) 114 dev[0].scan(freq=2437, type="ONLY") 115 dev[0].scan(freq=2437, type="ONLY") 116 117 bss = dev[0].get_bss(bssid) 118 if bss: 119 ie = parse_ie(bss['ie']) 120 # Check whether this is from a Beacon frame (TIM element included) since 121 # it is possible that a Beacon frame was received during the active 122 # scan. This test should fail only if a Probe Response frame was 123 # received. 124 if 5 not in ie: 125 raise Exception("2.4 GHz AP found unexpectedly") 126 127def test_ap_track_sta_no_auth(dev, apdev): 128 """Dualband AP rejecting authentication from dualband STA on 2.4 GHz""" 129 try: 130 params = {"ssid": "track", 131 "country_code": "US", 132 "hw_mode": "g", 133 "channel": "6", 134 "track_sta_max_num": "100", 135 "no_auth_if_seen_on": apdev[1]['ifname']} 136 hapd = hostapd.add_ap(apdev[0], params) 137 138 params = {"ssid": "track", 139 "country_code": "US", 140 "hw_mode": "a", 141 "channel": "40", 142 "track_sta_max_num": "100"} 143 hapd2 = hostapd.add_ap(apdev[1], params) 144 145 _test_ap_track_sta_no_auth(dev, apdev[0]['bssid'], apdev[1]['bssid']) 146 finally: 147 disable_hapd(hapd) 148 disable_hapd(hapd2) 149 clear_regdom_dev(dev, 2) 150 151def _test_ap_track_sta_no_auth(dev, bssid, bssid2): 152 dev[0].scan_for_bss(bssid, freq=2437, force_scan=True) 153 dev[0].scan_for_bss(bssid2, freq=5200, force_scan=True) 154 dev[1].scan_for_bss(bssid, freq=2437, force_scan=True) 155 156 dev[1].connect("track", key_mgmt="NONE", scan_freq="2437") 157 158 dev[0].connect("track", key_mgmt="NONE", scan_freq="2437", 159 freq_list="2437", wait_connect=False) 160 dev[1].request("DISCONNECT") 161 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", 162 "CTRL-EVENT-AUTH-REJECT"], timeout=10) 163 if ev is None: 164 raise Exception("Unknown connection result") 165 if "CTRL-EVENT-CONNECTED" in ev: 166 raise Exception("Unexpected connection") 167 if "status_code=82" not in ev: 168 raise Exception("Unexpected rejection reason: " + ev) 169 if "ie=34" not in ev: 170 raise Exception("No Neighbor Report element: " + ev) 171 dev[0].request("DISCONNECT") 172 173def test_ap_track_sta_no_auth_passive(dev, apdev): 174 """AP rejecting authentication from dualband STA on 2.4 GHz (passive)""" 175 try: 176 params = {"ssid": "track", 177 "country_code": "US", 178 "hw_mode": "g", 179 "channel": "6", 180 "no_auth_if_seen_on": apdev[1]['ifname']} 181 hapd = hostapd.add_ap(apdev[0], params) 182 183 params = {"ssid": "track", 184 "country_code": "US", 185 "hw_mode": "a", 186 "channel": "40", 187 "interworking": "1", 188 "venue_name": "eng:Venue", 189 "track_sta_max_num": "100"} 190 hapd2 = hostapd.add_ap(apdev[1], params) 191 192 _test_ap_track_sta_no_auth_passive(dev, apdev[0]['bssid'], 193 apdev[1]['bssid']) 194 finally: 195 disable_hapd(hapd) 196 disable_hapd(hapd2) 197 clear_regdom_dev(dev) 198 199def _test_ap_track_sta_no_auth_passive(dev, bssid, bssid2): 200 dev[0].flush_scan_cache() 201 202 dev[0].scan_for_bss(bssid, freq=2437, force_scan=True) 203 for i in range(10): 204 dev[0].request("SCAN freq=5200 passive=1") 205 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=5) 206 if ev is None: 207 raise Exception("Scan did not complete") 208 if dev[0].get_bss(bssid2): 209 break 210 if i == 9: 211 raise Exception("AP not found with passive scans") 212 213 if "OK" not in dev[0].request("ANQP_GET " + bssid2 + " 258"): 214 raise Exception("ANQP_GET command failed") 215 ev = dev[0].wait_event(["RX-ANQP"], timeout=1) 216 if ev is None or "Venue Name" not in ev: 217 raise Exception("Did not receive Venue Name") 218 219 dev[0].connect("track", key_mgmt="NONE", scan_freq="2437", 220 freq_list="2437", wait_connect=False) 221 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", 222 "CTRL-EVENT-AUTH-REJECT"], timeout=10) 223 if ev is None: 224 raise Exception("Unknown connection result") 225 if "CTRL-EVENT-CONNECTED" in ev: 226 raise Exception("Unexpected connection") 227 if "status_code=82" not in ev: 228 raise Exception("Unexpected rejection reason: " + ev) 229 dev[0].request("DISCONNECT") 230 231def test_ap_track_sta_force_5ghz(dev, apdev): 232 """Dualband AP forcing dualband STA to connect on 5 GHz""" 233 try: 234 params = {"ssid": "track", 235 "country_code": "US", 236 "hw_mode": "g", 237 "channel": "6", 238 "no_probe_resp_if_seen_on": apdev[1]['ifname'], 239 "no_auth_if_seen_on": apdev[1]['ifname']} 240 hapd = hostapd.add_ap(apdev[0], params) 241 242 params = {"ssid": "track", 243 "country_code": "US", 244 "hw_mode": "a", 245 "channel": "40", 246 "track_sta_max_num": "100"} 247 hapd2 = hostapd.add_ap(apdev[1], params) 248 249 _test_ap_track_sta_force_5ghz(dev, apdev[0]['bssid'], apdev[1]['bssid']) 250 finally: 251 disable_hapd(hapd) 252 disable_hapd(hapd2) 253 clear_regdom_dev(dev) 254 255def _test_ap_track_sta_force_5ghz(dev, bssid, bssid2): 256 dev[0].scan_for_bss(bssid, freq=2437, force_scan=True) 257 dev[0].scan_for_bss(bssid2, freq=5200, force_scan=True) 258 259 dev[0].connect("track", key_mgmt="NONE", scan_freq="2437 5200") 260 freq = dev[0].get_status_field('freq') 261 if freq != '5200': 262 raise Exception("Unexpected operating channel") 263 dev[0].request("DISCONNECT") 264 265def test_ap_track_sta_force_2ghz(dev, apdev): 266 """Dualband AP forcing dualband STA to connect on 2.4 GHz""" 267 try: 268 params = {"ssid": "track", 269 "country_code": "US", 270 "hw_mode": "g", 271 "channel": "6", 272 "track_sta_max_num": "100"} 273 hapd = hostapd.add_ap(apdev[0], params) 274 275 params = {"ssid": "track", 276 "country_code": "US", 277 "hw_mode": "a", 278 "channel": "40", 279 "no_probe_resp_if_seen_on": apdev[0]['ifname'], 280 "no_auth_if_seen_on": apdev[0]['ifname']} 281 hapd2 = hostapd.add_ap(apdev[1], params) 282 283 _test_ap_track_sta_force_2ghz(dev, apdev[0]['bssid'], apdev[1]['bssid']) 284 finally: 285 disable_hapd(hapd) 286 disable_hapd(hapd2) 287 clear_regdom_dev(dev) 288 289def _test_ap_track_sta_force_2ghz(dev, bssid, bssid2): 290 dev[0].scan_for_bss(bssid2, freq=5200, force_scan=True) 291 dev[0].scan_for_bss(bssid, freq=2437, force_scan=True) 292 293 dev[0].connect("track", key_mgmt="NONE", scan_freq="2437 5200") 294 freq = dev[0].get_status_field('freq') 295 if freq != '2437': 296 raise Exception("Unexpected operating channel") 297 dev[0].request("DISCONNECT") 298 299def test_ap_track_taxonomy(dev, apdev): 300 """AP tracking STA taxonomy""" 301 try: 302 _test_ap_track_taxonomy(dev, apdev) 303 finally: 304 dev[1].request("SET p2p_disabled 0") 305 subprocess.call(['iw', 'reg', 'set', '00']) 306 dev[0].flush_scan_cache() 307 dev[1].flush_scan_cache() 308 dev[2].flush_scan_cache() 309 310def _test_ap_track_taxonomy(dev, apdev): 311 params = {"ssid": "track", 312 "country_code": "US", 313 "hw_mode": "g", 314 "channel": "6", 315 "track_sta_max_num": "2"} 316 hapd = hostapd.add_ap(apdev[0], params) 317 bssid = apdev[0]['bssid'] 318 319 dev[0].scan_for_bss(bssid, freq=2437, force_scan=True) 320 addr0 = dev[0].own_addr() 321 dev[0].connect("track", key_mgmt="NONE", scan_freq="2437") 322 323 dev[1].request("SET p2p_disabled 1") 324 dev[1].scan_for_bss(bssid, freq=2437, force_scan=True) 325 addr1 = dev[1].own_addr() 326 dev[1].connect("track", key_mgmt="NONE", scan_freq="2437") 327 328 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 329 wpas.interface_add("wlan5") 330 wpas.request("SET model_name track test") 331 wpas.scan_for_bss(bssid, freq=2437, force_scan=True) 332 addr = wpas.own_addr() 333 wpas.connect("track", key_mgmt="NONE", scan_freq="2437") 334 335 if "FAIL" not in hapd.request("SIGNATURE abc"): 336 raise Exception("SIGNATURE failure not reported (1)") 337 if "FAIL" not in hapd.request("SIGNATURE 22:33:44:55:66:77"): 338 raise Exception("SIGNATURE failure not reported (2)") 339 340 res = hapd.request("SIGNATURE " + addr0) 341 logger.info("sta0: " + res) 342 if not res.startswith("wifi4|probe:"): 343 raise Exception("Unexpected SIGNATURE prefix") 344 if "|assoc:" not in res: 345 raise Exception("Missing assoc info in SIGNATURE") 346 if "wps:track_test" in res: 347 raise Exception("Unexpected WPS model name") 348 349 res = hapd.request("SIGNATURE " + addr1) 350 logger.info("sta1: " + res) 351 if not res.startswith("wifi4|probe:"): 352 raise Exception("Unexpected SIGNATURE prefix") 353 if "|assoc:" not in res: 354 raise Exception("Missing assoc info in SIGNATURE") 355 if "wps:" in res: 356 raise Exception("Unexpected WPS info") 357 if ",221(0050f2,4)," in res: 358 raise Exception("Unexpected WPS IE info") 359 if ",221(506f9a,9)," in res: 360 raise Exception("Unexpected P2P IE info") 361 362 res = hapd.request("SIGNATURE " + addr) 363 logger.info("sta: " + res) 364 if not res.startswith("wifi4|probe:"): 365 raise Exception("Unexpected SIGNATURE prefix") 366 if "|assoc:" not in res: 367 raise Exception("Missing assoc info in SIGNATURE") 368 if "wps:track_test" not in res: 369 raise Exception("Missing WPS model name") 370 if ",221(0050f2,4)," not in res: 371 raise Exception("Missing WPS IE info") 372 if ",221(506f9a,9)," not in res: 373 raise Exception("Missing P2P IE info") 374 375 addr2 = dev[2].own_addr() 376 res = hapd.request("SIGNATURE " + addr2) 377 if "FAIL" not in res: 378 raise Exception("Unexpected SIGNATURE success for sta2 (1)") 379 380 for i in range(10): 381 dev[2].request("SCAN freq=2437 passive=1") 382 ev = dev[2].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10) 383 if ev is None: 384 raise Exception("Scan did not complete") 385 if dev[2].get_bss(bssid): 386 break 387 388 res = hapd.request("SIGNATURE " + addr2) 389 if "FAIL" not in res: 390 raise Exception("Unexpected SIGNATURE success for sta2 (2)") 391 392 dev[2].connect("track", key_mgmt="NONE", scan_freq="2437") 393 394 res = hapd.request("SIGNATURE " + addr2) 395 if "FAIL" not in res and len(res) > 0: 396 raise Exception("Unexpected SIGNATURE success for sta2 (3)") 397 398 dev[2].scan_for_bss(bssid, freq=2437, force_scan=True) 399 400 res = hapd.request("SIGNATURE " + addr2) 401 logger.info("sta2: " + res) 402 if not res.startswith("wifi4|probe:"): 403 raise Exception("Unexpected SIGNATURE prefix") 404 if "|assoc:" not in res: 405 raise Exception("Missing assoc info in SIGNATURE") 406 407def test_ap_track_taxonomy_5g(dev, apdev): 408 """AP tracking STA taxonomy (5 GHz)""" 409 try: 410 _test_ap_track_taxonomy_5g(dev, apdev) 411 finally: 412 subprocess.call(['iw', 'reg', 'set', '00']) 413 dev[0].flush_scan_cache() 414 415def _test_ap_track_taxonomy_5g(dev, apdev): 416 params = {"ssid": "track", 417 "country_code": "US", 418 "hw_mode": "a", 419 "channel": "40", 420 "track_sta_max_num": "2"} 421 hapd = hostapd.add_ap(apdev[0], params) 422 bssid = apdev[0]['bssid'] 423 424 dev[0].scan_for_bss(bssid, freq=5200, force_scan=True) 425 addr0 = dev[0].own_addr() 426 dev[0].connect("track", key_mgmt="NONE", scan_freq="5200") 427 428 res = hapd.request("SIGNATURE " + addr0) 429 logger.info("sta0: " + res) 430 if not res.startswith("wifi4|probe:"): 431 raise Exception("Unexpected SIGNATURE prefix") 432 if "|assoc:" not in res: 433 raise Exception("Missing assoc info in SIGNATURE") 434 if ",htcap:" not in res: 435 raise Exception("Missing HT info in SIGNATURE") 436 if ",vhtcap:" not in res: 437 raise Exception("Missing VHT info in SIGNATURE") 438