]>
Commit | Line | Data |
---|---|---|
cf9189b9 | 1 | # Scanning tests |
8aeb6e3d | 2 | # Copyright (c) 2013-2015, 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 | ||
7 | import time | |
8 | import logging | |
9 | logger = logging.getLogger() | |
24e330f7 | 10 | import os |
e766f566 | 11 | import subprocess |
cf9189b9 JM |
12 | |
13 | import hostapd | |
5e29a900 | 14 | from wpasupplicant import WpaSupplicant |
708ec753 | 15 | from utils import HwsimSkip, fail_test |
2e1d7386 | 16 | from tshark import run_tshark |
cf9189b9 | 17 | |
9446f3c2 | 18 | def check_scan(dev, params, other_started=False, test_busy=False): |
e766f566 JM |
19 | if not other_started: |
20 | dev.dump_monitor() | |
cf9189b9 JM |
21 | id = dev.request("SCAN " + params) |
22 | if "FAIL" in id: | |
23 | raise Exception("Failed to start scan") | |
24 | id = int(id) | |
25 | ||
9446f3c2 JM |
26 | if test_busy: |
27 | if "FAIL-BUSY" not in dev.request("SCAN"): | |
28 | raise Exception("SCAN command while already scanning not rejected") | |
29 | ||
e766f566 JM |
30 | if other_started: |
31 | ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"]) | |
32 | if ev is None: | |
33 | raise Exception("Other scan did not start") | |
34 | if "id=" + str(id) in ev: | |
35 | raise Exception("Own scan id unexpectedly included in start event") | |
36 | ||
37 | ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"]) | |
38 | if ev is None: | |
39 | raise Exception("Other scan did not complete") | |
40 | if "id=" + str(id) in ev: | |
41 | raise Exception("Own scan id unexpectedly included in completed event") | |
42 | ||
cf9189b9 JM |
43 | ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"]) |
44 | if ev is None: | |
45 | raise Exception("Scan did not start") | |
46 | if "id=" + str(id) not in ev: | |
47 | raise Exception("Scan id not included in start event") | |
9446f3c2 JM |
48 | if test_busy: |
49 | if "FAIL-BUSY" not in dev.request("SCAN"): | |
50 | raise Exception("SCAN command while already scanning not rejected") | |
cf9189b9 JM |
51 | |
52 | ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"]) | |
53 | if ev is None: | |
54 | raise Exception("Scan did not complete") | |
55 | if "id=" + str(id) not in ev: | |
56 | raise Exception("Scan id not included in completed event") | |
57 | ||
814f7ac8 JM |
58 | def check_scan_retry(dev, params, bssid): |
59 | for i in range(0, 5): | |
60 | check_scan(dev, "freq=2412-2462,5180 use_id=1") | |
61 | if int(dev.get_bss(bssid)['age']) <= 1: | |
62 | return | |
63 | raise Exception("Unexpectedly old BSS entry") | |
64 | ||
cf9189b9 JM |
65 | def test_scan(dev, apdev): |
66 | """Control interface behavior on scan parameters""" | |
8b8a1864 | 67 | hostapd.add_ap(apdev[0], { "ssid": "test-scan" }) |
cf9189b9 JM |
68 | bssid = apdev[0]['bssid'] |
69 | ||
70 | logger.info("Full scan") | |
9446f3c2 | 71 | check_scan(dev[0], "use_id=1", test_busy=True) |
cf9189b9 JM |
72 | |
73 | logger.info("Limited channel scan") | |
814f7ac8 | 74 | check_scan_retry(dev[0], "freq=2412-2462,5180 use_id=1", bssid) |
cf9189b9 JM |
75 | |
76 | # wait long enough to allow next scans to be verified not to find the AP | |
77 | time.sleep(2) | |
78 | ||
79 | logger.info("Passive single-channel scan") | |
80 | check_scan(dev[0], "freq=2457 passive=1 use_id=1") | |
81 | logger.info("Active single-channel scan") | |
82 | check_scan(dev[0], "freq=2452 passive=0 use_id=1") | |
83 | if int(dev[0].get_bss(bssid)['age']) < 2: | |
84 | raise Exception("Unexpectedly updated BSS entry") | |
85 | ||
86 | logger.info("Active single-channel scan on AP's operating channel") | |
814f7ac8 | 87 | check_scan_retry(dev[0], "freq=2412 passive=0 use_id=1", bssid) |
cf9189b9 | 88 | |
76de2b67 JM |
89 | def test_scan_tsf(dev, apdev): |
90 | """Scan and TSF updates from Beacon/Probe Response frames""" | |
8b8a1864 JD |
91 | hostapd.add_ap(apdev[0], { "ssid": "test-scan", |
92 | 'beacon_int': "100" }) | |
76de2b67 JM |
93 | bssid = apdev[0]['bssid'] |
94 | ||
95 | tsf = [] | |
96 | for passive in [ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1 ]: | |
97 | check_scan(dev[0], "freq=2412 passive=%d use_id=1" % passive) | |
98 | bss = dev[0].get_bss(bssid) | |
99 | if bss: | |
100 | tsf.append(int(bss['tsf'])) | |
101 | logger.info("TSF: " + bss['tsf']) | |
102 | if tsf[-3] <= tsf[-4]: | |
103 | # For now, only write this in the log without failing the test case | |
104 | # since mac80211_hwsim does not yet update the Timestamp field in | |
105 | # Probe Response frames. | |
106 | logger.info("Probe Response did not update TSF") | |
107 | #raise Exception("Probe Response did not update TSF") | |
108 | if tsf[-1] <= tsf[-3]: | |
109 | raise Exception("Beacon did not update TSF") | |
110 | if 0 in tsf: | |
111 | raise Exception("0 TSF reported") | |
112 | ||
cf9189b9 JM |
113 | def test_scan_only(dev, apdev): |
114 | """Control interface behavior on scan parameters with type=only""" | |
8b8a1864 | 115 | hostapd.add_ap(apdev[0], { "ssid": "test-scan" }) |
cf9189b9 JM |
116 | bssid = apdev[0]['bssid'] |
117 | ||
118 | logger.info("Full scan") | |
119 | check_scan(dev[0], "type=only use_id=1") | |
120 | ||
121 | logger.info("Limited channel scan") | |
814f7ac8 | 122 | check_scan_retry(dev[0], "type=only freq=2412-2462,5180 use_id=1", bssid) |
cf9189b9 JM |
123 | |
124 | # wait long enough to allow next scans to be verified not to find the AP | |
125 | time.sleep(2) | |
126 | ||
127 | logger.info("Passive single-channel scan") | |
128 | check_scan(dev[0], "type=only freq=2457 passive=1 use_id=1") | |
129 | logger.info("Active single-channel scan") | |
130 | check_scan(dev[0], "type=only freq=2452 passive=0 use_id=1") | |
131 | if int(dev[0].get_bss(bssid)['age']) < 2: | |
132 | raise Exception("Unexpectedly updated BSS entry") | |
133 | ||
134 | logger.info("Active single-channel scan on AP's operating channel") | |
814f7ac8 | 135 | check_scan_retry(dev[0], "type=only freq=2412 passive=0 use_id=1", bssid) |
e766f566 JM |
136 | |
137 | def test_scan_external_trigger(dev, apdev): | |
138 | """Avoid operations during externally triggered scan""" | |
8b8a1864 | 139 | hostapd.add_ap(apdev[0], { "ssid": "test-scan" }) |
e766f566 | 140 | bssid = apdev[0]['bssid'] |
c4668009 | 141 | subprocess.call(['iw', dev[0].ifname, 'scan', 'trigger']) |
e766f566 | 142 | check_scan(dev[0], "use_id=1", other_started=True) |
b3ec107c JM |
143 | |
144 | def test_scan_bss_expiration_count(dev, apdev): | |
145 | """BSS entry expiration based on scan results without match""" | |
146 | if "FAIL" not in dev[0].request("BSS_EXPIRE_COUNT 0"): | |
147 | raise Exception("Invalid BSS_EXPIRE_COUNT accepted") | |
148 | if "OK" not in dev[0].request("BSS_EXPIRE_COUNT 2"): | |
149 | raise Exception("BSS_EXPIRE_COUNT failed") | |
8b8a1864 | 150 | hapd = hostapd.add_ap(apdev[0], { "ssid": "test-scan" }) |
b3ec107c JM |
151 | bssid = apdev[0]['bssid'] |
152 | dev[0].scan(freq="2412", only_new=True) | |
153 | if bssid not in dev[0].request("SCAN_RESULTS"): | |
154 | raise Exception("BSS not found in initial scan") | |
155 | hapd.request("DISABLE") | |
156 | dev[0].scan(freq="2412", only_new=True) | |
157 | if bssid not in dev[0].request("SCAN_RESULTS"): | |
158 | raise Exception("BSS not found in first scan without match") | |
159 | dev[0].scan(freq="2412", only_new=True) | |
160 | if bssid in dev[0].request("SCAN_RESULTS"): | |
161 | raise Exception("BSS found after two scans without match") | |
162 | ||
163 | def test_scan_bss_expiration_age(dev, apdev): | |
164 | """BSS entry expiration based on age""" | |
165 | try: | |
166 | if "FAIL" not in dev[0].request("BSS_EXPIRE_AGE COUNT 9"): | |
167 | raise Exception("Invalid BSS_EXPIRE_AGE accepted") | |
168 | if "OK" not in dev[0].request("BSS_EXPIRE_AGE 10"): | |
169 | raise Exception("BSS_EXPIRE_AGE failed") | |
8b8a1864 | 170 | hapd = hostapd.add_ap(apdev[0], { "ssid": "test-scan" }) |
b3ec107c | 171 | bssid = apdev[0]['bssid'] |
96425ea5 JM |
172 | # Allow couple more retries to avoid reporting errors during heavy load |
173 | for i in range(5): | |
174 | dev[0].scan(freq="2412") | |
175 | if bssid in dev[0].request("SCAN_RESULTS"): | |
176 | break | |
b3ec107c JM |
177 | if bssid not in dev[0].request("SCAN_RESULTS"): |
178 | raise Exception("BSS not found in initial scan") | |
179 | hapd.request("DISABLE") | |
180 | logger.info("Waiting for BSS entry to expire") | |
181 | time.sleep(7) | |
182 | if bssid not in dev[0].request("SCAN_RESULTS"): | |
183 | raise Exception("BSS expired too quickly") | |
184 | ev = dev[0].wait_event(["CTRL-EVENT-BSS-REMOVED"], timeout=15) | |
185 | if ev is None: | |
186 | raise Exception("BSS entry expiration timed out") | |
187 | if bssid in dev[0].request("SCAN_RESULTS"): | |
188 | raise Exception("BSS not removed after expiration time") | |
189 | finally: | |
190 | dev[0].request("BSS_EXPIRE_AGE 180") | |
167d8497 JM |
191 | |
192 | def test_scan_filter(dev, apdev): | |
193 | """Filter scan results based on SSID""" | |
194 | try: | |
195 | if "OK" not in dev[0].request("SET filter_ssids 1"): | |
196 | raise Exception("SET failed") | |
7749b1c9 | 197 | id = dev[0].connect("test-scan", key_mgmt="NONE", only_add_network=True) |
8b8a1864 | 198 | hostapd.add_ap(apdev[0], { "ssid": "test-scan" }) |
167d8497 | 199 | bssid = apdev[0]['bssid'] |
8b8a1864 | 200 | hostapd.add_ap(apdev[1], { "ssid": "test-scan2" }) |
167d8497 JM |
201 | bssid2 = apdev[1]['bssid'] |
202 | dev[0].scan(freq="2412", only_new=True) | |
203 | if bssid not in dev[0].request("SCAN_RESULTS"): | |
204 | raise Exception("BSS not found in scan results") | |
205 | if bssid2 in dev[0].request("SCAN_RESULTS"): | |
206 | raise Exception("Unexpected BSS found in scan results") | |
7749b1c9 JM |
207 | dev[0].set_network_quoted(id, "ssid", "") |
208 | dev[0].scan(freq="2412") | |
209 | id2 = dev[0].connect("test", key_mgmt="NONE", only_add_network=True) | |
210 | dev[0].scan(freq="2412") | |
167d8497 JM |
211 | finally: |
212 | dev[0].request("SET filter_ssids 0") | |
24e330f7 JM |
213 | |
214 | def test_scan_int(dev, apdev): | |
215 | """scan interval configuration""" | |
216 | try: | |
217 | if "FAIL" not in dev[0].request("SCAN_INTERVAL -1"): | |
218 | raise Exception("Accepted invalid scan interval") | |
219 | if "OK" not in dev[0].request("SCAN_INTERVAL 1"): | |
220 | raise Exception("Failed to set scan interval") | |
221 | dev[0].connect("not-used", key_mgmt="NONE", scan_freq="2412", | |
222 | wait_connect=False) | |
223 | times = {} | |
224 | for i in range(0, 3): | |
225 | logger.info("Waiting for scan to start") | |
226 | start = os.times()[4] | |
227 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5) | |
228 | if ev is None: | |
229 | raise Exception("did not start a scan") | |
230 | stop = os.times()[4] | |
231 | times[i] = stop - start | |
232 | logger.info("Waiting for scan to complete") | |
233 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10) | |
234 | if ev is None: | |
235 | raise Exception("did not complete a scan") | |
2e0d48e5 | 236 | logger.info("times=" + str(times)) |
24e330f7 JM |
237 | if times[0] > 1 or times[1] < 0.5 or times[1] > 1.5 or times[2] < 0.5 or times[2] > 1.5: |
238 | raise Exception("Unexpected scan timing: " + str(times)) | |
239 | finally: | |
240 | dev[0].request("SCAN_INTERVAL 5") | |
59650258 JM |
241 | |
242 | def test_scan_bss_operations(dev, apdev): | |
243 | """Control interface behavior on BSS parameters""" | |
8b8a1864 | 244 | hostapd.add_ap(apdev[0], { "ssid": "test-scan" }) |
59650258 | 245 | bssid = apdev[0]['bssid'] |
8b8a1864 | 246 | hostapd.add_ap(apdev[1], { "ssid": "test2-scan" }) |
59650258 JM |
247 | bssid2 = apdev[1]['bssid'] |
248 | ||
249 | dev[0].scan(freq="2412") | |
250 | dev[0].scan(freq="2412") | |
251 | dev[0].scan(freq="2412") | |
252 | ||
cb4ac38b JM |
253 | id1 = dev[0].request("BSS FIRST MASK=0x1").splitlines()[0].split('=')[1] |
254 | id2 = dev[0].request("BSS LAST MASK=0x1").splitlines()[0].split('=')[1] | |
255 | ||
59650258 | 256 | res = dev[0].request("BSS RANGE=ALL MASK=0x20001") |
cb4ac38b JM |
257 | if "id=" + id1 not in res: |
258 | raise Exception("Missing BSS " + id1) | |
259 | if "id=" + id2 not in res: | |
260 | raise Exception("Missing BSS " + id2) | |
59650258 JM |
261 | if "====" not in res: |
262 | raise Exception("Missing delim") | |
263 | if "####" not in res: | |
264 | raise Exception("Missing end") | |
265 | ||
5b2f1e24 JM |
266 | res = dev[0].request("BSS RANGE=ALL MASK=0") |
267 | if "id=" + id1 not in res: | |
268 | raise Exception("Missing BSS " + id1) | |
269 | if "id=" + id2 not in res: | |
270 | raise Exception("Missing BSS " + id2) | |
271 | if "====" in res: | |
272 | raise Exception("Unexpected delim") | |
273 | if "####" in res: | |
274 | raise Exception("Unexpected end delim") | |
275 | ||
59650258 JM |
276 | res = dev[0].request("BSS RANGE=ALL MASK=0x1").splitlines() |
277 | if len(res) != 2: | |
610cfff5 | 278 | raise Exception("Unexpected result: " + str(res)) |
59650258 | 279 | res = dev[0].request("BSS FIRST MASK=0x1") |
cb4ac38b | 280 | if "id=" + id1 not in res: |
59650258 JM |
281 | raise Exception("Unexpected result: " + res) |
282 | res = dev[0].request("BSS LAST MASK=0x1") | |
cb4ac38b | 283 | if "id=" + id2 not in res: |
59650258 | 284 | raise Exception("Unexpected result: " + res) |
cb4ac38b JM |
285 | res = dev[0].request("BSS ID-" + id1 + " MASK=0x1") |
286 | if "id=" + id1 not in res: | |
59650258 | 287 | raise Exception("Unexpected result: " + res) |
cb4ac38b JM |
288 | res = dev[0].request("BSS NEXT-" + id1 + " MASK=0x1") |
289 | if "id=" + id2 not in res: | |
59650258 | 290 | raise Exception("Unexpected result: " + res) |
5b2f1e24 JM |
291 | res = dev[0].request("BSS NEXT-" + id2 + " MASK=0x1") |
292 | if "id=" in res: | |
293 | raise Exception("Unexpected result: " + res) | |
59650258 | 294 | |
cb4ac38b | 295 | if len(dev[0].request("BSS RANGE=" + id2 + " MASK=0x1").splitlines()) != 0: |
59650258 | 296 | raise Exception("Unexpected RANGE=1 result") |
cb4ac38b | 297 | if len(dev[0].request("BSS RANGE=" + id1 + "- MASK=0x1").splitlines()) != 2: |
59650258 | 298 | raise Exception("Unexpected RANGE=0- result") |
cb4ac38b | 299 | if len(dev[0].request("BSS RANGE=-" + id2 + " MASK=0x1").splitlines()) != 2: |
59650258 | 300 | raise Exception("Unexpected RANGE=-1 result") |
cb4ac38b | 301 | if len(dev[0].request("BSS RANGE=" + id1 + "-" + id2 + " MASK=0x1").splitlines()) != 2: |
59650258 | 302 | raise Exception("Unexpected RANGE=0-1 result") |
cb4ac38b | 303 | if len(dev[0].request("BSS RANGE=" + id2 + "-" + id2 + " MASK=0x1").splitlines()) != 1: |
59650258 | 304 | raise Exception("Unexpected RANGE=1-1 result") |
cb4ac38b | 305 | if len(dev[0].request("BSS RANGE=" + str(int(id2) + 1) + "-" + str(int(id2) + 10) + " MASK=0x1").splitlines()) != 0: |
59650258 | 306 | raise Exception("Unexpected RANGE=2-10 result") |
cb4ac38b | 307 | if len(dev[0].request("BSS RANGE=0-" + str(int(id2) + 10) + " MASK=0x1").splitlines()) != 2: |
59650258 | 308 | raise Exception("Unexpected RANGE=0-10 result") |
5b2f1e24 JM |
309 | if len(dev[0].request("BSS RANGE=" + id1 + "-" + id1 + " MASK=0x1").splitlines()) != 1: |
310 | raise Exception("Unexpected RANGE=0-0 result") | |
311 | ||
312 | res = dev[0].request("BSS p2p_dev_addr=FOO") | |
313 | if "FAIL" in res or "id=" in res: | |
314 | raise Exception("Unexpected result: " + res) | |
315 | res = dev[0].request("BSS p2p_dev_addr=00:11:22:33:44:55") | |
316 | if "FAIL" in res or "id=" in res: | |
317 | raise Exception("Unexpected result: " + res) | |
318 | ||
319 | dev[0].request("BSS_FLUSH 1000") | |
320 | res = dev[0].request("BSS RANGE=ALL MASK=0x1").splitlines() | |
321 | if len(res) != 2: | |
322 | raise Exception("Unexpected result after BSS_FLUSH 1000") | |
323 | dev[0].request("BSS_FLUSH 0") | |
324 | res = dev[0].request("BSS RANGE=ALL MASK=0x1").splitlines() | |
325 | if len(res) != 0: | |
326 | raise Exception("Unexpected result after BSS_FLUSH 0") | |
23a6d4d8 JM |
327 | |
328 | def test_scan_and_interface_disabled(dev, apdev): | |
329 | """Scan operation when interface gets disabled""" | |
330 | try: | |
331 | dev[0].request("SCAN") | |
332 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"]) | |
333 | if ev is None: | |
334 | raise Exception("Scan did not start") | |
335 | dev[0].request("DRIVER_EVENT INTERFACE_DISABLED") | |
336 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=7) | |
337 | if ev is not None: | |
338 | raise Exception("Scan completed unexpectedly") | |
339 | ||
340 | # verify that scan is rejected | |
341 | if "FAIL" not in dev[0].request("SCAN"): | |
342 | raise Exception("New scan request was accepted unexpectedly") | |
343 | ||
344 | dev[0].request("DRIVER_EVENT INTERFACE_ENABLED") | |
345 | dev[0].scan(freq="2412") | |
346 | finally: | |
347 | dev[0].request("DRIVER_EVENT INTERFACE_ENABLED") | |
cf2f3698 JM |
348 | |
349 | def test_scan_for_auth(dev, apdev): | |
350 | """cfg80211 workaround with scan-for-auth""" | |
8b8a1864 | 351 | hapd = hostapd.add_ap(apdev[0], { "ssid": "open" }) |
cf2f3698 JM |
352 | dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") |
353 | # Block sme-connect radio work with an external radio work item, so that | |
354 | # SELECT_NETWORK can decide to use fast associate without a new scan while | |
355 | # cfg80211 still has the matching BSS entry, but the actual connection is | |
356 | # not yet started. | |
357 | id = dev[0].request("RADIO_WORK add block-work") | |
358 | ev = dev[0].wait_event(["EXT-RADIO-WORK-START"]) | |
359 | if ev is None: | |
360 | raise Exception("Timeout while waiting radio work to start") | |
361 | dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", | |
362 | wait_connect=False) | |
c7f35a9e | 363 | dev[0].dump_monitor() |
cf2f3698 | 364 | # Clear cfg80211 BSS table. |
a4a15cf1 JM |
365 | try: |
366 | subprocess.check_call(['iw', dev[0].ifname, 'scan', 'trigger', | |
367 | 'freq', '2457', 'flush']) | |
368 | except subprocess.CalledProcessError, e: | |
369 | raise HwsimSkip("iw scan trigger flush not supported") | |
c7f35a9e JM |
370 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5) |
371 | if ev is None: | |
372 | raise Exception("External flush scan timed out") | |
cf2f3698 JM |
373 | # Release blocking radio work to allow connection to go through with the |
374 | # cfg80211 BSS entry missing. | |
375 | dev[0].request("RADIO_WORK done " + id) | |
376 | ||
5f35a5e2 | 377 | dev[0].wait_connected(timeout=15) |
e8e571d7 | 378 | |
a5687274 JM |
379 | def test_scan_for_auth_fail(dev, apdev): |
380 | """cfg80211 workaround with scan-for-auth failing""" | |
8b8a1864 | 381 | hapd = hostapd.add_ap(apdev[0], { "ssid": "open" }) |
a5687274 JM |
382 | dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") |
383 | # Block sme-connect radio work with an external radio work item, so that | |
384 | # SELECT_NETWORK can decide to use fast associate without a new scan while | |
385 | # cfg80211 still has the matching BSS entry, but the actual connection is | |
386 | # not yet started. | |
387 | id = dev[0].request("RADIO_WORK add block-work") | |
388 | ev = dev[0].wait_event(["EXT-RADIO-WORK-START"]) | |
389 | if ev is None: | |
390 | raise Exception("Timeout while waiting radio work to start") | |
391 | dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", | |
392 | wait_connect=False) | |
393 | dev[0].dump_monitor() | |
394 | hapd.disable() | |
395 | # Clear cfg80211 BSS table. | |
a4a15cf1 JM |
396 | try: |
397 | subprocess.check_call(['iw', dev[0].ifname, 'scan', 'trigger', | |
398 | 'freq', '2457', 'flush']) | |
399 | except subprocess.CalledProcessError, e: | |
400 | raise HwsimSkip("iw scan trigger flush not supported") | |
a5687274 JM |
401 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5) |
402 | if ev is None: | |
403 | raise Exception("External flush scan timed out") | |
404 | # Release blocking radio work to allow connection to go through with the | |
405 | # cfg80211 BSS entry missing. | |
406 | dev[0].request("RADIO_WORK done " + id) | |
407 | ||
408 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS", | |
409 | "CTRL-EVENT-CONNECTED"], 15) | |
410 | if ev is None: | |
411 | raise Exception("Scan event missing") | |
412 | if "CTRL-EVENT-CONNECTED" in ev: | |
413 | raise Exception("Unexpected connection") | |
414 | dev[0].request("DISCONNECT") | |
415 | ||
1e752829 JM |
416 | def test_scan_for_auth_wep(dev, apdev): |
417 | """cfg80211 scan-for-auth workaround with WEP keys""" | |
418 | dev[0].flush_scan_cache() | |
8b8a1864 | 419 | hapd = hostapd.add_ap(apdev[0], |
1e752829 JM |
420 | { "ssid": "wep", "wep_key0": '"abcde"', |
421 | "auth_algs": "2" }) | |
422 | dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") | |
423 | # Block sme-connect radio work with an external radio work item, so that | |
424 | # SELECT_NETWORK can decide to use fast associate without a new scan while | |
425 | # cfg80211 still has the matching BSS entry, but the actual connection is | |
426 | # not yet started. | |
427 | id = dev[0].request("RADIO_WORK add block-work") | |
428 | ev = dev[0].wait_event(["EXT-RADIO-WORK-START"]) | |
429 | if ev is None: | |
430 | raise Exception("Timeout while waiting radio work to start") | |
431 | dev[0].connect("wep", key_mgmt="NONE", wep_key0='"abcde"', | |
432 | auth_alg="SHARED", scan_freq="2412", wait_connect=False) | |
433 | dev[0].dump_monitor() | |
434 | # Clear cfg80211 BSS table. | |
a4a15cf1 JM |
435 | try: |
436 | subprocess.check_call(['iw', dev[0].ifname, 'scan', 'trigger', | |
437 | 'freq', '2457', 'flush']) | |
438 | except subprocess.CalledProcessError, e: | |
439 | raise HwsimSkip("iw scan trigger flush not supported") | |
1e752829 JM |
440 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5) |
441 | if ev is None: | |
442 | raise Exception("External flush scan timed out") | |
443 | # Release blocking radio work to allow connection to go through with the | |
444 | # cfg80211 BSS entry missing. | |
445 | dev[0].request("RADIO_WORK done " + id) | |
446 | ||
447 | dev[0].wait_connected(timeout=15) | |
448 | ||
e8e571d7 JM |
449 | def test_scan_hidden(dev, apdev): |
450 | """Control interface behavior on scan parameters""" | |
8b8a1864 JD |
451 | hapd = hostapd.add_ap(apdev[0], { "ssid": "test-scan", |
452 | "ignore_broadcast_ssid": "1" }) | |
e8e571d7 JM |
453 | bssid = apdev[0]['bssid'] |
454 | ||
455 | check_scan(dev[0], "freq=2412 use_id=1") | |
456 | if "test-scan" in dev[0].request("SCAN_RESULTS"): | |
457 | raise Exception("BSS unexpectedly found in initial scan") | |
458 | ||
459 | id1 = dev[0].connect("foo", key_mgmt="NONE", scan_ssid="1", | |
460 | only_add_network=True) | |
461 | id2 = dev[0].connect("test-scan", key_mgmt="NONE", scan_ssid="1", | |
462 | only_add_network=True) | |
463 | id3 = dev[0].connect("bar", key_mgmt="NONE", only_add_network=True) | |
464 | ||
465 | check_scan(dev[0], "freq=2412 use_id=1") | |
466 | if "test-scan" in dev[0].request("SCAN_RESULTS"): | |
467 | raise Exception("BSS unexpectedly found in scan") | |
468 | ||
29bac7cb JM |
469 | # Allow multiple attempts to be more robust under heavy CPU load that can |
470 | # result in Probe Response frames getting sent only after the station has | |
471 | # already stopped waiting for the response on the channel. | |
472 | found = False | |
473 | for i in range(10): | |
474 | check_scan(dev[0], "scan_id=%d,%d,%d freq=2412 use_id=1" % (id1, id2, id3)) | |
475 | if "test-scan" in dev[0].request("SCAN_RESULTS"): | |
476 | found = True | |
477 | break | |
478 | if not found: | |
e8e571d7 | 479 | raise Exception("BSS not found in scan") |
5e29a900 | 480 | |
9446f3c2 JM |
481 | 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"): |
482 | raise Exception("Too many scan_id values accepted") | |
483 | ||
b3f41349 | 484 | dev[0].request("REMOVE_NETWORK all") |
610cfff5 | 485 | hapd.disable() |
b3f41349 JM |
486 | dev[0].flush_scan_cache(freq=2432) |
487 | dev[0].flush_scan_cache() | |
488 | ||
5e29a900 JM |
489 | def test_scan_and_bss_entry_removed(dev, apdev): |
490 | """Last scan result and connect work processing on BSS entry update""" | |
8b8a1864 JD |
491 | hapd = hostapd.add_ap(apdev[0], { "ssid": "open", |
492 | "eap_server": "1", | |
493 | "wps_state": "2" }) | |
5e29a900 JM |
494 | bssid = apdev[0]['bssid'] |
495 | ||
496 | wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') | |
497 | wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") | |
498 | ||
499 | # Add a BSS entry | |
500 | dev[0].scan_for_bss(bssid, freq="2412") | |
501 | wpas.scan_for_bss(bssid, freq="2412") | |
502 | ||
503 | # Start a connect radio work with a blocking entry preventing this from | |
504 | # proceeding; this stores a pointer to the selected BSS entry. | |
505 | id = dev[0].request("RADIO_WORK add block-work") | |
506 | w_id = wpas.request("RADIO_WORK add block-work") | |
507 | dev[0].wait_event(["EXT-RADIO-WORK-START"], timeout=1) | |
508 | wpas.wait_event(["EXT-RADIO-WORK-START"], timeout=1) | |
509 | nid = dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", | |
510 | wait_connect=False) | |
511 | w_nid = wpas.connect("open", key_mgmt="NONE", scan_freq="2412", | |
512 | wait_connect=False) | |
513 | time.sleep(0.1) | |
514 | ||
515 | # Remove the BSS entry | |
516 | dev[0].request("BSS_FLUSH 0") | |
517 | wpas.request("BSS_FLUSH 0") | |
518 | ||
519 | # Allow the connect radio work to continue. The bss entry stored in the | |
520 | # pending connect work is now stale. This will result in the connection | |
521 | # attempt failing since the BSS entry does not exist. | |
522 | dev[0].request("RADIO_WORK done " + id) | |
523 | wpas.request("RADIO_WORK done " + w_id) | |
524 | ||
525 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
526 | if ev is not None: | |
527 | raise Exception("Unexpected connection") | |
528 | dev[0].remove_network(nid) | |
529 | ev = wpas.wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
530 | if ev is not None: | |
531 | raise Exception("Unexpected connection") | |
532 | wpas.remove_network(w_nid) | |
533 | time.sleep(0.5) | |
534 | dev[0].request("BSS_FLUSH 0") | |
535 | wpas.request("BSS_FLUSH 0") | |
536 | ||
537 | # Add a BSS entry | |
538 | dev[0].scan_for_bss(bssid, freq="2412") | |
539 | wpas.scan_for_bss(bssid, freq="2412") | |
540 | ||
541 | # Start a connect radio work with a blocking entry preventing this from | |
542 | # proceeding; this stores a pointer to the selected BSS entry. | |
543 | id = dev[0].request("RADIO_WORK add block-work") | |
544 | w_id = wpas.request("RADIO_WORK add block-work") | |
545 | dev[0].wait_event(["EXT-RADIO-WORK-START"], timeout=1) | |
546 | wpas.wait_event(["EXT-RADIO-WORK-START"], timeout=1) | |
547 | ||
548 | # Schedule a connection based on the current BSS entry. | |
549 | dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", | |
550 | wait_connect=False) | |
551 | wpas.connect("open", key_mgmt="NONE", scan_freq="2412", | |
552 | wait_connect=False) | |
553 | ||
554 | # Update scan results with results that have longer set of IEs so that new | |
555 | # memory needs to be allocated for the BSS entry. | |
556 | hapd.request("WPS_PBC") | |
557 | time.sleep(0.1) | |
558 | subprocess.call(['iw', dev[0].ifname, 'scan', 'trigger', 'freq', '2412']) | |
559 | subprocess.call(['iw', wpas.ifname, 'scan', 'trigger', 'freq', '2412']) | |
560 | time.sleep(0.1) | |
561 | ||
562 | # Allow the connect radio work to continue. The bss entry stored in the | |
563 | # pending connect work becomes stale during the scan and it must have been | |
564 | # updated for the connection to work. | |
565 | dev[0].request("RADIO_WORK done " + id) | |
566 | wpas.request("RADIO_WORK done " + w_id) | |
567 | ||
5f35a5e2 JM |
568 | dev[0].wait_connected(timeout=15, error="No connection (sme-connect)") |
569 | wpas.wait_connected(timeout=15, error="No connection (connect)") | |
e51c8b2e JM |
570 | dev[0].request("DISCONNECT") |
571 | wpas.request("DISCONNECT") | |
572 | dev[0].flush_scan_cache() | |
573 | wpas.flush_scan_cache() | |
83e80d32 JM |
574 | |
575 | def test_scan_reqs_with_non_scan_radio_work(dev, apdev): | |
576 | """SCAN commands while non-scan radio_work is in progress""" | |
577 | id = dev[0].request("RADIO_WORK add test-work-a") | |
578 | ev = dev[0].wait_event(["EXT-RADIO-WORK-START"]) | |
579 | if ev is None: | |
580 | raise Exception("Timeout while waiting radio work to start") | |
581 | ||
582 | if "OK" not in dev[0].request("SCAN"): | |
583 | raise Exception("SCAN failed") | |
584 | if "FAIL-BUSY" not in dev[0].request("SCAN"): | |
585 | raise Exception("SCAN accepted while one is already pending") | |
586 | if "FAIL-BUSY" not in dev[0].request("SCAN"): | |
587 | raise Exception("SCAN accepted while one is already pending") | |
588 | ||
589 | res = dev[0].request("RADIO_WORK show").splitlines() | |
590 | count = 0 | |
591 | for l in res: | |
592 | if "scan" in l: | |
593 | count += 1 | |
594 | if count != 1: | |
595 | logger.info(res) | |
596 | raise Exception("Unexpected number of scan radio work items") | |
597 | ||
598 | dev[0].dump_monitor() | |
599 | dev[0].request("RADIO_WORK done " + id) | |
600 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5) | |
601 | if ev is None: | |
602 | raise Exception("Scan did not start") | |
603 | if "FAIL-BUSY" not in dev[0].request("SCAN"): | |
604 | raise Exception("SCAN accepted while one is already in progress") | |
605 | ||
606 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10) | |
607 | if ev is None: | |
608 | print "Scan did not complete" | |
609 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.2) | |
610 | if ev is not None: | |
611 | raise Exception("Unexpected scan started") | |
558ac77c JM |
612 | |
613 | def test_scan_setband(dev, apdev): | |
614 | """Band selection for scan operations""" | |
615 | try: | |
616 | hapd = None | |
617 | hapd2 = None | |
618 | params = { "ssid": "test-setband", | |
619 | "hw_mode": "a", | |
620 | "channel": "36", | |
621 | "country_code": "US" } | |
8b8a1864 | 622 | hapd = hostapd.add_ap(apdev[0], params) |
558ac77c JM |
623 | bssid = apdev[0]['bssid'] |
624 | ||
625 | params = { "ssid": "test-setband", | |
626 | "hw_mode": "g", | |
627 | "channel": "1" } | |
8b8a1864 | 628 | hapd2 = hostapd.add_ap(apdev[1], params) |
558ac77c JM |
629 | bssid2 = apdev[1]['bssid'] |
630 | ||
631 | if "FAIL" not in dev[0].request("SET setband FOO"): | |
632 | raise Exception("Invalid set setband accepted") | |
633 | if "OK" not in dev[0].request("SET setband AUTO"): | |
634 | raise Exception("Failed to set setband") | |
635 | if "OK" not in dev[1].request("SET setband 5G"): | |
636 | raise Exception("Failed to set setband") | |
637 | if "OK" not in dev[2].request("SET setband 2G"): | |
638 | raise Exception("Failed to set setband") | |
639 | ||
96425ea5 JM |
640 | # Allow a retry to avoid reporting errors during heavy load |
641 | for j in range(5): | |
642 | for i in range(3): | |
643 | dev[i].request("SCAN only_new=1") | |
558ac77c | 644 | |
96425ea5 JM |
645 | for i in range(3): |
646 | ev = dev[i].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15) | |
647 | if ev is None: | |
648 | raise Exception("Scan timed out") | |
649 | ||
650 | res0 = dev[0].request("SCAN_RESULTS") | |
651 | res1 = dev[1].request("SCAN_RESULTS") | |
652 | res2 = dev[2].request("SCAN_RESULTS") | |
653 | if bssid in res0 and bssid2 in res0 and bssid in res1 and bssid2 in res2: | |
654 | break | |
558ac77c JM |
655 | |
656 | res = dev[0].request("SCAN_RESULTS") | |
657 | if bssid not in res or bssid2 not in res: | |
658 | raise Exception("Missing scan result(0)") | |
659 | ||
660 | res = dev[1].request("SCAN_RESULTS") | |
661 | if bssid not in res: | |
662 | raise Exception("Missing scan result(1)") | |
663 | if bssid2 in res: | |
664 | raise Exception("Unexpected scan result(1)") | |
665 | ||
666 | res = dev[2].request("SCAN_RESULTS") | |
667 | if bssid2 not in res: | |
668 | raise Exception("Missing scan result(2)") | |
669 | if bssid in res: | |
670 | raise Exception("Unexpected scan result(2)") | |
671 | finally: | |
672 | if hapd: | |
673 | hapd.request("DISABLE") | |
674 | if hapd2: | |
675 | hapd2.request("DISABLE") | |
676 | subprocess.call(['iw', 'reg', 'set', '00']) | |
677 | for i in range(3): | |
678 | dev[i].request("SET setband AUTO") | |
679 | dev[i].flush_scan_cache() | |
42ce1a27 JM |
680 | |
681 | def test_scan_hidden_many(dev, apdev): | |
682 | """scan_ssid=1 with large number of profile with hidden SSID""" | |
683 | try: | |
684 | _test_scan_hidden_many(dev, apdev) | |
685 | finally: | |
610cfff5 | 686 | dev[0].flush_scan_cache(freq=2432) |
42ce1a27 JM |
687 | dev[0].flush_scan_cache() |
688 | dev[0].request("SCAN_INTERVAL 5") | |
689 | ||
690 | def _test_scan_hidden_many(dev, apdev): | |
8b8a1864 JD |
691 | hapd = hostapd.add_ap(apdev[0], { "ssid": "test-scan-ssid", |
692 | "ignore_broadcast_ssid": "1" }) | |
42ce1a27 JM |
693 | bssid = apdev[0]['bssid'] |
694 | ||
695 | dev[0].request("SCAN_INTERVAL 1") | |
696 | ||
697 | for i in range(5): | |
698 | id = dev[0].add_network() | |
699 | dev[0].set_network_quoted(id, "ssid", "foo") | |
700 | dev[0].set_network(id, "key_mgmt", "NONE") | |
701 | dev[0].set_network(id, "disabled", "0") | |
702 | dev[0].set_network(id, "scan_freq", "2412") | |
703 | dev[0].set_network(id, "scan_ssid", "1") | |
704 | ||
705 | dev[0].set_network_quoted(id, "ssid", "test-scan-ssid") | |
706 | dev[0].set_network(id, "key_mgmt", "NONE") | |
707 | dev[0].set_network(id, "disabled", "0") | |
708 | dev[0].set_network(id, "scan_freq", "2412") | |
709 | dev[0].set_network(id, "scan_ssid", "1") | |
710 | ||
711 | for i in range(5): | |
712 | id = dev[0].add_network() | |
713 | dev[0].set_network_quoted(id, "ssid", "foo") | |
714 | dev[0].set_network(id, "key_mgmt", "NONE") | |
715 | dev[0].set_network(id, "disabled", "0") | |
716 | dev[0].set_network(id, "scan_freq", "2412") | |
717 | dev[0].set_network(id, "scan_ssid", "1") | |
718 | ||
719 | dev[0].request("REASSOCIATE") | |
5f35a5e2 | 720 | dev[0].wait_connected(timeout=30) |
610cfff5 JM |
721 | dev[0].request("REMOVE_NETWORK all") |
722 | hapd.disable() | |
8aeb6e3d JM |
723 | |
724 | def test_scan_random_mac(dev, apdev, params): | |
725 | """Random MAC address in scans""" | |
726 | try: | |
727 | _test_scan_random_mac(dev, apdev, params) | |
728 | finally: | |
729 | dev[0].request("MAC_RAND_SCAN all enable=0") | |
730 | ||
731 | def _test_scan_random_mac(dev, apdev, params): | |
8b8a1864 | 732 | hostapd.add_ap(apdev[0], { "ssid": "test-scan" }) |
8aeb6e3d JM |
733 | bssid = apdev[0]['bssid'] |
734 | ||
735 | tests = [ "", | |
736 | "addr=foo", | |
737 | "mask=foo", | |
738 | "enable=1", | |
739 | "all enable=1 mask=00:11:22:33:44:55", | |
740 | "all enable=1 addr=00:11:22:33:44:55", | |
741 | "all enable=1 addr=01:11:22:33:44:55 mask=ff:ff:ff:ff:ff:ff", | |
742 | "all enable=1 addr=00:11:22:33:44:55 mask=fe:ff:ff:ff:ff:ff", | |
743 | "enable=2 scan sched pno all", | |
744 | "pno enable=1", | |
745 | "all enable=2", | |
746 | "foo" ] | |
747 | for args in tests: | |
748 | if "FAIL" not in dev[0].request("MAC_RAND_SCAN " + args): | |
749 | raise Exception("Invalid MAC_RAND_SCAN accepted: " + args) | |
750 | ||
751 | if dev[0].get_driver_status_field('capa.mac_addr_rand_scan_supported') != '1': | |
51c5aeb4 | 752 | raise HwsimSkip("Driver does not support random MAC address for scanning") |
8aeb6e3d JM |
753 | |
754 | tests = [ "all enable=1", | |
755 | "all enable=1 addr=f2:11:22:33:44:55 mask=ff:ff:ff:ff:ff:ff", | |
756 | "all enable=1 addr=f2:11:33:00:00:00 mask=ff:ff:ff:00:00:00" ] | |
757 | for args in tests: | |
758 | dev[0].request("MAC_RAND_SCAN " + args) | |
759 | dev[0].scan_for_bss(bssid, freq=2412, force_scan=True) | |
8aeb6e3d | 760 | |
2e1d7386 JB |
761 | out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"), |
762 | "wlan.fc.type_subtype == 4", ["wlan.ta" ]) | |
763 | if out is not None: | |
8aeb6e3d JM |
764 | addr = out.splitlines() |
765 | logger.info("Probe Request frames seen from: " + str(addr)) | |
766 | if dev[0].own_addr() in addr: | |
767 | raise Exception("Real address used to transmit Probe Request frame") | |
768 | if "f2:11:22:33:44:55" not in addr: | |
769 | raise Exception("Fully configured random address not seen") | |
770 | found = False | |
771 | for a in addr: | |
772 | if a.startswith('f2:11:33'): | |
773 | found = True | |
774 | break | |
775 | if not found: | |
776 | raise Exception("Fixed OUI random address not seen") | |
2dc18e9a JM |
777 | |
778 | def test_scan_trigger_failure(dev, apdev): | |
779 | """Scan trigger to the driver failing""" | |
8b8a1864 | 780 | hostapd.add_ap(apdev[0], { "ssid": "test-scan" }) |
2dc18e9a JM |
781 | bssid = apdev[0]['bssid'] |
782 | ||
783 | if "OK" not in dev[0].request("SET test_failure 1"): | |
784 | raise Exception("Failed to set test_failure") | |
785 | ||
786 | if "OK" not in dev[0].request("SCAN"): | |
787 | raise Exception("SCAN command failed") | |
788 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=10) | |
789 | if ev is None: | |
790 | raise Exception("Did not receive CTRL-EVENT-SCAN-FAILED event") | |
791 | if "retry=1" in ev: | |
792 | raise Exception("Unexpected scan retry indicated") | |
793 | if dev[0].get_status_field('wpa_state') == "SCANNING": | |
794 | raise Exception("wpa_state SCANNING not cleared") | |
795 | ||
796 | id = dev[0].connect("test-scan", key_mgmt="NONE", scan_freq="2412", | |
797 | only_add_network=True) | |
798 | dev[0].select_network(id) | |
799 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=10) | |
800 | if ev is None: | |
801 | raise Exception("Did not receive CTRL-EVENT-SCAN-FAILED event") | |
802 | if "retry=1" not in ev: | |
803 | raise Exception("No scan retry indicated for connection") | |
804 | if dev[0].get_status_field('wpa_state') == "SCANNING": | |
805 | raise Exception("wpa_state SCANNING not cleared") | |
806 | dev[0].request("SET test_failure 0") | |
807 | dev[0].wait_connected() | |
808 | ||
809 | dev[0].request("SET test_failure 1") | |
810 | if "OK" not in dev[0].request("SCAN"): | |
811 | raise Exception("SCAN command failed") | |
812 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=10) | |
813 | if ev is None: | |
814 | raise Exception("Did not receive CTRL-EVENT-SCAN-FAILED event") | |
815 | if "retry=1" in ev: | |
816 | raise Exception("Unexpected scan retry indicated") | |
817 | if dev[0].get_status_field('wpa_state') != "COMPLETED": | |
818 | raise Exception("wpa_state COMPLETED not restored") | |
819 | dev[0].request("SET test_failure 0") | |
98c71cf6 JM |
820 | |
821 | def test_scan_specify_ssid(dev, apdev): | |
822 | """Control interface behavior on scan SSID parameter""" | |
823 | dev[0].flush_scan_cache() | |
8b8a1864 JD |
824 | hapd = hostapd.add_ap(apdev[0], { "ssid": "test-hidden", |
825 | "ignore_broadcast_ssid": "1" }) | |
98c71cf6 JM |
826 | bssid = apdev[0]['bssid'] |
827 | check_scan(dev[0], "freq=2412 use_id=1 ssid 414243") | |
828 | bss = dev[0].get_bss(bssid) | |
829 | if bss is not None and bss['ssid'] == 'test-hidden': | |
830 | raise Exception("BSS entry for hidden AP present unexpectedly") | |
96425ea5 JM |
831 | # Allow couple more retries to avoid reporting errors during heavy load |
832 | for i in range(5): | |
833 | check_scan(dev[0], "freq=2412 ssid 414243 ssid 746573742d68696464656e ssid 616263313233 use_id=1") | |
834 | bss = dev[0].get_bss(bssid) | |
835 | if bss and 'test-hidden' in dev[0].request("SCAN_RESULTS"): | |
836 | break | |
98c71cf6 JM |
837 | if bss is None: |
838 | raise Exception("BSS entry for hidden AP not found") | |
839 | if 'test-hidden' not in dev[0].request("SCAN_RESULTS"): | |
840 | raise Exception("Expected SSID not included in the scan results"); | |
841 | ||
842 | hapd.disable() | |
843 | dev[0].flush_scan_cache(freq=2432) | |
844 | dev[0].flush_scan_cache() | |
845 | ||
846 | if "FAIL" not in dev[0].request("SCAN ssid foo"): | |
847 | raise Exception("Invalid SCAN command accepted") | |
708ec753 JM |
848 | |
849 | def test_scan_ap_scan_2_ap_mode(dev, apdev): | |
850 | """AP_SCAN 2 AP mode and scan()""" | |
851 | try: | |
852 | _test_scan_ap_scan_2_ap_mode(dev, apdev) | |
853 | finally: | |
854 | dev[0].request("AP_SCAN 1") | |
855 | ||
856 | def _test_scan_ap_scan_2_ap_mode(dev, apdev): | |
857 | if "OK" not in dev[0].request("AP_SCAN 2"): | |
858 | raise Exception("Failed to set AP_SCAN 2") | |
859 | ||
860 | id = dev[0].add_network() | |
861 | dev[0].set_network(id, "mode", "2") | |
862 | dev[0].set_network_quoted(id, "ssid", "wpas-ap-open") | |
863 | dev[0].set_network(id, "key_mgmt", "NONE") | |
864 | dev[0].set_network(id, "frequency", "2412") | |
865 | dev[0].set_network(id, "scan_freq", "2412") | |
866 | dev[0].set_network(id, "disabled", "0") | |
867 | dev[0].select_network(id) | |
868 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5) | |
869 | if ev is None: | |
870 | raise Exception("AP failed to start") | |
871 | ||
872 | with fail_test(dev[0], 1, "wpa_driver_nl80211_scan"): | |
873 | if "OK" not in dev[0].request("SCAN freq=2412"): | |
874 | raise Exception("SCAN command failed unexpectedly") | |
875 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED", | |
876 | "AP-DISABLED"], timeout=5) | |
877 | if ev is None: | |
878 | raise Exception("CTRL-EVENT-SCAN-FAILED not seen") | |
879 | if "AP-DISABLED" in ev: | |
880 | raise Exception("Unexpected AP-DISABLED event") | |
881 | if "retry=1" in ev: | |
882 | # Wait for the retry to scan happen | |
883 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED", | |
884 | "AP-DISABLED"], timeout=5) | |
885 | if ev is None: | |
886 | raise Exception("CTRL-EVENT-SCAN-FAILED not seen - retry") | |
887 | if "AP-DISABLED" in ev: | |
888 | raise Exception("Unexpected AP-DISABLED event - retry") | |
889 | ||
890 | dev[1].connect("wpas-ap-open", key_mgmt="NONE", scan_freq="2412") | |
891 | dev[1].request("DISCONNECT") | |
892 | dev[1].wait_disconnected() | |
893 | dev[0].request("DISCONNECT") | |
894 | dev[0].wait_disconnected() | |
2313e6c9 JM |
895 | |
896 | def test_scan_bss_expiration_on_ssid_change(dev, apdev): | |
897 | """BSS entry expiration when AP changes SSID""" | |
898 | dev[0].flush_scan_cache() | |
8b8a1864 | 899 | hapd = hostapd.add_ap(apdev[0], { "ssid": "test-scan" }) |
2313e6c9 JM |
900 | bssid = apdev[0]['bssid'] |
901 | dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") | |
902 | ||
903 | hapd.request("DISABLE") | |
8b8a1864 | 904 | hapd = hostapd.add_ap(apdev[0], { "ssid": "open" }) |
2313e6c9 JM |
905 | if "OK" not in dev[0].request("BSS_EXPIRE_COUNT 3"): |
906 | raise Exception("BSS_EXPIRE_COUNT failed") | |
907 | dev[0].scan(freq="2412") | |
908 | dev[0].scan(freq="2412") | |
909 | if "OK" not in dev[0].request("BSS_EXPIRE_COUNT 2"): | |
910 | raise Exception("BSS_EXPIRE_COUNT failed") | |
911 | res = dev[0].request("SCAN_RESULTS") | |
912 | if "test-scan" not in res: | |
913 | raise Exception("The first SSID not in scan results") | |
914 | if "open" not in res: | |
915 | raise Exception("The second SSID not in scan results") | |
916 | dev[0].connect("open", key_mgmt="NONE") | |
917 | ||
918 | dev[0].request("BSS_FLUSH 0") | |
919 | res = dev[0].request("SCAN_RESULTS") | |
920 | if "test-scan" in res: | |
921 | raise Exception("The BSS entry with the old SSID was not removed") | |
922 | dev[0].request("DISCONNECT") | |
923 | dev[0].wait_disconnected() | |
f9bf2225 JM |
924 | |
925 | def test_scan_dfs(dev, apdev, params): | |
926 | """Scan on DFS channels""" | |
927 | try: | |
928 | _test_scan_dfs(dev, apdev, params) | |
929 | finally: | |
930 | subprocess.call(['iw', 'reg', 'set', '00']) | |
931 | ||
932 | def _test_scan_dfs(dev, apdev, params): | |
933 | subprocess.call(['iw', 'reg', 'set', 'US']) | |
934 | for i in range(2): | |
935 | for j in range(5): | |
936 | ev = dev[i].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=5) | |
937 | if ev is None: | |
938 | raise Exception("No regdom change event") | |
939 | if "alpha2=US" in ev: | |
940 | break | |
941 | dev[i].dump_monitor() | |
942 | ||
943 | if "OK" not in dev[0].request("SCAN"): | |
944 | raise Exception("SCAN command failed") | |
945 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"]) | |
946 | if ev is None: | |
947 | raise Exception("Scan did not complete") | |
948 | ||
949 | if "OK" not in dev[0].request("SCAN freq=2412,5180,5260,5500,5600,5745"): | |
950 | raise Exception("SCAN command failed") | |
951 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"]) | |
952 | if ev is None: | |
953 | raise Exception("Scan did not complete") | |
954 | ||
955 | out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"), | |
956 | "wlan.fc.type_subtype == 4", [ "radiotap.channel.freq" ]) | |
957 | if out is not None: | |
958 | freq = out.splitlines() | |
b25f04d4 | 959 | freq = [int(f) for f in freq] |
f9bf2225 | 960 | freq = list(set(freq)) |
b25f04d4 | 961 | freq.sort() |
f9bf2225 | 962 | logger.info("Active scan seen on channels: " + str(freq)) |
b25f04d4 | 963 | for f in freq: |
f9bf2225 JM |
964 | if (f >= 5260 and f <= 5320) or (f >= 5500 and f <= 5700): |
965 | raise Exception("Active scan on DFS channel: %d" % f) | |
f0154bf4 JM |
966 | if f in [ 2467, 2472 ]: |
967 | raise Exception("Active scan on US-disallowed channel: %d" % f) | |
77676871 JM |
968 | |
969 | def test_scan_abort(dev, apdev): | |
970 | """Aborting a full scan""" | |
971 | dev[0].request("SCAN") | |
972 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"]) | |
973 | if ev is None: | |
974 | raise Exception("Scan did not start") | |
975 | if "OK" not in dev[0].request("ABORT_SCAN"): | |
976 | raise Exception("ABORT_SCAN command failed") | |
977 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=2) | |
978 | if ev is None: | |
979 | raise Exception("Scan did not terminate") | |
980 | ||
981 | def test_scan_abort_on_connect(dev, apdev): | |
982 | """Aborting a full scan on connection request""" | |
8b8a1864 | 983 | hostapd.add_ap(apdev[0], { "ssid": "test-scan" }) |
77676871 JM |
984 | bssid = apdev[0]['bssid'] |
985 | ||
986 | dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") | |
987 | dev[0].dump_monitor() | |
988 | dev[0].request("SCAN") | |
989 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"]) | |
990 | if ev is None: | |
991 | raise Exception("Scan did not start") | |
992 | dev[0].connect("test-scan", key_mgmt="NONE") |