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 start_wnm_tm(ap, country, dev):
560 params = { "ssid": "test-wnm",
561 "country_code": country,
565 "bss_transition": "1" }
566 hapd = hostapd.add_ap(ap['ifname'], params)
567 id = dev.connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
569 dev.set_network(id, "scan_freq", "")
572 def stop_wnm_tm(hapd, dev):
573 dev.request("DISCONNECT")
575 dev.wait_disconnected()
579 hapd.request("DISABLE")
580 subprocess.call(['iw', 'reg', 'set', '00'])
581 dev.flush_scan_cache()
583 def wnm_bss_tm_check(hapd, dev, data):
584 addr = dev.p2p_interface_addr()
585 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " " + data):
586 raise Exception("BSS_TM_REQ command failed")
587 ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
589 raise Exception("No scan started")
590 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
592 raise Exception("Scan did not complete")
594 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
596 raise Exception("No BSS Transition Management Response")
597 if "status_code=7" not in ev:
598 raise Exception("Unexpected response: " + ev)
600 def test_wnm_bss_tm_country_us(dev, apdev):
601 """WNM BSS Transition Management (US)"""
604 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
606 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
607 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")
609 # Make the test take less time by limiting full scans
610 dev[0].set_network(id, "scan_freq", "2412")
611 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
612 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")
614 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
615 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")
617 stop_wnm_tm(hapd, dev[0])
619 def test_wnm_bss_tm_country_fi(dev, apdev):
620 """WNM BSS Transition Management (FI)"""
621 addr = dev[0].p2p_interface_addr()
624 hapd, id = start_wnm_tm(apdev[0], "FI", dev[0])
626 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
627 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")
629 # Make the test take less time by limiting full scans
630 dev[0].set_network(id, "scan_freq", "2412")
631 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
632 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")
634 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
635 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,0,0,7")
637 stop_wnm_tm(hapd, dev[0])
639 def test_wnm_bss_tm_country_jp(dev, apdev):
640 """WNM BSS Transition Management (JP)"""
641 addr = dev[0].p2p_interface_addr()
644 hapd, id = start_wnm_tm(apdev[0], "JP", dev[0])
646 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
647 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")
649 # Make the test take less time by limiting full scans
650 dev[0].set_network(id, "scan_freq", "2412")
651 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
652 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")
654 stop_wnm_tm(hapd, dev[0])
656 def test_wnm_bss_tm_country_cn(dev, apdev):
657 """WNM BSS Transition Management (CN)"""
658 addr = dev[0].p2p_interface_addr()
661 hapd, id = start_wnm_tm(apdev[0], "CN", dev[0])
663 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
664 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")
666 # Make the test take less time by limiting full scans
667 dev[0].set_network(id, "scan_freq", "2412")
668 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
669 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")
671 stop_wnm_tm(hapd, dev[0])
673 def test_wnm_bss_tm_global(dev, apdev):
674 """WNM BSS Transition Management (global)"""
675 addr = dev[0].p2p_interface_addr()
678 hapd, id = start_wnm_tm(apdev[0], "XX", dev[0])
680 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
681 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")
683 # Make the test take less time by limiting full scans
684 dev[0].set_network(id, "scan_freq", "2412")
685 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
686 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")
688 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
689 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")
691 stop_wnm_tm(hapd, dev[0])
693 def test_wnm_bss_tm_op_class_0(dev, apdev):
694 """WNM BSS Transition Management with invalid operating class"""
697 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
699 logger.info("Preferred Candidate List (no matching neighbor, invalid op class specified for channels)")
700 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")
702 stop_wnm_tm(hapd, dev[0])
704 def test_wnm_action_proto(dev, apdev):
705 """WNM Action protocol testing"""
706 params = { "ssid": "test-wnm" }
707 params['wnm_sleep_mode'] = '1'
708 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
709 bssid = apdev[0]['bssid']
710 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
711 dev[0].request("WNM_SLEEP enter")
713 hapd.set("ext_mgmt_frame_handling", "1")
716 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
717 msg['da'] = dev[0].own_addr()
723 logger.debug("Unexpected WNM-Notification Response")
724 # Note: This is actually not registered for user space processing in
725 # driver_nl80211.c nl80211_mgmt_subscribe_non_ap() and as such, won't make
726 # it to wpa_supplicant.
727 msg['payload'] = struct.pack("<BBBB",
728 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_RESP,
733 logger.debug("Truncated WNM-Notification Request (no Type field)")
734 msg['payload'] = struct.pack("<BBB",
735 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
740 logger.debug("WFA WNM-Notification Request with truncated IE (min)")
741 msg['payload'] = struct.pack("<BBBBBB",
742 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
743 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 1)
747 logger.debug("WFA WNM-Notification Request with truncated IE (max)")
748 msg['payload'] = struct.pack("<BBBBBB",
749 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
750 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 255)
754 logger.debug("WFA WNM-Notification Request with too short IE")
755 msg['payload'] = struct.pack("<BBBBBB",
756 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
757 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 0)
761 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL")
762 msg['payload'] = struct.pack(">BBBBBBLB",
763 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
764 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
769 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(2)")
770 msg['payload'] = struct.pack(">BBBBBBLBB",
771 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
772 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 6,
777 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(3)")
778 msg['payload'] = struct.pack(">BBBBBBLB",
779 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
780 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
785 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(min)")
786 msg['payload'] = struct.pack(">BBBBBBLBHB",
787 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
788 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
793 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(max)")
794 msg['payload'] = struct.pack(">BBBBBBLBHB",
795 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
796 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
797 0x506f9a01, 0, 0, 0xff)
801 logger.debug("WFA WNM-Notification Request with unsupported IE")
802 msg['payload'] = struct.pack("<BBBBBBL",
803 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
804 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 4, 0)
808 logger.debug("WNM-Notification Request with unknown WNM-Notification type 0")
809 msg['payload'] = struct.pack("<BBBB",
810 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
811 dialog_token, WNM_NOTIF_TYPE_FW_UPGRADE)
815 logger.debug("Truncated WNM Sleep Mode Response - no Dialog Token")
816 msg['payload'] = struct.pack("<BB",
817 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP)
821 logger.debug("Truncated WNM Sleep Mode Response - no Key Data Length")
822 msg['payload'] = struct.pack("<BBB",
823 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0)
827 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (min)")
828 msg['payload'] = struct.pack("<BBBH",
829 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
834 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (max)")
835 msg['payload'] = struct.pack("<BBBH",
836 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
841 logger.debug("WNM Sleep Mode Response - truncated IE header")
842 msg['payload'] = struct.pack("<BBBHB",
843 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
848 logger.debug("WNM Sleep Mode Response - truncated IE")
849 msg['payload'] = struct.pack("<BBBHBB",
850 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
855 logger.debug("WNM Sleep Mode Response - Empty TFS Response")
856 msg['payload'] = struct.pack("<BBBHBB",
857 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
858 0, WLAN_EID_TFS_RESP, 0)
862 logger.debug("WNM Sleep Mode Response - EID 0 not recognized")
863 msg['payload'] = struct.pack("<BBBHBB",
864 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
869 logger.debug("WNM Sleep Mode Response - Empty WNM Sleep Mode element and TFS Response element")
870 msg['payload'] = struct.pack("<BBBHBBBB",
871 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
872 0, WLAN_EID_WNMSLEEP, 0, WLAN_EID_TFS_RESP, 0)
876 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element and empty TFS Response element")
877 msg['payload'] = struct.pack("<BBBHBBBBHBB",
878 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
879 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
880 WNM_STATUS_SLEEP_ACCEPT, 0,
881 WLAN_EID_TFS_RESP, 0)
885 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(exit, deny key) and empty TFS Response element")
886 msg['payload'] = struct.pack("<BBBHBBBBHBB",
887 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
888 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
889 WNM_STATUS_DENIED_KEY, 0,
890 WLAN_EID_TFS_RESP, 0)
894 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(enter, deny key) and empty TFS Response element")
895 msg['payload'] = struct.pack("<BBBHBBBBHBB",
896 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
897 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
898 WNM_STATUS_DENIED_KEY, 0,
899 WLAN_EID_TFS_RESP, 0)
903 def test_wnm_action_proto_pmf(dev, apdev):
904 """WNM Action protocol testing (PMF enabled)"""
905 ssid = "test-wnm-pmf"
906 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
907 params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
908 params["ieee80211w"] = "2"
909 params['wnm_sleep_mode'] = '1'
910 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
911 bssid = apdev[0]['bssid']
912 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
913 proto="WPA2", ieee80211w="2", scan_freq="2412")
914 dev[0].request("WNM_SLEEP enter")
916 hapd.set("ext_mgmt_frame_handling", "1")
919 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
920 msg['da'] = dev[0].own_addr()
924 logger.debug("WNM Sleep Mode Response - Invalid Key Data element length")
925 keydata = struct.pack("<BB", 0, 1)
926 msg['payload'] = struct.pack("<BBBH",
927 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
929 msg['payload'] += keydata
930 msg['payload'] += struct.pack("<BBBBHBB",
931 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
932 WNM_STATUS_SLEEP_ACCEPT, 0,
933 WLAN_EID_TFS_RESP, 0)
937 logger.debug("WNM Sleep Mode Response - Too short GTK subelem")
938 keydata = struct.pack("<BB", WNM_SLEEP_SUBELEM_GTK, 0)
939 msg['payload'] = struct.pack("<BBBH",
940 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
942 msg['payload'] += keydata
943 msg['payload'] += struct.pack("<BBBBHBB",
944 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
945 WNM_STATUS_SLEEP_ACCEPT, 0,
946 WLAN_EID_TFS_RESP, 0)
950 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem")
951 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
952 0, 17, 0, 0, 0, 0, 0, 0)
953 msg['payload'] = struct.pack("<BBBH",
954 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
956 msg['payload'] += keydata
957 msg['payload'] += struct.pack("<BBBBHBB",
958 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
959 WNM_STATUS_SLEEP_ACCEPT, 0,
960 WLAN_EID_TFS_RESP, 0)
964 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem (2)")
965 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
966 0, 0, 0, 0, 0, 0, 0, 0)
967 msg['payload'] = struct.pack("<BBBH",
968 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
970 msg['payload'] += keydata
971 msg['payload'] += struct.pack("<BBBBHBB",
972 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
973 WNM_STATUS_SLEEP_ACCEPT, 0,
974 WLAN_EID_TFS_RESP, 0)
978 logger.debug("WNM Sleep Mode Response - GTK subelem and too short IGTK subelem")
979 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
980 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
981 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
982 keydata += struct.pack("<BB", WNM_SLEEP_SUBELEM_IGTK, 0)
983 msg['payload'] = struct.pack("<BBBH",
984 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
986 msg['payload'] += keydata
987 msg['payload'] += struct.pack("<BBBBHBB",
988 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
989 WNM_STATUS_SLEEP_ACCEPT, 0,
990 WLAN_EID_TFS_RESP, 0)
994 logger.debug("WNM Sleep Mode Response - Unknown subelem")
995 keydata = struct.pack("<BB", 255, 0)
996 msg['payload'] = struct.pack("<BBBH",
997 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
999 msg['payload'] += keydata
1000 msg['payload'] += struct.pack("<BBBBHBB",
1001 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1002 WNM_STATUS_SLEEP_ACCEPT, 0,
1003 WLAN_EID_TFS_RESP, 0)
1007 def test_wnm_action_proto_no_pmf(dev, apdev):
1008 """WNM Action protocol testing (PMF disabled)"""
1009 ssid = "test-wnm-no-pmf"
1010 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1011 params['wnm_sleep_mode'] = '1'
1012 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1013 bssid = apdev[0]['bssid']
1014 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1015 proto="WPA2", ieee80211w="0", scan_freq="2412")
1016 dev[0].request("WNM_SLEEP enter")
1018 hapd.set("ext_mgmt_frame_handling", "1")
1021 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1022 msg['da'] = dev[0].own_addr()
1024 msg['bssid'] = bssid
1026 logger.debug("WNM Sleep Mode Response - GTK subelem and IGTK subelem")
1027 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1028 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1029 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1030 keydata += struct.pack("<BBHLH4L", WNM_SLEEP_SUBELEM_IGTK, 2 + 6 + 16, 0,
1032 0xf1f2f3f4, 0xf5f6f7f8, 0xf9f0fafb, 0xfcfdfeff)
1033 msg['payload'] = struct.pack("<BBBH",
1034 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1036 msg['payload'] += keydata
1037 msg['payload'] += struct.pack("<BBBBHBB",
1038 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1039 WNM_STATUS_SLEEP_ACCEPT, 0,
1040 WLAN_EID_TFS_RESP, 0)
1044 ev = dev[0].wait_event(["WNM: Ignore Key Data"], timeout=5)
1046 raise Exception("Key Data not ignored")
1048 def test_wnm_bss_tm_req_with_mbo_ie(dev, apdev):
1049 """WNM BSS transition request with MBO IE and reassociation delay attribute"""
1050 ssid = "test-wnm-mbo"
1051 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1052 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1053 bssid = apdev[0]['bssid']
1054 if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
1055 raise Exception("Failed to set STA as cellular data capable")
1057 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1058 proto="WPA2", ieee80211w="0", scan_freq="2412")
1060 logger.debug("BTM request with MBO reassociation delay when disassoc imminent is not set")
1061 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=3:2:1"):
1062 raise Exception("BSS transition management succeeded unexpectedly")
1064 logger.debug("BTM request with invalid MBO transition reason code")
1065 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=10:2:1"):
1066 raise Exception("BSS transition management succeeded unexpectedly")
1068 logger.debug("BTM request with MBO reassociation retry delay of 5 seconds")
1069 if 'OK' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " disassoc_imminent=1 disassoc_timer=3 mbo=3:5:1"):
1070 raise Exception("BSS transition management command failed")
1072 ev = dev[0].wait_event(['MBO-CELL-PREFERENCE'], 1)
1073 if ev is None or "preference=1" not in ev:
1074 raise Exception("Timeout waiting for MBO-CELL-PREFERENCE event")
1076 ev = dev[0].wait_event(['MBO-TRANSITION-REASON'], 1)
1077 if ev is None or "reason=3" not in ev:
1078 raise Exception("Timeout waiting for MBO-TRANSITION-REASON event")
1080 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1082 raise Exception("No BSS Transition Management Response")
1083 if dev[0].own_addr() not in ev:
1084 raise Exception("Unexpected BSS Transition Management Response address")
1086 ev = dev[0].wait_event(['CTRL-EVENT-DISCONNECTED'], 5)
1088 raise Exception("Station did not disconnect although disassoc imminent was set")
1090 # Set the scan interval to make dev[0] look for connections
1091 if 'OK' not in dev[0].request("SCAN_INTERVAL 1"):
1092 raise Exception("Failed to set scan interval")
1094 # Make sure no connection is made during the retry delay
1095 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1097 raise Exception("Station connected before assoc retry delay was over")
1099 # After the assoc retry delay is over, we can reconnect
1100 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1102 raise Exception("Station did not connect after assoc retry delay is over")
1104 if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
1105 raise Exception("Failed to set STA as cellular data not-capable")
1107 def test_wnm_bss_transition_mgmt_query(dev, apdev):
1108 """WNM BSS Transition Management query"""
1109 params = { "ssid": "test-wnm",
1110 "bss_transition": "1" }
1111 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1112 params = { "ssid": "another" }
1113 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
1115 dev[0].scan_for_bss(apdev[1]['bssid'], 2412)
1116 dev[0].scan_for_bss(apdev[0]['bssid'], 2412)
1118 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1119 dev[0].request("WNM_BSS_QUERY 0 list")
1121 ev = dev[0].wait_event(["WNM: BSS Transition Management Request"],
1124 raise Exception("No BSS Transition Management Request frame seen")
1126 ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1128 raise Exception("No BSS Transition Management Response frame seen")