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 # Preferred Candidate List followed by vendor element
423 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
424 req_mode=0x01, dialog_token=8)
426 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
428 0, 81, 1, 7) + subelems
429 req['payload'] += binascii.unhexlify("DD0411223344")
431 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
433 def test_wnm_bss_keep_alive(dev, apdev):
435 params = { "ssid": "test-wnm",
436 "ap_max_inactivity": "1" }
437 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
439 addr = dev[0].p2p_interface_addr()
440 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
441 start = hapd.get_sta(addr)
442 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=2)
444 raise Exception("Unexpected disconnection")
445 end = hapd.get_sta(addr)
446 if int(end['rx_packets']) <= int(start['rx_packets']):
447 raise Exception("No keep-alive packets received")
449 # Disable client keep-alive so that hostapd will verify connection
451 dev[0].request("SET no_keep_alive 1")
453 sta = hapd.get_sta(addr)
454 logger.info("timeout_next=%s rx_packets=%s tx_packets=%s" % (sta['timeout_next'], sta['rx_packets'], sta['tx_packets']))
455 if i > 1 and sta['timeout_next'] != "NULLFUNC POLL" and int(sta['tx_packets']) > int(end['tx_packets']):
457 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
459 raise Exception("Unexpected disconnection (client poll expected)")
461 dev[0].request("SET no_keep_alive 0")
462 if int(sta['tx_packets']) <= int(end['tx_packets']):
463 raise Exception("No client poll packet seen")
465 def test_wnm_bss_tm(dev, apdev):
466 """WNM BSS Transition Management"""
470 params = { "ssid": "test-wnm",
471 "country_code": "FI",
475 "bss_transition": "1" }
476 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
478 id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
479 dev[0].set_network(id, "scan_freq", "")
481 params = { "ssid": "test-wnm",
482 "country_code": "FI",
486 "bss_transition": "1" }
487 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
489 addr = dev[0].p2p_interface_addr()
490 dev[0].dump_monitor()
492 logger.info("No neighbor list entries")
493 if "OK" not in hapd.request("BSS_TM_REQ " + addr):
494 raise Exception("BSS_TM_REQ command failed")
495 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
497 raise Exception("No BSS Transition Management Response")
499 raise Exception("Unexpected BSS Transition Management Response address")
500 if "status_code=0" in ev:
501 raise Exception("BSS transition accepted unexpectedly")
502 dev[0].dump_monitor()
504 logger.info("Neighbor list entry, but not claimed as Preferred Candidate List")
505 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " neighbor=11:22:33:44:55:66,0x0000,81,3,7"):
506 raise Exception("BSS_TM_REQ command failed")
507 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
509 raise Exception("No BSS Transition Management Response")
510 if "status_code=0" in ev:
511 raise Exception("BSS transition accepted unexpectedly")
512 dev[0].dump_monitor()
514 logger.info("Preferred Candidate List (no matching neighbor) without Disassociation Imminent")
515 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"):
516 raise Exception("BSS_TM_REQ command failed")
517 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
519 raise Exception("No BSS Transition Management Response")
520 if "status_code=0" in ev:
521 raise Exception("BSS transition accepted unexpectedly")
522 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
524 raise Exception("No scan started")
525 dev[0].dump_monitor()
527 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
528 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"):
529 raise Exception("BSS_TM_REQ command failed")
530 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
532 raise Exception("No BSS Transition Management Response")
533 if "status_code=0" not in ev:
534 raise Exception("BSS transition request was not accepted: " + ev)
535 if "target_bssid=" + apdev[1]['bssid'] not in ev:
536 raise Exception("Unexpected target BSS: " + ev)
537 dev[0].wait_connected(timeout=15, error="No reassociation seen")
538 if apdev[1]['bssid'] not in ev:
539 raise Exception("Unexpected reassociation target: " + ev)
540 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
542 raise Exception("Unexpected scan started")
543 dev[0].dump_monitor()
545 logger.info("Preferred Candidate List with two matches, no roam needed")
546 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"):
547 raise Exception("BSS_TM_REQ command failed")
548 ev = hapd2.wait_event(['BSS-TM-RESP'], timeout=10)
550 raise Exception("No BSS Transition Management Response")
551 if "status_code=0" not in ev:
552 raise Exception("BSS transition request was not accepted: " + ev)
553 if "target_bssid=" + apdev[1]['bssid'] not in ev:
554 raise Exception("Unexpected target BSS: " + ev)
555 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
557 raise Exception("Unexpected scan started")
558 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
560 raise Exception("Unexpected reassociation");
562 dev[0].request("DISCONNECT")
564 hapd.request("DISABLE")
566 hapd2.request("DISABLE")
567 subprocess.call(['iw', 'reg', 'set', '00'])
568 dev[0].flush_scan_cache()
570 def test_wnm_bss_tm_scan_not_needed(dev, apdev):
571 """WNM BSS Transition Management and scan not needed"""
575 params = { "ssid": "test-wnm",
576 "country_code": "FI",
580 "bss_transition": "1" }
581 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
583 params = { "ssid": "test-wnm",
584 "country_code": "FI",
588 "bss_transition": "1" }
589 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
591 dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
593 id = dev[0].connect("test-wnm", key_mgmt="NONE",
594 bssid=apdev[0]['bssid'], scan_freq="2412")
595 dev[0].set_network(id, "scan_freq", "")
596 dev[0].set_network(id, "bssid", "")
598 addr = dev[0].own_addr()
599 dev[0].dump_monitor()
601 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
602 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"):
603 raise Exception("BSS_TM_REQ command failed")
604 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
606 raise Exception("No BSS Transition Management Response")
607 if "status_code=0" not in ev:
608 raise Exception("BSS transition request was not accepted: " + ev)
609 if "target_bssid=" + apdev[1]['bssid'] not in ev:
610 raise Exception("Unexpected target BSS: " + ev)
611 dev[0].wait_connected(timeout=15, error="No reassociation seen")
612 if apdev[1]['bssid'] not in ev:
613 raise Exception("Unexpected reassociation target: " + ev)
614 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
616 raise Exception("Unexpected scan started")
617 dev[0].dump_monitor()
619 dev[0].request("DISCONNECT")
621 hapd.request("DISABLE")
623 hapd2.request("DISABLE")
624 subprocess.call(['iw', 'reg', 'set', '00'])
625 dev[0].flush_scan_cache()
627 def test_wnm_bss_tm_scan_needed(dev, apdev):
628 """WNM BSS Transition Management and scan needed"""
632 params = { "ssid": "test-wnm",
633 "country_code": "FI",
637 "bss_transition": "1" }
638 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
640 params = { "ssid": "test-wnm",
641 "country_code": "FI",
645 "bss_transition": "1" }
646 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
648 dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
650 id = dev[0].connect("test-wnm", key_mgmt="NONE",
651 bssid=apdev[0]['bssid'], scan_freq="2412")
652 dev[0].set_network(id, "scan_freq", "")
653 dev[0].set_network(id, "bssid", "")
655 addr = dev[0].own_addr()
656 dev[0].dump_monitor()
658 logger.info("Wait 11 seconds for the last scan result to be too old, but still present in BSS table")
660 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
661 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"):
662 raise Exception("BSS_TM_REQ command failed")
663 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
665 raise Exception("No BSS Transition Management Response")
666 if "status_code=0" not in ev:
667 raise Exception("BSS transition request was not accepted: " + ev)
668 if "target_bssid=" + apdev[1]['bssid'] not in ev:
669 raise Exception("Unexpected target BSS: " + ev)
670 dev[0].wait_connected(timeout=15, error="No reassociation seen")
671 if apdev[1]['bssid'] not in ev:
672 raise Exception("Unexpected reassociation target: " + ev)
673 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
675 raise Exception("Unexpected scan started")
676 dev[0].dump_monitor()
678 dev[0].request("DISCONNECT")
680 hapd.request("DISABLE")
682 hapd2.request("DISABLE")
683 subprocess.call(['iw', 'reg', 'set', '00'])
684 dev[0].flush_scan_cache()
686 def start_wnm_tm(ap, country, dev):
687 params = { "ssid": "test-wnm",
688 "country_code": country,
692 "bss_transition": "1" }
693 hapd = hostapd.add_ap(ap['ifname'], params)
694 id = dev.connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
696 dev.set_network(id, "scan_freq", "")
699 def stop_wnm_tm(hapd, dev):
700 dev.request("DISCONNECT")
702 dev.wait_disconnected()
706 hapd.request("DISABLE")
707 subprocess.call(['iw', 'reg', 'set', '00'])
708 dev.flush_scan_cache()
710 def wnm_bss_tm_check(hapd, dev, data):
711 addr = dev.p2p_interface_addr()
712 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " " + data):
713 raise Exception("BSS_TM_REQ command failed")
714 ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
716 raise Exception("No scan started")
717 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
719 raise Exception("Scan did not complete")
721 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
723 raise Exception("No BSS Transition Management Response")
724 if "status_code=7" not in ev:
725 raise Exception("Unexpected response: " + ev)
727 def test_wnm_bss_tm_country_us(dev, apdev):
728 """WNM BSS Transition Management (US)"""
731 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
733 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
734 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")
736 # Make the test take less time by limiting full scans
737 dev[0].set_network(id, "scan_freq", "2412")
738 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
739 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")
741 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
742 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")
744 stop_wnm_tm(hapd, dev[0])
746 def test_wnm_bss_tm_country_fi(dev, apdev):
747 """WNM BSS Transition Management (FI)"""
748 addr = dev[0].p2p_interface_addr()
751 hapd, id = start_wnm_tm(apdev[0], "FI", dev[0])
753 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
754 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")
756 # Make the test take less time by limiting full scans
757 dev[0].set_network(id, "scan_freq", "2412")
758 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
759 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")
761 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
762 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,0,0,7")
764 stop_wnm_tm(hapd, dev[0])
766 def test_wnm_bss_tm_country_jp(dev, apdev):
767 """WNM BSS Transition Management (JP)"""
768 addr = dev[0].p2p_interface_addr()
771 hapd, id = start_wnm_tm(apdev[0], "JP", dev[0])
773 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
774 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")
776 # Make the test take less time by limiting full scans
777 dev[0].set_network(id, "scan_freq", "2412")
778 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
779 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")
781 stop_wnm_tm(hapd, dev[0])
783 def test_wnm_bss_tm_country_cn(dev, apdev):
784 """WNM BSS Transition Management (CN)"""
785 addr = dev[0].p2p_interface_addr()
788 hapd, id = start_wnm_tm(apdev[0], "CN", dev[0])
790 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
791 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")
793 # Make the test take less time by limiting full scans
794 dev[0].set_network(id, "scan_freq", "2412")
795 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
796 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")
798 stop_wnm_tm(hapd, dev[0])
800 def test_wnm_bss_tm_global(dev, apdev):
801 """WNM BSS Transition Management (global)"""
802 addr = dev[0].p2p_interface_addr()
805 hapd, id = start_wnm_tm(apdev[0], "XX", dev[0])
807 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
808 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")
810 # Make the test take less time by limiting full scans
811 dev[0].set_network(id, "scan_freq", "2412")
812 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
813 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")
815 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
816 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")
818 stop_wnm_tm(hapd, dev[0])
820 def test_wnm_bss_tm_op_class_0(dev, apdev):
821 """WNM BSS Transition Management with invalid operating class"""
824 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
826 logger.info("Preferred Candidate List (no matching neighbor, invalid op class specified for channels)")
827 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")
829 stop_wnm_tm(hapd, dev[0])
831 def test_wnm_action_proto(dev, apdev):
832 """WNM Action protocol testing"""
833 params = { "ssid": "test-wnm" }
834 params['wnm_sleep_mode'] = '1'
835 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
836 bssid = apdev[0]['bssid']
837 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
838 dev[0].request("WNM_SLEEP enter")
840 hapd.set("ext_mgmt_frame_handling", "1")
843 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
844 msg['da'] = dev[0].own_addr()
850 logger.debug("Unexpected WNM-Notification Response")
851 # Note: This is actually not registered for user space processing in
852 # driver_nl80211.c nl80211_mgmt_subscribe_non_ap() and as such, won't make
853 # it to wpa_supplicant.
854 msg['payload'] = struct.pack("<BBBB",
855 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_RESP,
860 logger.debug("Truncated WNM-Notification Request (no Type field)")
861 msg['payload'] = struct.pack("<BBB",
862 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
867 logger.debug("WFA WNM-Notification Request with truncated IE (min)")
868 msg['payload'] = struct.pack("<BBBBBB",
869 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
870 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 1)
874 logger.debug("WFA WNM-Notification Request with truncated IE (max)")
875 msg['payload'] = struct.pack("<BBBBBB",
876 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
877 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 255)
881 logger.debug("WFA WNM-Notification Request with too short IE")
882 msg['payload'] = struct.pack("<BBBBBB",
883 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
884 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 0)
888 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL")
889 msg['payload'] = struct.pack(">BBBBBBLB",
890 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
891 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
896 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(2)")
897 msg['payload'] = struct.pack(">BBBBBBLBB",
898 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
899 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 6,
904 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(3)")
905 msg['payload'] = struct.pack(">BBBBBBLB",
906 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
907 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
912 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(min)")
913 msg['payload'] = struct.pack(">BBBBBBLBHB",
914 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
915 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
920 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(max)")
921 msg['payload'] = struct.pack(">BBBBBBLBHB",
922 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
923 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
924 0x506f9a01, 0, 0, 0xff)
928 logger.debug("WFA WNM-Notification Request with unsupported IE")
929 msg['payload'] = struct.pack("<BBBBBBL",
930 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
931 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 4, 0)
935 logger.debug("WNM-Notification Request with unknown WNM-Notification type 0")
936 msg['payload'] = struct.pack("<BBBB",
937 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
938 dialog_token, WNM_NOTIF_TYPE_FW_UPGRADE)
942 logger.debug("Truncated WNM Sleep Mode Response - no Dialog Token")
943 msg['payload'] = struct.pack("<BB",
944 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP)
948 logger.debug("Truncated WNM Sleep Mode Response - no Key Data Length")
949 msg['payload'] = struct.pack("<BBB",
950 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0)
954 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (min)")
955 msg['payload'] = struct.pack("<BBBH",
956 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
961 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (max)")
962 msg['payload'] = struct.pack("<BBBH",
963 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
968 logger.debug("WNM Sleep Mode Response - truncated IE header")
969 msg['payload'] = struct.pack("<BBBHB",
970 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
975 logger.debug("WNM Sleep Mode Response - truncated IE")
976 msg['payload'] = struct.pack("<BBBHBB",
977 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
982 logger.debug("WNM Sleep Mode Response - Empty TFS Response")
983 msg['payload'] = struct.pack("<BBBHBB",
984 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
985 0, WLAN_EID_TFS_RESP, 0)
989 logger.debug("WNM Sleep Mode Response - EID 0 not recognized")
990 msg['payload'] = struct.pack("<BBBHBB",
991 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
996 logger.debug("WNM Sleep Mode Response - Empty WNM Sleep Mode element and TFS Response element")
997 msg['payload'] = struct.pack("<BBBHBBBB",
998 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
999 0, WLAN_EID_WNMSLEEP, 0, WLAN_EID_TFS_RESP, 0)
1003 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element and empty TFS Response element")
1004 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1005 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1006 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1007 WNM_STATUS_SLEEP_ACCEPT, 0,
1008 WLAN_EID_TFS_RESP, 0)
1012 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(exit, deny key) and empty TFS Response element")
1013 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1014 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1015 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1016 WNM_STATUS_DENIED_KEY, 0,
1017 WLAN_EID_TFS_RESP, 0)
1021 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(enter, deny key) and empty TFS Response element")
1022 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1023 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1024 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1025 WNM_STATUS_DENIED_KEY, 0,
1026 WLAN_EID_TFS_RESP, 0)
1030 def test_wnm_action_proto_pmf(dev, apdev):
1031 """WNM Action protocol testing (PMF enabled)"""
1032 ssid = "test-wnm-pmf"
1033 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1034 params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1035 params["ieee80211w"] = "2"
1036 params['wnm_sleep_mode'] = '1'
1037 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1038 bssid = apdev[0]['bssid']
1039 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
1040 proto="WPA2", ieee80211w="2", scan_freq="2412")
1041 dev[0].request("WNM_SLEEP enter")
1043 hapd.set("ext_mgmt_frame_handling", "1")
1046 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1047 msg['da'] = dev[0].own_addr()
1049 msg['bssid'] = bssid
1051 logger.debug("WNM Sleep Mode Response - Invalid Key Data element length")
1052 keydata = struct.pack("<BB", 0, 1)
1053 msg['payload'] = struct.pack("<BBBH",
1054 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1056 msg['payload'] += keydata
1057 msg['payload'] += struct.pack("<BBBBHBB",
1058 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1059 WNM_STATUS_SLEEP_ACCEPT, 0,
1060 WLAN_EID_TFS_RESP, 0)
1064 logger.debug("WNM Sleep Mode Response - Too short GTK subelem")
1065 keydata = struct.pack("<BB", WNM_SLEEP_SUBELEM_GTK, 0)
1066 msg['payload'] = struct.pack("<BBBH",
1067 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1069 msg['payload'] += keydata
1070 msg['payload'] += struct.pack("<BBBBHBB",
1071 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1072 WNM_STATUS_SLEEP_ACCEPT, 0,
1073 WLAN_EID_TFS_RESP, 0)
1077 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem")
1078 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1079 0, 17, 0, 0, 0, 0, 0, 0)
1080 msg['payload'] = struct.pack("<BBBH",
1081 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1083 msg['payload'] += keydata
1084 msg['payload'] += struct.pack("<BBBBHBB",
1085 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1086 WNM_STATUS_SLEEP_ACCEPT, 0,
1087 WLAN_EID_TFS_RESP, 0)
1091 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem (2)")
1092 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1093 0, 0, 0, 0, 0, 0, 0, 0)
1094 msg['payload'] = struct.pack("<BBBH",
1095 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1097 msg['payload'] += keydata
1098 msg['payload'] += struct.pack("<BBBBHBB",
1099 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1100 WNM_STATUS_SLEEP_ACCEPT, 0,
1101 WLAN_EID_TFS_RESP, 0)
1105 logger.debug("WNM Sleep Mode Response - GTK subelem and too short IGTK subelem")
1106 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1107 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1108 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1109 keydata += struct.pack("<BB", WNM_SLEEP_SUBELEM_IGTK, 0)
1110 msg['payload'] = struct.pack("<BBBH",
1111 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1113 msg['payload'] += keydata
1114 msg['payload'] += struct.pack("<BBBBHBB",
1115 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1116 WNM_STATUS_SLEEP_ACCEPT, 0,
1117 WLAN_EID_TFS_RESP, 0)
1121 logger.debug("WNM Sleep Mode Response - Unknown subelem")
1122 keydata = struct.pack("<BB", 255, 0)
1123 msg['payload'] = struct.pack("<BBBH",
1124 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1126 msg['payload'] += keydata
1127 msg['payload'] += struct.pack("<BBBBHBB",
1128 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1129 WNM_STATUS_SLEEP_ACCEPT, 0,
1130 WLAN_EID_TFS_RESP, 0)
1134 def test_wnm_action_proto_no_pmf(dev, apdev):
1135 """WNM Action protocol testing (PMF disabled)"""
1136 ssid = "test-wnm-no-pmf"
1137 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1138 params['wnm_sleep_mode'] = '1'
1139 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1140 bssid = apdev[0]['bssid']
1141 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1142 proto="WPA2", ieee80211w="0", scan_freq="2412")
1143 dev[0].request("WNM_SLEEP enter")
1145 hapd.set("ext_mgmt_frame_handling", "1")
1148 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1149 msg['da'] = dev[0].own_addr()
1151 msg['bssid'] = bssid
1153 logger.debug("WNM Sleep Mode Response - GTK subelem and IGTK subelem")
1154 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1155 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1156 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1157 keydata += struct.pack("<BBHLH4L", WNM_SLEEP_SUBELEM_IGTK, 2 + 6 + 16, 0,
1159 0xf1f2f3f4, 0xf5f6f7f8, 0xf9f0fafb, 0xfcfdfeff)
1160 msg['payload'] = struct.pack("<BBBH",
1161 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1163 msg['payload'] += keydata
1164 msg['payload'] += struct.pack("<BBBBHBB",
1165 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1166 WNM_STATUS_SLEEP_ACCEPT, 0,
1167 WLAN_EID_TFS_RESP, 0)
1171 ev = dev[0].wait_event(["WNM: Ignore Key Data"], timeout=5)
1173 raise Exception("Key Data not ignored")
1175 def test_wnm_bss_tm_req_with_mbo_ie(dev, apdev):
1176 """WNM BSS transition request with MBO IE and reassociation delay attribute"""
1177 ssid = "test-wnm-mbo"
1178 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1179 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1180 bssid = apdev[0]['bssid']
1181 if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
1182 raise Exception("Failed to set STA as cellular data capable")
1184 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1185 proto="WPA2", ieee80211w="0", scan_freq="2412")
1187 logger.debug("BTM request with MBO reassociation delay when disassoc imminent is not set")
1188 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=3:2:1"):
1189 raise Exception("BSS transition management succeeded unexpectedly")
1191 logger.debug("BTM request with invalid MBO transition reason code")
1192 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=10:2:1"):
1193 raise Exception("BSS transition management succeeded unexpectedly")
1195 logger.debug("BTM request with MBO reassociation retry delay of 5 seconds")
1196 if 'OK' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " disassoc_imminent=1 disassoc_timer=3 mbo=3:5:1"):
1197 raise Exception("BSS transition management command failed")
1199 ev = dev[0].wait_event(['MBO-CELL-PREFERENCE'], 1)
1200 if ev is None or "preference=1" not in ev:
1201 raise Exception("Timeout waiting for MBO-CELL-PREFERENCE event")
1203 ev = dev[0].wait_event(['MBO-TRANSITION-REASON'], 1)
1204 if ev is None or "reason=3" not in ev:
1205 raise Exception("Timeout waiting for MBO-TRANSITION-REASON event")
1207 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1209 raise Exception("No BSS Transition Management Response")
1210 if dev[0].own_addr() not in ev:
1211 raise Exception("Unexpected BSS Transition Management Response address")
1213 ev = dev[0].wait_event(['CTRL-EVENT-DISCONNECTED'], 5)
1215 raise Exception("Station did not disconnect although disassoc imminent was set")
1217 # Set the scan interval to make dev[0] look for connections
1218 if 'OK' not in dev[0].request("SCAN_INTERVAL 1"):
1219 raise Exception("Failed to set scan interval")
1221 # Make sure no connection is made during the retry delay
1222 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1224 raise Exception("Station connected before assoc retry delay was over")
1226 # After the assoc retry delay is over, we can reconnect
1227 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1229 raise Exception("Station did not connect after assoc retry delay is over")
1231 if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
1232 raise Exception("Failed to set STA as cellular data not-capable")
1234 def test_wnm_bss_transition_mgmt_query(dev, apdev):
1235 """WNM BSS Transition Management query"""
1236 params = { "ssid": "test-wnm",
1237 "bss_transition": "1" }
1238 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1239 params = { "ssid": "another" }
1240 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
1242 dev[0].scan_for_bss(apdev[1]['bssid'], 2412)
1243 dev[0].scan_for_bss(apdev[0]['bssid'], 2412)
1245 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1246 dev[0].request("WNM_BSS_QUERY 0 list")
1248 ev = dev[0].wait_event(["WNM: BSS Transition Management Request"],
1251 raise Exception("No BSS Transition Management Request frame seen")
1253 ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1255 raise Exception("No BSS Transition Management Response frame seen")
1257 def test_wnm_bss_tm_security_mismatch(dev, apdev):
1258 """WNM BSS Transition Management and security mismatch"""
1259 params = { "ssid": "test-wnm",
1261 "wpa_key_mgmt": "WPA-PSK",
1262 "rsn_pairwise": "CCMP",
1263 "wpa_passphrase": "12345678",
1266 "bss_transition": "1" }
1267 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1269 params = { "ssid": "test-wnm",
1272 "bss_transition": "1" }
1273 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
1275 dev[0].scan_for_bss(apdev[1]['bssid'], 2462)
1277 id = dev[0].connect("test-wnm", psk="12345678",
1278 bssid=apdev[0]['bssid'], scan_freq="2412")
1279 dev[0].set_network(id, "scan_freq", "")
1280 dev[0].set_network(id, "bssid", "")
1282 addr = dev[0].own_addr()
1283 dev[0].dump_monitor()
1285 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1286 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"):
1287 raise Exception("BSS_TM_REQ command failed")
1288 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1290 raise Exception("No BSS Transition Management Response")
1291 if "status_code=7" not in ev:
1292 raise Exception("Unexpected BSS transition request response: " + ev)