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 utils import alloc_fail, wait_fail_trigger
16 from wlantest import Wlantest
18 def test_wnm_bss_transition_mgmt(dev, apdev):
19 """WNM BSS Transition Management"""
20 params = { "ssid": "test-wnm",
21 "time_advertisement": "2",
23 "wnm_sleep_mode": "1",
24 "bss_transition": "1" }
25 hostapd.add_ap(apdev[0]['ifname'], params)
27 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
28 dev[0].request("WNM_BSS_QUERY 0")
30 def test_wnm_disassoc_imminent(dev, apdev):
31 """WNM Disassociation Imminent"""
32 params = { "ssid": "test-wnm",
33 "time_advertisement": "2",
35 "wnm_sleep_mode": "1",
36 "bss_transition": "1" }
37 hostapd.add_ap(apdev[0]['ifname'], params)
38 hapd = hostapd.Hostapd(apdev[0]['ifname'])
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 hostapd.add_ap(apdev[0]['ifname'], params)
60 hapd = hostapd.Hostapd(apdev[0]['ifname'])
62 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
63 addr = dev[0].p2p_interface_addr()
64 hapd.request("ESS_DISASSOC " + addr + " 10 http://example.com/session-info")
65 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"])
67 raise Exception("Timeout while waiting for ESS disassociation imminent")
68 if "0 1024 http://example.com/session-info" not in ev:
69 raise Exception("Unexpected ESS disassociation imminent message contents")
70 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
72 raise Exception("Timeout while waiting for re-connection scan")
74 def test_wnm_ess_disassoc_imminent_pmf(dev, apdev):
75 """WNM ESS Disassociation Imminent"""
76 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
77 params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
78 params["ieee80211w"] = "2";
79 params["bss_transition"] = "1"
80 hostapd.add_ap(apdev[0]['ifname'], params)
81 hapd = hostapd.Hostapd(apdev[0]['ifname'])
83 dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
84 key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
85 addr = dev[0].p2p_interface_addr()
86 hapd.request("ESS_DISASSOC " + addr + " 10 http://example.com/session-info")
87 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"])
89 raise Exception("Timeout while waiting for ESS disassociation imminent")
90 if "1 1024 http://example.com/session-info" not in ev:
91 raise Exception("Unexpected ESS disassociation imminent message contents")
92 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
94 raise Exception("Timeout while waiting for re-connection scan")
96 def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None):
97 addr = dev.p2p_interface_addr()
98 sta = hapd.get_sta(addr)
99 if "[WNM_SLEEP_MODE]" in sta['flags']:
100 raise Exception("Station unexpectedly in WNM-Sleep Mode")
102 logger.info("Going to WNM Sleep Mode")
104 if interval is not None:
105 extra += " interval=" + str(interval)
107 extra += " tfs_req=" + tfs_req
108 if "OK" not in dev.request("WNM_SLEEP enter" + extra):
109 raise Exception("WNM_SLEEP failed")
113 sta = hapd.get_sta(addr)
114 if "[WNM_SLEEP_MODE]" in sta['flags']:
118 raise Exception("Station failed to enter WNM-Sleep Mode")
120 logger.info("Waking up from WNM Sleep Mode")
122 dev.request("WNM_SLEEP exit")
125 sta = hapd.get_sta(addr)
126 if "[WNM_SLEEP_MODE]" not in sta['flags']:
130 raise Exception("Station failed to exit WNM-Sleep Mode")
132 def test_wnm_sleep_mode_open(dev, apdev):
133 """WNM Sleep Mode - open"""
134 params = { "ssid": "test-wnm",
135 "time_advertisement": "2",
137 "wnm_sleep_mode": "1",
138 "bss_transition": "1" }
139 hostapd.add_ap(apdev[0]['ifname'], params)
140 hapd = hostapd.Hostapd(apdev[0]['ifname'])
142 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
143 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
145 raise Exception("No connection event received from hostapd")
146 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
147 check_wnm_sleep_mode_enter_exit(hapd, dev[0], interval=100)
148 check_wnm_sleep_mode_enter_exit(hapd, dev[0], tfs_req="5b17010001130e110000071122334455661122334455661234")
151 "exit tfs_req=123 interval=10",
152 "enter tfs_req=qq interval=10" ]
154 if "FAIL" not in dev[0].request("WNM_SLEEP " + cmd):
155 raise Exception("Invalid WNM_SLEEP accepted")
157 def test_wnm_sleep_mode_rsn(dev, apdev):
158 """WNM Sleep Mode - RSN"""
159 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
160 params["time_advertisement"] = "2"
161 params["time_zone"] = "EST5"
162 params["wnm_sleep_mode"] = "1"
163 params["bss_transition"] = "1"
164 hostapd.add_ap(apdev[0]['ifname'], params)
165 hapd = hostapd.Hostapd(apdev[0]['ifname'])
167 dev[0].connect("test-wnm-rsn", psk="12345678", scan_freq="2412")
168 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
170 raise Exception("No connection event received from hostapd")
171 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
173 def test_wnm_sleep_mode_ap_oom(dev, apdev):
174 """WNM Sleep Mode - AP side OOM"""
175 params = { "ssid": "test-wnm",
176 "wnm_sleep_mode": "1" }
177 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
179 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
180 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
182 raise Exception("No connection event received from hostapd")
183 with alloc_fail(hapd, 1, "ieee802_11_send_wnmsleep_resp"):
184 dev[0].request("WNM_SLEEP enter")
185 wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
186 with alloc_fail(hapd, 2, "ieee802_11_send_wnmsleep_resp"):
187 dev[0].request("WNM_SLEEP exit")
188 wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
190 def test_wnm_sleep_mode_rsn_pmf(dev, apdev):
191 """WNM Sleep Mode - RSN with PMF"""
194 wt.add_passphrase("12345678")
195 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
196 params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
197 params["ieee80211w"] = "2";
198 params["time_advertisement"] = "2"
199 params["time_zone"] = "EST5"
200 params["wnm_sleep_mode"] = "1"
201 params["bss_transition"] = "1"
202 hostapd.add_ap(apdev[0]['ifname'], params)
203 hapd = hostapd.Hostapd(apdev[0]['ifname'])
205 dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
206 key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
207 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
209 raise Exception("No connection event received from hostapd")
210 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
212 MGMT_SUBTYPE_ACTION = 13
213 ACTION_CATEG_WNM = 10
214 WNM_ACT_BSS_TM_REQ = 7
215 WNM_ACT_BSS_TM_RESP = 8
216 WNM_ACT_SLEEP_MODE_REQ = 16
217 WNM_ACT_SLEEP_MODE_RESP = 17
218 WNM_ACT_NOTIFICATION_REQ = 26
219 WNM_ACT_NOTIFICATION_RESP = 27
220 WNM_NOTIF_TYPE_FW_UPGRADE = 0
221 WNM_NOTIF_TYPE_WFA = 1
222 WLAN_EID_TFS_RESP = 92
223 WLAN_EID_WNMSLEEP = 93
224 WNM_SLEEP_MODE_ENTER = 0
225 WNM_SLEEP_MODE_EXIT = 1
226 WNM_STATUS_SLEEP_ACCEPT = 0
227 WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE = 1
228 WNM_STATUS_DENIED_ACTION = 2
229 WNM_STATUS_DENIED_TMP = 3
230 WNM_STATUS_DENIED_KEY = 4
231 WNM_STATUS_DENIED_OTHER_WNM_SERVICE = 5
232 WNM_SLEEP_SUBELEM_GTK = 0
233 WNM_SLEEP_SUBELEM_IGTK = 1
235 def bss_tm_req(dst, src, dialog_token=1, req_mode=0, disassoc_timer=0,
236 validity_interval=1):
238 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
242 msg['payload'] = struct.pack("<BBBBHB",
243 ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
244 dialog_token, req_mode, disassoc_timer,
248 def rx_bss_tm_resp(hapd, expect_dialog=None, expect_status=None):
249 for i in range(0, 100):
250 resp = hapd.mgmt_rx()
252 raise Exception("No BSS TM Response received")
253 if resp['subtype'] == MGMT_SUBTYPE_ACTION:
256 raise Exception("Not an Action frame")
257 payload = resp['payload']
258 if len(payload) < 2 + 3:
259 raise Exception("Too short payload")
260 (category, action) = struct.unpack('BB', payload[0:2])
261 if category != ACTION_CATEG_WNM or action != WNM_ACT_BSS_TM_RESP:
262 raise Exception("Not a BSS TM Response")
264 (dialog, status, bss_term_delay) = struct.unpack('BBB', pos[0:3])
265 resp['dialog'] = dialog
266 resp['status'] = status
267 resp['bss_term_delay'] = bss_term_delay
269 if len(pos) >= 6 and status == 0:
270 resp['target_bssid'] = binascii.hexlify(pos[0:6])
272 resp['candidates'] = pos
273 if expect_dialog is not None and dialog != expect_dialog:
274 raise Exception("Unexpected dialog token")
275 if expect_status is not None and status != expect_status:
276 raise Exception("Unexpected status code %d" % status)
279 def expect_ack(hapd):
280 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
282 raise Exception("Missing TX status")
284 raise Exception("Action frame not acknowledged")
286 def test_wnm_bss_tm_req(dev, apdev):
287 """BSS Transition Management Request"""
288 params = { "ssid": "test-wnm", "bss_transition": "1" }
289 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
290 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
291 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
293 hapd.set("ext_mgmt_frame_handling", "1")
295 # truncated BSS TM Request
296 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
298 req['payload'] = struct.pack("<BBBBH",
299 ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
304 # no disassociation and no candidate list
305 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
308 resp = rx_bss_tm_resp(hapd, expect_dialog=2, expect_status=1)
310 # truncated BSS Termination Duration
311 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
316 # BSS Termination Duration with TSF=0 and Duration=10
317 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
318 req_mode=0x08, dialog_token=3)
319 req['payload'] += struct.pack("<BBQH", 4, 10, 0, 10)
321 resp = rx_bss_tm_resp(hapd, expect_dialog=3, expect_status=1)
323 # truncated Session Information URL
324 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
328 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
330 req['payload'] += struct.pack("<BBB", 3, 65, 66)
334 # Session Information URL
335 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
336 req_mode=0x10, dialog_token=4)
337 req['payload'] += struct.pack("<BBB", 2, 65, 66)
339 resp = rx_bss_tm_resp(hapd, expect_dialog=4, expect_status=0)
341 # Preferred Candidate List without any entries
342 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
343 req_mode=0x01, dialog_token=5)
345 resp = rx_bss_tm_resp(hapd, expect_dialog=5, expect_status=7)
347 # Preferred Candidate List with a truncated entry
348 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
350 req['payload'] += struct.pack("<BB", 52, 1)
354 # Preferred Candidate List with a too short entry
355 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
356 req_mode=0x01, dialog_token=6)
357 req['payload'] += struct.pack("<BB", 52, 0)
359 resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
361 # Preferred Candidate List with a non-matching entry
362 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
363 req_mode=0x01, dialog_token=6)
364 req['payload'] += struct.pack("<BB6BLBBB", 52, 13,
368 resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
370 # Preferred Candidate List with a truncated subelement
371 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
372 req_mode=0x01, dialog_token=7)
373 req['payload'] += struct.pack("<BB6BLBBBBB", 52, 13 + 2,
378 resp = rx_bss_tm_resp(hapd, expect_dialog=7, expect_status=7)
380 # Preferred Candidate List with lots of invalid optional subelements
381 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
382 req_mode=0x01, dialog_token=8)
383 subelems = struct.pack("<BBHB", 1, 3, 0, 100)
384 subelems += struct.pack("<BBB", 2, 1, 65)
385 subelems += struct.pack("<BB", 3, 0)
386 subelems += struct.pack("<BBQB", 4, 9, 0, 10)
387 subelems += struct.pack("<BBHLB", 5, 7, 0, 0, 0)
388 subelems += struct.pack("<BB", 66, 0)
389 subelems += struct.pack("<BBBBBB", 70, 4, 0, 0, 0, 0)
390 subelems += struct.pack("<BB", 71, 0)
391 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
393 0, 81, 1, 7) + subelems
395 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
397 # Preferred Candidate List with lots of valid optional subelements (twice)
398 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
399 req_mode=0x01, dialog_token=8)
401 subelems = struct.pack("<BBHH", 1, 4, 0, 100)
402 # Condensed Country String
403 subelems += struct.pack("<BBBB", 2, 2, 65, 66)
404 # BSS Transition Candidate Preference
405 subelems += struct.pack("<BBB", 3, 1, 100)
406 # BSS Termination Duration
407 subelems += struct.pack("<BBQH", 4, 10, 0, 10)
409 subelems += struct.pack("<BBHLH", 5, 8, 0, 0, 0)
410 # Measurement Pilot Transmission
411 subelems += struct.pack("<BBBBB", 66, 3, 0, 0, 0)
412 # RM Enabled Capabilities
413 subelems += struct.pack("<BBBBBBB", 70, 5, 0, 0, 0, 0, 0)
415 subelems += struct.pack("<BBBB", 71, 2, 0, 0)
416 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems) * 2,
418 0, 81, 1, 7) + subelems + subelems
420 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
422 def test_wnm_bss_keep_alive(dev, apdev):
424 params = { "ssid": "test-wnm",
425 "ap_max_inactivity": "1" }
426 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
428 addr = dev[0].p2p_interface_addr()
429 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
430 start = hapd.get_sta(addr)
431 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=2)
433 raise Exception("Unexpected disconnection")
434 end = hapd.get_sta(addr)
435 if int(end['rx_packets']) <= int(start['rx_packets']):
436 raise Exception("No keep-alive packets received")
438 # Disable client keep-alive so that hostapd will verify connection
440 dev[0].request("SET no_keep_alive 1")
442 sta = hapd.get_sta(addr)
443 logger.info("timeout_next=%s rx_packets=%s tx_packets=%s" % (sta['timeout_next'], sta['rx_packets'], sta['tx_packets']))
444 if i > 1 and sta['timeout_next'] != "NULLFUNC POLL" and int(sta['tx_packets']) > int(end['tx_packets']):
446 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
448 raise Exception("Unexpected disconnection (client poll expected)")
450 dev[0].request("SET no_keep_alive 0")
451 if int(sta['tx_packets']) <= int(end['tx_packets']):
452 raise Exception("No client poll packet seen")
454 def test_wnm_bss_tm(dev, apdev):
455 """WNM BSS Transition Management"""
459 params = { "ssid": "test-wnm",
460 "country_code": "FI",
464 "bss_transition": "1" }
465 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
467 id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
468 dev[0].set_network(id, "scan_freq", "")
470 params = { "ssid": "test-wnm",
471 "country_code": "FI",
475 "bss_transition": "1" }
476 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
478 addr = dev[0].p2p_interface_addr()
479 dev[0].dump_monitor()
481 logger.info("No neighbor list entries")
482 if "OK" not in hapd.request("BSS_TM_REQ " + addr):
483 raise Exception("BSS_TM_REQ command failed")
484 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
486 raise Exception("No BSS Transition Management Response")
488 raise Exception("Unexpected BSS Transition Management Response address")
489 if "status_code=0" in ev:
490 raise Exception("BSS transition accepted unexpectedly")
491 dev[0].dump_monitor()
493 logger.info("Neighbor list entry, but not claimed as Preferred Candidate List")
494 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " neighbor=11:22:33:44:55:66,0x0000,81,3,7"):
495 raise Exception("BSS_TM_REQ command failed")
496 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
498 raise Exception("No BSS Transition Management Response")
499 if "status_code=0" in ev:
500 raise Exception("BSS transition accepted unexpectedly")
501 dev[0].dump_monitor()
503 logger.info("Preferred Candidate List (no matching neighbor) without Disassociation Imminent")
504 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"):
505 raise Exception("BSS_TM_REQ command failed")
506 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
508 raise Exception("No BSS Transition Management Response")
509 if "status_code=0" in ev:
510 raise Exception("BSS transition accepted unexpectedly")
511 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
513 raise Exception("No scan started")
514 dev[0].dump_monitor()
516 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
517 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"):
518 raise Exception("BSS_TM_REQ command failed")
519 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
521 raise Exception("No BSS Transition Management Response")
522 if "status_code=0" not in ev:
523 raise Exception("BSS transition request was not accepted: " + ev)
524 if "target_bssid=" + apdev[1]['bssid'] not in ev:
525 raise Exception("Unexpected target BSS: " + ev)
526 dev[0].wait_connected(timeout=15, error="No reassociation seen")
527 if apdev[1]['bssid'] not in ev:
528 raise Exception("Unexpected reassociation target: " + ev)
529 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
531 raise Exception("Unexpected scan started")
532 dev[0].dump_monitor()
534 logger.info("Preferred Candidate List with two matches, no roam needed")
535 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"):
536 raise Exception("BSS_TM_REQ command failed")
537 ev = hapd2.wait_event(['BSS-TM-RESP'], timeout=10)
539 raise Exception("No BSS Transition Management Response")
540 if "status_code=0" not in ev:
541 raise Exception("BSS transition request was not accepted: " + ev)
542 if "target_bssid=" + apdev[1]['bssid'] not in ev:
543 raise Exception("Unexpected target BSS: " + ev)
544 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
546 raise Exception("Unexpected scan started")
547 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
549 raise Exception("Unexpected reassociation");
551 dev[0].request("DISCONNECT")
553 hapd.request("DISABLE")
555 hapd2.request("DISABLE")
556 subprocess.call(['iw', 'reg', 'set', '00'])
557 dev[0].flush_scan_cache()
559 def test_wnm_bss_tm_scan_not_needed(dev, apdev):
560 """WNM BSS Transition Management and scan not needed"""
564 params = { "ssid": "test-wnm",
565 "country_code": "FI",
569 "bss_transition": "1" }
570 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
572 params = { "ssid": "test-wnm",
573 "country_code": "FI",
577 "bss_transition": "1" }
578 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
580 dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
582 id = dev[0].connect("test-wnm", key_mgmt="NONE",
583 bssid=apdev[0]['bssid'], scan_freq="2412")
584 dev[0].set_network(id, "scan_freq", "")
585 dev[0].set_network(id, "bssid", "")
587 addr = dev[0].own_addr()
588 dev[0].dump_monitor()
590 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
591 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"):
592 raise Exception("BSS_TM_REQ command failed")
593 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
595 raise Exception("No BSS Transition Management Response")
596 if "status_code=0" not in ev:
597 raise Exception("BSS transition request was not accepted: " + ev)
598 if "target_bssid=" + apdev[1]['bssid'] not in ev:
599 raise Exception("Unexpected target BSS: " + ev)
600 dev[0].wait_connected(timeout=15, error="No reassociation seen")
601 if apdev[1]['bssid'] not in ev:
602 raise Exception("Unexpected reassociation target: " + ev)
603 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
605 raise Exception("Unexpected scan started")
606 dev[0].dump_monitor()
608 dev[0].request("DISCONNECT")
610 hapd.request("DISABLE")
612 hapd2.request("DISABLE")
613 subprocess.call(['iw', 'reg', 'set', '00'])
614 dev[0].flush_scan_cache()
616 def test_wnm_bss_tm_scan_needed(dev, apdev):
617 """WNM BSS Transition Management and scan needed"""
621 params = { "ssid": "test-wnm",
622 "country_code": "FI",
626 "bss_transition": "1" }
627 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
629 params = { "ssid": "test-wnm",
630 "country_code": "FI",
634 "bss_transition": "1" }
635 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
637 dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
639 id = dev[0].connect("test-wnm", key_mgmt="NONE",
640 bssid=apdev[0]['bssid'], scan_freq="2412")
641 dev[0].set_network(id, "scan_freq", "")
642 dev[0].set_network(id, "bssid", "")
644 addr = dev[0].own_addr()
645 dev[0].dump_monitor()
647 logger.info("Wait 11 seconds for the last scan result to be too old, but still present in BSS table")
649 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
650 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"):
651 raise Exception("BSS_TM_REQ command failed")
652 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
654 raise Exception("No BSS Transition Management Response")
655 if "status_code=0" not in ev:
656 raise Exception("BSS transition request was not accepted: " + ev)
657 if "target_bssid=" + apdev[1]['bssid'] not in ev:
658 raise Exception("Unexpected target BSS: " + ev)
659 dev[0].wait_connected(timeout=15, error="No reassociation seen")
660 if apdev[1]['bssid'] not in ev:
661 raise Exception("Unexpected reassociation target: " + ev)
662 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
664 raise Exception("Unexpected scan started")
665 dev[0].dump_monitor()
667 dev[0].request("DISCONNECT")
669 hapd.request("DISABLE")
671 hapd2.request("DISABLE")
672 subprocess.call(['iw', 'reg', 'set', '00'])
673 dev[0].flush_scan_cache()
675 def start_wnm_tm(ap, country, dev):
676 params = { "ssid": "test-wnm",
677 "country_code": country,
681 "bss_transition": "1" }
682 hapd = hostapd.add_ap(ap['ifname'], params)
683 id = dev.connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
685 dev.set_network(id, "scan_freq", "")
688 def stop_wnm_tm(hapd, dev):
689 dev.request("DISCONNECT")
691 dev.wait_disconnected()
695 hapd.request("DISABLE")
696 subprocess.call(['iw', 'reg', 'set', '00'])
697 dev.flush_scan_cache()
699 def wnm_bss_tm_check(hapd, dev, data):
700 addr = dev.p2p_interface_addr()
701 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " " + data):
702 raise Exception("BSS_TM_REQ command failed")
703 ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
705 raise Exception("No scan started")
706 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
708 raise Exception("Scan did not complete")
710 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
712 raise Exception("No BSS Transition Management Response")
713 if "status_code=7" not in ev:
714 raise Exception("Unexpected response: " + ev)
716 def test_wnm_bss_tm_country_us(dev, apdev):
717 """WNM BSS Transition Management (US)"""
720 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
722 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
723 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")
725 # Make the test take less time by limiting full scans
726 dev[0].set_network(id, "scan_freq", "2412")
727 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
728 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")
730 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
731 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")
733 stop_wnm_tm(hapd, dev[0])
735 def test_wnm_bss_tm_country_fi(dev, apdev):
736 """WNM BSS Transition Management (FI)"""
737 addr = dev[0].p2p_interface_addr()
740 hapd, id = start_wnm_tm(apdev[0], "FI", dev[0])
742 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
743 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")
745 # Make the test take less time by limiting full scans
746 dev[0].set_network(id, "scan_freq", "2412")
747 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
748 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")
750 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
751 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,0,0,7")
753 stop_wnm_tm(hapd, dev[0])
755 def test_wnm_bss_tm_country_jp(dev, apdev):
756 """WNM BSS Transition Management (JP)"""
757 addr = dev[0].p2p_interface_addr()
760 hapd, id = start_wnm_tm(apdev[0], "JP", dev[0])
762 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
763 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")
765 # Make the test take less time by limiting full scans
766 dev[0].set_network(id, "scan_freq", "2412")
767 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
768 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")
770 stop_wnm_tm(hapd, dev[0])
772 def test_wnm_bss_tm_country_cn(dev, apdev):
773 """WNM BSS Transition Management (CN)"""
774 addr = dev[0].p2p_interface_addr()
777 hapd, id = start_wnm_tm(apdev[0], "CN", dev[0])
779 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
780 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")
782 # Make the test take less time by limiting full scans
783 dev[0].set_network(id, "scan_freq", "2412")
784 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
785 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")
787 stop_wnm_tm(hapd, dev[0])
789 def test_wnm_bss_tm_global(dev, apdev):
790 """WNM BSS Transition Management (global)"""
791 addr = dev[0].p2p_interface_addr()
794 hapd, id = start_wnm_tm(apdev[0], "XX", dev[0])
796 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
797 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")
799 # Make the test take less time by limiting full scans
800 dev[0].set_network(id, "scan_freq", "2412")
801 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
802 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")
804 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
805 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")
807 stop_wnm_tm(hapd, dev[0])
809 def test_wnm_bss_tm_op_class_0(dev, apdev):
810 """WNM BSS Transition Management with invalid operating class"""
813 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
815 logger.info("Preferred Candidate List (no matching neighbor, invalid op class specified for channels)")
816 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")
818 stop_wnm_tm(hapd, dev[0])
820 def test_wnm_action_proto(dev, apdev):
821 """WNM Action protocol testing"""
822 params = { "ssid": "test-wnm" }
823 params['wnm_sleep_mode'] = '1'
824 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
825 bssid = apdev[0]['bssid']
826 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
827 dev[0].request("WNM_SLEEP enter")
829 hapd.set("ext_mgmt_frame_handling", "1")
832 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
833 msg['da'] = dev[0].own_addr()
839 logger.debug("Unexpected WNM-Notification Response")
840 # Note: This is actually not registered for user space processing in
841 # driver_nl80211.c nl80211_mgmt_subscribe_non_ap() and as such, won't make
842 # it to wpa_supplicant.
843 msg['payload'] = struct.pack("<BBBB",
844 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_RESP,
849 logger.debug("Truncated WNM-Notification Request (no Type field)")
850 msg['payload'] = struct.pack("<BBB",
851 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
856 logger.debug("WFA WNM-Notification Request with truncated IE (min)")
857 msg['payload'] = struct.pack("<BBBBBB",
858 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
859 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 1)
863 logger.debug("WFA WNM-Notification Request with truncated IE (max)")
864 msg['payload'] = struct.pack("<BBBBBB",
865 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
866 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 255)
870 logger.debug("WFA WNM-Notification Request with too short IE")
871 msg['payload'] = struct.pack("<BBBBBB",
872 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
873 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 0)
877 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL")
878 msg['payload'] = struct.pack(">BBBBBBLB",
879 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
880 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
885 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(2)")
886 msg['payload'] = struct.pack(">BBBBBBLBB",
887 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
888 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 6,
893 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(3)")
894 msg['payload'] = struct.pack(">BBBBBBLB",
895 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
896 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
901 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(min)")
902 msg['payload'] = struct.pack(">BBBBBBLBHB",
903 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
904 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
909 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(max)")
910 msg['payload'] = struct.pack(">BBBBBBLBHB",
911 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
912 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
913 0x506f9a01, 0, 0, 0xff)
917 logger.debug("WFA WNM-Notification Request with unsupported IE")
918 msg['payload'] = struct.pack("<BBBBBBL",
919 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
920 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 4, 0)
924 logger.debug("WNM-Notification Request with unknown WNM-Notification type 0")
925 msg['payload'] = struct.pack("<BBBB",
926 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
927 dialog_token, WNM_NOTIF_TYPE_FW_UPGRADE)
931 logger.debug("Truncated WNM Sleep Mode Response - no Dialog Token")
932 msg['payload'] = struct.pack("<BB",
933 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP)
937 logger.debug("Truncated WNM Sleep Mode Response - no Key Data Length")
938 msg['payload'] = struct.pack("<BBB",
939 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0)
943 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (min)")
944 msg['payload'] = struct.pack("<BBBH",
945 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
950 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (max)")
951 msg['payload'] = struct.pack("<BBBH",
952 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
957 logger.debug("WNM Sleep Mode Response - truncated IE header")
958 msg['payload'] = struct.pack("<BBBHB",
959 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
964 logger.debug("WNM Sleep Mode Response - truncated IE")
965 msg['payload'] = struct.pack("<BBBHBB",
966 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
971 logger.debug("WNM Sleep Mode Response - Empty TFS Response")
972 msg['payload'] = struct.pack("<BBBHBB",
973 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
974 0, WLAN_EID_TFS_RESP, 0)
978 logger.debug("WNM Sleep Mode Response - EID 0 not recognized")
979 msg['payload'] = struct.pack("<BBBHBB",
980 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
985 logger.debug("WNM Sleep Mode Response - Empty WNM Sleep Mode element and TFS Response element")
986 msg['payload'] = struct.pack("<BBBHBBBB",
987 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
988 0, WLAN_EID_WNMSLEEP, 0, WLAN_EID_TFS_RESP, 0)
992 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element and empty TFS Response element")
993 msg['payload'] = struct.pack("<BBBHBBBBHBB",
994 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
995 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
996 WNM_STATUS_SLEEP_ACCEPT, 0,
997 WLAN_EID_TFS_RESP, 0)
1001 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(exit, deny key) and empty TFS Response element")
1002 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1003 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1004 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1005 WNM_STATUS_DENIED_KEY, 0,
1006 WLAN_EID_TFS_RESP, 0)
1010 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(enter, deny key) and empty TFS Response element")
1011 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1012 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1013 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1014 WNM_STATUS_DENIED_KEY, 0,
1015 WLAN_EID_TFS_RESP, 0)
1019 def test_wnm_action_proto_pmf(dev, apdev):
1020 """WNM Action protocol testing (PMF enabled)"""
1021 ssid = "test-wnm-pmf"
1022 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1023 params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1024 params["ieee80211w"] = "2"
1025 params['wnm_sleep_mode'] = '1'
1026 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1027 bssid = apdev[0]['bssid']
1028 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
1029 proto="WPA2", ieee80211w="2", scan_freq="2412")
1030 dev[0].request("WNM_SLEEP enter")
1032 hapd.set("ext_mgmt_frame_handling", "1")
1035 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1036 msg['da'] = dev[0].own_addr()
1038 msg['bssid'] = bssid
1040 logger.debug("WNM Sleep Mode Response - Invalid Key Data element length")
1041 keydata = struct.pack("<BB", 0, 1)
1042 msg['payload'] = struct.pack("<BBBH",
1043 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1045 msg['payload'] += keydata
1046 msg['payload'] += struct.pack("<BBBBHBB",
1047 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1048 WNM_STATUS_SLEEP_ACCEPT, 0,
1049 WLAN_EID_TFS_RESP, 0)
1053 logger.debug("WNM Sleep Mode Response - Too short GTK subelem")
1054 keydata = struct.pack("<BB", WNM_SLEEP_SUBELEM_GTK, 0)
1055 msg['payload'] = struct.pack("<BBBH",
1056 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1058 msg['payload'] += keydata
1059 msg['payload'] += struct.pack("<BBBBHBB",
1060 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1061 WNM_STATUS_SLEEP_ACCEPT, 0,
1062 WLAN_EID_TFS_RESP, 0)
1066 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem")
1067 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1068 0, 17, 0, 0, 0, 0, 0, 0)
1069 msg['payload'] = struct.pack("<BBBH",
1070 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1072 msg['payload'] += keydata
1073 msg['payload'] += struct.pack("<BBBBHBB",
1074 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1075 WNM_STATUS_SLEEP_ACCEPT, 0,
1076 WLAN_EID_TFS_RESP, 0)
1080 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem (2)")
1081 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1082 0, 0, 0, 0, 0, 0, 0, 0)
1083 msg['payload'] = struct.pack("<BBBH",
1084 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1086 msg['payload'] += keydata
1087 msg['payload'] += struct.pack("<BBBBHBB",
1088 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1089 WNM_STATUS_SLEEP_ACCEPT, 0,
1090 WLAN_EID_TFS_RESP, 0)
1094 logger.debug("WNM Sleep Mode Response - GTK subelem and too short IGTK subelem")
1095 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1096 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1097 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1098 keydata += struct.pack("<BB", WNM_SLEEP_SUBELEM_IGTK, 0)
1099 msg['payload'] = struct.pack("<BBBH",
1100 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1102 msg['payload'] += keydata
1103 msg['payload'] += struct.pack("<BBBBHBB",
1104 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1105 WNM_STATUS_SLEEP_ACCEPT, 0,
1106 WLAN_EID_TFS_RESP, 0)
1110 logger.debug("WNM Sleep Mode Response - Unknown subelem")
1111 keydata = struct.pack("<BB", 255, 0)
1112 msg['payload'] = struct.pack("<BBBH",
1113 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1115 msg['payload'] += keydata
1116 msg['payload'] += struct.pack("<BBBBHBB",
1117 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1118 WNM_STATUS_SLEEP_ACCEPT, 0,
1119 WLAN_EID_TFS_RESP, 0)
1123 def test_wnm_action_proto_no_pmf(dev, apdev):
1124 """WNM Action protocol testing (PMF disabled)"""
1125 ssid = "test-wnm-no-pmf"
1126 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1127 params['wnm_sleep_mode'] = '1'
1128 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1129 bssid = apdev[0]['bssid']
1130 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1131 proto="WPA2", ieee80211w="0", scan_freq="2412")
1132 dev[0].request("WNM_SLEEP enter")
1134 hapd.set("ext_mgmt_frame_handling", "1")
1137 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1138 msg['da'] = dev[0].own_addr()
1140 msg['bssid'] = bssid
1142 logger.debug("WNM Sleep Mode Response - GTK subelem and IGTK subelem")
1143 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1144 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1145 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1146 keydata += struct.pack("<BBHLH4L", WNM_SLEEP_SUBELEM_IGTK, 2 + 6 + 16, 0,
1148 0xf1f2f3f4, 0xf5f6f7f8, 0xf9f0fafb, 0xfcfdfeff)
1149 msg['payload'] = struct.pack("<BBBH",
1150 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1152 msg['payload'] += keydata
1153 msg['payload'] += struct.pack("<BBBBHBB",
1154 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1155 WNM_STATUS_SLEEP_ACCEPT, 0,
1156 WLAN_EID_TFS_RESP, 0)
1160 ev = dev[0].wait_event(["WNM: Ignore Key Data"], timeout=5)
1162 raise Exception("Key Data not ignored")
1164 def test_wnm_bss_tm_req_with_mbo_ie(dev, apdev):
1165 """WNM BSS transition request with MBO IE and reassociation delay attribute"""
1166 ssid = "test-wnm-mbo"
1167 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1168 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1169 bssid = apdev[0]['bssid']
1170 if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
1171 raise Exception("Failed to set STA as cellular data capable")
1173 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1174 proto="WPA2", ieee80211w="0", scan_freq="2412")
1176 logger.debug("BTM request with MBO reassociation delay when disassoc imminent is not set")
1177 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=3:2:1"):
1178 raise Exception("BSS transition management succeeded unexpectedly")
1180 logger.debug("BTM request with invalid MBO transition reason code")
1181 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=10:2:1"):
1182 raise Exception("BSS transition management succeeded unexpectedly")
1184 logger.debug("BTM request with MBO reassociation retry delay of 5 seconds")
1185 if 'OK' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " disassoc_imminent=1 disassoc_timer=3 mbo=3:5:1"):
1186 raise Exception("BSS transition management command failed")
1188 ev = dev[0].wait_event(['MBO-CELL-PREFERENCE'], 1)
1189 if ev is None or "preference=1" not in ev:
1190 raise Exception("Timeout waiting for MBO-CELL-PREFERENCE event")
1192 ev = dev[0].wait_event(['MBO-TRANSITION-REASON'], 1)
1193 if ev is None or "reason=3" not in ev:
1194 raise Exception("Timeout waiting for MBO-TRANSITION-REASON event")
1196 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1198 raise Exception("No BSS Transition Management Response")
1199 if dev[0].own_addr() not in ev:
1200 raise Exception("Unexpected BSS Transition Management Response address")
1202 ev = dev[0].wait_event(['CTRL-EVENT-DISCONNECTED'], 5)
1204 raise Exception("Station did not disconnect although disassoc imminent was set")
1206 # Set the scan interval to make dev[0] look for connections
1207 if 'OK' not in dev[0].request("SCAN_INTERVAL 1"):
1208 raise Exception("Failed to set scan interval")
1210 # Make sure no connection is made during the retry delay
1211 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1213 raise Exception("Station connected before assoc retry delay was over")
1215 # After the assoc retry delay is over, we can reconnect
1216 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1218 raise Exception("Station did not connect after assoc retry delay is over")
1220 if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
1221 raise Exception("Failed to set STA as cellular data not-capable")
1223 def test_wnm_bss_transition_mgmt_query(dev, apdev):
1224 """WNM BSS Transition Management query"""
1225 params = { "ssid": "test-wnm",
1226 "bss_transition": "1" }
1227 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1228 params = { "ssid": "another" }
1229 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
1231 dev[0].scan_for_bss(apdev[1]['bssid'], 2412)
1232 dev[0].scan_for_bss(apdev[0]['bssid'], 2412)
1234 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1235 dev[0].request("WNM_BSS_QUERY 0 list")
1237 ev = dev[0].wait_event(["WNM: BSS Transition Management Request"],
1240 raise Exception("No BSS Transition Management Request frame seen")
1242 ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1244 raise Exception("No BSS Transition Management Response frame seen")