]> git.ipfire.org Git - thirdparty/hostap.git/blame - tests/hwsim/test_scan.py
tests: Make scan_bss_expiration_count more robust with UML
[thirdparty/hostap.git] / tests / hwsim / test_scan.py
CommitLineData
cf9189b9 1# Scanning tests
27b69833 2# Copyright (c) 2013-2016, Jouni Malinen <j@w1.fi>
cf9189b9
JM
3#
4# This software may be distributed under the terms of the BSD license.
5# See README for more details.
6
9fd6804d 7from remotehost import remote_compatible
586826d4 8import binascii
cf9189b9
JM
9import time
10import logging
11logger = logging.getLogger()
24e330f7 12import os
586826d4 13import struct
e766f566 14import subprocess
cf9189b9
JM
15
16import hostapd
5e29a900 17from wpasupplicant import WpaSupplicant
58bd7dc3 18from utils import HwsimSkip, fail_test, alloc_fail, wait_fail_trigger, parse_ie
9a1046a7 19from utils import clear_regdom_dev
2e1d7386 20from tshark import run_tshark
27b69833 21from test_ap_csa import switch_channel, wait_channel_switch, csa_supported
cf9189b9 22
9446f3c2 23def check_scan(dev, params, other_started=False, test_busy=False):
e766f566
JM
24 if not other_started:
25 dev.dump_monitor()
cf9189b9
JM
26 id = dev.request("SCAN " + params)
27 if "FAIL" in id:
28 raise Exception("Failed to start scan")
29 id = int(id)
30
9446f3c2
JM
31 if test_busy:
32 if "FAIL-BUSY" not in dev.request("SCAN"):
33 raise Exception("SCAN command while already scanning not rejected")
34
e766f566
JM
35 if other_started:
36 ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"])
37 if ev is None:
38 raise Exception("Other scan did not start")
39 if "id=" + str(id) in ev:
40 raise Exception("Own scan id unexpectedly included in start event")
41
42 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"])
43 if ev is None:
44 raise Exception("Other scan did not complete")
45 if "id=" + str(id) in ev:
46 raise Exception("Own scan id unexpectedly included in completed event")
47
cf9189b9
JM
48 ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"])
49 if ev is None:
50 raise Exception("Scan did not start")
51 if "id=" + str(id) not in ev:
52 raise Exception("Scan id not included in start event")
9446f3c2
JM
53 if test_busy:
54 if "FAIL-BUSY" not in dev.request("SCAN"):
55 raise Exception("SCAN command while already scanning not rejected")
cf9189b9
JM
56
57 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"])
58 if ev is None:
59 raise Exception("Scan did not complete")
60 if "id=" + str(id) not in ev:
61 raise Exception("Scan id not included in completed event")
62
814f7ac8
JM
63def check_scan_retry(dev, params, bssid):
64 for i in range(0, 5):
65 check_scan(dev, "freq=2412-2462,5180 use_id=1")
66 if int(dev.get_bss(bssid)['age']) <= 1:
67 return
68 raise Exception("Unexpectedly old BSS entry")
69
9fd6804d 70@remote_compatible
cf9189b9
JM
71def test_scan(dev, apdev):
72 """Control interface behavior on scan parameters"""
fab49f61 73 hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
cf9189b9
JM
74 bssid = apdev[0]['bssid']
75
76 logger.info("Full scan")
9446f3c2 77 check_scan(dev[0], "use_id=1", test_busy=True)
cf9189b9
JM
78
79 logger.info("Limited channel scan")
814f7ac8 80 check_scan_retry(dev[0], "freq=2412-2462,5180 use_id=1", bssid)
cf9189b9
JM
81
82 # wait long enough to allow next scans to be verified not to find the AP
83 time.sleep(2)
84
85 logger.info("Passive single-channel scan")
86 check_scan(dev[0], "freq=2457 passive=1 use_id=1")
87 logger.info("Active single-channel scan")
88 check_scan(dev[0], "freq=2452 passive=0 use_id=1")
89 if int(dev[0].get_bss(bssid)['age']) < 2:
90 raise Exception("Unexpectedly updated BSS entry")
91
92 logger.info("Active single-channel scan on AP's operating channel")
814f7ac8 93 check_scan_retry(dev[0], "freq=2412 passive=0 use_id=1", bssid)
cf9189b9 94
9fd6804d 95@remote_compatible
76de2b67
JM
96def test_scan_tsf(dev, apdev):
97 """Scan and TSF updates from Beacon/Probe Response frames"""
fab49f61
JM
98 hostapd.add_ap(apdev[0], {"ssid": "test-scan",
99 'beacon_int': "100"})
76de2b67
JM
100 bssid = apdev[0]['bssid']
101
102 tsf = []
fab49f61 103 for passive in [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1]:
76de2b67
JM
104 check_scan(dev[0], "freq=2412 passive=%d use_id=1" % passive)
105 bss = dev[0].get_bss(bssid)
106 if bss:
107 tsf.append(int(bss['tsf']))
108 logger.info("TSF: " + bss['tsf'])
109 if tsf[-3] <= tsf[-4]:
110 # For now, only write this in the log without failing the test case
111 # since mac80211_hwsim does not yet update the Timestamp field in
112 # Probe Response frames.
113 logger.info("Probe Response did not update TSF")
114 #raise Exception("Probe Response did not update TSF")
115 if tsf[-1] <= tsf[-3]:
116 raise Exception("Beacon did not update TSF")
117 if 0 in tsf:
118 raise Exception("0 TSF reported")
119
9fd6804d 120@remote_compatible
cf9189b9
JM
121def test_scan_only(dev, apdev):
122 """Control interface behavior on scan parameters with type=only"""
fab49f61 123 hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
cf9189b9
JM
124 bssid = apdev[0]['bssid']
125
126 logger.info("Full scan")
127 check_scan(dev[0], "type=only use_id=1")
128
129 logger.info("Limited channel scan")
814f7ac8 130 check_scan_retry(dev[0], "type=only freq=2412-2462,5180 use_id=1", bssid)
cf9189b9
JM
131
132 # wait long enough to allow next scans to be verified not to find the AP
133 time.sleep(2)
134
135 logger.info("Passive single-channel scan")
136 check_scan(dev[0], "type=only freq=2457 passive=1 use_id=1")
137 logger.info("Active single-channel scan")
138 check_scan(dev[0], "type=only freq=2452 passive=0 use_id=1")
139 if int(dev[0].get_bss(bssid)['age']) < 2:
140 raise Exception("Unexpectedly updated BSS entry")
141
142 logger.info("Active single-channel scan on AP's operating channel")
814f7ac8 143 check_scan_retry(dev[0], "type=only freq=2412 passive=0 use_id=1", bssid)
e766f566 144
9fd6804d 145@remote_compatible
e766f566
JM
146def test_scan_external_trigger(dev, apdev):
147 """Avoid operations during externally triggered scan"""
fab49f61 148 hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
e766f566 149 bssid = apdev[0]['bssid']
2d588c65 150 dev[0].cmd_execute(['iw', dev[0].ifname, 'scan', 'trigger'])
e766f566 151 check_scan(dev[0], "use_id=1", other_started=True)
b3ec107c
JM
152
153def test_scan_bss_expiration_count(dev, apdev):
154 """BSS entry expiration based on scan results without match"""
155 if "FAIL" not in dev[0].request("BSS_EXPIRE_COUNT 0"):
156 raise Exception("Invalid BSS_EXPIRE_COUNT accepted")
157 if "OK" not in dev[0].request("BSS_EXPIRE_COUNT 2"):
158 raise Exception("BSS_EXPIRE_COUNT failed")
fab49f61 159 hapd = hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
b3ec107c
JM
160 bssid = apdev[0]['bssid']
161 dev[0].scan(freq="2412", only_new=True)
162 if bssid not in dev[0].request("SCAN_RESULTS"):
163 raise Exception("BSS not found in initial scan")
164 hapd.request("DISABLE")
ac069a31
JM
165 # Try to give enough time for hostapd to have stopped mac80211 from
166 # beaconing before checking a new scan. This is needed with UML time travel
167 # testing.
168 hapd.ping()
169 time.sleep(0.2)
b3ec107c
JM
170 dev[0].scan(freq="2412", only_new=True)
171 if bssid not in dev[0].request("SCAN_RESULTS"):
172 raise Exception("BSS not found in first scan without match")
173 dev[0].scan(freq="2412", only_new=True)
174 if bssid in dev[0].request("SCAN_RESULTS"):
175 raise Exception("BSS found after two scans without match")
176
9fd6804d 177@remote_compatible
b3ec107c
JM
178def test_scan_bss_expiration_age(dev, apdev):
179 """BSS entry expiration based on age"""
180 try:
181 if "FAIL" not in dev[0].request("BSS_EXPIRE_AGE COUNT 9"):
182 raise Exception("Invalid BSS_EXPIRE_AGE accepted")
183 if "OK" not in dev[0].request("BSS_EXPIRE_AGE 10"):
184 raise Exception("BSS_EXPIRE_AGE failed")
fab49f61 185 hapd = hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
b3ec107c 186 bssid = apdev[0]['bssid']
96425ea5
JM
187 # Allow couple more retries to avoid reporting errors during heavy load
188 for i in range(5):
189 dev[0].scan(freq="2412")
190 if bssid in dev[0].request("SCAN_RESULTS"):
191 break
b3ec107c
JM
192 if bssid not in dev[0].request("SCAN_RESULTS"):
193 raise Exception("BSS not found in initial scan")
194 hapd.request("DISABLE")
195 logger.info("Waiting for BSS entry to expire")
196 time.sleep(7)
197 if bssid not in dev[0].request("SCAN_RESULTS"):
198 raise Exception("BSS expired too quickly")
199 ev = dev[0].wait_event(["CTRL-EVENT-BSS-REMOVED"], timeout=15)
200 if ev is None:
201 raise Exception("BSS entry expiration timed out")
202 if bssid in dev[0].request("SCAN_RESULTS"):
203 raise Exception("BSS not removed after expiration time")
204 finally:
205 dev[0].request("BSS_EXPIRE_AGE 180")
167d8497 206
9fd6804d 207@remote_compatible
167d8497
JM
208def test_scan_filter(dev, apdev):
209 """Filter scan results based on SSID"""
210 try:
211 if "OK" not in dev[0].request("SET filter_ssids 1"):
212 raise Exception("SET failed")
7749b1c9 213 id = dev[0].connect("test-scan", key_mgmt="NONE", only_add_network=True)
fab49f61 214 hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
167d8497 215 bssid = apdev[0]['bssid']
fab49f61 216 hostapd.add_ap(apdev[1], {"ssid": "test-scan2"})
167d8497
JM
217 bssid2 = apdev[1]['bssid']
218 dev[0].scan(freq="2412", only_new=True)
219 if bssid not in dev[0].request("SCAN_RESULTS"):
220 raise Exception("BSS not found in scan results")
221 if bssid2 in dev[0].request("SCAN_RESULTS"):
222 raise Exception("Unexpected BSS found in scan results")
7749b1c9
JM
223 dev[0].set_network_quoted(id, "ssid", "")
224 dev[0].scan(freq="2412")
225 id2 = dev[0].connect("test", key_mgmt="NONE", only_add_network=True)
226 dev[0].scan(freq="2412")
167d8497
JM
227 finally:
228 dev[0].request("SET filter_ssids 0")
24e330f7 229
9fd6804d 230@remote_compatible
24e330f7
JM
231def test_scan_int(dev, apdev):
232 """scan interval configuration"""
233 try:
234 if "FAIL" not in dev[0].request("SCAN_INTERVAL -1"):
235 raise Exception("Accepted invalid scan interval")
236 if "OK" not in dev[0].request("SCAN_INTERVAL 1"):
237 raise Exception("Failed to set scan interval")
238 dev[0].connect("not-used", key_mgmt="NONE", scan_freq="2412",
239 wait_connect=False)
240 times = {}
241 for i in range(0, 3):
242 logger.info("Waiting for scan to start")
243 start = os.times()[4]
244 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
245 if ev is None:
246 raise Exception("did not start a scan")
247 stop = os.times()[4]
248 times[i] = stop - start
249 logger.info("Waiting for scan to complete")
250 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
251 if ev is None:
252 raise Exception("did not complete a scan")
2e0d48e5 253 logger.info("times=" + str(times))
24e330f7
JM
254 if times[0] > 1 or times[1] < 0.5 or times[1] > 1.5 or times[2] < 0.5 or times[2] > 1.5:
255 raise Exception("Unexpected scan timing: " + str(times))
256 finally:
257 dev[0].request("SCAN_INTERVAL 5")
59650258
JM
258
259def test_scan_bss_operations(dev, apdev):
260 """Control interface behavior on BSS parameters"""
fab49f61 261 hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
59650258 262 bssid = apdev[0]['bssid']
fab49f61 263 hostapd.add_ap(apdev[1], {"ssid": "test2-scan"})
59650258
JM
264 bssid2 = apdev[1]['bssid']
265
266 dev[0].scan(freq="2412")
267 dev[0].scan(freq="2412")
268 dev[0].scan(freq="2412")
269
cb4ac38b
JM
270 id1 = dev[0].request("BSS FIRST MASK=0x1").splitlines()[0].split('=')[1]
271 id2 = dev[0].request("BSS LAST MASK=0x1").splitlines()[0].split('=')[1]
272
59650258 273 res = dev[0].request("BSS RANGE=ALL MASK=0x20001")
cb4ac38b
JM
274 if "id=" + id1 not in res:
275 raise Exception("Missing BSS " + id1)
276 if "id=" + id2 not in res:
277 raise Exception("Missing BSS " + id2)
59650258
JM
278 if "====" not in res:
279 raise Exception("Missing delim")
280 if "####" not in res:
281 raise Exception("Missing end")
282
5b2f1e24
JM
283 res = dev[0].request("BSS RANGE=ALL MASK=0")
284 if "id=" + id1 not in res:
285 raise Exception("Missing BSS " + id1)
286 if "id=" + id2 not in res:
287 raise Exception("Missing BSS " + id2)
288 if "====" in res:
289 raise Exception("Unexpected delim")
290 if "####" in res:
291 raise Exception("Unexpected end delim")
292
59650258
JM
293 res = dev[0].request("BSS RANGE=ALL MASK=0x1").splitlines()
294 if len(res) != 2:
610cfff5 295 raise Exception("Unexpected result: " + str(res))
59650258 296 res = dev[0].request("BSS FIRST MASK=0x1")
cb4ac38b 297 if "id=" + id1 not in res:
59650258
JM
298 raise Exception("Unexpected result: " + res)
299 res = dev[0].request("BSS LAST MASK=0x1")
cb4ac38b 300 if "id=" + id2 not in res:
59650258 301 raise Exception("Unexpected result: " + res)
cb4ac38b
JM
302 res = dev[0].request("BSS ID-" + id1 + " MASK=0x1")
303 if "id=" + id1 not in res:
59650258 304 raise Exception("Unexpected result: " + res)
cb4ac38b
JM
305 res = dev[0].request("BSS NEXT-" + id1 + " MASK=0x1")
306 if "id=" + id2 not in res:
59650258 307 raise Exception("Unexpected result: " + res)
5b2f1e24
JM
308 res = dev[0].request("BSS NEXT-" + id2 + " MASK=0x1")
309 if "id=" in res:
310 raise Exception("Unexpected result: " + res)
59650258 311
cb4ac38b 312 if len(dev[0].request("BSS RANGE=" + id2 + " MASK=0x1").splitlines()) != 0:
59650258 313 raise Exception("Unexpected RANGE=1 result")
cb4ac38b 314 if len(dev[0].request("BSS RANGE=" + id1 + "- MASK=0x1").splitlines()) != 2:
59650258 315 raise Exception("Unexpected RANGE=0- result")
cb4ac38b 316 if len(dev[0].request("BSS RANGE=-" + id2 + " MASK=0x1").splitlines()) != 2:
59650258 317 raise Exception("Unexpected RANGE=-1 result")
cb4ac38b 318 if len(dev[0].request("BSS RANGE=" + id1 + "-" + id2 + " MASK=0x1").splitlines()) != 2:
59650258 319 raise Exception("Unexpected RANGE=0-1 result")
cb4ac38b 320 if len(dev[0].request("BSS RANGE=" + id2 + "-" + id2 + " MASK=0x1").splitlines()) != 1:
59650258 321 raise Exception("Unexpected RANGE=1-1 result")
cb4ac38b 322 if len(dev[0].request("BSS RANGE=" + str(int(id2) + 1) + "-" + str(int(id2) + 10) + " MASK=0x1").splitlines()) != 0:
59650258 323 raise Exception("Unexpected RANGE=2-10 result")
cb4ac38b 324 if len(dev[0].request("BSS RANGE=0-" + str(int(id2) + 10) + " MASK=0x1").splitlines()) != 2:
59650258 325 raise Exception("Unexpected RANGE=0-10 result")
5b2f1e24
JM
326 if len(dev[0].request("BSS RANGE=" + id1 + "-" + id1 + " MASK=0x1").splitlines()) != 1:
327 raise Exception("Unexpected RANGE=0-0 result")
328
329 res = dev[0].request("BSS p2p_dev_addr=FOO")
330 if "FAIL" in res or "id=" in res:
331 raise Exception("Unexpected result: " + res)
332 res = dev[0].request("BSS p2p_dev_addr=00:11:22:33:44:55")
333 if "FAIL" in res or "id=" in res:
334 raise Exception("Unexpected result: " + res)
335
336 dev[0].request("BSS_FLUSH 1000")
337 res = dev[0].request("BSS RANGE=ALL MASK=0x1").splitlines()
338 if len(res) != 2:
339 raise Exception("Unexpected result after BSS_FLUSH 1000")
340 dev[0].request("BSS_FLUSH 0")
341 res = dev[0].request("BSS RANGE=ALL MASK=0x1").splitlines()
342 if len(res) != 0:
343 raise Exception("Unexpected result after BSS_FLUSH 0")
23a6d4d8 344
9fd6804d 345@remote_compatible
23a6d4d8
JM
346def test_scan_and_interface_disabled(dev, apdev):
347 """Scan operation when interface gets disabled"""
348 try:
349 dev[0].request("SCAN")
350 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"])
351 if ev is None:
352 raise Exception("Scan did not start")
353 dev[0].request("DRIVER_EVENT INTERFACE_DISABLED")
354 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=7)
355 if ev is not None:
356 raise Exception("Scan completed unexpectedly")
357
358 # verify that scan is rejected
359 if "FAIL" not in dev[0].request("SCAN"):
360 raise Exception("New scan request was accepted unexpectedly")
361
362 dev[0].request("DRIVER_EVENT INTERFACE_ENABLED")
363 dev[0].scan(freq="2412")
364 finally:
365 dev[0].request("DRIVER_EVENT INTERFACE_ENABLED")
cf2f3698 366
9fd6804d 367@remote_compatible
cf2f3698
JM
368def test_scan_for_auth(dev, apdev):
369 """cfg80211 workaround with scan-for-auth"""
fab49f61 370 hapd = hostapd.add_ap(apdev[0], {"ssid": "open"})
cf2f3698
JM
371 dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
372 # Block sme-connect radio work with an external radio work item, so that
373 # SELECT_NETWORK can decide to use fast associate without a new scan while
374 # cfg80211 still has the matching BSS entry, but the actual connection is
375 # not yet started.
376 id = dev[0].request("RADIO_WORK add block-work")
377 ev = dev[0].wait_event(["EXT-RADIO-WORK-START"])
378 if ev is None:
379 raise Exception("Timeout while waiting radio work to start")
380 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
381 wait_connect=False)
c7f35a9e 382 dev[0].dump_monitor()
cf2f3698 383 # Clear cfg80211 BSS table.
2d588c65
JA
384 res, data = dev[0].cmd_execute(['iw', dev[0].ifname, 'scan', 'trigger',
385 'freq', '2457', 'flush'])
386 if res != 0:
a4a15cf1 387 raise HwsimSkip("iw scan trigger flush not supported")
c7f35a9e
JM
388 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
389 if ev is None:
390 raise Exception("External flush scan timed out")
cf2f3698
JM
391 # Release blocking radio work to allow connection to go through with the
392 # cfg80211 BSS entry missing.
393 dev[0].request("RADIO_WORK done " + id)
394
5f35a5e2 395 dev[0].wait_connected(timeout=15)
e8e571d7 396
9fd6804d 397@remote_compatible
a5687274
JM
398def test_scan_for_auth_fail(dev, apdev):
399 """cfg80211 workaround with scan-for-auth failing"""
fab49f61 400 hapd = hostapd.add_ap(apdev[0], {"ssid": "open"})
a5687274
JM
401 dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
402 # Block sme-connect radio work with an external radio work item, so that
403 # SELECT_NETWORK can decide to use fast associate without a new scan while
404 # cfg80211 still has the matching BSS entry, but the actual connection is
405 # not yet started.
406 id = dev[0].request("RADIO_WORK add block-work")
407 ev = dev[0].wait_event(["EXT-RADIO-WORK-START"])
408 if ev is None:
409 raise Exception("Timeout while waiting radio work to start")
410 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
411 wait_connect=False)
412 dev[0].dump_monitor()
413 hapd.disable()
414 # Clear cfg80211 BSS table.
2d588c65
JA
415 res, data = dev[0].cmd_execute(['iw', dev[0].ifname, 'scan', 'trigger',
416 'freq', '2457', 'flush'])
417 if res != 0:
a4a15cf1 418 raise HwsimSkip("iw scan trigger flush not supported")
a5687274
JM
419 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
420 if ev is None:
421 raise Exception("External flush scan timed out")
422 # Release blocking radio work to allow connection to go through with the
423 # cfg80211 BSS entry missing.
424 dev[0].request("RADIO_WORK done " + id)
425
426 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS",
427 "CTRL-EVENT-CONNECTED"], 15)
428 if ev is None:
429 raise Exception("Scan event missing")
430 if "CTRL-EVENT-CONNECTED" in ev:
431 raise Exception("Unexpected connection")
432 dev[0].request("DISCONNECT")
433
9fd6804d 434@remote_compatible
1e752829
JM
435def test_scan_for_auth_wep(dev, apdev):
436 """cfg80211 scan-for-auth workaround with WEP keys"""
437 dev[0].flush_scan_cache()
8b8a1864 438 hapd = hostapd.add_ap(apdev[0],
fab49f61
JM
439 {"ssid": "wep", "wep_key0": '"abcde"',
440 "auth_algs": "2"})
1e752829
JM
441 dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
442 # Block sme-connect radio work with an external radio work item, so that
443 # SELECT_NETWORK can decide to use fast associate without a new scan while
444 # cfg80211 still has the matching BSS entry, but the actual connection is
445 # not yet started.
446 id = dev[0].request("RADIO_WORK add block-work")
447 ev = dev[0].wait_event(["EXT-RADIO-WORK-START"])
448 if ev is None:
449 raise Exception("Timeout while waiting radio work to start")
450 dev[0].connect("wep", key_mgmt="NONE", wep_key0='"abcde"',
451 auth_alg="SHARED", scan_freq="2412", wait_connect=False)
452 dev[0].dump_monitor()
453 # Clear cfg80211 BSS table.
2d588c65
JA
454 res, data = dev[0].cmd_execute(['iw', dev[0].ifname, 'scan', 'trigger',
455 'freq', '2457', 'flush'])
456 if res != 0:
a4a15cf1 457 raise HwsimSkip("iw scan trigger flush not supported")
1e752829
JM
458 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
459 if ev is None:
460 raise Exception("External flush scan timed out")
461 # Release blocking radio work to allow connection to go through with the
462 # cfg80211 BSS entry missing.
463 dev[0].request("RADIO_WORK done " + id)
464
465 dev[0].wait_connected(timeout=15)
466
9fd6804d 467@remote_compatible
e8e571d7
JM
468def test_scan_hidden(dev, apdev):
469 """Control interface behavior on scan parameters"""
fab49f61
JM
470 hapd = hostapd.add_ap(apdev[0], {"ssid": "test-scan",
471 "ignore_broadcast_ssid": "1"})
e8e571d7
JM
472 bssid = apdev[0]['bssid']
473
474 check_scan(dev[0], "freq=2412 use_id=1")
475 if "test-scan" in dev[0].request("SCAN_RESULTS"):
476 raise Exception("BSS unexpectedly found in initial scan")
477
478 id1 = dev[0].connect("foo", key_mgmt="NONE", scan_ssid="1",
479 only_add_network=True)
480 id2 = dev[0].connect("test-scan", key_mgmt="NONE", scan_ssid="1",
481 only_add_network=True)
482 id3 = dev[0].connect("bar", key_mgmt="NONE", only_add_network=True)
483
484 check_scan(dev[0], "freq=2412 use_id=1")
485 if "test-scan" in dev[0].request("SCAN_RESULTS"):
486 raise Exception("BSS unexpectedly found in scan")
487
29bac7cb
JM
488 # Allow multiple attempts to be more robust under heavy CPU load that can
489 # result in Probe Response frames getting sent only after the station has
490 # already stopped waiting for the response on the channel.
491 found = False
492 for i in range(10):
493 check_scan(dev[0], "scan_id=%d,%d,%d freq=2412 use_id=1" % (id1, id2, id3))
494 if "test-scan" in dev[0].request("SCAN_RESULTS"):
495 found = True
496 break
497 if not found:
e8e571d7 498 raise Exception("BSS not found in scan")
5e29a900 499
9446f3c2
JM
500 if "FAIL" not in dev[0].request("SCAN scan_id=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17"):
501 raise Exception("Too many scan_id values accepted")
502
fccc4bd5
JM
503 # Duplicate SSID removal
504 check_scan(dev[0], "scan_id=%d,%d,%d freq=2412 use_id=1" % (id1, id1, id2))
505
b3f41349 506 dev[0].request("REMOVE_NETWORK all")
610cfff5 507 hapd.disable()
b3f41349
JM
508 dev[0].flush_scan_cache(freq=2432)
509 dev[0].flush_scan_cache()
510
5e29a900
JM
511def test_scan_and_bss_entry_removed(dev, apdev):
512 """Last scan result and connect work processing on BSS entry update"""
fab49f61
JM
513 hapd = hostapd.add_ap(apdev[0], {"ssid": "open",
514 "eap_server": "1",
515 "wps_state": "2"})
5e29a900
JM
516 bssid = apdev[0]['bssid']
517
518 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
519 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
520
521 # Add a BSS entry
522 dev[0].scan_for_bss(bssid, freq="2412")
523 wpas.scan_for_bss(bssid, freq="2412")
524
525 # Start a connect radio work with a blocking entry preventing this from
526 # proceeding; this stores a pointer to the selected BSS entry.
527 id = dev[0].request("RADIO_WORK add block-work")
528 w_id = wpas.request("RADIO_WORK add block-work")
529 dev[0].wait_event(["EXT-RADIO-WORK-START"], timeout=1)
530 wpas.wait_event(["EXT-RADIO-WORK-START"], timeout=1)
531 nid = dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
532 wait_connect=False)
533 w_nid = wpas.connect("open", key_mgmt="NONE", scan_freq="2412",
534 wait_connect=False)
535 time.sleep(0.1)
536
537 # Remove the BSS entry
538 dev[0].request("BSS_FLUSH 0")
539 wpas.request("BSS_FLUSH 0")
540
541 # Allow the connect radio work to continue. The bss entry stored in the
542 # pending connect work is now stale. This will result in the connection
543 # attempt failing since the BSS entry does not exist.
544 dev[0].request("RADIO_WORK done " + id)
545 wpas.request("RADIO_WORK done " + w_id)
546
547 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
548 if ev is not None:
549 raise Exception("Unexpected connection")
550 dev[0].remove_network(nid)
551 ev = wpas.wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
552 if ev is not None:
553 raise Exception("Unexpected connection")
554 wpas.remove_network(w_nid)
555 time.sleep(0.5)
556 dev[0].request("BSS_FLUSH 0")
557 wpas.request("BSS_FLUSH 0")
558
559 # Add a BSS entry
560 dev[0].scan_for_bss(bssid, freq="2412")
561 wpas.scan_for_bss(bssid, freq="2412")
562
563 # Start a connect radio work with a blocking entry preventing this from
564 # proceeding; this stores a pointer to the selected BSS entry.
565 id = dev[0].request("RADIO_WORK add block-work")
566 w_id = wpas.request("RADIO_WORK add block-work")
567 dev[0].wait_event(["EXT-RADIO-WORK-START"], timeout=1)
568 wpas.wait_event(["EXT-RADIO-WORK-START"], timeout=1)
569
570 # Schedule a connection based on the current BSS entry.
571 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
572 wait_connect=False)
573 wpas.connect("open", key_mgmt="NONE", scan_freq="2412",
574 wait_connect=False)
575
576 # Update scan results with results that have longer set of IEs so that new
577 # memory needs to be allocated for the BSS entry.
578 hapd.request("WPS_PBC")
579 time.sleep(0.1)
580 subprocess.call(['iw', dev[0].ifname, 'scan', 'trigger', 'freq', '2412'])
581 subprocess.call(['iw', wpas.ifname, 'scan', 'trigger', 'freq', '2412'])
582 time.sleep(0.1)
583
584 # Allow the connect radio work to continue. The bss entry stored in the
585 # pending connect work becomes stale during the scan and it must have been
586 # updated for the connection to work.
587 dev[0].request("RADIO_WORK done " + id)
588 wpas.request("RADIO_WORK done " + w_id)
589
5f35a5e2
JM
590 dev[0].wait_connected(timeout=15, error="No connection (sme-connect)")
591 wpas.wait_connected(timeout=15, error="No connection (connect)")
e51c8b2e
JM
592 dev[0].request("DISCONNECT")
593 wpas.request("DISCONNECT")
594 dev[0].flush_scan_cache()
595 wpas.flush_scan_cache()
83e80d32 596
9fd6804d 597@remote_compatible
83e80d32
JM
598def test_scan_reqs_with_non_scan_radio_work(dev, apdev):
599 """SCAN commands while non-scan radio_work is in progress"""
600 id = dev[0].request("RADIO_WORK add test-work-a")
601 ev = dev[0].wait_event(["EXT-RADIO-WORK-START"])
602 if ev is None:
603 raise Exception("Timeout while waiting radio work to start")
604
605 if "OK" not in dev[0].request("SCAN"):
606 raise Exception("SCAN failed")
607 if "FAIL-BUSY" not in dev[0].request("SCAN"):
608 raise Exception("SCAN accepted while one is already pending")
609 if "FAIL-BUSY" not in dev[0].request("SCAN"):
610 raise Exception("SCAN accepted while one is already pending")
611
612 res = dev[0].request("RADIO_WORK show").splitlines()
613 count = 0
614 for l in res:
615 if "scan" in l:
616 count += 1
617 if count != 1:
618 logger.info(res)
619 raise Exception("Unexpected number of scan radio work items")
620
621 dev[0].dump_monitor()
622 dev[0].request("RADIO_WORK done " + id)
623 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
624 if ev is None:
625 raise Exception("Scan did not start")
626 if "FAIL-BUSY" not in dev[0].request("SCAN"):
627 raise Exception("SCAN accepted while one is already in progress")
628
629 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
630 if ev is None:
0aca60b8 631 raise Exception("Scan did not complete")
83e80d32
JM
632 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.2)
633 if ev is not None:
634 raise Exception("Unexpected scan started")
558ac77c
JM
635
636def test_scan_setband(dev, apdev):
637 """Band selection for scan operations"""
638 try:
639 hapd = None
640 hapd2 = None
fab49f61
JM
641 params = {"ssid": "test-setband",
642 "hw_mode": "a",
643 "channel": "36",
644 "country_code": "US"}
8b8a1864 645 hapd = hostapd.add_ap(apdev[0], params)
558ac77c
JM
646 bssid = apdev[0]['bssid']
647
fab49f61
JM
648 params = {"ssid": "test-setband",
649 "hw_mode": "g",
650 "channel": "1"}
8b8a1864 651 hapd2 = hostapd.add_ap(apdev[1], params)
558ac77c
JM
652 bssid2 = apdev[1]['bssid']
653
654 if "FAIL" not in dev[0].request("SET setband FOO"):
655 raise Exception("Invalid set setband accepted")
656 if "OK" not in dev[0].request("SET setband AUTO"):
657 raise Exception("Failed to set setband")
658 if "OK" not in dev[1].request("SET setband 5G"):
659 raise Exception("Failed to set setband")
660 if "OK" not in dev[2].request("SET setband 2G"):
661 raise Exception("Failed to set setband")
662
96425ea5
JM
663 # Allow a retry to avoid reporting errors during heavy load
664 for j in range(5):
665 for i in range(3):
666 dev[i].request("SCAN only_new=1")
558ac77c 667
96425ea5
JM
668 for i in range(3):
669 ev = dev[i].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
670 if ev is None:
671 raise Exception("Scan timed out")
672
673 res0 = dev[0].request("SCAN_RESULTS")
674 res1 = dev[1].request("SCAN_RESULTS")
675 res2 = dev[2].request("SCAN_RESULTS")
676 if bssid in res0 and bssid2 in res0 and bssid in res1 and bssid2 in res2:
677 break
558ac77c
JM
678
679 res = dev[0].request("SCAN_RESULTS")
680 if bssid not in res or bssid2 not in res:
681 raise Exception("Missing scan result(0)")
682
683 res = dev[1].request("SCAN_RESULTS")
684 if bssid not in res:
685 raise Exception("Missing scan result(1)")
686 if bssid2 in res:
687 raise Exception("Unexpected scan result(1)")
688
689 res = dev[2].request("SCAN_RESULTS")
690 if bssid2 not in res:
691 raise Exception("Missing scan result(2)")
692 if bssid in res:
693 raise Exception("Unexpected scan result(2)")
694 finally:
695 if hapd:
696 hapd.request("DISABLE")
697 if hapd2:
698 hapd2.request("DISABLE")
699 subprocess.call(['iw', 'reg', 'set', '00'])
700 for i in range(3):
701 dev[i].request("SET setband AUTO")
702 dev[i].flush_scan_cache()
42ce1a27 703
9fd6804d 704@remote_compatible
42ce1a27
JM
705def test_scan_hidden_many(dev, apdev):
706 """scan_ssid=1 with large number of profile with hidden SSID"""
707 try:
708 _test_scan_hidden_many(dev, apdev)
709 finally:
610cfff5 710 dev[0].flush_scan_cache(freq=2432)
42ce1a27
JM
711 dev[0].flush_scan_cache()
712 dev[0].request("SCAN_INTERVAL 5")
713
714def _test_scan_hidden_many(dev, apdev):
fab49f61
JM
715 hapd = hostapd.add_ap(apdev[0], {"ssid": "test-scan-ssid",
716 "ignore_broadcast_ssid": "1"})
42ce1a27
JM
717 bssid = apdev[0]['bssid']
718
719 dev[0].request("SCAN_INTERVAL 1")
720
721 for i in range(5):
722 id = dev[0].add_network()
723 dev[0].set_network_quoted(id, "ssid", "foo")
724 dev[0].set_network(id, "key_mgmt", "NONE")
725 dev[0].set_network(id, "disabled", "0")
726 dev[0].set_network(id, "scan_freq", "2412")
727 dev[0].set_network(id, "scan_ssid", "1")
728
729 dev[0].set_network_quoted(id, "ssid", "test-scan-ssid")
730 dev[0].set_network(id, "key_mgmt", "NONE")
731 dev[0].set_network(id, "disabled", "0")
732 dev[0].set_network(id, "scan_freq", "2412")
733 dev[0].set_network(id, "scan_ssid", "1")
734
735 for i in range(5):
736 id = dev[0].add_network()
737 dev[0].set_network_quoted(id, "ssid", "foo")
738 dev[0].set_network(id, "key_mgmt", "NONE")
739 dev[0].set_network(id, "disabled", "0")
740 dev[0].set_network(id, "scan_freq", "2412")
741 dev[0].set_network(id, "scan_ssid", "1")
742
743 dev[0].request("REASSOCIATE")
5f35a5e2 744 dev[0].wait_connected(timeout=30)
610cfff5
JM
745 dev[0].request("REMOVE_NETWORK all")
746 hapd.disable()
8aeb6e3d
JM
747
748def test_scan_random_mac(dev, apdev, params):
749 """Random MAC address in scans"""
750 try:
751 _test_scan_random_mac(dev, apdev, params)
752 finally:
753 dev[0].request("MAC_RAND_SCAN all enable=0")
754
755def _test_scan_random_mac(dev, apdev, params):
fab49f61 756 hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
8aeb6e3d
JM
757 bssid = apdev[0]['bssid']
758
fab49f61
JM
759 tests = ["",
760 "addr=foo",
761 "mask=foo",
762 "enable=1",
763 "all enable=1 mask=00:11:22:33:44:55",
764 "all enable=1 addr=00:11:22:33:44:55",
765 "all enable=1 addr=01:11:22:33:44:55 mask=ff:ff:ff:ff:ff:ff",
766 "all enable=1 addr=00:11:22:33:44:55 mask=fe:ff:ff:ff:ff:ff",
767 "enable=2 scan sched pno all",
768 "pno enable=1",
769 "all enable=2",
770 "foo"]
8aeb6e3d
JM
771 for args in tests:
772 if "FAIL" not in dev[0].request("MAC_RAND_SCAN " + args):
773 raise Exception("Invalid MAC_RAND_SCAN accepted: " + args)
774
775 if dev[0].get_driver_status_field('capa.mac_addr_rand_scan_supported') != '1':
51c5aeb4 776 raise HwsimSkip("Driver does not support random MAC address for scanning")
8aeb6e3d 777
fab49f61
JM
778 tests = ["all enable=1",
779 "all enable=1 addr=f2:11:22:33:44:55 mask=ff:ff:ff:ff:ff:ff",
780 "all enable=1 addr=f2:11:33:00:00:00 mask=ff:ff:ff:00:00:00"]
8aeb6e3d
JM
781 for args in tests:
782 dev[0].request("MAC_RAND_SCAN " + args)
783 dev[0].scan_for_bss(bssid, freq=2412, force_scan=True)
8aeb6e3d 784
2e1d7386 785 out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
fab49f61 786 "wlan.fc.type_subtype == 4", ["wlan.ta"])
2e1d7386 787 if out is not None:
8aeb6e3d
JM
788 addr = out.splitlines()
789 logger.info("Probe Request frames seen from: " + str(addr))
790 if dev[0].own_addr() in addr:
791 raise Exception("Real address used to transmit Probe Request frame")
792 if "f2:11:22:33:44:55" not in addr:
793 raise Exception("Fully configured random address not seen")
794 found = False
795 for a in addr:
796 if a.startswith('f2:11:33'):
797 found = True
798 break
799 if not found:
800 raise Exception("Fixed OUI random address not seen")
2dc18e9a 801
dff690b8
JM
802def test_scan_random_mac_connected(dev, apdev, params):
803 """Random MAC address in scans while connected"""
804 try:
805 _test_scan_random_mac_connected(dev, apdev, params)
806 finally:
807 dev[0].request("MAC_RAND_SCAN all enable=0")
808
809def _test_scan_random_mac_connected(dev, apdev, params):
fab49f61 810 hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
dff690b8
JM
811 bssid = apdev[0]['bssid']
812 if dev[0].get_driver_status_field('capa.mac_addr_rand_scan_supported') != '1':
813 raise HwsimSkip("Driver does not support random MAC address for scanning")
814
815 dev[0].connect("test-scan", key_mgmt="NONE", scan_freq="2412")
816
fab49f61 817 hostapd.add_ap(apdev[1], {"ssid": "test-scan-2", "channel": "11"})
dff690b8
JM
818 bssid1 = apdev[1]['bssid']
819
820 # Verify that scanning can be completed while connected even if that means
821 # disabling use of random MAC address.
822 dev[0].request("MAC_RAND_SCAN all enable=1")
823 dev[0].scan_for_bss(bssid1, freq=2462, force_scan=True)
824
9fd6804d 825@remote_compatible
2dc18e9a
JM
826def test_scan_trigger_failure(dev, apdev):
827 """Scan trigger to the driver failing"""
15aa8042
JM
828 if dev[0].get_status_field('wpa_state') == "SCANNING":
829 raise Exception("wpa_state was already SCANNING")
830
fab49f61 831 hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
2dc18e9a
JM
832 bssid = apdev[0]['bssid']
833
834 if "OK" not in dev[0].request("SET test_failure 1"):
835 raise Exception("Failed to set test_failure")
836
837 if "OK" not in dev[0].request("SCAN"):
838 raise Exception("SCAN command failed")
839 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=10)
840 if ev is None:
841 raise Exception("Did not receive CTRL-EVENT-SCAN-FAILED event")
842 if "retry=1" in ev:
843 raise Exception("Unexpected scan retry indicated")
844 if dev[0].get_status_field('wpa_state') == "SCANNING":
845 raise Exception("wpa_state SCANNING not cleared")
846
847 id = dev[0].connect("test-scan", key_mgmt="NONE", scan_freq="2412",
848 only_add_network=True)
849 dev[0].select_network(id)
850 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=10)
851 if ev is None:
852 raise Exception("Did not receive CTRL-EVENT-SCAN-FAILED event")
853 if "retry=1" not in ev:
854 raise Exception("No scan retry indicated for connection")
855 if dev[0].get_status_field('wpa_state') == "SCANNING":
856 raise Exception("wpa_state SCANNING not cleared")
857 dev[0].request("SET test_failure 0")
858 dev[0].wait_connected()
859
860 dev[0].request("SET test_failure 1")
861 if "OK" not in dev[0].request("SCAN"):
862 raise Exception("SCAN command failed")
863 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=10)
864 if ev is None:
865 raise Exception("Did not receive CTRL-EVENT-SCAN-FAILED event")
866 if "retry=1" in ev:
867 raise Exception("Unexpected scan retry indicated")
868 if dev[0].get_status_field('wpa_state') != "COMPLETED":
869 raise Exception("wpa_state COMPLETED not restored")
870 dev[0].request("SET test_failure 0")
98c71cf6 871
9fd6804d 872@remote_compatible
98c71cf6
JM
873def test_scan_specify_ssid(dev, apdev):
874 """Control interface behavior on scan SSID parameter"""
875 dev[0].flush_scan_cache()
fab49f61
JM
876 hapd = hostapd.add_ap(apdev[0], {"ssid": "test-hidden",
877 "ignore_broadcast_ssid": "1"})
98c71cf6
JM
878 bssid = apdev[0]['bssid']
879 check_scan(dev[0], "freq=2412 use_id=1 ssid 414243")
880 bss = dev[0].get_bss(bssid)
881 if bss is not None and bss['ssid'] == 'test-hidden':
882 raise Exception("BSS entry for hidden AP present unexpectedly")
96425ea5
JM
883 # Allow couple more retries to avoid reporting errors during heavy load
884 for i in range(5):
885 check_scan(dev[0], "freq=2412 ssid 414243 ssid 746573742d68696464656e ssid 616263313233 use_id=1")
886 bss = dev[0].get_bss(bssid)
887 if bss and 'test-hidden' in dev[0].request("SCAN_RESULTS"):
888 break
98c71cf6
JM
889 if bss is None:
890 raise Exception("BSS entry for hidden AP not found")
891 if 'test-hidden' not in dev[0].request("SCAN_RESULTS"):
bc6e3288 892 raise Exception("Expected SSID not included in the scan results")
98c71cf6
JM
893
894 hapd.disable()
895 dev[0].flush_scan_cache(freq=2432)
896 dev[0].flush_scan_cache()
897
898 if "FAIL" not in dev[0].request("SCAN ssid foo"):
899 raise Exception("Invalid SCAN command accepted")
708ec753 900
9fd6804d 901@remote_compatible
708ec753
JM
902def test_scan_ap_scan_2_ap_mode(dev, apdev):
903 """AP_SCAN 2 AP mode and scan()"""
904 try:
905 _test_scan_ap_scan_2_ap_mode(dev, apdev)
906 finally:
907 dev[0].request("AP_SCAN 1")
908
909def _test_scan_ap_scan_2_ap_mode(dev, apdev):
910 if "OK" not in dev[0].request("AP_SCAN 2"):
911 raise Exception("Failed to set AP_SCAN 2")
912
913 id = dev[0].add_network()
914 dev[0].set_network(id, "mode", "2")
915 dev[0].set_network_quoted(id, "ssid", "wpas-ap-open")
916 dev[0].set_network(id, "key_mgmt", "NONE")
917 dev[0].set_network(id, "frequency", "2412")
918 dev[0].set_network(id, "scan_freq", "2412")
919 dev[0].set_network(id, "disabled", "0")
920 dev[0].select_network(id)
921 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5)
922 if ev is None:
923 raise Exception("AP failed to start")
924
925 with fail_test(dev[0], 1, "wpa_driver_nl80211_scan"):
926 if "OK" not in dev[0].request("SCAN freq=2412"):
927 raise Exception("SCAN command failed unexpectedly")
928 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED",
929 "AP-DISABLED"], timeout=5)
930 if ev is None:
931 raise Exception("CTRL-EVENT-SCAN-FAILED not seen")
932 if "AP-DISABLED" in ev:
933 raise Exception("Unexpected AP-DISABLED event")
934 if "retry=1" in ev:
935 # Wait for the retry to scan happen
936 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED",
937 "AP-DISABLED"], timeout=5)
938 if ev is None:
939 raise Exception("CTRL-EVENT-SCAN-FAILED not seen - retry")
940 if "AP-DISABLED" in ev:
941 raise Exception("Unexpected AP-DISABLED event - retry")
942
943 dev[1].connect("wpas-ap-open", key_mgmt="NONE", scan_freq="2412")
944 dev[1].request("DISCONNECT")
945 dev[1].wait_disconnected()
946 dev[0].request("DISCONNECT")
947 dev[0].wait_disconnected()
2313e6c9
JM
948
949def test_scan_bss_expiration_on_ssid_change(dev, apdev):
950 """BSS entry expiration when AP changes SSID"""
951 dev[0].flush_scan_cache()
fab49f61 952 hapd = hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
2313e6c9
JM
953 bssid = apdev[0]['bssid']
954 dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
955
956 hapd.request("DISABLE")
fab49f61 957 hapd = hostapd.add_ap(apdev[0], {"ssid": "open"})
2313e6c9
JM
958 if "OK" not in dev[0].request("BSS_EXPIRE_COUNT 3"):
959 raise Exception("BSS_EXPIRE_COUNT failed")
960 dev[0].scan(freq="2412")
961 dev[0].scan(freq="2412")
962 if "OK" not in dev[0].request("BSS_EXPIRE_COUNT 2"):
963 raise Exception("BSS_EXPIRE_COUNT failed")
964 res = dev[0].request("SCAN_RESULTS")
965 if "test-scan" not in res:
966 raise Exception("The first SSID not in scan results")
967 if "open" not in res:
968 raise Exception("The second SSID not in scan results")
969 dev[0].connect("open", key_mgmt="NONE")
970
971 dev[0].request("BSS_FLUSH 0")
972 res = dev[0].request("SCAN_RESULTS")
973 if "test-scan" in res:
974 raise Exception("The BSS entry with the old SSID was not removed")
975 dev[0].request("DISCONNECT")
976 dev[0].wait_disconnected()
f9bf2225
JM
977
978def test_scan_dfs(dev, apdev, params):
979 """Scan on DFS channels"""
980 try:
981 _test_scan_dfs(dev, apdev, params)
982 finally:
9a1046a7 983 clear_regdom_dev(dev)
f9bf2225
JM
984
985def _test_scan_dfs(dev, apdev, params):
986 subprocess.call(['iw', 'reg', 'set', 'US'])
987 for i in range(2):
988 for j in range(5):
989 ev = dev[i].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=5)
990 if ev is None:
991 raise Exception("No regdom change event")
992 if "alpha2=US" in ev:
993 break
994 dev[i].dump_monitor()
995
996 if "OK" not in dev[0].request("SCAN"):
997 raise Exception("SCAN command failed")
998 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
999 if ev is None:
1000 raise Exception("Scan did not complete")
1001
1002 if "OK" not in dev[0].request("SCAN freq=2412,5180,5260,5500,5600,5745"):
1003 raise Exception("SCAN command failed")
1004 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
1005 if ev is None:
1006 raise Exception("Scan did not complete")
1007
1008 out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
fab49f61 1009 "wlan.fc.type_subtype == 4", ["radiotap.channel.freq"])
f9bf2225
JM
1010 if out is not None:
1011 freq = out.splitlines()
b25f04d4 1012 freq = [int(f) for f in freq]
f9bf2225 1013 freq = list(set(freq))
b25f04d4 1014 freq.sort()
f9bf2225 1015 logger.info("Active scan seen on channels: " + str(freq))
b25f04d4 1016 for f in freq:
f9bf2225
JM
1017 if (f >= 5260 and f <= 5320) or (f >= 5500 and f <= 5700):
1018 raise Exception("Active scan on DFS channel: %d" % f)
fab49f61 1019 if f in [2467, 2472]:
f0154bf4 1020 raise Exception("Active scan on US-disallowed channel: %d" % f)
77676871 1021
9fd6804d 1022@remote_compatible
77676871
JM
1023def test_scan_abort(dev, apdev):
1024 """Aborting a full scan"""
1025 dev[0].request("SCAN")
1026 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"])
1027 if ev is None:
1028 raise Exception("Scan did not start")
1029 if "OK" not in dev[0].request("ABORT_SCAN"):
1030 raise Exception("ABORT_SCAN command failed")
1031 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=2)
1032 if ev is None:
1033 raise Exception("Scan did not terminate")
1034
9fd6804d 1035@remote_compatible
77676871
JM
1036def test_scan_abort_on_connect(dev, apdev):
1037 """Aborting a full scan on connection request"""
fab49f61 1038 hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
77676871
JM
1039 bssid = apdev[0]['bssid']
1040
1041 dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
1042 dev[0].dump_monitor()
1043 dev[0].request("SCAN")
1044 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"])
1045 if ev is None:
1046 raise Exception("Scan did not start")
1047 dev[0].connect("test-scan", key_mgmt="NONE")
2d3525be 1048
9fd6804d 1049@remote_compatible
2d3525be
JM
1050def test_scan_ext(dev, apdev):
1051 """Custom IE in Probe Request frame"""
fab49f61 1052 hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
2d3525be
JM
1053 bssid = apdev[0]['bssid']
1054
1055 try:
1056 if "OK" not in dev[0].request("VENDOR_ELEM_ADD 14 dd050011223300"):
1057 raise Exception("VENDOR_ELEM_ADD failed")
1058 check_scan(dev[0], "freq=2412 use_id=1")
1059 finally:
1060 dev[0].request("VENDOR_ELEM_REMOVE 14 *")
7f03ecc8
JM
1061
1062def test_scan_fail(dev, apdev):
1063 """Scan failures"""
1064 with fail_test(dev[0], 1, "wpa_driver_nl80211_scan"):
1065 dev[0].request("DISCONNECT")
1066 if "OK" not in dev[0].request("SCAN freq=2412"):
1067 raise Exception("SCAN failed")
1068 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=5)
1069 if ev is None:
1070 raise Exception("Did not see scan failure event")
1071 dev[0].dump_monitor()
1072
0b0e4792
JM
1073 for i in range(1, 5):
1074 with alloc_fail(dev[0], i,
1075 "wpa_scan_clone_params;wpa_supplicant_trigger_scan"):
1076 if "OK" not in dev[0].request("SCAN ssid 112233 freq=2412"):
1077 raise Exception("SCAN failed")
1078 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=5)
1079 if ev is None:
1080 raise Exception("Did not see scan failure event")
1081 dev[0].dump_monitor()
1082
7f03ecc8
JM
1083 with alloc_fail(dev[0], 1, "radio_add_work;wpa_supplicant_trigger_scan"):
1084 if "OK" not in dev[0].request("SCAN freq=2412"):
1085 raise Exception("SCAN failed")
1086 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=5)
1087 if ev is None:
1088 raise Exception("Did not see scan failure event")
1089 dev[0].dump_monitor()
1090
1091 try:
1092 if "OK" not in dev[0].request("SET filter_ssids 1"):
1093 raise Exception("SET failed")
1094 id = dev[0].connect("test-scan", key_mgmt="NONE", only_add_network=True)
1095 with alloc_fail(dev[0], 1, "wpa_supplicant_build_filter_ssids"):
1096 # While the filter list cannot be created due to memory allocation
1097 # failure, this scan is expected to be completed without SSID
1098 # filtering.
1099 if "OK" not in dev[0].request("SCAN freq=2412"):
1100 raise Exception("SCAN failed")
1101 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
1102 if ev is None:
1103 raise Exception("Scan did not complete")
1104 dev[0].remove_network(id)
1105 finally:
1106 dev[0].request("SET filter_ssids 0")
1107 dev[0].dump_monitor()
1108
1109 with alloc_fail(dev[0], 1, "nl80211_get_scan_results"):
1110 if "OK" not in dev[0].request("SCAN freq=2412"):
1111 raise Exception("SCAN failed")
1112 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
1113 if ev is None:
1114 raise Exception("Did not see scan started event")
1115 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
1116 dev[0].dump_monitor()
1117
0b0e4792
JM
1118 try:
1119 if "OK" not in dev[0].request("SET setband 2G"):
1120 raise Exception("SET setband failed")
1121 with alloc_fail(dev[0], 1, "=wpa_setband_scan_freqs_list"):
1122 # While the frequency list cannot be created due to memory
1123 # allocation failure, this scan is expected to be completed without
1124 # frequency filtering.
1125 if "OK" not in dev[0].request("SCAN"):
1126 raise Exception("SCAN failed")
1127 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
1128 dev[0].request("ABORT_SCAN")
1129 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
1130 if ev is None:
1131 raise Exception("Scan did not complete")
1132 finally:
1133 dev[0].request("SET setband AUTO")
1134 dev[0].dump_monitor()
1135
7f03ecc8
JM
1136 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1137 wpas.interface_add("wlan5")
1138 wpas.request("SET preassoc_mac_addr 1")
1139 with fail_test(wpas, 1, "nl80211_set_mac_addr;wpas_trigger_scan_cb"):
1140 if "OK" not in wpas.request("SCAN freq=2412"):
1141 raise Exception("SCAN failed")
1142 ev = wpas.wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=5)
1143 if ev is None:
1144 raise Exception("Did not see scan failure event")
1145 wpas.request("SET preassoc_mac_addr 0")
1146 wpas.dump_monitor()
42083295 1147
fab49f61 1148 hapd = hostapd.add_ap(apdev[0], {"ssid": "open"})
20c7d26f
JM
1149 with alloc_fail(dev[0], 1, "wpa_bss_add"):
1150 dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
1151
c7a72189
JM
1152def test_scan_fail_type_only(dev, apdev):
1153 """Scan failures for TYPE=ONLY"""
1154 with fail_test(dev[0], 1, "wpa_driver_nl80211_scan"):
1155 dev[0].request("SCAN TYPE=ONLY freq=2417")
1156 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=5)
1157 if ev is None:
1158 raise Exception("Scan trigger failure not reported")
1159 # Verify that scan_only_handler() does not get left set as the
1160 # wpa_s->scan_res_handler in failure case.
fab49f61 1161 hapd = hostapd.add_ap(apdev[0], {"ssid": "open"})
c7a72189
JM
1162 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
1163
9fd6804d 1164@remote_compatible
42083295
JM
1165def test_scan_freq_list(dev, apdev):
1166 """Scan with SET freq_list and scan_cur_freq"""
1167 try:
1168 if "OK" not in dev[0].request("SET freq_list 2412 2417"):
1169 raise Exception("SET freq_list failed")
1170 check_scan(dev[0], "use_id=1")
1171 finally:
1172 dev[0].request("SET freq_list ")
1173
fab49f61 1174 hapd = hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
42083295
JM
1175 dev[0].connect("test-scan", key_mgmt="NONE", scan_freq="2412")
1176 try:
1177 if "OK" not in dev[0].request("SET scan_cur_freq 1"):
1178 raise Exception("SET scan_cur_freq failed")
1179 check_scan(dev[0], "use_id=1")
1180 finally:
1181 dev[0].request("SET scan_cur_freq 0")
1182 dev[0].request("REMOVE_NETWORK all")
1183 dev[0].wait_disconnected()
20c7d26f
JM
1184
1185def test_scan_bss_limit(dev, apdev):
1186 """Scan and wpa_supplicant BSS entry limit"""
1187 try:
1188 _test_scan_bss_limit(dev, apdev)
1189 finally:
1190 dev[0].request("SET bss_max_count 200")
1191 pass
1192
1193def _test_scan_bss_limit(dev, apdev):
1194 # Trigger 'Increasing the MAX BSS count to 2 because all BSSes are in use.
1195 # We should normally not get here!' message by limiting the maximum BSS
1196 # count to one so that the second AP would not fit in the BSS list and the
1197 # first AP cannot be removed from the list since it is still in use.
1198 dev[0].request("SET bss_max_count 1")
fab49f61 1199 hapd = hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
20c7d26f 1200 dev[0].connect("test-scan", key_mgmt="NONE", scan_freq="2412")
fab49f61
JM
1201 hapd2 = hostapd.add_ap(apdev[1], {"ssid": "test-scan-2",
1202 "channel": "6"})
20c7d26f 1203 dev[0].scan_for_bss(apdev[1]['bssid'], freq=2437, force_scan=True)
27b69833
JM
1204
1205def run_scan(dev, bssid, exp_freq):
1206 for i in range(5):
1207 dev.request("SCAN freq=2412,2437,2462")
1208 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"])
1209 if ev is None:
1210 raise Exception("Scan did not complete")
1211 bss = dev.get_bss(bssid)
1212 freq = int(bss['freq']) if bss else 0
1213 if freq == exp_freq:
1214 break
1215 if freq != exp_freq:
1216 raise Exception("BSS entry shows incorrect frequency: %d != %d" % (freq, exp_freq))
1217
1218def test_scan_chan_switch(dev, apdev):
1219 """Scanning and AP changing channels"""
1220
1221 # This test verifies that wpa_supplicant updates its local BSS table based
1222 # on the correct cfg80211 scan entry in cases where the cfg80211 BSS table
1223 # has multiple (one for each frequency) BSS entries for the same BSS.
1224
1225 csa_supported(dev[0])
fab49f61 1226 hapd = hostapd.add_ap(apdev[0], {"ssid": "test-scan", "channel": "1"})
27b69833
JM
1227 csa_supported(hapd)
1228 bssid = hapd.own_addr()
1229
1230 logger.info("AP channel switch while not connected")
1231 run_scan(dev[0], bssid, 2412)
1232 dev[0].dump_monitor()
1233 switch_channel(hapd, 1, 2437)
1234 run_scan(dev[0], bssid, 2437)
1235 dev[0].dump_monitor()
1236 switch_channel(hapd, 1, 2462)
1237 run_scan(dev[0], bssid, 2462)
1238 dev[0].dump_monitor()
1239
1240 logger.info("AP channel switch while connected")
1241 dev[0].connect("test-scan", key_mgmt="NONE", scan_freq="2412 2437 2462")
1242 run_scan(dev[0], bssid, 2462)
1243 dev[0].dump_monitor()
1244 switch_channel(hapd, 2, 2437)
1245 wait_channel_switch(dev[0], 2437)
1246 dev[0].dump_monitor()
1247 run_scan(dev[0], bssid, 2437)
1248 dev[0].dump_monitor()
1249 switch_channel(hapd, 2, 2412)
1250 wait_channel_switch(dev[0], 2412)
1251 dev[0].dump_monitor()
1252 run_scan(dev[0], bssid, 2412)
1253 dev[0].dump_monitor()
79124c7b
JM
1254
1255def test_scan_new_only(dev, apdev):
1256 """Scan and only_new=1 multiple times"""
1257 try:
1258 _test_scan_new_only(dev, apdev)
1259 finally:
1260 dev[0].set("ignore_old_scan_res", "0")
1261def _test_scan_new_only(dev, apdev):
1262 dev[0].flush_scan_cache()
fab49f61 1263 hapd = hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
79124c7b
JM
1264 dev[0].set("ignore_old_scan_res", "1")
1265 # Get the BSS added to cfg80211 BSS list
1266 bssid = hapd.own_addr()
1267 dev[0].scan_for_bss(bssid, freq=2412)
1268 bss = dev[0].get_bss(bssid)
1269 idx1 = bss['update_idx']
1270 dev[0].scan_for_bss(bssid, freq=2412, force_scan=True)
1271 dev[0].scan_for_bss(bssid, freq=2412, force_scan=True)
1272 bss = dev[0].get_bss(bssid)
1273 idx2 = bss['update_idx']
1274 if int(idx2) <= int(idx1):
1275 raise Exception("Scan result update_idx did not increase")
1276 # Disable AP to ensure there are no new scan results after this.
1277 hapd.disable()
1278
1279 # Try to scan multiple times to verify that old scan results do not get
1280 # accepted as new.
1281 for i in range(10):
1282 dev[0].scan(freq=2412)
1283 bss = dev[0].get_bss(bssid)
1284 if bss:
1285 idx = bss['update_idx']
1286 if int(idx) > int(idx2):
1287 raise Exception("Unexpected update_idx increase")
0ef0921a
JM
1288
1289def test_scan_flush(dev, apdev):
1290 """Ongoing scan and FLUSH"""
1291 dev[0].flush_scan_cache()
fab49f61 1292 hapd = hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
0ef0921a
JM
1293 dev[0].dump_monitor()
1294 dev[0].request("SCAN TYPE=ONLY freq=2412-2472 passive=1")
1295 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=10)
1296 if ev is None:
1297 raise Exception("Scan did not start")
1298 time.sleep(0.1)
1299 dev[0].request("FLUSH")
1300 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS",
1301 "CTRL-EVENT-SCAN-FAILED",
1302 "CTRL-EVENT-BSS-ADDED"], timeout=10)
1303 if ev is None:
1304 raise Exception("Scan did not complete")
1305 if "CTRL-EVENT-BSS-ADDED" in ev:
1306 raise Exception("Unexpected BSS entry addition after FLUSH")
58bd7dc3
JM
1307
1308def test_scan_ies(dev, apdev):
1309 """Scan and both Beacon and Probe Response frame IEs"""
1310 dev[0].flush_scan_cache()
fab49f61
JM
1311 hapd = hostapd.add_ap(apdev[0], {"ssid": "test-scan",
1312 "beacon_int": "20"})
58bd7dc3
JM
1313 bssid = hapd.own_addr()
1314 dev[0].dump_monitor()
1315
1316 for i in range(10):
1317 dev[0].request("SCAN TYPE=ONLY freq=2412 passive=1")
1318 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=15)
1319 if ev is None:
1320 raise Exception("Scan did not complete")
1321 if dev[0].get_bss(bssid):
1322 break
1323
1324 for i in range(10):
1325 dev[0].scan_for_bss(bssid, freq=2412, force_scan=True)
1326 bss = dev[0].get_bss(bssid)
1327 if 'beacon_ie' in bss:
1328 if bss['ie'] != bss['beacon_ie']:
1329 break
1330
1331 if not bss or 'beacon_ie' not in bss:
1332 raise Exception("beacon_ie not present")
1333 ie = parse_ie(bss['ie'])
35d8c254 1334 logger.info("ie: " + str(list(ie.keys())))
58bd7dc3 1335 beacon_ie = parse_ie(bss['beacon_ie'])
35d8c254 1336 logger.info("beacon_ie: " + str(list(ie.keys())))
58bd7dc3
JM
1337 if bss['ie'] == bss['beacon_ie']:
1338 raise Exception("Both ie and beacon_ie show same data")
e437a5ab
JM
1339
1340def test_scan_parsing(dev, apdev):
1341 """Scan result parsing"""
1342 if "OK" not in dev[0].request("DRIVER_EVENT SCAN_RES START"):
1343 raise Exception("DRIVER_EVENT SCAN_RES START failed")
1344
1345 if "FAIL" not in dev[0].request("DRIVER_EVENT SCAN_RES foo "):
1346 raise Exception("Invalid DRIVER_EVENT SCAN_RES accepted")
1347
fab49f61
JM
1348 tests = ["",
1349 "flags=ffffffff",
1350 "bssid=02:03:04:05:06:07",
1351 "freq=1234",
1352 "beacon_int=102",
1353 "caps=1234",
1354 "qual=10",
1355 "noise=10",
1356 "level=10",
1357 "tsf=1122334455667788",
1358 "age=123",
1359 "est_throughput=100",
1360 "snr=10",
1361 "parent_tsf=1122334455667788",
1362 "tsf_bssid=02:03:04:05:06:07",
1363 "ie=00",
1364 "beacon_ie=00",
1365 # Too long SSID
1366 "bssid=02:ff:00:00:00:01 ie=0033" + 33*'FF',
1367 # All parameters
1368 "flags=ffffffff bssid=02:ff:00:00:00:02 freq=1234 beacon_int=102 caps=1234 qual=10 noise=10 level=10 tsf=1122334455667788 age=123456 est_throughput=100 snr=10 parent_tsf=1122334455667788 tsf_bssid=02:03:04:05:06:07 ie=000474657374 beacon_ie=000474657374",
1369 # Beacon IEs truncated
1370 "bssid=02:ff:00:00:00:03 ie=0000 beacon_ie=0003ffff",
1371 # Probe Response IEs truncated
1372 "bssid=02:ff:00:00:00:04 ie=00000101 beacon_ie=0000",
1373 # DMG (invalid caps)
1374 "bssid=02:ff:00:00:00:05 freq=58320 ie=0003646d67",
1375 # DMG (IBSS)
1376 "bssid=02:ff:00:00:00:06 freq=60480 caps=0001 ie=0003646d67",
1377 # DMG (PBSS)
1378 "bssid=02:ff:00:00:00:07 freq=62640 caps=0002 ie=0003646d67",
1379 # DMG (AP)
1380 "bssid=02:ff:00:00:00:08 freq=64800 caps=0003 ie=0003646d67",
1381 # Test BSS for updates
1382 "bssid=02:ff:00:00:00:09 freq=2412 caps=0011 level=1 ie=0003757064010182",
1383 # Minimal BSS data
1384 "bssid=02:ff:00:00:00:00 ie=0000"]
e437a5ab
JM
1385 for t in tests:
1386 if "OK" not in dev[0].request("DRIVER_EVENT SCAN_RES BSS " + t):
1387 raise Exception("DRIVER_EVENT SCAN_RES BSS failed")
1388
1389 if "OK" not in dev[0].request("DRIVER_EVENT SCAN_RES END"):
1390 raise Exception("DRIVER_EVENT SCAN_RES END failed")
1391
1392 res = dev[0].request("SCAN_RESULTS")
1393 logger.info("SCAN_RESULTS:\n" + res)
1394
1395 bss = []
1396 res = dev[0].request("BSS FIRST")
1397 if "FAIL" in res:
1398 raise Exception("BSS FIRST failed")
1399 while "\nbssid=" in res:
1400 logger.info("BSS output:\n" + res)
1401 bssid = None
1402 id = None
1403 for val in res.splitlines():
1404 if val.startswith("id="):
1405 id = val.split('=')[1]
1406 if val.startswith("bssid="):
1407 bssid = val.split('=')[1]
1408 if bssid is None or id is None:
1409 raise Exception("Missing id or bssid line")
1410 bss.append(bssid)
1411 res = dev[0].request("BSS NEXT-" + id)
1412
1413 logger.info("Discovered BSSs: " + str(bss))
fab49f61
JM
1414 invalid_bss = ["02:03:04:05:06:07", "02:ff:00:00:00:01"]
1415 valid_bss = ["02:ff:00:00:00:00", "02:ff:00:00:00:02",
1416 "02:ff:00:00:00:03", "02:ff:00:00:00:04",
1417 "02:ff:00:00:00:05", "02:ff:00:00:00:06",
1418 "02:ff:00:00:00:07", "02:ff:00:00:00:08",
1419 "02:ff:00:00:00:09"]
e437a5ab
JM
1420 for bssid in invalid_bss:
1421 if bssid in bss:
1422 raise Exception("Invalid BSS included: " + bssid)
1423 for bssid in valid_bss:
1424 if bssid not in bss:
1425 raise Exception("Valid BSS missing: " + bssid)
1426
1427 logger.info("Update BSS parameters")
1428 if "OK" not in dev[0].request("DRIVER_EVENT SCAN_RES START"):
1429 raise Exception("DRIVER_EVENT SCAN_RES START failed")
1430 if "OK" not in dev[0].request("DRIVER_EVENT SCAN_RES BSS bssid=02:ff:00:00:00:09 freq=2412 caps=0002 level=2 ie=000375706401028204"):
1431 raise Exception("DRIVER_EVENT SCAN_RES BSS failed")
1432 if "OK" not in dev[0].request("DRIVER_EVENT SCAN_RES END"):
1433 raise Exception("DRIVER_EVENT SCAN_RES END failed")
1434 res = dev[0].request("BSS 02:ff:00:00:00:09")
1435 logger.info("Updated BSS:\n" + res)
1c13be83
JM
1436
1437def test_scan_specific_bssid(dev, apdev):
1438 """Scan for a specific BSSID"""
1439 dev[0].flush_scan_cache()
fab49f61
JM
1440 hapd = hostapd.add_ap(apdev[0], {"ssid": "test-scan",
1441 "beacon_int": "1000"})
1c13be83
JM
1442 bssid = hapd.own_addr()
1443
1444 time.sleep(0.1)
1445 dev[0].request("SCAN TYPE=ONLY freq=2412 bssid=02:ff:ff:ff:ff:ff")
1446 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
1447 if ev is None:
1448 raise Exception("Scan did not complete")
1449 bss1 = dev[0].get_bss(bssid)
1450
1451 for i in range(10):
1452 dev[0].request("SCAN TYPE=ONLY freq=2412 bssid=" + bssid)
1453 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
1454 if ev is None:
1455 raise Exception("Scan did not complete")
1456 bss2 = dev[0].get_bss(bssid)
1457 if bss2:
1458 break
1459
1460 if not bss2:
1461 raise Exception("Did not find BSS")
abaa0893 1462 if bss1 and 'beacon_ie' in bss1 and 'ie' in bss1 and bss1['beacon_ie'] != bss1['ie']:
1c13be83
JM
1463 raise Exception("First scan for unknown BSSID returned unexpected response")
1464 if bss2 and 'beacon_ie' in bss2 and 'ie' in bss2 and bss2['beacon_ie'] == bss2['ie']:
1465 raise Exception("Second scan did find Probe Response frame")
9f85f0ed
JM
1466
1467def test_scan_probe_req_events(dev, apdev):
1468 """Probe Request frame RX events from hostapd"""
fab49f61 1469 hapd = hostapd.add_ap(apdev[0], {"ssid": "open"})
9f85f0ed
JM
1470 hapd2 = hostapd.Hostapd(apdev[0]['ifname'])
1471 if "OK" not in hapd2.mon.request("ATTACH probe_rx_events=1"):
1472 raise Exception("Failed to register for events")
1473
1474 dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
1475
1476 ev = hapd2.wait_event(["RX-PROBE-REQUEST"], timeout=5)
1477 if ev is None:
1478 raise Exception("RX-PROBE-REQUEST not reported")
1479 if "sa=" + dev[0].own_addr() not in ev:
1480 raise Exception("Unexpected event parameters: " + ev)
1481
1482 ev = hapd.wait_event(["RX-PROBE-REQUEST"], timeout=0.1)
1483 if ev is not None:
1484 raise Exception("Unexpected RX-PROBE-REQUEST")
e18b4792
JM
1485
1486 if "OK" not in hapd2.mon.request("ATTACH probe_rx_events=0"):
1487 raise Exception("Failed to update event registration")
1488
1489 dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
1490 ev = hapd2.wait_event(["RX-PROBE-REQUEST"], timeout=0.5)
1491 if ev is not None:
1492 raise Exception("Unexpected RX-PROBE-REQUEST")
1493
fab49f61 1494 tests = ["probe_rx_events", "probe_rx_events=-1", "probe_rx_events=2"]
e18b4792
JM
1495 for val in tests:
1496 if "FAIL" not in hapd2.mon.request("ATTACH " + val):
1497 raise Exception("Invalid ATTACH command accepted")
586826d4
JM
1498
1499def elem_capab(capab):
1500 # Nontransmitted BSSID Capability element (83 = 0x53)
1501 return struct.pack('<BBH', 83, 2, capab)
1502
1503def elem_ssid(ssid):
1504 # SSID element
d5cac059 1505 return struct.pack('BB', 0, len(ssid)) + ssid.encode()
586826d4
JM
1506
1507def elem_bssid_index(index):
1508 # Multiple BSSID-index element (85 = 0x55)
1509 return struct.pack('BBB', 85, 1, index)
1510
1511def elem_multibssid(profiles, max_bssid_indic):
1512 # TODO: add support for fragmenting over multiple Multiple BSSID elements
1513 if 1 + len(profiles) > 255:
1514 raise Exception("Too long Multiple BSSID element")
1515 elem = struct.pack('BBB', 71, 1 + len(profiles), max_bssid_indic) + profiles
d5cac059 1516 return binascii.hexlify(elem).decode()
586826d4
JM
1517
1518def run_scans(dev, check):
1519 for i in range(2):
1520 dev.request("SCAN TYPE=ONLY freq=2412")
1521 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
1522 if ev is None:
1523 raise Exception("Scan did not complete")
1524
1525 # TODO: Check IEs
1526 for (bssid, ssid, capab) in check:
1527 bss = dev.get_bss(bssid)
1528 if bss is None:
1529 raise Exception("AP " + bssid + " missing from scan results")
1530 logger.info("AP " + bssid + ": " + str(bss))
1531 if bss['ssid'] != ssid:
1532 raise Exception("Unexpected AP " + bssid + " SSID")
1533 if int(bss['capabilities'], 16) != capab:
1534 raise Exception("Unexpected AP " + bssid + " capabilities")
1535
1536def check_multibss_sta_capa(dev):
1537 res = dev.get_capability("multibss")
1538 if res is None or 'MULTIBSS-STA' not in res:
1539 raise HwsimSkip("Multi-BSS STA functionality not supported")
1540
1541def test_scan_multi_bssid(dev, apdev):
1542 """Scan and Multiple BSSID element"""
1543 check_multibss_sta_capa(dev[0])
1544 dev[0].flush_scan_cache()
1545
fab49f61 1546 params = {"ssid": "test-scan"}
586826d4 1547 # Max BSSID Indicator 0 (max 1 BSSID) and no subelements
d5cac059 1548 params['vendor_elements'] = elem_multibssid(b'', 0)
586826d4
JM
1549 hostapd.add_ap(apdev[0], params)
1550
fab49f61 1551 params = {"ssid": "test-scan"}
586826d4
JM
1552 elems = elem_capab(0x0401) + elem_ssid("1") + elem_bssid_index(1)
1553 profile1 = struct.pack('BB', 0, len(elems)) + elems
1554 params['vendor_elements'] = elem_multibssid(profile1, 1)
1555 hostapd.add_ap(apdev[1], params)
1556
1557 bssid0 = apdev[0]['bssid']
1558 bssid1 = apdev[1]['bssid']
fab49f61
JM
1559 check = [(bssid0, 'test-scan', 0x401),
1560 (bssid1, 'test-scan', 0x401),
1561 (bssid1[0:16] + '1', '1', 0x401)]
586826d4
JM
1562 run_scans(dev[0], check)
1563
1564def test_scan_multi_bssid_2(dev, apdev):
1565 """Scan and Multiple BSSID element (2)"""
1566 check_multibss_sta_capa(dev[0])
1567 dev[0].flush_scan_cache()
1568
fab49f61 1569 params = {"ssid": "transmitted"}
586826d4
JM
1570
1571 # Duplicated entry for the transmitted BSS (not a normal use case)
1572 elems = elem_capab(1) + elem_ssid("transmitted") + elem_bssid_index(0)
1573 profile1 = struct.pack('BB', 0, len(elems)) + elems
1574
1575 elems = elem_capab(1) + elem_ssid("nontransmitted") + elem_bssid_index(1)
1576 profile2 = struct.pack('BB', 0, len(elems)) + elems
1577
1578 elems = elem_capab(1) + elem_ssid("nontransmitted_2") + elem_bssid_index(2)
1579 profile3 = struct.pack('BB', 0, len(elems)) + elems
1580
1581 profiles = profile1 + profile2 + profile3
1582 params['vendor_elements'] = elem_multibssid(profiles, 4)
1583 hostapd.add_ap(apdev[0], params)
1584
1585 bssid = apdev[0]['bssid']
fab49f61
JM
1586 check = [(bssid, 'transmitted', 0x401),
1587 (bssid[0:16] + '1', 'nontransmitted', 0x1),
1588 (bssid[0:16] + '2', 'nontransmitted_2', 0x1)]
586826d4
JM
1589 run_scans(dev[0], check)
1590
1591def test_scan_multi_bssid_3(dev, apdev):
1592 """Scan and Multiple BSSID element (3)"""
1593 check_multibss_sta_capa(dev[0])
1594 dev[0].flush_scan_cache()
1595
fab49f61 1596 params = {"ssid": "transmitted"}
586826d4
JM
1597
1598 # Duplicated nontransmitted BSS (not a normal use case)
1599 elems = elem_capab(1) + elem_ssid("nontransmitted") + elem_bssid_index(1)
1600 profile1 = struct.pack('BB', 0, len(elems)) + elems
1601
1602 elems = elem_capab(1) + elem_ssid("nontransmitted") + elem_bssid_index(1)
1603 profile2 = struct.pack('BB', 0, len(elems)) + elems
1604
1605 profiles = profile1 + profile2
1606 params['vendor_elements'] = elem_multibssid(profiles, 2)
1607 hostapd.add_ap(apdev[0], params)
1608
1609 bssid = apdev[0]['bssid']
fab49f61
JM
1610 check = [(bssid, 'transmitted', 0x401),
1611 (bssid[0:16] + '1', 'nontransmitted', 0x1)]
586826d4
JM
1612 run_scans(dev[0], check)
1613
1614def test_scan_multi_bssid_4(dev, apdev):
1615 """Scan and Multiple BSSID element (3)"""
1616 check_multibss_sta_capa(dev[0])
1617 dev[0].flush_scan_cache()
1618
1619 # Transmitted BSSID is not the first one in the block
1620 bssid = apdev[0]['bssid']
1621 hapd = None
1622 try:
fab49f61
JM
1623 params = {"ssid": "transmitted",
1624 "bssid": bssid[0:16] + '1'}
586826d4
JM
1625
1626 elems = elem_capab(1) + elem_ssid("1") + elem_bssid_index(1)
1627 profile1 = struct.pack('BB', 0, len(elems)) + elems
1628
1629 elems = elem_capab(1) + elem_ssid("2") + elem_bssid_index(2)
1630 profile2 = struct.pack('BB', 0, len(elems)) + elems
1631
1632 elems = elem_capab(1) + elem_ssid("3") + elem_bssid_index(3)
1633 profile3 = struct.pack('BB', 0, len(elems)) + elems
1634
1635 profiles = profile1 + profile2 + profile3
1636 params['vendor_elements'] = elem_multibssid(profiles, 2)
1637 hapd = hostapd.add_ap(apdev[0], params)
1638
fab49f61
JM
1639 check = [(bssid[0:16] + '1', 'transmitted', 0x401),
1640 (bssid[0:16] + '2', '1', 0x1),
1641 (bssid[0:16] + '3', '2', 0x1),
1642 (bssid[0:16] + '0', '3', 0x1)]
586826d4
JM
1643 run_scans(dev[0], check)
1644 finally:
1645 if hapd:
1646 hapd.disable()
1647 hapd.set('bssid', bssid)
1648 hapd.enable()
8d176ae6
PX
1649
1650def test_scan_multi_bssid_check_ie(dev, apdev):
1651 """Scan and check if nontransmitting BSS inherits IE from transmitting BSS"""
1652 check_multibss_sta_capa(dev[0])
1653 dev[0].flush_scan_cache()
1654
fab49f61 1655 params = {"ssid": "transmitted"}
8d176ae6
PX
1656
1657 # Duplicated entry for the transmitted BSS (not a normal use case)
1658 elems = elem_capab(1) + elem_ssid("transmitted") + elem_bssid_index(0)
1659 profile1 = struct.pack('BB', 0, len(elems)) + elems
1660
1661 elems = elem_capab(1) + elem_ssid("nontransmitted") + elem_bssid_index(1)
1662 profile2 = struct.pack('BB', 0, len(elems)) + elems
1663
1664 profiles = profile1 + profile2
1665 params['vendor_elements'] = elem_multibssid(profiles, 2)
1666 hostapd.add_ap(apdev[0], params)
1667
1668 bssid = apdev[0]['bssid']
1669
1670 for i in range(10):
1671 dev[0].request("SCAN TYPE=ONLY freq=2412 passive=1")
1672 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=15)
1673 if ev is None:
1674 raise Exception("Scan did not complete")
1675 if dev[0].get_bss(bssid):
1676 break
1677
1678 for i in range(10):
1679 dev[0].scan_for_bss(bssid, freq=2412, force_scan=True)
1680 bss = dev[0].get_bss(bssid)
1681 if 'beacon_ie' in bss:
1682 break
1683
1684 trans_bss = dev[0].get_bss(bssid)
1685 if trans_bss is None:
1686 raise Exception("AP " + bssid + " missing from scan results")
1687
1688 if not trans_bss or 'beacon_ie' not in trans_bss:
1689 raise Exception("beacon_ie not present in trans_bss")
1690
1691 beacon_ie = parse_ie(trans_bss['beacon_ie'])
35d8c254 1692 logger.info("trans_bss beacon_ie: " + str(list(beacon_ie.keys())))
8d176ae6
PX
1693
1694 bssid = bssid[0:16] + '1'
1695 nontrans_bss1 = dev[0].get_bss(bssid)
1696 if nontrans_bss1 is None:
1697 raise Exception("AP " + bssid + " missing from scan results")
1698
1699 if not trans_bss or 'beacon_ie' not in nontrans_bss1:
1700 raise Exception("beacon_ie not present in nontrans_bss1")
1701
1702 nontx_beacon_ie = parse_ie(nontrans_bss1['beacon_ie'])
35d8c254 1703 logger.info("nontrans_bss1 beacon_ie: " + str(list(nontx_beacon_ie.keys())))
8d176ae6 1704
35d8c254
MH
1705 if 71 in list(beacon_ie.keys()):
1706 ie_list = list(beacon_ie.keys())
8d176ae6 1707 ie_list.remove(71)
8f5b1c40
JM
1708 nontx_ie_list = list(nontx_beacon_ie.keys())
1709 try:
1710 nontx_ie_list.remove(85)
1711 except ValueError:
1712 pass
1713 if sorted(ie_list) != sorted(nontx_ie_list):
8d176ae6
PX
1714 raise Exception("check IE failed")
1715
1716def elem_fms1():
1717 # this FMS IE has 1 FMS counter
1718 fms_counters = struct.pack('B', 0x39)
1719 fms_ids = struct.pack('B', 0x01)
1720 return struct.pack('BBB', 86, 3, 1) + fms_counters + fms_ids
1721
1722def elem_fms2():
1723 # this FMS IE has 2 FMS counters
1724 fms_counters = struct.pack('BB', 0x29, 0x32)
1725 fms_ids = struct.pack('BB', 0x01, 0x02)
1726 return struct.pack('BBB', 86, 5, 2) + fms_counters + fms_ids
1727
1728def test_scan_multi_bssid_fms(dev, apdev):
1729 """Non-transmitting BSS has different FMS IE from transmitting BSS"""
1730 check_multibss_sta_capa(dev[0])
1731 dev[0].flush_scan_cache()
1732
fab49f61 1733 params = {"ssid": "transmitted"}
8d176ae6
PX
1734
1735 # construct transmitting BSS Beacon with FMS IE
1736 elems = elem_capab(1) + elem_ssid("transmitted") + elem_bssid_index(0) + elem_fms1()
1737 profile1 = struct.pack('BB', 0, len(elems)) + elems
1738
1739 elems = elem_capab(1) + elem_ssid("nontransmitted") + elem_bssid_index(1) + elem_fms2()
1740 profile2 = struct.pack('BB', 0, len(elems)) + elems
1741
1742 profiles = profile1 + profile2
d5cac059 1743 params['vendor_elements'] = elem_multibssid(profiles, 2) + binascii.hexlify(elem_fms1()).decode()
8d176ae6
PX
1744 hostapd.add_ap(apdev[0], params)
1745
1746 bssid = apdev[0]['bssid']
1747
1748 for i in range(10):
1749 dev[0].request("SCAN TYPE=ONLY freq=2412 passive=1")
1750 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=15)
1751 if ev is None:
1752 raise Exception("Scan did not complete")
1753 if dev[0].get_bss(bssid):
1754 break
1755
1756 for i in range(10):
1757 dev[0].scan_for_bss(bssid, freq=2412, force_scan=True)
1758 bss = dev[0].get_bss(bssid)
1759 if 'beacon_ie' in bss:
1760 break
1761
1762 trans_bss = dev[0].get_bss(bssid)
1763 if trans_bss is None:
1764 raise Exception("AP " + bssid + " missing from scan results")
1765
1766 if not trans_bss or 'beacon_ie' not in trans_bss:
1767 raise Exception("beacon_ie not present in trans_bss")
1768
1769 beacon_ie = parse_ie(trans_bss['beacon_ie'])
1770 trans_bss_fms = beacon_ie[86]
d5cac059 1771 logger.info("trans_bss fms ie: " + binascii.hexlify(trans_bss_fms).decode())
8d176ae6
PX
1772
1773 bssid = bssid[0:16] + '1'
1774 nontrans_bss1 = dev[0].get_bss(bssid)
1775 if nontrans_bss1 is None:
1776 raise Exception("AP " + bssid + " missing from scan results")
1777
1778 if not nontrans_bss1 or 'beacon_ie' not in nontrans_bss1:
1779 raise Exception("beacon_ie not present in nontrans_bss1")
1780
1781 nontrans_beacon_ie = parse_ie(nontrans_bss1['beacon_ie'])
1782 nontrans_bss_fms = nontrans_beacon_ie[86]
d5cac059 1783 logger.info("nontrans_bss fms ie: " + binascii.hexlify(nontrans_bss_fms).decode())
8d176ae6
PX
1784
1785 if binascii.hexlify(trans_bss_fms) == binascii.hexlify(nontrans_bss_fms):
1786 raise Exception("Nontrans BSS has the same FMS IE as trans BSS")
1787
1788def test_scan_multiple_mbssid_ie(dev, apdev):
1789 """Transmitting BSS has 2 MBSSID IE"""
1790 check_multibss_sta_capa(dev[0])
1791 dev[0].flush_scan_cache()
1792
1793 bssid = apdev[0]['bssid']
58be42b2 1794 logger.info("bssid: " + bssid)
8d176ae6
PX
1795 hapd = None
1796
1797 # construct 2 MBSSID IEs, each MBSSID IE contains 1 profile
fab49f61
JM
1798 params = {"ssid": "transmitted",
1799 "bssid": bssid}
8d176ae6
PX
1800
1801 elems = elem_capab(1) + elem_ssid("1") + elem_bssid_index(1)
1802 profile1 = struct.pack('BB', 0, len(elems)) + elems
1803
1804 elems = elem_capab(2) + elem_ssid("2") + elem_bssid_index(2)
1805 profile2 = struct.pack('BB', 0, len(elems)) + elems
1806
fab49f61 1807 params['vendor_elements'] = elem_multibssid(profile1, 2) + elem_multibssid(profile2, 2)
8d176ae6
PX
1808 hapd = hostapd.add_ap(apdev[0], params)
1809
fab49f61
JM
1810 check = [(bssid, 'transmitted', 0x401),
1811 (bssid[0:16] + '1', '1', 0x1),
1812 (bssid[0:16] + '2', '2', 0x2)]
8d176ae6
PX
1813 run_scans(dev[0], check)
1814
1815def test_scan_mbssid_hidden_ssid(dev, apdev):
1816 """Non-transmitting BSS has hidden SSID"""
1817 check_multibss_sta_capa(dev[0])
1818 dev[0].flush_scan_cache()
1819
1820 bssid = apdev[0]['bssid']
58be42b2 1821 logger.info("bssid: " + bssid)
8d176ae6
PX
1822 hapd = None
1823
1824 # construct 2 MBSSID IEs, each MBSSID IE contains 1 profile
fab49f61
JM
1825 params = {"ssid": "transmitted",
1826 "bssid": bssid}
8d176ae6
PX
1827
1828 elems = elem_capab(1) + elem_ssid("") + elem_bssid_index(1)
1829 profile1 = struct.pack('BB', 0, len(elems)) + elems
1830
1831 elems = elem_capab(2) + elem_ssid("2") + elem_bssid_index(2)
1832 profile2 = struct.pack('BB', 0, len(elems)) + elems
1833
1834 profiles = profile1 + profile2
1835 params['vendor_elements'] = elem_multibssid(profiles, 2)
1836 hapd = hostapd.add_ap(apdev[0], params)
1837
fab49f61
JM
1838 check = [(bssid, 'transmitted', 0x401),
1839 (bssid[0:16] + '1', '', 0x1),
1840 (bssid[0:16] + '2', '2', 0x2)]
8d176ae6 1841 run_scans(dev[0], check)
432c0972
JM
1842
1843def test_connect_mbssid_open_1(dev, apdev):
1844 """Connect to transmitting and nontransmitting BSS in open mode"""
1845 check_multibss_sta_capa(dev[0])
1846 dev[0].flush_scan_cache()
1847
1848 bssid = apdev[0]['bssid']
fab49f61 1849 params = {"ssid": "transmitted"}
432c0972
JM
1850
1851 elems = elem_capab(1) + elem_ssid("nontransmitted") + elem_bssid_index(1)
1852 profile1 = struct.pack('BB', 0, len(elems)) + elems
1853
1854 elems = elem_capab(1) + elem_ssid("nontransmitted_2") + elem_bssid_index(2)
1855 profile2 = struct.pack('BB', 0, len(elems)) + elems
1856
1857 profiles = profile1 + profile2
1858 params['vendor_elements'] = elem_multibssid(profiles, 4)
1859 hostapd.add_ap(apdev[0], params)
1860
1861 dev[0].connect("transmitted", key_mgmt="NONE", scan_freq="2412")
1862 dev[0].request("REMOVE_NETWORK all")
1863 dev[0].wait_disconnected()
1864 dev[0].dump_monitor()
1865
1866 dev[0].connect("nontransmitted", key_mgmt="NONE", scan_freq="2412",
1867 wait_connect=False)
1868 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=10)
1869 if ev is None:
1870 raise Exception("Connection attempt to nontransmitted BSS not started")
1871 if "02:00:00:00:03:01 (SSID='nontransmitted'" not in ev:
1872 raise Exception("Unexpected authentication target")
1873 # hostapd does not yet support Multiple-BSSID, so only verify that STA is
1874 # able to start connection attempt.
1875 dev[0].request("REMOVE_NETWORK all")
1876 dev[0].dump_monitor()
1877
1878 dev[0].connect("nontransmitted_2", key_mgmt="NONE", scan_freq="2412",
1879 wait_connect=False)
1880 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=10)
1881 if ev is None:
1882 raise Exception("Connection attempt to nontransmitted BSS not started")
1883 if "02:00:00:00:03:02 (SSID='nontransmitted_2'" not in ev:
1884 raise Exception("Unexpected authentication target")
1885 # hostapd does not yet support Multiple-BSSID, so only verify that STA is
1886 # able to start connection attempt.
1887 dev[0].request("REMOVE_NETWORK all")
1888 dev[0].dump_monitor()