]>
Commit | Line | Data |
---|---|---|
cf9189b9 JM |
1 | # Scanning tests |
2 | # Copyright (c) 2013, Jouni Malinen <j@w1.fi> | |
3 | # | |
4 | # This software may be distributed under the terms of the BSD license. | |
5 | # See README for more details. | |
6 | ||
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 |
cf9189b9 | 15 | |
9446f3c2 | 16 | def check_scan(dev, params, other_started=False, test_busy=False): |
e766f566 JM |
17 | if not other_started: |
18 | dev.dump_monitor() | |
cf9189b9 JM |
19 | id = dev.request("SCAN " + params) |
20 | if "FAIL" in id: | |
21 | raise Exception("Failed to start scan") | |
22 | id = int(id) | |
23 | ||
9446f3c2 JM |
24 | if test_busy: |
25 | if "FAIL-BUSY" not in dev.request("SCAN"): | |
26 | raise Exception("SCAN command while already scanning not rejected") | |
27 | ||
e766f566 JM |
28 | if other_started: |
29 | ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"]) | |
30 | if ev is None: | |
31 | raise Exception("Other scan did not start") | |
32 | if "id=" + str(id) in ev: | |
33 | raise Exception("Own scan id unexpectedly included in start event") | |
34 | ||
35 | ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"]) | |
36 | if ev is None: | |
37 | raise Exception("Other scan did not complete") | |
38 | if "id=" + str(id) in ev: | |
39 | raise Exception("Own scan id unexpectedly included in completed event") | |
40 | ||
cf9189b9 JM |
41 | ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"]) |
42 | if ev is None: | |
43 | raise Exception("Scan did not start") | |
44 | if "id=" + str(id) not in ev: | |
45 | raise Exception("Scan id not included in start event") | |
9446f3c2 JM |
46 | if test_busy: |
47 | if "FAIL-BUSY" not in dev.request("SCAN"): | |
48 | raise Exception("SCAN command while already scanning not rejected") | |
cf9189b9 JM |
49 | |
50 | ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"]) | |
51 | if ev is None: | |
52 | raise Exception("Scan did not complete") | |
53 | if "id=" + str(id) not in ev: | |
54 | raise Exception("Scan id not included in completed event") | |
55 | ||
814f7ac8 JM |
56 | def check_scan_retry(dev, params, bssid): |
57 | for i in range(0, 5): | |
58 | check_scan(dev, "freq=2412-2462,5180 use_id=1") | |
59 | if int(dev.get_bss(bssid)['age']) <= 1: | |
60 | return | |
61 | raise Exception("Unexpectedly old BSS entry") | |
62 | ||
cf9189b9 JM |
63 | def test_scan(dev, apdev): |
64 | """Control interface behavior on scan parameters""" | |
65 | hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" }) | |
66 | bssid = apdev[0]['bssid'] | |
67 | ||
68 | logger.info("Full scan") | |
9446f3c2 | 69 | check_scan(dev[0], "use_id=1", test_busy=True) |
cf9189b9 JM |
70 | |
71 | logger.info("Limited channel scan") | |
814f7ac8 | 72 | check_scan_retry(dev[0], "freq=2412-2462,5180 use_id=1", bssid) |
cf9189b9 JM |
73 | |
74 | # wait long enough to allow next scans to be verified not to find the AP | |
75 | time.sleep(2) | |
76 | ||
77 | logger.info("Passive single-channel scan") | |
78 | check_scan(dev[0], "freq=2457 passive=1 use_id=1") | |
79 | logger.info("Active single-channel scan") | |
80 | check_scan(dev[0], "freq=2452 passive=0 use_id=1") | |
81 | if int(dev[0].get_bss(bssid)['age']) < 2: | |
82 | raise Exception("Unexpectedly updated BSS entry") | |
83 | ||
84 | logger.info("Active single-channel scan on AP's operating channel") | |
814f7ac8 | 85 | check_scan_retry(dev[0], "freq=2412 passive=0 use_id=1", bssid) |
cf9189b9 JM |
86 | |
87 | def test_scan_only(dev, apdev): | |
88 | """Control interface behavior on scan parameters with type=only""" | |
89 | hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" }) | |
90 | bssid = apdev[0]['bssid'] | |
91 | ||
92 | logger.info("Full scan") | |
93 | check_scan(dev[0], "type=only use_id=1") | |
94 | ||
95 | logger.info("Limited channel scan") | |
814f7ac8 | 96 | check_scan_retry(dev[0], "type=only freq=2412-2462,5180 use_id=1", bssid) |
cf9189b9 JM |
97 | |
98 | # wait long enough to allow next scans to be verified not to find the AP | |
99 | time.sleep(2) | |
100 | ||
101 | logger.info("Passive single-channel scan") | |
102 | check_scan(dev[0], "type=only freq=2457 passive=1 use_id=1") | |
103 | logger.info("Active single-channel scan") | |
104 | check_scan(dev[0], "type=only freq=2452 passive=0 use_id=1") | |
105 | if int(dev[0].get_bss(bssid)['age']) < 2: | |
106 | raise Exception("Unexpectedly updated BSS entry") | |
107 | ||
108 | logger.info("Active single-channel scan on AP's operating channel") | |
814f7ac8 | 109 | check_scan_retry(dev[0], "type=only freq=2412 passive=0 use_id=1", bssid) |
e766f566 JM |
110 | |
111 | def test_scan_external_trigger(dev, apdev): | |
112 | """Avoid operations during externally triggered scan""" | |
113 | hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" }) | |
114 | bssid = apdev[0]['bssid'] | |
115 | subprocess.call(['sudo', 'iw', dev[0].ifname, 'scan', 'trigger']) | |
116 | check_scan(dev[0], "use_id=1", other_started=True) | |
b3ec107c JM |
117 | |
118 | def test_scan_bss_expiration_count(dev, apdev): | |
119 | """BSS entry expiration based on scan results without match""" | |
120 | if "FAIL" not in dev[0].request("BSS_EXPIRE_COUNT 0"): | |
121 | raise Exception("Invalid BSS_EXPIRE_COUNT accepted") | |
122 | if "OK" not in dev[0].request("BSS_EXPIRE_COUNT 2"): | |
123 | raise Exception("BSS_EXPIRE_COUNT failed") | |
124 | hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" }) | |
125 | bssid = apdev[0]['bssid'] | |
126 | dev[0].scan(freq="2412", only_new=True) | |
127 | if bssid not in dev[0].request("SCAN_RESULTS"): | |
128 | raise Exception("BSS not found in initial scan") | |
129 | hapd.request("DISABLE") | |
130 | dev[0].scan(freq="2412", only_new=True) | |
131 | if bssid not in dev[0].request("SCAN_RESULTS"): | |
132 | raise Exception("BSS not found in first scan without match") | |
133 | dev[0].scan(freq="2412", only_new=True) | |
134 | if bssid in dev[0].request("SCAN_RESULTS"): | |
135 | raise Exception("BSS found after two scans without match") | |
136 | ||
137 | def test_scan_bss_expiration_age(dev, apdev): | |
138 | """BSS entry expiration based on age""" | |
139 | try: | |
140 | if "FAIL" not in dev[0].request("BSS_EXPIRE_AGE COUNT 9"): | |
141 | raise Exception("Invalid BSS_EXPIRE_AGE accepted") | |
142 | if "OK" not in dev[0].request("BSS_EXPIRE_AGE 10"): | |
143 | raise Exception("BSS_EXPIRE_AGE failed") | |
144 | hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" }) | |
145 | bssid = apdev[0]['bssid'] | |
146 | dev[0].scan(freq="2412") | |
147 | if bssid not in dev[0].request("SCAN_RESULTS"): | |
148 | raise Exception("BSS not found in initial scan") | |
149 | hapd.request("DISABLE") | |
150 | logger.info("Waiting for BSS entry to expire") | |
151 | time.sleep(7) | |
152 | if bssid not in dev[0].request("SCAN_RESULTS"): | |
153 | raise Exception("BSS expired too quickly") | |
154 | ev = dev[0].wait_event(["CTRL-EVENT-BSS-REMOVED"], timeout=15) | |
155 | if ev is None: | |
156 | raise Exception("BSS entry expiration timed out") | |
157 | if bssid in dev[0].request("SCAN_RESULTS"): | |
158 | raise Exception("BSS not removed after expiration time") | |
159 | finally: | |
160 | dev[0].request("BSS_EXPIRE_AGE 180") | |
167d8497 JM |
161 | |
162 | def test_scan_filter(dev, apdev): | |
163 | """Filter scan results based on SSID""" | |
164 | try: | |
165 | if "OK" not in dev[0].request("SET filter_ssids 1"): | |
166 | raise Exception("SET failed") | |
7749b1c9 | 167 | id = dev[0].connect("test-scan", key_mgmt="NONE", only_add_network=True) |
167d8497 JM |
168 | hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" }) |
169 | bssid = apdev[0]['bssid'] | |
170 | hostapd.add_ap(apdev[1]['ifname'], { "ssid": "test-scan2" }) | |
171 | bssid2 = apdev[1]['bssid'] | |
172 | dev[0].scan(freq="2412", only_new=True) | |
173 | if bssid not in dev[0].request("SCAN_RESULTS"): | |
174 | raise Exception("BSS not found in scan results") | |
175 | if bssid2 in dev[0].request("SCAN_RESULTS"): | |
176 | raise Exception("Unexpected BSS found in scan results") | |
7749b1c9 JM |
177 | dev[0].set_network_quoted(id, "ssid", "") |
178 | dev[0].scan(freq="2412") | |
179 | id2 = dev[0].connect("test", key_mgmt="NONE", only_add_network=True) | |
180 | dev[0].scan(freq="2412") | |
167d8497 JM |
181 | finally: |
182 | dev[0].request("SET filter_ssids 0") | |
24e330f7 JM |
183 | |
184 | def test_scan_int(dev, apdev): | |
185 | """scan interval configuration""" | |
186 | try: | |
187 | if "FAIL" not in dev[0].request("SCAN_INTERVAL -1"): | |
188 | raise Exception("Accepted invalid scan interval") | |
189 | if "OK" not in dev[0].request("SCAN_INTERVAL 1"): | |
190 | raise Exception("Failed to set scan interval") | |
191 | dev[0].connect("not-used", key_mgmt="NONE", scan_freq="2412", | |
192 | wait_connect=False) | |
193 | times = {} | |
194 | for i in range(0, 3): | |
195 | logger.info("Waiting for scan to start") | |
196 | start = os.times()[4] | |
197 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5) | |
198 | if ev is None: | |
199 | raise Exception("did not start a scan") | |
200 | stop = os.times()[4] | |
201 | times[i] = stop - start | |
202 | logger.info("Waiting for scan to complete") | |
203 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10) | |
204 | if ev is None: | |
205 | raise Exception("did not complete a scan") | |
206 | print times | |
207 | if times[0] > 1 or times[1] < 0.5 or times[1] > 1.5 or times[2] < 0.5 or times[2] > 1.5: | |
208 | raise Exception("Unexpected scan timing: " + str(times)) | |
209 | finally: | |
210 | dev[0].request("SCAN_INTERVAL 5") | |
59650258 JM |
211 | |
212 | def test_scan_bss_operations(dev, apdev): | |
213 | """Control interface behavior on BSS parameters""" | |
214 | hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" }) | |
215 | bssid = apdev[0]['bssid'] | |
216 | hostapd.add_ap(apdev[1]['ifname'], { "ssid": "test2-scan" }) | |
217 | bssid2 = apdev[1]['bssid'] | |
218 | ||
219 | dev[0].scan(freq="2412") | |
220 | dev[0].scan(freq="2412") | |
221 | dev[0].scan(freq="2412") | |
222 | ||
cb4ac38b JM |
223 | id1 = dev[0].request("BSS FIRST MASK=0x1").splitlines()[0].split('=')[1] |
224 | id2 = dev[0].request("BSS LAST MASK=0x1").splitlines()[0].split('=')[1] | |
225 | ||
59650258 | 226 | res = dev[0].request("BSS RANGE=ALL MASK=0x20001") |
cb4ac38b JM |
227 | if "id=" + id1 not in res: |
228 | raise Exception("Missing BSS " + id1) | |
229 | if "id=" + id2 not in res: | |
230 | raise Exception("Missing BSS " + id2) | |
59650258 JM |
231 | if "====" not in res: |
232 | raise Exception("Missing delim") | |
233 | if "####" not in res: | |
234 | raise Exception("Missing end") | |
235 | ||
5b2f1e24 JM |
236 | res = dev[0].request("BSS RANGE=ALL MASK=0") |
237 | if "id=" + id1 not in res: | |
238 | raise Exception("Missing BSS " + id1) | |
239 | if "id=" + id2 not in res: | |
240 | raise Exception("Missing BSS " + id2) | |
241 | if "====" in res: | |
242 | raise Exception("Unexpected delim") | |
243 | if "####" in res: | |
244 | raise Exception("Unexpected end delim") | |
245 | ||
59650258 JM |
246 | res = dev[0].request("BSS RANGE=ALL MASK=0x1").splitlines() |
247 | if len(res) != 2: | |
248 | raise Exception("Unexpected result") | |
249 | res = dev[0].request("BSS FIRST MASK=0x1") | |
cb4ac38b | 250 | if "id=" + id1 not in res: |
59650258 JM |
251 | raise Exception("Unexpected result: " + res) |
252 | res = dev[0].request("BSS LAST MASK=0x1") | |
cb4ac38b | 253 | if "id=" + id2 not in res: |
59650258 | 254 | raise Exception("Unexpected result: " + res) |
cb4ac38b JM |
255 | res = dev[0].request("BSS ID-" + id1 + " MASK=0x1") |
256 | if "id=" + id1 not in res: | |
59650258 | 257 | raise Exception("Unexpected result: " + res) |
cb4ac38b JM |
258 | res = dev[0].request("BSS NEXT-" + id1 + " MASK=0x1") |
259 | if "id=" + id2 not in res: | |
59650258 | 260 | raise Exception("Unexpected result: " + res) |
5b2f1e24 JM |
261 | res = dev[0].request("BSS NEXT-" + id2 + " MASK=0x1") |
262 | if "id=" in res: | |
263 | raise Exception("Unexpected result: " + res) | |
59650258 | 264 | |
cb4ac38b | 265 | if len(dev[0].request("BSS RANGE=" + id2 + " MASK=0x1").splitlines()) != 0: |
59650258 | 266 | raise Exception("Unexpected RANGE=1 result") |
cb4ac38b | 267 | if len(dev[0].request("BSS RANGE=" + id1 + "- MASK=0x1").splitlines()) != 2: |
59650258 | 268 | raise Exception("Unexpected RANGE=0- result") |
cb4ac38b | 269 | if len(dev[0].request("BSS RANGE=-" + id2 + " MASK=0x1").splitlines()) != 2: |
59650258 | 270 | raise Exception("Unexpected RANGE=-1 result") |
cb4ac38b | 271 | if len(dev[0].request("BSS RANGE=" + id1 + "-" + id2 + " MASK=0x1").splitlines()) != 2: |
59650258 | 272 | raise Exception("Unexpected RANGE=0-1 result") |
cb4ac38b | 273 | if len(dev[0].request("BSS RANGE=" + id2 + "-" + id2 + " MASK=0x1").splitlines()) != 1: |
59650258 | 274 | raise Exception("Unexpected RANGE=1-1 result") |
cb4ac38b | 275 | if len(dev[0].request("BSS RANGE=" + str(int(id2) + 1) + "-" + str(int(id2) + 10) + " MASK=0x1").splitlines()) != 0: |
59650258 | 276 | raise Exception("Unexpected RANGE=2-10 result") |
cb4ac38b | 277 | if len(dev[0].request("BSS RANGE=0-" + str(int(id2) + 10) + " MASK=0x1").splitlines()) != 2: |
59650258 | 278 | raise Exception("Unexpected RANGE=0-10 result") |
5b2f1e24 JM |
279 | if len(dev[0].request("BSS RANGE=" + id1 + "-" + id1 + " MASK=0x1").splitlines()) != 1: |
280 | raise Exception("Unexpected RANGE=0-0 result") | |
281 | ||
282 | res = dev[0].request("BSS p2p_dev_addr=FOO") | |
283 | if "FAIL" in res or "id=" in res: | |
284 | raise Exception("Unexpected result: " + res) | |
285 | res = dev[0].request("BSS p2p_dev_addr=00:11:22:33:44:55") | |
286 | if "FAIL" in res or "id=" in res: | |
287 | raise Exception("Unexpected result: " + res) | |
288 | ||
289 | dev[0].request("BSS_FLUSH 1000") | |
290 | res = dev[0].request("BSS RANGE=ALL MASK=0x1").splitlines() | |
291 | if len(res) != 2: | |
292 | raise Exception("Unexpected result after BSS_FLUSH 1000") | |
293 | dev[0].request("BSS_FLUSH 0") | |
294 | res = dev[0].request("BSS RANGE=ALL MASK=0x1").splitlines() | |
295 | if len(res) != 0: | |
296 | raise Exception("Unexpected result after BSS_FLUSH 0") | |
23a6d4d8 JM |
297 | |
298 | def test_scan_and_interface_disabled(dev, apdev): | |
299 | """Scan operation when interface gets disabled""" | |
300 | try: | |
301 | dev[0].request("SCAN") | |
302 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"]) | |
303 | if ev is None: | |
304 | raise Exception("Scan did not start") | |
305 | dev[0].request("DRIVER_EVENT INTERFACE_DISABLED") | |
306 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=7) | |
307 | if ev is not None: | |
308 | raise Exception("Scan completed unexpectedly") | |
309 | ||
310 | # verify that scan is rejected | |
311 | if "FAIL" not in dev[0].request("SCAN"): | |
312 | raise Exception("New scan request was accepted unexpectedly") | |
313 | ||
314 | dev[0].request("DRIVER_EVENT INTERFACE_ENABLED") | |
315 | dev[0].scan(freq="2412") | |
316 | finally: | |
317 | dev[0].request("DRIVER_EVENT INTERFACE_ENABLED") | |
cf2f3698 JM |
318 | |
319 | def test_scan_for_auth(dev, apdev): | |
320 | """cfg80211 workaround with scan-for-auth""" | |
321 | hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" }) | |
322 | dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") | |
323 | # Block sme-connect radio work with an external radio work item, so that | |
324 | # SELECT_NETWORK can decide to use fast associate without a new scan while | |
325 | # cfg80211 still has the matching BSS entry, but the actual connection is | |
326 | # not yet started. | |
327 | id = dev[0].request("RADIO_WORK add block-work") | |
328 | ev = dev[0].wait_event(["EXT-RADIO-WORK-START"]) | |
329 | if ev is None: | |
330 | raise Exception("Timeout while waiting radio work to start") | |
331 | dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", | |
332 | wait_connect=False) | |
c7f35a9e | 333 | dev[0].dump_monitor() |
cf2f3698 | 334 | # Clear cfg80211 BSS table. |
c7f35a9e JM |
335 | subprocess.call(['iw', dev[0].ifname, 'scan', 'trigger', |
336 | 'freq', '2457', 'flush']) | |
337 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5) | |
338 | if ev is None: | |
339 | raise Exception("External flush scan timed out") | |
cf2f3698 JM |
340 | # Release blocking radio work to allow connection to go through with the |
341 | # cfg80211 BSS entry missing. | |
342 | dev[0].request("RADIO_WORK done " + id) | |
343 | ||
5f35a5e2 | 344 | dev[0].wait_connected(timeout=15) |
e8e571d7 JM |
345 | |
346 | def test_scan_hidden(dev, apdev): | |
347 | """Control interface behavior on scan parameters""" | |
348 | hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan", | |
349 | "ignore_broadcast_ssid": "1" }) | |
350 | bssid = apdev[0]['bssid'] | |
351 | ||
352 | check_scan(dev[0], "freq=2412 use_id=1") | |
353 | if "test-scan" in dev[0].request("SCAN_RESULTS"): | |
354 | raise Exception("BSS unexpectedly found in initial scan") | |
355 | ||
356 | id1 = dev[0].connect("foo", key_mgmt="NONE", scan_ssid="1", | |
357 | only_add_network=True) | |
358 | id2 = dev[0].connect("test-scan", key_mgmt="NONE", scan_ssid="1", | |
359 | only_add_network=True) | |
360 | id3 = dev[0].connect("bar", key_mgmt="NONE", only_add_network=True) | |
361 | ||
362 | check_scan(dev[0], "freq=2412 use_id=1") | |
363 | if "test-scan" in dev[0].request("SCAN_RESULTS"): | |
364 | raise Exception("BSS unexpectedly found in scan") | |
365 | ||
366 | check_scan(dev[0], "scan_id=%d,%d,%d freq=2412 use_id=1" % (id1, id2, id3)) | |
367 | if "test-scan" not in dev[0].request("SCAN_RESULTS"): | |
368 | raise Exception("BSS not found in scan") | |
5e29a900 | 369 | |
9446f3c2 JM |
370 | 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"): |
371 | raise Exception("Too many scan_id values accepted") | |
372 | ||
5e29a900 JM |
373 | def test_scan_and_bss_entry_removed(dev, apdev): |
374 | """Last scan result and connect work processing on BSS entry update""" | |
375 | hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open", | |
376 | "eap_server": "1", | |
377 | "wps_state": "2" }) | |
378 | bssid = apdev[0]['bssid'] | |
379 | ||
380 | wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') | |
381 | wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") | |
382 | ||
383 | # Add a BSS entry | |
384 | dev[0].scan_for_bss(bssid, freq="2412") | |
385 | wpas.scan_for_bss(bssid, freq="2412") | |
386 | ||
387 | # Start a connect radio work with a blocking entry preventing this from | |
388 | # proceeding; this stores a pointer to the selected BSS entry. | |
389 | id = dev[0].request("RADIO_WORK add block-work") | |
390 | w_id = wpas.request("RADIO_WORK add block-work") | |
391 | dev[0].wait_event(["EXT-RADIO-WORK-START"], timeout=1) | |
392 | wpas.wait_event(["EXT-RADIO-WORK-START"], timeout=1) | |
393 | nid = dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", | |
394 | wait_connect=False) | |
395 | w_nid = wpas.connect("open", key_mgmt="NONE", scan_freq="2412", | |
396 | wait_connect=False) | |
397 | time.sleep(0.1) | |
398 | ||
399 | # Remove the BSS entry | |
400 | dev[0].request("BSS_FLUSH 0") | |
401 | wpas.request("BSS_FLUSH 0") | |
402 | ||
403 | # Allow the connect radio work to continue. The bss entry stored in the | |
404 | # pending connect work is now stale. This will result in the connection | |
405 | # attempt failing since the BSS entry does not exist. | |
406 | dev[0].request("RADIO_WORK done " + id) | |
407 | wpas.request("RADIO_WORK done " + w_id) | |
408 | ||
409 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
410 | if ev is not None: | |
411 | raise Exception("Unexpected connection") | |
412 | dev[0].remove_network(nid) | |
413 | ev = wpas.wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
414 | if ev is not None: | |
415 | raise Exception("Unexpected connection") | |
416 | wpas.remove_network(w_nid) | |
417 | time.sleep(0.5) | |
418 | dev[0].request("BSS_FLUSH 0") | |
419 | wpas.request("BSS_FLUSH 0") | |
420 | ||
421 | # Add a BSS entry | |
422 | dev[0].scan_for_bss(bssid, freq="2412") | |
423 | wpas.scan_for_bss(bssid, freq="2412") | |
424 | ||
425 | # Start a connect radio work with a blocking entry preventing this from | |
426 | # proceeding; this stores a pointer to the selected BSS entry. | |
427 | id = dev[0].request("RADIO_WORK add block-work") | |
428 | w_id = wpas.request("RADIO_WORK add block-work") | |
429 | dev[0].wait_event(["EXT-RADIO-WORK-START"], timeout=1) | |
430 | wpas.wait_event(["EXT-RADIO-WORK-START"], timeout=1) | |
431 | ||
432 | # Schedule a connection based on the current BSS entry. | |
433 | dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", | |
434 | wait_connect=False) | |
435 | wpas.connect("open", key_mgmt="NONE", scan_freq="2412", | |
436 | wait_connect=False) | |
437 | ||
438 | # Update scan results with results that have longer set of IEs so that new | |
439 | # memory needs to be allocated for the BSS entry. | |
440 | hapd.request("WPS_PBC") | |
441 | time.sleep(0.1) | |
442 | subprocess.call(['iw', dev[0].ifname, 'scan', 'trigger', 'freq', '2412']) | |
443 | subprocess.call(['iw', wpas.ifname, 'scan', 'trigger', 'freq', '2412']) | |
444 | time.sleep(0.1) | |
445 | ||
446 | # Allow the connect radio work to continue. The bss entry stored in the | |
447 | # pending connect work becomes stale during the scan and it must have been | |
448 | # updated for the connection to work. | |
449 | dev[0].request("RADIO_WORK done " + id) | |
450 | wpas.request("RADIO_WORK done " + w_id) | |
451 | ||
5f35a5e2 JM |
452 | dev[0].wait_connected(timeout=15, error="No connection (sme-connect)") |
453 | wpas.wait_connected(timeout=15, error="No connection (connect)") | |
83e80d32 JM |
454 | |
455 | def test_scan_reqs_with_non_scan_radio_work(dev, apdev): | |
456 | """SCAN commands while non-scan radio_work is in progress""" | |
457 | id = dev[0].request("RADIO_WORK add test-work-a") | |
458 | ev = dev[0].wait_event(["EXT-RADIO-WORK-START"]) | |
459 | if ev is None: | |
460 | raise Exception("Timeout while waiting radio work to start") | |
461 | ||
462 | if "OK" not in dev[0].request("SCAN"): | |
463 | raise Exception("SCAN failed") | |
464 | if "FAIL-BUSY" not in dev[0].request("SCAN"): | |
465 | raise Exception("SCAN accepted while one is already pending") | |
466 | if "FAIL-BUSY" not in dev[0].request("SCAN"): | |
467 | raise Exception("SCAN accepted while one is already pending") | |
468 | ||
469 | res = dev[0].request("RADIO_WORK show").splitlines() | |
470 | count = 0 | |
471 | for l in res: | |
472 | if "scan" in l: | |
473 | count += 1 | |
474 | if count != 1: | |
475 | logger.info(res) | |
476 | raise Exception("Unexpected number of scan radio work items") | |
477 | ||
478 | dev[0].dump_monitor() | |
479 | dev[0].request("RADIO_WORK done " + id) | |
480 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5) | |
481 | if ev is None: | |
482 | raise Exception("Scan did not start") | |
483 | if "FAIL-BUSY" not in dev[0].request("SCAN"): | |
484 | raise Exception("SCAN accepted while one is already in progress") | |
485 | ||
486 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10) | |
487 | if ev is None: | |
488 | print "Scan did not complete" | |
489 | ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.2) | |
490 | if ev is not None: | |
491 | raise Exception("Unexpected scan started") | |
558ac77c JM |
492 | |
493 | def test_scan_setband(dev, apdev): | |
494 | """Band selection for scan operations""" | |
495 | try: | |
496 | hapd = None | |
497 | hapd2 = None | |
498 | params = { "ssid": "test-setband", | |
499 | "hw_mode": "a", | |
500 | "channel": "36", | |
501 | "country_code": "US" } | |
502 | hapd = hostapd.add_ap(apdev[0]['ifname'], params) | |
503 | bssid = apdev[0]['bssid'] | |
504 | ||
505 | params = { "ssid": "test-setband", | |
506 | "hw_mode": "g", | |
507 | "channel": "1" } | |
508 | hapd2 = hostapd.add_ap(apdev[1]['ifname'], params) | |
509 | bssid2 = apdev[1]['bssid'] | |
510 | ||
511 | if "FAIL" not in dev[0].request("SET setband FOO"): | |
512 | raise Exception("Invalid set setband accepted") | |
513 | if "OK" not in dev[0].request("SET setband AUTO"): | |
514 | raise Exception("Failed to set setband") | |
515 | if "OK" not in dev[1].request("SET setband 5G"): | |
516 | raise Exception("Failed to set setband") | |
517 | if "OK" not in dev[2].request("SET setband 2G"): | |
518 | raise Exception("Failed to set setband") | |
519 | ||
520 | for i in range(3): | |
521 | dev[i].request("SCAN only_new=1") | |
522 | ||
523 | for i in range(3): | |
524 | ev = dev[i].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15) | |
525 | if ev is None: | |
526 | raise Exception("Scan timed out") | |
527 | ||
528 | res = dev[0].request("SCAN_RESULTS") | |
529 | if bssid not in res or bssid2 not in res: | |
530 | raise Exception("Missing scan result(0)") | |
531 | ||
532 | res = dev[1].request("SCAN_RESULTS") | |
533 | if bssid not in res: | |
534 | raise Exception("Missing scan result(1)") | |
535 | if bssid2 in res: | |
536 | raise Exception("Unexpected scan result(1)") | |
537 | ||
538 | res = dev[2].request("SCAN_RESULTS") | |
539 | if bssid2 not in res: | |
540 | raise Exception("Missing scan result(2)") | |
541 | if bssid in res: | |
542 | raise Exception("Unexpected scan result(2)") | |
543 | finally: | |
544 | if hapd: | |
545 | hapd.request("DISABLE") | |
546 | if hapd2: | |
547 | hapd2.request("DISABLE") | |
548 | subprocess.call(['iw', 'reg', 'set', '00']) | |
549 | for i in range(3): | |
550 | dev[i].request("SET setband AUTO") | |
551 | dev[i].flush_scan_cache() | |
42ce1a27 JM |
552 | |
553 | def test_scan_hidden_many(dev, apdev): | |
554 | """scan_ssid=1 with large number of profile with hidden SSID""" | |
555 | try: | |
556 | _test_scan_hidden_many(dev, apdev) | |
557 | finally: | |
558 | dev[0].flush_scan_cache() | |
559 | dev[0].request("SCAN_INTERVAL 5") | |
560 | ||
561 | def _test_scan_hidden_many(dev, apdev): | |
562 | hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan-ssid", | |
563 | "ignore_broadcast_ssid": "1" }) | |
564 | bssid = apdev[0]['bssid'] | |
565 | ||
566 | dev[0].request("SCAN_INTERVAL 1") | |
567 | ||
568 | for i in range(5): | |
569 | id = dev[0].add_network() | |
570 | dev[0].set_network_quoted(id, "ssid", "foo") | |
571 | dev[0].set_network(id, "key_mgmt", "NONE") | |
572 | dev[0].set_network(id, "disabled", "0") | |
573 | dev[0].set_network(id, "scan_freq", "2412") | |
574 | dev[0].set_network(id, "scan_ssid", "1") | |
575 | ||
576 | dev[0].set_network_quoted(id, "ssid", "test-scan-ssid") | |
577 | dev[0].set_network(id, "key_mgmt", "NONE") | |
578 | dev[0].set_network(id, "disabled", "0") | |
579 | dev[0].set_network(id, "scan_freq", "2412") | |
580 | dev[0].set_network(id, "scan_ssid", "1") | |
581 | ||
582 | for i in range(5): | |
583 | id = dev[0].add_network() | |
584 | dev[0].set_network_quoted(id, "ssid", "foo") | |
585 | dev[0].set_network(id, "key_mgmt", "NONE") | |
586 | dev[0].set_network(id, "disabled", "0") | |
587 | dev[0].set_network(id, "scan_freq", "2412") | |
588 | dev[0].set_network(id, "scan_ssid", "1") | |
589 | ||
590 | dev[0].request("REASSOCIATE") | |
5f35a5e2 | 591 | dev[0].wait_connected(timeout=30) |