2 # Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi>
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
11 logger = logging.getLogger()
15 from wpasupplicant import WpaSupplicant
16 from utils import alloc_fail, wait_fail_trigger
17 from wlantest import Wlantest
19 def test_wnm_bss_transition_mgmt(dev, apdev):
20 """WNM BSS Transition Management"""
21 params = { "ssid": "test-wnm",
22 "time_advertisement": "2",
24 "wnm_sleep_mode": "1",
25 "bss_transition": "1" }
26 hostapd.add_ap(apdev[0], params)
28 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
29 dev[0].request("WNM_BSS_QUERY 0")
31 def test_wnm_disassoc_imminent(dev, apdev):
32 """WNM Disassociation Imminent"""
33 params = { "ssid": "test-wnm",
34 "time_advertisement": "2",
36 "wnm_sleep_mode": "1",
37 "bss_transition": "1" }
38 hapd = hostapd.add_ap(apdev[0], params)
40 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
41 addr = dev[0].p2p_interface_addr()
42 hapd.request("DISASSOC_IMMINENT " + addr + " 10")
43 ev = dev[0].wait_event(["WNM: Disassociation Imminent"])
45 raise Exception("Timeout while waiting for disassociation imminent")
46 if "Disassociation Timer 10" not in ev:
47 raise Exception("Unexpected disassociation imminent contents")
48 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
50 raise Exception("Timeout while waiting for re-connection scan")
52 def test_wnm_ess_disassoc_imminent(dev, apdev):
53 """WNM ESS Disassociation Imminent"""
54 params = { "ssid": "test-wnm",
55 "time_advertisement": "2",
57 "wnm_sleep_mode": "1",
58 "bss_transition": "1" }
59 hapd = hostapd.add_ap(apdev[0], params)
61 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
62 addr = dev[0].p2p_interface_addr()
63 hapd.request("ESS_DISASSOC " + addr + " 10 http://example.com/session-info")
64 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"])
66 raise Exception("Timeout while waiting for ESS disassociation imminent")
67 if "0 1024 http://example.com/session-info" not in ev:
68 raise Exception("Unexpected ESS disassociation imminent message contents")
69 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
71 raise Exception("Timeout while waiting for re-connection scan")
73 def test_wnm_ess_disassoc_imminent_pmf(dev, apdev):
74 """WNM ESS Disassociation Imminent"""
75 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
76 params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
77 params["ieee80211w"] = "2";
78 params["bss_transition"] = "1"
79 hapd = hostapd.add_ap(apdev[0], params)
81 dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
82 key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
83 addr = dev[0].p2p_interface_addr()
84 hapd.request("ESS_DISASSOC " + addr + " 10 http://example.com/session-info")
85 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"])
87 raise Exception("Timeout while waiting for ESS disassociation imminent")
88 if "1 1024 http://example.com/session-info" not in ev:
89 raise Exception("Unexpected ESS disassociation imminent message contents")
90 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
92 raise Exception("Timeout while waiting for re-connection scan")
94 def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None):
95 addr = dev.p2p_interface_addr()
96 sta = hapd.get_sta(addr)
97 if "[WNM_SLEEP_MODE]" in sta['flags']:
98 raise Exception("Station unexpectedly in WNM-Sleep Mode")
100 logger.info("Going to WNM Sleep Mode")
102 if interval is not None:
103 extra += " interval=" + str(interval)
105 extra += " tfs_req=" + tfs_req
106 if "OK" not in dev.request("WNM_SLEEP enter" + extra):
107 raise Exception("WNM_SLEEP failed")
111 sta = hapd.get_sta(addr)
112 if "[WNM_SLEEP_MODE]" in sta['flags']:
116 raise Exception("Station failed to enter WNM-Sleep Mode")
118 logger.info("Waking up from WNM Sleep Mode")
120 dev.request("WNM_SLEEP exit")
123 sta = hapd.get_sta(addr)
124 if "[WNM_SLEEP_MODE]" not in sta['flags']:
128 raise Exception("Station failed to exit WNM-Sleep Mode")
130 def test_wnm_sleep_mode_open(dev, apdev):
131 """WNM Sleep Mode - open"""
132 params = { "ssid": "test-wnm",
133 "time_advertisement": "2",
135 "wnm_sleep_mode": "1",
136 "bss_transition": "1" }
137 hapd = hostapd.add_ap(apdev[0], params)
139 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
140 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
142 raise Exception("No connection event received from hostapd")
143 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
144 check_wnm_sleep_mode_enter_exit(hapd, dev[0], interval=100)
145 check_wnm_sleep_mode_enter_exit(hapd, dev[0], tfs_req="5b17010001130e110000071122334455661122334455661234")
148 "exit tfs_req=123 interval=10",
149 "enter tfs_req=qq interval=10" ]
151 if "FAIL" not in dev[0].request("WNM_SLEEP " + cmd):
152 raise Exception("Invalid WNM_SLEEP accepted")
154 def test_wnm_sleep_mode_rsn(dev, apdev):
155 """WNM Sleep Mode - RSN"""
156 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
157 params["time_advertisement"] = "2"
158 params["time_zone"] = "EST5"
159 params["wnm_sleep_mode"] = "1"
160 params["bss_transition"] = "1"
161 hapd = hostapd.add_ap(apdev[0], params)
163 dev[0].connect("test-wnm-rsn", psk="12345678", scan_freq="2412")
164 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
166 raise Exception("No connection event received from hostapd")
167 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
169 def test_wnm_sleep_mode_ap_oom(dev, apdev):
170 """WNM Sleep Mode - AP side OOM"""
171 params = { "ssid": "test-wnm",
172 "wnm_sleep_mode": "1" }
173 hapd = hostapd.add_ap(apdev[0], params)
175 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
176 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
178 raise Exception("No connection event received from hostapd")
179 with alloc_fail(hapd, 1, "ieee802_11_send_wnmsleep_resp"):
180 dev[0].request("WNM_SLEEP enter")
181 wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
182 with alloc_fail(hapd, 2, "ieee802_11_send_wnmsleep_resp"):
183 dev[0].request("WNM_SLEEP exit")
184 wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
186 def test_wnm_sleep_mode_rsn_pmf(dev, apdev):
187 """WNM Sleep Mode - RSN with PMF"""
190 wt.add_passphrase("12345678")
191 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
192 params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
193 params["ieee80211w"] = "2";
194 params["time_advertisement"] = "2"
195 params["time_zone"] = "EST5"
196 params["wnm_sleep_mode"] = "1"
197 params["bss_transition"] = "1"
198 hapd = hostapd.add_ap(apdev[0], params)
200 dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
201 key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
202 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
204 raise Exception("No connection event received from hostapd")
205 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
207 MGMT_SUBTYPE_ACTION = 13
208 ACTION_CATEG_WNM = 10
209 WNM_ACT_BSS_TM_REQ = 7
210 WNM_ACT_BSS_TM_RESP = 8
211 WNM_ACT_SLEEP_MODE_REQ = 16
212 WNM_ACT_SLEEP_MODE_RESP = 17
213 WNM_ACT_NOTIFICATION_REQ = 26
214 WNM_ACT_NOTIFICATION_RESP = 27
215 WNM_NOTIF_TYPE_FW_UPGRADE = 0
216 WNM_NOTIF_TYPE_WFA = 1
217 WLAN_EID_TFS_RESP = 92
218 WLAN_EID_WNMSLEEP = 93
219 WNM_SLEEP_MODE_ENTER = 0
220 WNM_SLEEP_MODE_EXIT = 1
221 WNM_STATUS_SLEEP_ACCEPT = 0
222 WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE = 1
223 WNM_STATUS_DENIED_ACTION = 2
224 WNM_STATUS_DENIED_TMP = 3
225 WNM_STATUS_DENIED_KEY = 4
226 WNM_STATUS_DENIED_OTHER_WNM_SERVICE = 5
227 WNM_SLEEP_SUBELEM_GTK = 0
228 WNM_SLEEP_SUBELEM_IGTK = 1
230 def bss_tm_req(dst, src, dialog_token=1, req_mode=0, disassoc_timer=0,
231 validity_interval=1):
233 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
237 msg['payload'] = struct.pack("<BBBBHB",
238 ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
239 dialog_token, req_mode, disassoc_timer,
243 def rx_bss_tm_resp(hapd, expect_dialog=None, expect_status=None):
244 for i in range(0, 100):
245 resp = hapd.mgmt_rx()
247 raise Exception("No BSS TM Response received")
248 if resp['subtype'] == MGMT_SUBTYPE_ACTION:
251 raise Exception("Not an Action frame")
252 payload = resp['payload']
253 if len(payload) < 2 + 3:
254 raise Exception("Too short payload")
255 (category, action) = struct.unpack('BB', payload[0:2])
256 if category != ACTION_CATEG_WNM or action != WNM_ACT_BSS_TM_RESP:
257 raise Exception("Not a BSS TM Response")
259 (dialog, status, bss_term_delay) = struct.unpack('BBB', pos[0:3])
260 resp['dialog'] = dialog
261 resp['status'] = status
262 resp['bss_term_delay'] = bss_term_delay
264 if len(pos) >= 6 and status == 0:
265 resp['target_bssid'] = binascii.hexlify(pos[0:6])
267 resp['candidates'] = pos
268 if expect_dialog is not None and dialog != expect_dialog:
269 raise Exception("Unexpected dialog token")
270 if expect_status is not None and status != expect_status:
271 raise Exception("Unexpected status code %d" % status)
274 def expect_ack(hapd):
275 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
277 raise Exception("Missing TX status")
279 raise Exception("Action frame not acknowledged")
281 def test_wnm_bss_tm_req(dev, apdev):
282 """BSS Transition Management Request"""
283 params = { "ssid": "test-wnm", "bss_transition": "1" }
284 hapd = hostapd.add_ap(apdev[0], params)
285 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
286 hapd2 = hostapd.add_ap(apdev[1], params)
288 hapd.set("ext_mgmt_frame_handling", "1")
290 # truncated BSS TM Request
291 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
293 req['payload'] = struct.pack("<BBBBH",
294 ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
299 # no disassociation and no candidate list
300 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
303 resp = rx_bss_tm_resp(hapd, expect_dialog=2, expect_status=1)
305 # truncated BSS Termination Duration
306 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
311 # BSS Termination Duration with TSF=0 and Duration=10
312 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
313 req_mode=0x08, dialog_token=3)
314 req['payload'] += struct.pack("<BBQH", 4, 10, 0, 10)
316 resp = rx_bss_tm_resp(hapd, expect_dialog=3, expect_status=1)
318 # truncated Session Information URL
319 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
323 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
325 req['payload'] += struct.pack("<BBB", 3, 65, 66)
329 # Session Information URL
330 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
331 req_mode=0x10, dialog_token=4)
332 req['payload'] += struct.pack("<BBB", 2, 65, 66)
334 resp = rx_bss_tm_resp(hapd, expect_dialog=4, expect_status=0)
336 # Preferred Candidate List without any entries
337 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
338 req_mode=0x01, dialog_token=5)
340 resp = rx_bss_tm_resp(hapd, expect_dialog=5, expect_status=7)
342 # Preferred Candidate List with a truncated entry
343 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
345 req['payload'] += struct.pack("<BB", 52, 1)
349 # Preferred Candidate List with a too short entry
350 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
351 req_mode=0x01, dialog_token=6)
352 req['payload'] += struct.pack("<BB", 52, 0)
354 resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
356 # Preferred Candidate List with a non-matching entry
357 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
358 req_mode=0x01, dialog_token=6)
359 req['payload'] += struct.pack("<BB6BLBBB", 52, 13,
363 resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
365 # Preferred Candidate List with a truncated subelement
366 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
367 req_mode=0x01, dialog_token=7)
368 req['payload'] += struct.pack("<BB6BLBBBBB", 52, 13 + 2,
373 resp = rx_bss_tm_resp(hapd, expect_dialog=7, expect_status=7)
375 # Preferred Candidate List with lots of invalid optional subelements
376 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
377 req_mode=0x01, dialog_token=8)
378 subelems = struct.pack("<BBHB", 1, 3, 0, 100)
379 subelems += struct.pack("<BBB", 2, 1, 65)
380 subelems += struct.pack("<BB", 3, 0)
381 subelems += struct.pack("<BBQB", 4, 9, 0, 10)
382 subelems += struct.pack("<BBHLB", 5, 7, 0, 0, 0)
383 subelems += struct.pack("<BB", 66, 0)
384 subelems += struct.pack("<BBBBBB", 70, 4, 0, 0, 0, 0)
385 subelems += struct.pack("<BB", 71, 0)
386 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
388 0, 81, 1, 7) + subelems
390 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
392 # Preferred Candidate List with lots of valid optional subelements (twice)
393 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
394 req_mode=0x01, dialog_token=8)
396 subelems = struct.pack("<BBHH", 1, 4, 0, 100)
397 # Condensed Country String
398 subelems += struct.pack("<BBBB", 2, 2, 65, 66)
399 # BSS Transition Candidate Preference
400 subelems += struct.pack("<BBB", 3, 1, 100)
401 # BSS Termination Duration
402 subelems += struct.pack("<BBQH", 4, 10, 0, 10)
404 subelems += struct.pack("<BBHLH", 5, 8, 0, 0, 0)
405 # Measurement Pilot Transmission
406 subelems += struct.pack("<BBBBB", 66, 3, 0, 0, 0)
407 # RM Enabled Capabilities
408 subelems += struct.pack("<BBBBBBB", 70, 5, 0, 0, 0, 0, 0)
410 subelems += struct.pack("<BBBB", 71, 2, 0, 0)
411 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems) * 2,
413 0, 81, 1, 7) + subelems + subelems
415 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
417 # Preferred Candidate List followed by vendor element
418 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
419 req_mode=0x01, dialog_token=8)
421 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
423 0, 81, 1, 7) + subelems
424 req['payload'] += binascii.unhexlify("DD0411223344")
426 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
428 def test_wnm_bss_keep_alive(dev, apdev):
430 params = { "ssid": "test-wnm",
431 "ap_max_inactivity": "1" }
432 hapd = hostapd.add_ap(apdev[0], params)
434 addr = dev[0].p2p_interface_addr()
435 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
436 start = hapd.get_sta(addr)
437 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=2)
439 raise Exception("Unexpected disconnection")
440 end = hapd.get_sta(addr)
441 if int(end['rx_packets']) <= int(start['rx_packets']):
442 raise Exception("No keep-alive packets received")
444 # Disable client keep-alive so that hostapd will verify connection
446 dev[0].request("SET no_keep_alive 1")
448 sta = hapd.get_sta(addr)
449 logger.info("timeout_next=%s rx_packets=%s tx_packets=%s" % (sta['timeout_next'], sta['rx_packets'], sta['tx_packets']))
450 if i > 1 and sta['timeout_next'] != "NULLFUNC POLL" and int(sta['tx_packets']) > int(end['tx_packets']):
452 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
454 raise Exception("Unexpected disconnection (client poll expected)")
456 dev[0].request("SET no_keep_alive 0")
457 if int(sta['tx_packets']) <= int(end['tx_packets']):
458 raise Exception("No client poll packet seen")
460 def test_wnm_bss_tm(dev, apdev):
461 """WNM BSS Transition Management"""
465 params = { "ssid": "test-wnm",
466 "country_code": "FI",
470 "bss_transition": "1" }
471 hapd = hostapd.add_ap(apdev[0], params)
473 id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
474 dev[0].set_network(id, "scan_freq", "")
476 params = { "ssid": "test-wnm",
477 "country_code": "FI",
481 "bss_transition": "1" }
482 hapd2 = hostapd.add_ap(apdev[1], params)
484 addr = dev[0].p2p_interface_addr()
485 dev[0].dump_monitor()
487 logger.info("No neighbor list entries")
488 if "OK" not in hapd.request("BSS_TM_REQ " + addr):
489 raise Exception("BSS_TM_REQ command failed")
490 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
492 raise Exception("No BSS Transition Management Response")
494 raise Exception("Unexpected BSS Transition Management Response address")
495 if "status_code=0" in ev:
496 raise Exception("BSS transition accepted unexpectedly")
497 dev[0].dump_monitor()
499 logger.info("Neighbor list entry, but not claimed as Preferred Candidate List")
500 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " neighbor=11:22:33:44:55:66,0x0000,81,3,7"):
501 raise Exception("BSS_TM_REQ command failed")
502 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
504 raise Exception("No BSS Transition Management Response")
505 if "status_code=0" in ev:
506 raise Exception("BSS transition accepted unexpectedly")
507 dev[0].dump_monitor()
509 logger.info("Preferred Candidate List (no matching neighbor) without Disassociation Imminent")
510 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 neighbor=11:22:33:44:55:66,0x0000,81,3,7,0301ff neighbor=22:33:44:55:66:77,0x0000,1,36,7 neighbor=00:11:22:33:44:55,0x0000,81,4,7,03010a"):
511 raise Exception("BSS_TM_REQ command failed")
512 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
514 raise Exception("No BSS Transition Management Response")
515 if "status_code=0" in ev:
516 raise Exception("BSS transition accepted unexpectedly")
517 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
519 raise Exception("No scan started")
520 dev[0].dump_monitor()
522 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
523 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000,115,36,7,0301ff"):
524 raise Exception("BSS_TM_REQ command failed")
525 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
527 raise Exception("No BSS Transition Management Response")
528 if "status_code=0" not in ev:
529 raise Exception("BSS transition request was not accepted: " + ev)
530 if "target_bssid=" + apdev[1]['bssid'] not in ev:
531 raise Exception("Unexpected target BSS: " + ev)
532 dev[0].wait_connected(timeout=15, error="No reassociation seen")
533 if apdev[1]['bssid'] not in ev:
534 raise Exception("Unexpected reassociation target: " + ev)
535 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
537 raise Exception("Unexpected scan started")
538 dev[0].dump_monitor()
540 logger.info("Preferred Candidate List with two matches, no roam needed")
541 if "OK" not in hapd2.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[0]['bssid'] + ",0x0000,81,1,7,030101 neighbor=" + apdev[1]['bssid'] + ",0x0000,115,36,7,0301ff"):
542 raise Exception("BSS_TM_REQ command failed")
543 ev = hapd2.wait_event(['BSS-TM-RESP'], timeout=10)
545 raise Exception("No BSS Transition Management Response")
546 if "status_code=0" not in ev:
547 raise Exception("BSS transition request was not accepted: " + ev)
548 if "target_bssid=" + apdev[1]['bssid'] not in ev:
549 raise Exception("Unexpected target BSS: " + ev)
550 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
552 raise Exception("Unexpected scan started")
553 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
555 raise Exception("Unexpected reassociation");
557 dev[0].request("DISCONNECT")
559 hapd.request("DISABLE")
561 hapd2.request("DISABLE")
562 subprocess.call(['iw', 'reg', 'set', '00'])
563 dev[0].flush_scan_cache()
565 def test_wnm_bss_tm_scan_not_needed(dev, apdev):
566 """WNM BSS Transition Management and scan not needed"""
567 run_wnm_bss_tm_scan_not_needed(dev, apdev)
569 def test_wnm_bss_tm_nei_vht(dev, apdev):
570 """WNM BSS Transition Management and VHT neighbor"""
571 run_wnm_bss_tm_scan_not_needed(dev, apdev, vht=True, nei_info="115,36,9")
573 def test_wnm_bss_tm_nei_11a(dev, apdev):
574 """WNM BSS Transition Management and 11a neighbor"""
575 run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, nei_info="115,36,4")
577 def test_wnm_bss_tm_nei_11g(dev, apdev):
578 """WNM BSS Transition Management and 11g neighbor"""
579 run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, hwmode='g',
580 channel='2', freq=2417, nei_info="81,2,6")
582 def test_wnm_bss_tm_nei_11b(dev, apdev):
583 """WNM BSS Transition Management and 11g neighbor"""
584 run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, hwmode='b',
585 channel='3', freq=2422, nei_info="81,2,5")
587 def run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=True, vht=False, hwmode='a',
588 channel='36', freq=5180,
589 nei_info="115,36,7,0301ff"):
593 params = { "ssid": "test-wnm",
594 "country_code": "FI",
598 "bss_transition": "1" }
599 hapd = hostapd.add_ap(apdev[0], params)
601 params = { "ssid": "test-wnm",
602 "country_code": "FI",
606 "bss_transition": "1" }
608 params['ieee80211n'] = '0'
610 params['ieee80211ac'] = "1"
611 params["vht_oper_chwidth"] = "0"
612 params["vht_oper_centr_freq_seg0_idx"] = "0"
614 hapd2 = hostapd.add_ap(apdev[1], params)
616 dev[0].scan_for_bss(apdev[1]['bssid'], freq)
618 id = dev[0].connect("test-wnm", key_mgmt="NONE",
619 bssid=apdev[0]['bssid'], scan_freq="2412")
620 dev[0].set_network(id, "scan_freq", "")
621 dev[0].set_network(id, "bssid", "")
623 addr = dev[0].own_addr()
624 dev[0].dump_monitor()
626 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
627 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000," + nei_info):
628 raise Exception("BSS_TM_REQ command failed")
629 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
631 raise Exception("No BSS Transition Management Response")
632 if "status_code=0" not in ev:
633 raise Exception("BSS transition request was not accepted: " + ev)
634 if "target_bssid=" + apdev[1]['bssid'] not in ev:
635 raise Exception("Unexpected target BSS: " + ev)
636 dev[0].wait_connected(timeout=15, error="No reassociation seen")
637 if apdev[1]['bssid'] not in ev:
638 raise Exception("Unexpected reassociation target: " + ev)
639 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
641 raise Exception("Unexpected scan started")
642 dev[0].dump_monitor()
644 dev[0].request("DISCONNECT")
646 hapd.request("DISABLE")
648 hapd2.request("DISABLE")
649 subprocess.call(['iw', 'reg', 'set', '00'])
650 dev[0].flush_scan_cache()
652 def test_wnm_bss_tm_scan_needed(dev, apdev):
653 """WNM BSS Transition Management and scan needed"""
657 params = { "ssid": "test-wnm",
658 "country_code": "FI",
662 "bss_transition": "1" }
663 hapd = hostapd.add_ap(apdev[0], params)
665 params = { "ssid": "test-wnm",
666 "country_code": "FI",
670 "bss_transition": "1" }
671 hapd2 = hostapd.add_ap(apdev[1], params)
673 dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
675 id = dev[0].connect("test-wnm", key_mgmt="NONE",
676 bssid=apdev[0]['bssid'], scan_freq="2412")
677 dev[0].set_network(id, "scan_freq", "")
678 dev[0].set_network(id, "bssid", "")
680 addr = dev[0].own_addr()
681 dev[0].dump_monitor()
683 logger.info("Wait 11 seconds for the last scan result to be too old, but still present in BSS table")
685 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
686 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000,115,36,7,0301ff"):
687 raise Exception("BSS_TM_REQ command failed")
688 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
690 raise Exception("No BSS Transition Management Response")
691 if "status_code=0" not in ev:
692 raise Exception("BSS transition request was not accepted: " + ev)
693 if "target_bssid=" + apdev[1]['bssid'] not in ev:
694 raise Exception("Unexpected target BSS: " + ev)
695 dev[0].wait_connected(timeout=15, error="No reassociation seen")
696 if apdev[1]['bssid'] not in ev:
697 raise Exception("Unexpected reassociation target: " + ev)
698 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
700 raise Exception("Unexpected scan started")
701 dev[0].dump_monitor()
703 dev[0].request("DISCONNECT")
705 hapd.request("DISABLE")
707 hapd2.request("DISABLE")
708 subprocess.call(['iw', 'reg', 'set', '00'])
709 dev[0].flush_scan_cache()
711 def start_wnm_tm(ap, country, dev):
712 params = { "ssid": "test-wnm",
713 "country_code": country,
717 "bss_transition": "1" }
718 hapd = hostapd.add_ap(ap, params)
719 id = dev.connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
721 dev.set_network(id, "scan_freq", "")
724 def stop_wnm_tm(hapd, dev):
725 dev.request("DISCONNECT")
727 dev.wait_disconnected()
731 hapd.request("DISABLE")
732 subprocess.call(['iw', 'reg', 'set', '00'])
733 dev.flush_scan_cache()
735 def wnm_bss_tm_check(hapd, dev, data):
736 addr = dev.p2p_interface_addr()
737 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " " + data):
738 raise Exception("BSS_TM_REQ command failed")
739 ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
741 raise Exception("No scan started")
742 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
744 raise Exception("Scan did not complete")
746 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
748 raise Exception("No BSS Transition Management Response")
749 if "status_code=7" not in ev:
750 raise Exception("Unexpected response: " + ev)
752 def test_wnm_bss_tm_country_us(dev, apdev):
753 """WNM BSS Transition Management (US)"""
756 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
758 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
759 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=11:22:33:44:55:66,0x0000,12,3,7,0301ff neighbor=00:11:22:33:44:55,0x0000,2,52,7,03010a neighbor=00:11:22:33:44:57,0x0000,4,100,7 neighbor=00:11:22:33:44:59,0x0000,3,149,7 neighbor=00:11:22:33:44:5b,0x0000,34,1,7 neighbor=00:11:22:33:44:5d,0x0000,5,149,7")
761 # Make the test take less time by limiting full scans
762 dev[0].set_network(id, "scan_freq", "2412")
763 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
764 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=11:22:33:44:55:66,0x0000,12,0,7,0301ff neighbor=22:33:44:55:66:77,0x0000,12,12,7 neighbor=00:11:22:33:44:55,0x0000,2,35,7,03010a neighbor=00:11:22:33:44:56,0x0000,2,65,7 neighbor=00:11:22:33:44:57,0x0000,4,99,7 neighbor=00:11:22:33:44:58,0x0000,4,145,7")
766 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
767 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:59,0x0000,3,148,7 neighbor=00:11:22:33:44:5a,0x0000,3,162,7 neighbor=00:11:22:33:44:5b,0x0000,34,0,7 neighbor=00:11:22:33:44:5c,0x0000,34,4,7 neighbor=00:11:22:33:44:5d,0x0000,5,148,7 neighbor=00:11:22:33:44:5e,0x0000,5,166,7 neighbor=00:11:22:33:44:5f,0x0000,0,0,7")
769 stop_wnm_tm(hapd, dev[0])
771 def test_wnm_bss_tm_country_fi(dev, apdev):
772 """WNM BSS Transition Management (FI)"""
773 addr = dev[0].p2p_interface_addr()
776 hapd, id = start_wnm_tm(apdev[0], "FI", dev[0])
778 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
779 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=11:22:33:44:55:66,0x0000,4,3,7,0301ff neighbor=00:11:22:33:44:55,0x0000,1,36,7,03010a neighbor=00:11:22:33:44:57,0x0000,3,100,7 neighbor=00:11:22:33:44:59,0x0000,17,149,7 neighbor=00:11:22:33:44:5c,0x0000,18,1,7")
781 # Make the test take less time by limiting full scans
782 dev[0].set_network(id, "scan_freq", "2412")
783 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
784 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,4,0,7 neighbor=00:11:22:33:44:01,0x0000,4,14,7 neighbor=00:11:22:33:44:02,0x0000,1,35,7 neighbor=00:11:22:33:44:03,0x0000,1,65,7 neighbor=00:11:22:33:44:04,0x0000,3,99,7 neighbor=00:11:22:33:44:05,0x0000,3,141,7 neighbor=00:11:22:33:44:06,0x0000,17,148,7 neighbor=00:11:22:33:44:07,0x0000,17,170,7 neighbor=00:11:22:33:44:08,0x0000,18,0,7 neighbor=00:11:22:33:44:09,0x0000,18,5,7")
786 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
787 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,0,0,7")
789 stop_wnm_tm(hapd, dev[0])
791 def test_wnm_bss_tm_country_jp(dev, apdev):
792 """WNM BSS Transition Management (JP)"""
793 addr = dev[0].p2p_interface_addr()
796 hapd, id = start_wnm_tm(apdev[0], "JP", dev[0])
798 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
799 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=11:22:33:44:55:66,0x0000,30,3,7,0301ff neighbor=00:11:22:33:44:55,0x0000,31,14,7,03010a neighbor=00:11:22:33:44:57,0x0000,1,36,7 neighbor=00:11:22:33:44:59,0x0000,34,100,7 neighbor=00:11:22:33:44:5c,0x0000,59,1,7")
801 # Make the test take less time by limiting full scans
802 dev[0].set_network(id, "scan_freq", "2412")
803 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
804 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=11:22:33:44:55:66,0x0000,30,0,7,0301ff neighbor=22:33:44:55:66:77,0x0000,30,14,7 neighbor=00:11:22:33:44:56,0x0000,31,13,7 neighbor=00:11:22:33:44:57,0x0000,1,33,7 neighbor=00:11:22:33:44:58,0x0000,1,65,7 neighbor=00:11:22:33:44:5a,0x0000,34,99,7 neighbor=00:11:22:33:44:5b,0x0000,34,141,7 neighbor=00:11:22:33:44:5d,0x0000,59,0,7 neighbor=00:11:22:33:44:5e,0x0000,59,4,7 neighbor=00:11:22:33:44:5f,0x0000,0,0,7")
806 stop_wnm_tm(hapd, dev[0])
808 def test_wnm_bss_tm_country_cn(dev, apdev):
809 """WNM BSS Transition Management (CN)"""
810 addr = dev[0].p2p_interface_addr()
813 hapd, id = start_wnm_tm(apdev[0], "CN", dev[0])
815 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
816 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=11:22:33:44:55:66,0x0000,7,3,7,0301ff neighbor=00:11:22:33:44:55,0x0000,1,36,7,03010a neighbor=00:11:22:33:44:57,0x0000,3,149,7 neighbor=00:11:22:33:44:59,0x0000,6,149,7")
818 # Make the test take less time by limiting full scans
819 dev[0].set_network(id, "scan_freq", "2412")
820 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
821 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=11:22:33:44:55:66,0x0000,7,0,7,0301ff neighbor=22:33:44:55:66:77,0x0000,7,14,7 neighbor=00:11:22:33:44:56,0x0000,1,35,7 neighbor=00:11:22:33:44:57,0x0000,1,65,7 neighbor=00:11:22:33:44:58,0x0000,3,148,7 neighbor=00:11:22:33:44:5a,0x0000,3,166,7 neighbor=00:11:22:33:44:5f,0x0000,0,0,7")
823 stop_wnm_tm(hapd, dev[0])
825 def test_wnm_bss_tm_global(dev, apdev):
826 """WNM BSS Transition Management (global)"""
827 addr = dev[0].p2p_interface_addr()
830 hapd, id = start_wnm_tm(apdev[0], "XX", dev[0])
832 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
833 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=11:22:33:44:55:66,0x0000,81,3,7,0301ff neighbor=00:11:22:33:44:55,0x0000,82,14,7,03010a neighbor=00:11:22:33:44:57,0x0000,83,1,7 neighbor=00:11:22:33:44:59,0x0000,115,36,7 neighbor=00:11:22:33:44:5a,0x0000,121,100,7 neighbor=00:11:22:33:44:5c,0x0000,124,149,7 neighbor=00:11:22:33:44:5d,0x0000,125,149,7 neighbor=00:11:22:33:44:5e,0x0000,128,42,7 neighbor=00:11:22:33:44:5f,0x0000,129,50,7 neighbor=00:11:22:33:44:60,0x0000,180,1,7")
835 # Make the test take less time by limiting full scans
836 dev[0].set_network(id, "scan_freq", "2412")
837 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
838 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,81,0,7 neighbor=00:11:22:33:44:01,0x0000,81,14,7 neighbor=00:11:22:33:44:02,0x0000,82,13,7 neighbor=00:11:22:33:44:03,0x0000,83,0,7 neighbor=00:11:22:33:44:04,0x0000,83,14,7 neighbor=00:11:22:33:44:05,0x0000,115,35,7 neighbor=00:11:22:33:44:06,0x0000,115,65,7 neighbor=00:11:22:33:44:07,0x0000,121,99,7 neighbor=00:11:22:33:44:08,0x0000,121,141,7 neighbor=00:11:22:33:44:09,0x0000,124,148,7")
840 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
841 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,124,162,7 neighbor=00:11:22:33:44:01,0x0000,125,148,7 neighbor=00:11:22:33:44:02,0x0000,125,170,7 neighbor=00:11:22:33:44:03,0x0000,128,35,7 neighbor=00:11:22:33:44:04,0x0000,128,162,7 neighbor=00:11:22:33:44:05,0x0000,129,49,7 neighbor=00:11:22:33:44:06,0x0000,129,115,7 neighbor=00:11:22:33:44:07,0x0000,180,0,7 neighbor=00:11:22:33:44:08,0x0000,180,5,7 neighbor=00:11:22:33:44:09,0x0000,0,0,7")
843 stop_wnm_tm(hapd, dev[0])
845 def test_wnm_bss_tm_op_class_0(dev, apdev):
846 """WNM BSS Transition Management with invalid operating class"""
849 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
851 logger.info("Preferred Candidate List (no matching neighbor, invalid op class specified for channels)")
852 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:59,0x0000,0,149,7 neighbor=00:11:22:33:44:5b,0x0000,0,1,7")
854 stop_wnm_tm(hapd, dev[0])
856 def test_wnm_action_proto(dev, apdev):
857 """WNM Action protocol testing"""
858 params = { "ssid": "test-wnm" }
859 params['wnm_sleep_mode'] = '1'
860 hapd = hostapd.add_ap(apdev[0], params)
861 bssid = apdev[0]['bssid']
862 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
863 dev[0].request("WNM_SLEEP enter")
865 hapd.set("ext_mgmt_frame_handling", "1")
868 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
869 msg['da'] = dev[0].own_addr()
875 logger.debug("Unexpected WNM-Notification Response")
876 # Note: This is actually not registered for user space processing in
877 # driver_nl80211.c nl80211_mgmt_subscribe_non_ap() and as such, won't make
878 # it to wpa_supplicant.
879 msg['payload'] = struct.pack("<BBBB",
880 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_RESP,
885 logger.debug("Truncated WNM-Notification Request (no Type field)")
886 msg['payload'] = struct.pack("<BBB",
887 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
892 logger.debug("WFA WNM-Notification Request with truncated IE (min)")
893 msg['payload'] = struct.pack("<BBBBBB",
894 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
895 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 1)
899 logger.debug("WFA WNM-Notification Request with truncated IE (max)")
900 msg['payload'] = struct.pack("<BBBBBB",
901 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
902 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 255)
906 logger.debug("WFA WNM-Notification Request with too short IE")
907 msg['payload'] = struct.pack("<BBBBBB",
908 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
909 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 0)
913 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL")
914 msg['payload'] = struct.pack(">BBBBBBLB",
915 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
916 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
921 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(2)")
922 msg['payload'] = struct.pack(">BBBBBBLBB",
923 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
924 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 6,
929 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(3)")
930 msg['payload'] = struct.pack(">BBBBBBLB",
931 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
932 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
937 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(min)")
938 msg['payload'] = struct.pack(">BBBBBBLBHB",
939 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
940 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
945 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(max)")
946 msg['payload'] = struct.pack(">BBBBBBLBHB",
947 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
948 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
949 0x506f9a01, 0, 0, 0xff)
953 logger.debug("WFA WNM-Notification Request with unsupported IE")
954 msg['payload'] = struct.pack("<BBBBBBL",
955 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
956 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 4, 0)
960 logger.debug("WNM-Notification Request with unknown WNM-Notification type 0")
961 msg['payload'] = struct.pack("<BBBB",
962 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
963 dialog_token, WNM_NOTIF_TYPE_FW_UPGRADE)
967 logger.debug("Truncated WNM Sleep Mode Response - no Dialog Token")
968 msg['payload'] = struct.pack("<BB",
969 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP)
973 logger.debug("Truncated WNM Sleep Mode Response - no Key Data Length")
974 msg['payload'] = struct.pack("<BBB",
975 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0)
979 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (min)")
980 msg['payload'] = struct.pack("<BBBH",
981 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
986 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (max)")
987 msg['payload'] = struct.pack("<BBBH",
988 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
993 logger.debug("WNM Sleep Mode Response - truncated IE header")
994 msg['payload'] = struct.pack("<BBBHB",
995 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1000 logger.debug("WNM Sleep Mode Response - truncated IE")
1001 msg['payload'] = struct.pack("<BBBHBB",
1002 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1007 logger.debug("WNM Sleep Mode Response - Empty TFS Response")
1008 msg['payload'] = struct.pack("<BBBHBB",
1009 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1010 0, WLAN_EID_TFS_RESP, 0)
1014 logger.debug("WNM Sleep Mode Response - EID 0 not recognized")
1015 msg['payload'] = struct.pack("<BBBHBB",
1016 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1021 logger.debug("WNM Sleep Mode Response - Empty WNM Sleep Mode element and TFS Response element")
1022 msg['payload'] = struct.pack("<BBBHBBBB",
1023 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1024 0, WLAN_EID_WNMSLEEP, 0, WLAN_EID_TFS_RESP, 0)
1028 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element and empty TFS Response element")
1029 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1030 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1031 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1032 WNM_STATUS_SLEEP_ACCEPT, 0,
1033 WLAN_EID_TFS_RESP, 0)
1037 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(exit, deny key) and empty TFS Response element")
1038 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1039 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1040 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1041 WNM_STATUS_DENIED_KEY, 0,
1042 WLAN_EID_TFS_RESP, 0)
1046 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(enter, deny key) and empty TFS Response element")
1047 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1048 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1049 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1050 WNM_STATUS_DENIED_KEY, 0,
1051 WLAN_EID_TFS_RESP, 0)
1055 def test_wnm_action_proto_pmf(dev, apdev):
1056 """WNM Action protocol testing (PMF enabled)"""
1057 ssid = "test-wnm-pmf"
1058 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1059 params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1060 params["ieee80211w"] = "2"
1061 params['wnm_sleep_mode'] = '1'
1062 hapd = hostapd.add_ap(apdev[0], params)
1063 bssid = apdev[0]['bssid']
1064 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
1065 proto="WPA2", ieee80211w="2", scan_freq="2412")
1066 dev[0].request("WNM_SLEEP enter")
1068 hapd.set("ext_mgmt_frame_handling", "1")
1071 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1072 msg['da'] = dev[0].own_addr()
1074 msg['bssid'] = bssid
1076 logger.debug("WNM Sleep Mode Response - Invalid Key Data element length")
1077 keydata = struct.pack("<BB", 0, 1)
1078 msg['payload'] = struct.pack("<BBBH",
1079 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1081 msg['payload'] += keydata
1082 msg['payload'] += struct.pack("<BBBBHBB",
1083 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1084 WNM_STATUS_SLEEP_ACCEPT, 0,
1085 WLAN_EID_TFS_RESP, 0)
1089 logger.debug("WNM Sleep Mode Response - Too short GTK subelem")
1090 keydata = struct.pack("<BB", WNM_SLEEP_SUBELEM_GTK, 0)
1091 msg['payload'] = struct.pack("<BBBH",
1092 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1094 msg['payload'] += keydata
1095 msg['payload'] += struct.pack("<BBBBHBB",
1096 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1097 WNM_STATUS_SLEEP_ACCEPT, 0,
1098 WLAN_EID_TFS_RESP, 0)
1102 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem")
1103 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1104 0, 17, 0, 0, 0, 0, 0, 0)
1105 msg['payload'] = struct.pack("<BBBH",
1106 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1108 msg['payload'] += keydata
1109 msg['payload'] += struct.pack("<BBBBHBB",
1110 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1111 WNM_STATUS_SLEEP_ACCEPT, 0,
1112 WLAN_EID_TFS_RESP, 0)
1116 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem (2)")
1117 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1118 0, 0, 0, 0, 0, 0, 0, 0)
1119 msg['payload'] = struct.pack("<BBBH",
1120 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1122 msg['payload'] += keydata
1123 msg['payload'] += struct.pack("<BBBBHBB",
1124 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1125 WNM_STATUS_SLEEP_ACCEPT, 0,
1126 WLAN_EID_TFS_RESP, 0)
1130 logger.debug("WNM Sleep Mode Response - GTK subelem and too short IGTK subelem")
1131 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1132 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1133 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1134 keydata += struct.pack("<BB", WNM_SLEEP_SUBELEM_IGTK, 0)
1135 msg['payload'] = struct.pack("<BBBH",
1136 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1138 msg['payload'] += keydata
1139 msg['payload'] += struct.pack("<BBBBHBB",
1140 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1141 WNM_STATUS_SLEEP_ACCEPT, 0,
1142 WLAN_EID_TFS_RESP, 0)
1146 logger.debug("WNM Sleep Mode Response - Unknown subelem")
1147 keydata = struct.pack("<BB", 255, 0)
1148 msg['payload'] = struct.pack("<BBBH",
1149 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1151 msg['payload'] += keydata
1152 msg['payload'] += struct.pack("<BBBBHBB",
1153 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1154 WNM_STATUS_SLEEP_ACCEPT, 0,
1155 WLAN_EID_TFS_RESP, 0)
1159 def test_wnm_action_proto_no_pmf(dev, apdev):
1160 """WNM Action protocol testing (PMF disabled)"""
1161 ssid = "test-wnm-no-pmf"
1162 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1163 params['wnm_sleep_mode'] = '1'
1164 hapd = hostapd.add_ap(apdev[0], params)
1165 bssid = apdev[0]['bssid']
1166 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1167 proto="WPA2", ieee80211w="0", scan_freq="2412")
1168 dev[0].request("WNM_SLEEP enter")
1170 hapd.set("ext_mgmt_frame_handling", "1")
1173 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1174 msg['da'] = dev[0].own_addr()
1176 msg['bssid'] = bssid
1178 logger.debug("WNM Sleep Mode Response - GTK subelem and IGTK subelem")
1179 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1180 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1181 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1182 keydata += struct.pack("<BBHLH4L", WNM_SLEEP_SUBELEM_IGTK, 2 + 6 + 16, 0,
1184 0xf1f2f3f4, 0xf5f6f7f8, 0xf9f0fafb, 0xfcfdfeff)
1185 msg['payload'] = struct.pack("<BBBH",
1186 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1188 msg['payload'] += keydata
1189 msg['payload'] += struct.pack("<BBBBHBB",
1190 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1191 WNM_STATUS_SLEEP_ACCEPT, 0,
1192 WLAN_EID_TFS_RESP, 0)
1196 ev = dev[0].wait_event(["WNM: Ignore Key Data"], timeout=5)
1198 raise Exception("Key Data not ignored")
1200 def test_wnm_bss_tm_req_with_mbo_ie(dev, apdev):
1201 """WNM BSS transition request with MBO IE and reassociation delay attribute"""
1202 ssid = "test-wnm-mbo"
1203 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1204 hapd = hostapd.add_ap(apdev[0], params)
1205 bssid = apdev[0]['bssid']
1206 if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
1207 raise Exception("Failed to set STA as cellular data capable")
1209 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1210 proto="WPA2", ieee80211w="0", scan_freq="2412")
1212 logger.debug("BTM request with MBO reassociation delay when disassoc imminent is not set")
1213 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=3:2:1"):
1214 raise Exception("BSS transition management succeeded unexpectedly")
1216 logger.debug("BTM request with invalid MBO transition reason code")
1217 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=10:2:1"):
1218 raise Exception("BSS transition management succeeded unexpectedly")
1220 logger.debug("BTM request with MBO reassociation retry delay of 5 seconds")
1221 if 'OK' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " disassoc_imminent=1 disassoc_timer=3 mbo=3:5:1"):
1222 raise Exception("BSS transition management command failed")
1224 ev = dev[0].wait_event(['MBO-CELL-PREFERENCE'], 1)
1225 if ev is None or "preference=1" not in ev:
1226 raise Exception("Timeout waiting for MBO-CELL-PREFERENCE event")
1228 ev = dev[0].wait_event(['MBO-TRANSITION-REASON'], 1)
1229 if ev is None or "reason=3" not in ev:
1230 raise Exception("Timeout waiting for MBO-TRANSITION-REASON event")
1232 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1234 raise Exception("No BSS Transition Management Response")
1235 if dev[0].own_addr() not in ev:
1236 raise Exception("Unexpected BSS Transition Management Response address")
1238 ev = dev[0].wait_event(['CTRL-EVENT-DISCONNECTED'], 5)
1240 raise Exception("Station did not disconnect although disassoc imminent was set")
1242 # Set the scan interval to make dev[0] look for connections
1243 if 'OK' not in dev[0].request("SCAN_INTERVAL 1"):
1244 raise Exception("Failed to set scan interval")
1246 # Make sure no connection is made during the retry delay
1247 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1249 raise Exception("Station connected before assoc retry delay was over")
1251 # After the assoc retry delay is over, we can reconnect
1252 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1254 raise Exception("Station did not connect after assoc retry delay is over")
1256 if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
1257 raise Exception("Failed to set STA as cellular data not-capable")
1259 def test_wnm_bss_transition_mgmt_query(dev, apdev):
1260 """WNM BSS Transition Management query"""
1261 params = { "ssid": "test-wnm",
1262 "bss_transition": "1" }
1263 hapd = hostapd.add_ap(apdev[0], params)
1264 params = { "ssid": "another" }
1265 hapd2 = hostapd.add_ap(apdev[1], params)
1267 dev[0].scan_for_bss(apdev[1]['bssid'], 2412)
1268 dev[0].scan_for_bss(apdev[0]['bssid'], 2412)
1270 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1271 dev[0].request("WNM_BSS_QUERY 0 list")
1273 ev = dev[0].wait_event(["WNM: BSS Transition Management Request"],
1276 raise Exception("No BSS Transition Management Request frame seen")
1278 ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1280 raise Exception("No BSS Transition Management Response frame seen")
1282 def test_wnm_bss_tm_security_mismatch(dev, apdev):
1283 """WNM BSS Transition Management and security mismatch"""
1284 params = { "ssid": "test-wnm",
1286 "wpa_key_mgmt": "WPA-PSK",
1287 "rsn_pairwise": "CCMP",
1288 "wpa_passphrase": "12345678",
1291 "bss_transition": "1" }
1292 hapd = hostapd.add_ap(apdev[0], params)
1294 params = { "ssid": "test-wnm",
1297 "bss_transition": "1" }
1298 hapd2 = hostapd.add_ap(apdev[1], params)
1300 dev[0].scan_for_bss(apdev[1]['bssid'], 2462)
1302 id = dev[0].connect("test-wnm", psk="12345678",
1303 bssid=apdev[0]['bssid'], scan_freq="2412")
1304 dev[0].set_network(id, "scan_freq", "")
1305 dev[0].set_network(id, "bssid", "")
1307 addr = dev[0].own_addr()
1308 dev[0].dump_monitor()
1310 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1311 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000,115,36,7,0301ff"):
1312 raise Exception("BSS_TM_REQ command failed")
1313 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1315 raise Exception("No BSS Transition Management Response")
1316 if "status_code=7" not in ev:
1317 raise Exception("Unexpected BSS transition request response: " + ev)
1319 def test_wnm_bss_tm_connect_cmd(dev, apdev):
1320 """WNM BSS Transition Management and cfg80211 connect command"""
1321 params = { "ssid": "test-wnm",
1324 "bss_transition": "1" }
1325 hapd = hostapd.add_ap(apdev[0], params)
1327 params = { "ssid": "test-wnm",
1330 "bss_transition": "1" }
1331 hapd2 = hostapd.add_ap(apdev[1], params)
1333 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1334 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
1336 wpas.scan_for_bss(apdev[1]['bssid'], 2462)
1338 id = wpas.connect("test-wnm", key_mgmt="NONE",
1339 bssid=apdev[0]['bssid'], scan_freq="2412")
1340 wpas.set_network(id, "scan_freq", "")
1341 wpas.set_network(id, "bssid", "")
1343 addr = wpas.own_addr()
1346 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1347 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000,115,36,7,0301ff"):
1348 raise Exception("BSS_TM_REQ command failed")
1349 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1351 raise Exception("No BSS Transition Management Response")
1352 if "status_code=0" not in ev:
1353 raise Exception("BSS transition request was not accepted: " + ev)
1354 if "target_bssid=" + apdev[1]['bssid'] not in ev:
1355 raise Exception("Unexpected target BSS: " + ev)
1356 ev = wpas.wait_event(["CTRL-EVENT-CONNECTED",
1357 "CTRL-EVENT-DISCONNECTED"], timeout=10)
1359 raise Exception("No reassociation seen")
1360 if "CTRL-EVENT-DISCONNECTED" in ev:
1361 #TODO: Uncomment this once kernel side changes for Connect command
1362 #reassociation are in upstream.
1363 #raise Exception("Unexpected disconnection reported")
1364 logger.info("Unexpected disconnection reported")
1365 ev = wpas.wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
1367 raise Exception("No reassociation seen")
1368 if apdev[1]['bssid'] not in ev:
1369 raise Exception("Unexpected reassociation target: " + ev)