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