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