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.
7 from remotehost import remote_compatible
12 logger = logging.getLogger()
16 from wpasupplicant import WpaSupplicant
17 from utils import alloc_fail, wait_fail_trigger
18 from wlantest import Wlantest
21 def test_wnm_bss_transition_mgmt(dev, apdev):
22 """WNM BSS Transition Management"""
23 params = { "ssid": "test-wnm",
24 "time_advertisement": "2",
26 "wnm_sleep_mode": "1",
27 "bss_transition": "1" }
28 hostapd.add_ap(apdev[0], params)
30 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
31 dev[0].request("WNM_BSS_QUERY 0")
34 def test_wnm_disassoc_imminent(dev, apdev):
35 """WNM Disassociation Imminent"""
36 params = { "ssid": "test-wnm",
37 "time_advertisement": "2",
39 "wnm_sleep_mode": "1",
40 "bss_transition": "1" }
41 hapd = hostapd.add_ap(apdev[0], params)
43 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
44 addr = dev[0].p2p_interface_addr()
45 hapd.request("DISASSOC_IMMINENT " + addr + " 10")
46 ev = dev[0].wait_event(["WNM: Disassociation Imminent"])
48 raise Exception("Timeout while waiting for disassociation imminent")
49 if "Disassociation Timer 10" not in ev:
50 raise Exception("Unexpected disassociation imminent contents")
51 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
53 raise Exception("Timeout while waiting for re-connection scan")
56 def test_wnm_ess_disassoc_imminent(dev, apdev):
57 """WNM ESS Disassociation Imminent"""
58 params = { "ssid": "test-wnm",
59 "time_advertisement": "2",
61 "wnm_sleep_mode": "1",
62 "bss_transition": "1" }
63 hapd = hostapd.add_ap(apdev[0], params)
65 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
66 addr = dev[0].p2p_interface_addr()
67 hapd.request("ESS_DISASSOC " + addr + " 10 http://example.com/session-info")
68 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"])
70 raise Exception("Timeout while waiting for ESS disassociation imminent")
71 if "0 1024 http://example.com/session-info" not in ev:
72 raise Exception("Unexpected ESS disassociation imminent message contents")
73 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
75 raise Exception("Timeout while waiting for re-connection scan")
77 def test_wnm_ess_disassoc_imminent_reject(dev, apdev):
78 """WNM ESS Disassociation Imminent getting rejected"""
79 params = { "ssid": "test-wnm",
80 "bss_transition": "1" }
81 hapd = hostapd.add_ap(apdev[0], params)
83 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
84 addr = dev[0].own_addr()
85 if "OK" not in dev[0].request("SET reject_btm_req_reason 123"):
86 raise Exception("Failed to set reject_btm_req_reason")
88 hapd.request("ESS_DISASSOC " + addr + " 1 http://example.com/session-info")
89 ev = hapd.wait_event(["BSS-TM-RESP"], timeout=10)
91 raise Exception("BSS-TM-RESP not seen")
92 if "status_code=123" not in ev:
93 raise Exception("Unexpected response status: " + ev)
94 dev[0].wait_disconnected()
95 dev[0].request("DISCONNECT")
98 def test_wnm_ess_disassoc_imminent_pmf(dev, apdev):
99 """WNM ESS Disassociation Imminent"""
100 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
101 params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
102 params["ieee80211w"] = "2"
103 params["bss_transition"] = "1"
104 hapd = hostapd.add_ap(apdev[0], params)
106 dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
107 key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
108 addr = dev[0].p2p_interface_addr()
109 hapd.request("ESS_DISASSOC " + addr + " 10 http://example.com/session-info")
110 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"])
112 raise Exception("Timeout while waiting for ESS disassociation imminent")
113 if "1 1024 http://example.com/session-info" not in ev:
114 raise Exception("Unexpected ESS disassociation imminent message contents")
115 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
117 raise Exception("Timeout while waiting for re-connection scan")
119 def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None):
120 addr = dev.p2p_interface_addr()
121 sta = hapd.get_sta(addr)
122 if "[WNM_SLEEP_MODE]" in sta['flags']:
123 raise Exception("Station unexpectedly in WNM-Sleep Mode")
125 logger.info("Going to WNM Sleep Mode")
127 if interval is not None:
128 extra += " interval=" + str(interval)
130 extra += " tfs_req=" + tfs_req
131 if "OK" not in dev.request("WNM_SLEEP enter" + extra):
132 raise Exception("WNM_SLEEP failed")
136 sta = hapd.get_sta(addr)
137 if "[WNM_SLEEP_MODE]" in sta['flags']:
141 raise Exception("Station failed to enter WNM-Sleep Mode")
143 logger.info("Waking up from WNM Sleep Mode")
145 dev.request("WNM_SLEEP exit")
148 sta = hapd.get_sta(addr)
149 if "[WNM_SLEEP_MODE]" not in sta['flags']:
153 raise Exception("Station failed to exit WNM-Sleep Mode")
156 def test_wnm_sleep_mode_open(dev, apdev):
157 """WNM Sleep Mode - open"""
158 params = { "ssid": "test-wnm",
159 "time_advertisement": "2",
161 "wnm_sleep_mode": "1",
162 "bss_transition": "1" }
163 hapd = hostapd.add_ap(apdev[0], params)
165 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
166 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
168 raise Exception("No connection event received from hostapd")
169 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
170 check_wnm_sleep_mode_enter_exit(hapd, dev[0], interval=100)
171 check_wnm_sleep_mode_enter_exit(hapd, dev[0], tfs_req="5b17010001130e110000071122334455661122334455661234")
174 "exit tfs_req=123 interval=10",
175 "enter tfs_req=qq interval=10" ]
177 if "FAIL" not in dev[0].request("WNM_SLEEP " + cmd):
178 raise Exception("Invalid WNM_SLEEP accepted")
181 def test_wnm_sleep_mode_rsn(dev, apdev):
182 """WNM Sleep Mode - RSN"""
183 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
184 params["time_advertisement"] = "2"
185 params["time_zone"] = "EST5"
186 params["wnm_sleep_mode"] = "1"
187 params["bss_transition"] = "1"
188 hapd = hostapd.add_ap(apdev[0], params)
190 dev[0].connect("test-wnm-rsn", psk="12345678", scan_freq="2412")
191 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
193 raise Exception("No connection event received from hostapd")
194 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
197 def test_wnm_sleep_mode_ap_oom(dev, apdev):
198 """WNM Sleep Mode - AP side OOM"""
199 params = { "ssid": "test-wnm",
200 "wnm_sleep_mode": "1" }
201 hapd = hostapd.add_ap(apdev[0], params)
203 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
204 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
206 raise Exception("No connection event received from hostapd")
207 with alloc_fail(hapd, 1, "ieee802_11_send_wnmsleep_resp"):
208 dev[0].request("WNM_SLEEP enter")
209 wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
210 with alloc_fail(hapd, 2, "ieee802_11_send_wnmsleep_resp"):
211 dev[0].request("WNM_SLEEP exit")
212 wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
215 def test_wnm_sleep_mode_rsn_pmf(dev, apdev):
216 """WNM Sleep Mode - RSN with PMF"""
217 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
218 params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
219 params["ieee80211w"] = "2"
220 params["time_advertisement"] = "2"
221 params["time_zone"] = "EST5"
222 params["wnm_sleep_mode"] = "1"
223 params["bss_transition"] = "1"
224 hapd = hostapd.add_ap(apdev[0], params)
229 wt.add_passphrase("12345678")
231 dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
232 key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
233 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
235 raise Exception("No connection event received from hostapd")
236 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
238 MGMT_SUBTYPE_ACTION = 13
239 ACTION_CATEG_WNM = 10
240 WNM_ACT_BSS_TM_REQ = 7
241 WNM_ACT_BSS_TM_RESP = 8
242 WNM_ACT_SLEEP_MODE_REQ = 16
243 WNM_ACT_SLEEP_MODE_RESP = 17
244 WNM_ACT_NOTIFICATION_REQ = 26
245 WNM_ACT_NOTIFICATION_RESP = 27
246 WNM_NOTIF_TYPE_FW_UPGRADE = 0
247 WNM_NOTIF_TYPE_WFA = 1
248 WLAN_EID_TFS_RESP = 92
249 WLAN_EID_WNMSLEEP = 93
250 WNM_SLEEP_MODE_ENTER = 0
251 WNM_SLEEP_MODE_EXIT = 1
252 WNM_STATUS_SLEEP_ACCEPT = 0
253 WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE = 1
254 WNM_STATUS_DENIED_ACTION = 2
255 WNM_STATUS_DENIED_TMP = 3
256 WNM_STATUS_DENIED_KEY = 4
257 WNM_STATUS_DENIED_OTHER_WNM_SERVICE = 5
258 WNM_SLEEP_SUBELEM_GTK = 0
259 WNM_SLEEP_SUBELEM_IGTK = 1
261 def bss_tm_req(dst, src, dialog_token=1, req_mode=0, disassoc_timer=0,
262 validity_interval=1):
264 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
268 msg['payload'] = struct.pack("<BBBBHB",
269 ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
270 dialog_token, req_mode, disassoc_timer,
274 def rx_bss_tm_resp(hapd, expect_dialog=None, expect_status=None):
275 for i in range(0, 100):
276 resp = hapd.mgmt_rx()
278 raise Exception("No BSS TM Response received")
279 if resp['subtype'] == MGMT_SUBTYPE_ACTION:
282 raise Exception("Not an Action frame")
283 payload = resp['payload']
284 if len(payload) < 2 + 3:
285 raise Exception("Too short payload")
286 (category, action) = struct.unpack('BB', payload[0:2])
287 if category != ACTION_CATEG_WNM or action != WNM_ACT_BSS_TM_RESP:
288 raise Exception("Not a BSS TM Response")
290 (dialog, status, bss_term_delay) = struct.unpack('BBB', pos[0:3])
291 resp['dialog'] = dialog
292 resp['status'] = status
293 resp['bss_term_delay'] = bss_term_delay
295 if len(pos) >= 6 and status == 0:
296 resp['target_bssid'] = binascii.hexlify(pos[0:6])
298 resp['candidates'] = pos
299 if expect_dialog is not None and dialog != expect_dialog:
300 raise Exception("Unexpected dialog token")
301 if expect_status is not None and status != expect_status:
302 raise Exception("Unexpected status code %d" % status)
305 def expect_ack(hapd):
306 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
308 raise Exception("Missing TX status")
310 raise Exception("Action frame not acknowledged")
313 def test_wnm_bss_tm_req(dev, apdev):
314 """BSS Transition Management Request"""
315 params = { "ssid": "test-wnm", "bss_transition": "1" }
316 hapd = hostapd.add_ap(apdev[0], params)
317 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
318 hapd2 = hostapd.add_ap(apdev[1], params)
320 hapd.set("ext_mgmt_frame_handling", "1")
322 # truncated BSS TM Request
323 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
325 req['payload'] = struct.pack("<BBBBH",
326 ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
331 # no disassociation and no candidate list
332 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
335 resp = rx_bss_tm_resp(hapd, expect_dialog=2, expect_status=1)
337 # truncated BSS Termination Duration
338 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
343 # BSS Termination Duration with TSF=0 and Duration=10
344 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
345 req_mode=0x08, dialog_token=3)
346 req['payload'] += struct.pack("<BBQH", 4, 10, 0, 10)
348 resp = rx_bss_tm_resp(hapd, expect_dialog=3, expect_status=1)
350 # truncated Session Information URL
351 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
355 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
357 req['payload'] += struct.pack("<BBB", 3, 65, 66)
361 # Session Information URL
362 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
363 req_mode=0x10, dialog_token=4)
364 req['payload'] += struct.pack("<BBB", 2, 65, 66)
366 resp = rx_bss_tm_resp(hapd, expect_dialog=4, expect_status=0)
368 # Preferred Candidate List without any entries
369 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
370 req_mode=0x01, dialog_token=5)
372 resp = rx_bss_tm_resp(hapd, expect_dialog=5, expect_status=7)
374 # Preferred Candidate List with a truncated entry
375 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
377 req['payload'] += struct.pack("<BB", 52, 1)
381 # Preferred Candidate List with a too short entry
382 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
383 req_mode=0x01, dialog_token=6)
384 req['payload'] += struct.pack("<BB", 52, 0)
386 resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
388 # Preferred Candidate List with a non-matching entry
389 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
390 req_mode=0x01, dialog_token=6)
391 req['payload'] += struct.pack("<BB6BLBBB", 52, 13,
395 resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
397 # Preferred Candidate List with a truncated subelement
398 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
399 req_mode=0x01, dialog_token=7)
400 req['payload'] += struct.pack("<BB6BLBBBBB", 52, 13 + 2,
405 resp = rx_bss_tm_resp(hapd, expect_dialog=7, expect_status=7)
407 # Preferred Candidate List with lots of invalid optional subelements
408 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
409 req_mode=0x01, dialog_token=8)
410 subelems = struct.pack("<BBHB", 1, 3, 0, 100)
411 subelems += struct.pack("<BBB", 2, 1, 65)
412 subelems += struct.pack("<BB", 3, 0)
413 subelems += struct.pack("<BBQB", 4, 9, 0, 10)
414 subelems += struct.pack("<BBHLB", 5, 7, 0, 0, 0)
415 subelems += struct.pack("<BB", 66, 0)
416 subelems += struct.pack("<BBBBBB", 70, 4, 0, 0, 0, 0)
417 subelems += struct.pack("<BB", 71, 0)
418 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
420 0, 81, 1, 7) + subelems
422 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
424 # Preferred Candidate List with lots of valid optional subelements (twice)
425 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
426 req_mode=0x01, dialog_token=8)
428 subelems = struct.pack("<BBHH", 1, 4, 0, 100)
429 # Condensed Country String
430 subelems += struct.pack("<BBBB", 2, 2, 65, 66)
431 # BSS Transition Candidate Preference
432 subelems += struct.pack("<BBB", 3, 1, 100)
433 # BSS Termination Duration
434 subelems += struct.pack("<BBQH", 4, 10, 0, 10)
436 subelems += struct.pack("<BBHLH", 5, 8, 0, 0, 0)
437 # Measurement Pilot Transmission
438 subelems += struct.pack("<BBBBB", 66, 3, 0, 0, 0)
439 # RM Enabled Capabilities
440 subelems += struct.pack("<BBBBBBB", 70, 5, 0, 0, 0, 0, 0)
442 subelems += struct.pack("<BBBB", 71, 2, 0, 0)
443 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems) * 2,
445 0, 81, 1, 7) + subelems + subelems
447 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
449 # Preferred Candidate List followed by vendor element
450 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
451 req_mode=0x01, dialog_token=8)
453 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
455 0, 81, 1, 7) + subelems
456 req['payload'] += binascii.unhexlify("DD0411223344")
458 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
461 def test_wnm_bss_keep_alive(dev, apdev):
463 params = { "ssid": "test-wnm",
464 "ap_max_inactivity": "1" }
465 hapd = hostapd.add_ap(apdev[0], params)
467 addr = dev[0].p2p_interface_addr()
468 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
469 start = hapd.get_sta(addr)
470 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=2)
472 raise Exception("Unexpected disconnection")
473 end = hapd.get_sta(addr)
474 if int(end['rx_packets']) <= int(start['rx_packets']):
475 raise Exception("No keep-alive packets received")
477 # Disable client keep-alive so that hostapd will verify connection
479 dev[0].request("SET no_keep_alive 1")
481 sta = hapd.get_sta(addr)
482 logger.info("timeout_next=%s rx_packets=%s tx_packets=%s" % (sta['timeout_next'], sta['rx_packets'], sta['tx_packets']))
483 if i > 1 and sta['timeout_next'] != "NULLFUNC POLL" and int(sta['tx_packets']) > int(end['tx_packets']):
485 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
487 raise Exception("Unexpected disconnection (client poll expected)")
489 dev[0].request("SET no_keep_alive 0")
490 if int(sta['tx_packets']) <= int(end['tx_packets']):
491 raise Exception("No client poll packet seen")
493 def test_wnm_bss_tm(dev, apdev):
494 """WNM BSS Transition Management"""
498 params = { "ssid": "test-wnm",
499 "country_code": "FI",
503 "bss_transition": "1" }
504 hapd = hostapd.add_ap(apdev[0], params)
506 id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
507 dev[0].set_network(id, "scan_freq", "")
509 params = { "ssid": "test-wnm",
510 "country_code": "FI",
514 "bss_transition": "1" }
515 hapd2 = hostapd.add_ap(apdev[1], params)
517 addr = dev[0].p2p_interface_addr()
518 dev[0].dump_monitor()
520 logger.info("No neighbor list entries")
521 if "OK" not in hapd.request("BSS_TM_REQ " + addr):
522 raise Exception("BSS_TM_REQ command failed")
523 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
525 raise Exception("No BSS Transition Management Response")
527 raise Exception("Unexpected BSS Transition Management Response address")
528 if "status_code=0" in ev:
529 raise Exception("BSS transition accepted unexpectedly")
530 dev[0].dump_monitor()
532 logger.info("Neighbor list entry, but not claimed as Preferred Candidate List")
533 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " neighbor=11:22:33:44:55:66,0x0000,81,3,7"):
534 raise Exception("BSS_TM_REQ command failed")
535 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
537 raise Exception("No BSS Transition Management Response")
538 if "status_code=0" in ev:
539 raise Exception("BSS transition accepted unexpectedly")
540 dev[0].dump_monitor()
542 logger.info("Preferred Candidate List (no matching neighbor) without Disassociation Imminent")
543 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"):
544 raise Exception("BSS_TM_REQ command failed")
545 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
547 raise Exception("No BSS Transition Management Response")
548 if "status_code=0" in ev:
549 raise Exception("BSS transition accepted unexpectedly")
550 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
552 raise Exception("No scan started")
553 dev[0].dump_monitor()
555 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
556 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"):
557 raise Exception("BSS_TM_REQ command failed")
558 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
560 raise Exception("No BSS Transition Management Response")
561 if "status_code=0" not in ev:
562 raise Exception("BSS transition request was not accepted: " + ev)
563 if "target_bssid=" + apdev[1]['bssid'] not in ev:
564 raise Exception("Unexpected target BSS: " + ev)
565 dev[0].wait_connected(timeout=15, error="No reassociation seen")
566 if apdev[1]['bssid'] not in ev:
567 raise Exception("Unexpected reassociation target: " + ev)
568 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
570 raise Exception("Unexpected scan started")
571 dev[0].dump_monitor()
573 logger.info("Preferred Candidate List with two matches, no roam needed")
574 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"):
575 raise Exception("BSS_TM_REQ command failed")
576 ev = hapd2.wait_event(['BSS-TM-RESP'], timeout=10)
578 raise Exception("No BSS Transition Management Response")
579 if "status_code=0" not in ev:
580 raise Exception("BSS transition request was not accepted: " + ev)
581 if "target_bssid=" + apdev[1]['bssid'] not in ev:
582 raise Exception("Unexpected target BSS: " + ev)
583 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
585 raise Exception("Unexpected scan started")
586 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
588 raise Exception("Unexpected reassociation")
590 dev[0].request("DISCONNECT")
592 hapd.request("DISABLE")
594 hapd2.request("DISABLE")
595 subprocess.call(['iw', 'reg', 'set', '00'])
596 dev[0].flush_scan_cache()
598 def test_wnm_bss_tm_scan_not_needed(dev, apdev):
599 """WNM BSS Transition Management and scan not needed"""
600 run_wnm_bss_tm_scan_not_needed(dev, apdev)
602 def test_wnm_bss_tm_nei_vht(dev, apdev):
603 """WNM BSS Transition Management and VHT neighbor"""
604 run_wnm_bss_tm_scan_not_needed(dev, apdev, vht=True, nei_info="115,36,9")
606 def test_wnm_bss_tm_nei_11a(dev, apdev):
607 """WNM BSS Transition Management and 11a neighbor"""
608 run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, nei_info="115,36,4")
610 def test_wnm_bss_tm_nei_11g(dev, apdev):
611 """WNM BSS Transition Management and 11g neighbor"""
612 run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, hwmode='g',
613 channel='2', freq=2417, nei_info="81,2,6")
615 def test_wnm_bss_tm_nei_11b(dev, apdev):
616 """WNM BSS Transition Management and 11g neighbor"""
617 run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, hwmode='b',
618 channel='3', freq=2422, nei_info="81,2,5")
620 def run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=True, vht=False, hwmode='a',
621 channel='36', freq=5180,
622 nei_info="115,36,7,0301ff"):
626 params = { "ssid": "test-wnm",
627 "country_code": "FI",
631 "bss_transition": "1" }
632 hapd = hostapd.add_ap(apdev[0], params)
634 params = { "ssid": "test-wnm",
635 "country_code": "FI",
639 "bss_transition": "1" }
641 params['ieee80211n'] = '0'
643 params['ieee80211ac'] = "1"
644 params["vht_oper_chwidth"] = "0"
645 params["vht_oper_centr_freq_seg0_idx"] = "0"
647 hapd2 = hostapd.add_ap(apdev[1], params)
649 dev[0].scan_for_bss(apdev[1]['bssid'], freq)
651 id = dev[0].connect("test-wnm", key_mgmt="NONE",
652 bssid=apdev[0]['bssid'], scan_freq="2412")
653 dev[0].set_network(id, "scan_freq", "")
654 dev[0].set_network(id, "bssid", "")
656 addr = dev[0].own_addr()
657 dev[0].dump_monitor()
659 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
660 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000," + nei_info):
661 raise Exception("BSS_TM_REQ command failed")
662 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
664 raise Exception("No BSS Transition Management Response")
665 if "status_code=0" not in ev:
666 raise Exception("BSS transition request was not accepted: " + ev)
667 if "target_bssid=" + apdev[1]['bssid'] not in ev:
668 raise Exception("Unexpected target BSS: " + ev)
669 dev[0].wait_connected(timeout=15, error="No reassociation seen")
670 if apdev[1]['bssid'] not in ev:
671 raise Exception("Unexpected reassociation target: " + ev)
672 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
674 raise Exception("Unexpected scan started")
675 dev[0].dump_monitor()
677 dev[0].request("DISCONNECT")
679 hapd.request("DISABLE")
681 hapd2.request("DISABLE")
682 subprocess.call(['iw', 'reg', 'set', '00'])
683 dev[0].flush_scan_cache()
685 def test_wnm_bss_tm_scan_needed(dev, apdev):
686 """WNM BSS Transition Management and scan needed"""
690 params = { "ssid": "test-wnm",
691 "country_code": "FI",
695 "bss_transition": "1" }
696 hapd = hostapd.add_ap(apdev[0], params)
698 params = { "ssid": "test-wnm",
699 "country_code": "FI",
703 "bss_transition": "1" }
704 hapd2 = hostapd.add_ap(apdev[1], params)
706 dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
708 id = dev[0].connect("test-wnm", key_mgmt="NONE",
709 bssid=apdev[0]['bssid'], scan_freq="2412")
710 dev[0].set_network(id, "scan_freq", "")
711 dev[0].set_network(id, "bssid", "")
713 addr = dev[0].own_addr()
714 dev[0].dump_monitor()
716 logger.info("Wait 11 seconds for the last scan result to be too old, but still present in BSS table")
718 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
719 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"):
720 raise Exception("BSS_TM_REQ command failed")
721 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
723 raise Exception("No BSS Transition Management Response")
724 if "status_code=0" not in ev:
725 raise Exception("BSS transition request was not accepted: " + ev)
726 if "target_bssid=" + apdev[1]['bssid'] not in ev:
727 raise Exception("Unexpected target BSS: " + ev)
728 dev[0].wait_connected(timeout=15, error="No reassociation seen")
729 if apdev[1]['bssid'] not in ev:
730 raise Exception("Unexpected reassociation target: " + ev)
731 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
733 raise Exception("Unexpected scan started")
734 dev[0].dump_monitor()
736 dev[0].request("DISCONNECT")
738 hapd.request("DISABLE")
740 hapd2.request("DISABLE")
741 subprocess.call(['iw', 'reg', 'set', '00'])
742 dev[0].flush_scan_cache()
744 def start_wnm_tm(ap, country, dev):
745 params = { "ssid": "test-wnm",
746 "country_code": country,
750 "bss_transition": "1" }
751 hapd = hostapd.add_ap(ap, params)
752 id = dev.connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
754 dev.set_network(id, "scan_freq", "")
757 def stop_wnm_tm(hapd, dev):
758 dev.request("DISCONNECT")
760 dev.wait_disconnected()
764 hapd.request("DISABLE")
765 subprocess.call(['iw', 'reg', 'set', '00'])
766 dev.flush_scan_cache()
768 def wnm_bss_tm_check(hapd, dev, data):
769 addr = dev.p2p_interface_addr()
770 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " " + data):
771 raise Exception("BSS_TM_REQ command failed")
772 ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
774 raise Exception("No scan started")
775 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
777 raise Exception("Scan did not complete")
779 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
781 raise Exception("No BSS Transition Management Response")
782 if "status_code=7" not in ev:
783 raise Exception("Unexpected response: " + ev)
785 def test_wnm_bss_tm_country_us(dev, apdev):
786 """WNM BSS Transition Management (US)"""
789 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
791 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
792 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")
794 # Make the test take less time by limiting full scans
795 dev[0].set_network(id, "scan_freq", "2412")
796 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
797 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")
799 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
800 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")
802 stop_wnm_tm(hapd, dev[0])
804 def test_wnm_bss_tm_country_fi(dev, apdev):
805 """WNM BSS Transition Management (FI)"""
806 addr = dev[0].p2p_interface_addr()
809 hapd, id = start_wnm_tm(apdev[0], "FI", dev[0])
811 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
812 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")
814 # Make the test take less time by limiting full scans
815 dev[0].set_network(id, "scan_freq", "2412")
816 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
817 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")
819 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
820 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,0,0,7")
822 stop_wnm_tm(hapd, dev[0])
824 def test_wnm_bss_tm_country_jp(dev, apdev):
825 """WNM BSS Transition Management (JP)"""
826 addr = dev[0].p2p_interface_addr()
829 hapd, id = start_wnm_tm(apdev[0], "JP", dev[0])
831 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
832 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")
834 # Make the test take less time by limiting full scans
835 dev[0].set_network(id, "scan_freq", "2412")
836 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
837 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")
839 stop_wnm_tm(hapd, dev[0])
841 def test_wnm_bss_tm_country_cn(dev, apdev):
842 """WNM BSS Transition Management (CN)"""
843 addr = dev[0].p2p_interface_addr()
846 hapd, id = start_wnm_tm(apdev[0], "CN", dev[0])
848 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
849 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")
851 # Make the test take less time by limiting full scans
852 dev[0].set_network(id, "scan_freq", "2412")
853 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
854 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")
856 stop_wnm_tm(hapd, dev[0])
858 def test_wnm_bss_tm_global(dev, apdev):
859 """WNM BSS Transition Management (global)"""
860 addr = dev[0].p2p_interface_addr()
863 hapd, id = start_wnm_tm(apdev[0], "XX", dev[0])
865 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
866 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")
868 # Make the test take less time by limiting full scans
869 dev[0].set_network(id, "scan_freq", "2412")
870 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
871 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")
873 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
874 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")
876 stop_wnm_tm(hapd, dev[0])
878 def test_wnm_bss_tm_op_class_0(dev, apdev):
879 """WNM BSS Transition Management with invalid operating class"""
882 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
884 logger.info("Preferred Candidate List (no matching neighbor, invalid op class specified for channels)")
885 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")
887 stop_wnm_tm(hapd, dev[0])
889 def test_wnm_action_proto(dev, apdev):
890 """WNM Action protocol testing"""
891 params = { "ssid": "test-wnm" }
892 params['wnm_sleep_mode'] = '1'
893 hapd = hostapd.add_ap(apdev[0], params)
894 bssid = apdev[0]['bssid']
895 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
896 dev[0].request("WNM_SLEEP enter")
898 hapd.set("ext_mgmt_frame_handling", "1")
901 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
902 msg['da'] = dev[0].own_addr()
908 logger.debug("Unexpected WNM-Notification Response")
909 # Note: This is actually not registered for user space processing in
910 # driver_nl80211.c nl80211_mgmt_subscribe_non_ap() and as such, won't make
911 # it to wpa_supplicant.
912 msg['payload'] = struct.pack("<BBBB",
913 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_RESP,
918 logger.debug("Truncated WNM-Notification Request (no Type field)")
919 msg['payload'] = struct.pack("<BBB",
920 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
925 logger.debug("WFA WNM-Notification Request with truncated IE (min)")
926 msg['payload'] = struct.pack("<BBBBBB",
927 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
928 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 1)
932 logger.debug("WFA WNM-Notification Request with truncated IE (max)")
933 msg['payload'] = struct.pack("<BBBBBB",
934 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
935 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 255)
939 logger.debug("WFA WNM-Notification Request with too short IE")
940 msg['payload'] = struct.pack("<BBBBBB",
941 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
942 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 0)
946 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL")
947 msg['payload'] = struct.pack(">BBBBBBLB",
948 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
949 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
954 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(2)")
955 msg['payload'] = struct.pack(">BBBBBBLBB",
956 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
957 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 6,
962 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(3)")
963 msg['payload'] = struct.pack(">BBBBBBLB",
964 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
965 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
970 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(min)")
971 msg['payload'] = struct.pack(">BBBBBBLBHB",
972 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
973 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
978 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(max)")
979 msg['payload'] = struct.pack(">BBBBBBLBHB",
980 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
981 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
982 0x506f9a01, 0, 0, 0xff)
986 logger.debug("WFA WNM-Notification Request with unsupported IE")
987 msg['payload'] = struct.pack("<BBBBBBL",
988 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
989 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 4, 0)
993 logger.debug("WNM-Notification Request with unknown WNM-Notification type 0")
994 msg['payload'] = struct.pack("<BBBB",
995 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
996 dialog_token, WNM_NOTIF_TYPE_FW_UPGRADE)
1000 logger.debug("Truncated WNM Sleep Mode Response - no Dialog Token")
1001 msg['payload'] = struct.pack("<BB",
1002 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP)
1006 logger.debug("Truncated WNM Sleep Mode Response - no Key Data Length")
1007 msg['payload'] = struct.pack("<BBB",
1008 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0)
1012 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (min)")
1013 msg['payload'] = struct.pack("<BBBH",
1014 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1019 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (max)")
1020 msg['payload'] = struct.pack("<BBBH",
1021 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1026 logger.debug("WNM Sleep Mode Response - truncated IE header")
1027 msg['payload'] = struct.pack("<BBBHB",
1028 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1033 logger.debug("WNM Sleep Mode Response - truncated IE")
1034 msg['payload'] = struct.pack("<BBBHBB",
1035 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1040 logger.debug("WNM Sleep Mode Response - Empty TFS Response")
1041 msg['payload'] = struct.pack("<BBBHBB",
1042 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1043 0, WLAN_EID_TFS_RESP, 0)
1047 logger.debug("WNM Sleep Mode Response - EID 0 not recognized")
1048 msg['payload'] = struct.pack("<BBBHBB",
1049 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1054 logger.debug("WNM Sleep Mode Response - Empty WNM Sleep Mode element and TFS Response element")
1055 msg['payload'] = struct.pack("<BBBHBBBB",
1056 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1057 0, WLAN_EID_WNMSLEEP, 0, WLAN_EID_TFS_RESP, 0)
1061 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element and empty TFS Response element")
1062 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1063 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1064 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1065 WNM_STATUS_SLEEP_ACCEPT, 0,
1066 WLAN_EID_TFS_RESP, 0)
1070 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(exit, deny key) and empty TFS Response element")
1071 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1072 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1073 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1074 WNM_STATUS_DENIED_KEY, 0,
1075 WLAN_EID_TFS_RESP, 0)
1079 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(enter, deny key) and empty TFS Response element")
1080 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1081 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1082 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1083 WNM_STATUS_DENIED_KEY, 0,
1084 WLAN_EID_TFS_RESP, 0)
1089 def test_wnm_action_proto_pmf(dev, apdev):
1090 """WNM Action protocol testing (PMF enabled)"""
1091 ssid = "test-wnm-pmf"
1092 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1093 params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1094 params["ieee80211w"] = "2"
1095 params['wnm_sleep_mode'] = '1'
1096 hapd = hostapd.add_ap(apdev[0], params)
1097 bssid = apdev[0]['bssid']
1098 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
1099 proto="WPA2", ieee80211w="2", scan_freq="2412")
1100 dev[0].request("WNM_SLEEP enter")
1102 hapd.set("ext_mgmt_frame_handling", "1")
1105 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1106 msg['da'] = dev[0].own_addr()
1108 msg['bssid'] = bssid
1110 logger.debug("WNM Sleep Mode Response - Invalid Key Data element length")
1111 keydata = struct.pack("<BB", 0, 1)
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 logger.debug("WNM Sleep Mode Response - Too short GTK subelem")
1124 keydata = struct.pack("<BB", WNM_SLEEP_SUBELEM_GTK, 0)
1125 msg['payload'] = struct.pack("<BBBH",
1126 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1128 msg['payload'] += keydata
1129 msg['payload'] += struct.pack("<BBBBHBB",
1130 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1131 WNM_STATUS_SLEEP_ACCEPT, 0,
1132 WLAN_EID_TFS_RESP, 0)
1136 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem")
1137 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1138 0, 17, 0, 0, 0, 0, 0, 0)
1139 msg['payload'] = struct.pack("<BBBH",
1140 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1142 msg['payload'] += keydata
1143 msg['payload'] += struct.pack("<BBBBHBB",
1144 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1145 WNM_STATUS_SLEEP_ACCEPT, 0,
1146 WLAN_EID_TFS_RESP, 0)
1150 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem (2)")
1151 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1152 0, 0, 0, 0, 0, 0, 0, 0)
1153 msg['payload'] = struct.pack("<BBBH",
1154 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1156 msg['payload'] += keydata
1157 msg['payload'] += struct.pack("<BBBBHBB",
1158 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1159 WNM_STATUS_SLEEP_ACCEPT, 0,
1160 WLAN_EID_TFS_RESP, 0)
1164 logger.debug("WNM Sleep Mode Response - GTK subelem and too short IGTK subelem")
1165 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1166 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1167 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1168 keydata += struct.pack("<BB", WNM_SLEEP_SUBELEM_IGTK, 0)
1169 msg['payload'] = struct.pack("<BBBH",
1170 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1172 msg['payload'] += keydata
1173 msg['payload'] += struct.pack("<BBBBHBB",
1174 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1175 WNM_STATUS_SLEEP_ACCEPT, 0,
1176 WLAN_EID_TFS_RESP, 0)
1180 logger.debug("WNM Sleep Mode Response - Unknown subelem")
1181 keydata = struct.pack("<BB", 255, 0)
1182 msg['payload'] = struct.pack("<BBBH",
1183 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1185 msg['payload'] += keydata
1186 msg['payload'] += struct.pack("<BBBBHBB",
1187 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1188 WNM_STATUS_SLEEP_ACCEPT, 0,
1189 WLAN_EID_TFS_RESP, 0)
1194 def test_wnm_action_proto_no_pmf(dev, apdev):
1195 """WNM Action protocol testing (PMF disabled)"""
1196 ssid = "test-wnm-no-pmf"
1197 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1198 params['wnm_sleep_mode'] = '1'
1199 hapd = hostapd.add_ap(apdev[0], params)
1200 bssid = apdev[0]['bssid']
1201 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1202 proto="WPA2", ieee80211w="0", scan_freq="2412")
1203 dev[0].request("WNM_SLEEP enter")
1205 hapd.set("ext_mgmt_frame_handling", "1")
1208 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1209 msg['da'] = dev[0].own_addr()
1211 msg['bssid'] = bssid
1213 logger.debug("WNM Sleep Mode Response - GTK subelem and IGTK subelem")
1214 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1215 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1216 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1217 keydata += struct.pack("<BBHLH4L", WNM_SLEEP_SUBELEM_IGTK, 2 + 6 + 16, 0,
1219 0xf1f2f3f4, 0xf5f6f7f8, 0xf9f0fafb, 0xfcfdfeff)
1220 msg['payload'] = struct.pack("<BBBH",
1221 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1223 msg['payload'] += keydata
1224 msg['payload'] += struct.pack("<BBBBHBB",
1225 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1226 WNM_STATUS_SLEEP_ACCEPT, 0,
1227 WLAN_EID_TFS_RESP, 0)
1231 ev = dev[0].wait_event(["WNM: Ignore Key Data"], timeout=5)
1233 raise Exception("Key Data not ignored")
1235 def test_wnm_bss_tm_req_with_mbo_ie(dev, apdev):
1236 """WNM BSS transition request with MBO IE and reassociation delay attribute"""
1237 ssid = "test-wnm-mbo"
1238 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1239 hapd = hostapd.add_ap(apdev[0], params)
1240 bssid = apdev[0]['bssid']
1241 if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
1242 raise Exception("Failed to set STA as cellular data capable")
1244 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1245 proto="WPA2", ieee80211w="0", scan_freq="2412")
1247 logger.debug("BTM request with MBO reassociation delay when disassoc imminent is not set")
1248 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=3:2:1"):
1249 raise Exception("BSS transition management succeeded unexpectedly")
1251 logger.debug("BTM request with invalid MBO transition reason code")
1252 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=10:2:1"):
1253 raise Exception("BSS transition management succeeded unexpectedly")
1255 logger.debug("BTM request with MBO reassociation retry delay of 5 seconds")
1256 if 'OK' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " disassoc_imminent=1 disassoc_timer=3 mbo=3:5:1"):
1257 raise Exception("BSS transition management command failed")
1259 ev = dev[0].wait_event(['MBO-CELL-PREFERENCE'], 1)
1260 if ev is None or "preference=1" not in ev:
1261 raise Exception("Timeout waiting for MBO-CELL-PREFERENCE event")
1263 ev = dev[0].wait_event(['MBO-TRANSITION-REASON'], 1)
1264 if ev is None or "reason=3" not in ev:
1265 raise Exception("Timeout waiting for MBO-TRANSITION-REASON event")
1267 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1269 raise Exception("No BSS Transition Management Response")
1270 if dev[0].own_addr() not in ev:
1271 raise Exception("Unexpected BSS Transition Management Response address")
1273 ev = dev[0].wait_event(['CTRL-EVENT-DISCONNECTED'], 5)
1275 raise Exception("Station did not disconnect although disassoc imminent was set")
1277 # Set the scan interval to make dev[0] look for connections
1278 if 'OK' not in dev[0].request("SCAN_INTERVAL 1"):
1279 raise Exception("Failed to set scan interval")
1281 # Make sure no connection is made during the retry delay
1282 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1284 raise Exception("Station connected before assoc retry delay was over")
1286 # After the assoc retry delay is over, we can reconnect
1287 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1289 raise Exception("Station did not connect after assoc retry delay is over")
1291 if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
1292 raise Exception("Failed to set STA as cellular data not-capable")
1295 def test_wnm_bss_transition_mgmt_query(dev, apdev):
1296 """WNM BSS Transition Management query"""
1297 params = { "ssid": "test-wnm",
1298 "bss_transition": "1" }
1299 hapd = hostapd.add_ap(apdev[0], params)
1300 params = { "ssid": "another" }
1301 hapd2 = hostapd.add_ap(apdev[1], params)
1303 dev[0].scan_for_bss(apdev[1]['bssid'], 2412)
1304 dev[0].scan_for_bss(apdev[0]['bssid'], 2412)
1306 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1307 dev[0].request("WNM_BSS_QUERY 0 list")
1309 ev = dev[0].wait_event(["WNM: BSS Transition Management Request"],
1312 raise Exception("No BSS Transition Management Request frame seen")
1314 ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1316 raise Exception("No BSS Transition Management Response frame seen")
1319 def test_wnm_bss_tm_security_mismatch(dev, apdev):
1320 """WNM BSS Transition Management and security mismatch"""
1321 params = { "ssid": "test-wnm",
1323 "wpa_key_mgmt": "WPA-PSK",
1324 "rsn_pairwise": "CCMP",
1325 "wpa_passphrase": "12345678",
1328 "bss_transition": "1" }
1329 hapd = hostapd.add_ap(apdev[0], params)
1331 params = { "ssid": "test-wnm",
1334 "bss_transition": "1" }
1335 hapd2 = hostapd.add_ap(apdev[1], params)
1337 dev[0].scan_for_bss(apdev[1]['bssid'], 2462)
1339 id = dev[0].connect("test-wnm", psk="12345678",
1340 bssid=apdev[0]['bssid'], scan_freq="2412")
1341 dev[0].set_network(id, "scan_freq", "")
1342 dev[0].set_network(id, "bssid", "")
1344 addr = dev[0].own_addr()
1345 dev[0].dump_monitor()
1347 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1348 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"):
1349 raise Exception("BSS_TM_REQ command failed")
1350 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1352 raise Exception("No BSS Transition Management Response")
1353 if "status_code=7" not in ev:
1354 raise Exception("Unexpected BSS transition request response: " + ev)
1356 def test_wnm_bss_tm_connect_cmd(dev, apdev):
1357 """WNM BSS Transition Management and cfg80211 connect command"""
1358 params = { "ssid": "test-wnm",
1361 "bss_transition": "1" }
1362 hapd = hostapd.add_ap(apdev[0], params)
1364 params = { "ssid": "test-wnm",
1367 "bss_transition": "1" }
1368 hapd2 = hostapd.add_ap(apdev[1], params)
1370 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1371 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
1373 wpas.scan_for_bss(apdev[1]['bssid'], 2462)
1375 id = wpas.connect("test-wnm", key_mgmt="NONE",
1376 bssid=apdev[0]['bssid'], scan_freq="2412")
1377 wpas.set_network(id, "scan_freq", "")
1378 wpas.set_network(id, "bssid", "")
1380 addr = wpas.own_addr()
1383 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1384 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"):
1385 raise Exception("BSS_TM_REQ command failed")
1386 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1388 raise Exception("No BSS Transition Management Response")
1389 if "status_code=0" not in ev:
1390 raise Exception("BSS transition request was not accepted: " + ev)
1391 if "target_bssid=" + apdev[1]['bssid'] not in ev:
1392 raise Exception("Unexpected target BSS: " + ev)
1393 ev = wpas.wait_event(["CTRL-EVENT-CONNECTED",
1394 "CTRL-EVENT-DISCONNECTED"], timeout=10)
1396 raise Exception("No reassociation seen")
1397 if "CTRL-EVENT-DISCONNECTED" in ev:
1398 #TODO: Uncomment this once kernel side changes for Connect command
1399 #reassociation are in upstream.
1400 #raise Exception("Unexpected disconnection reported")
1401 logger.info("Unexpected disconnection reported")
1402 ev = wpas.wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
1404 raise Exception("No reassociation seen")
1405 if apdev[1]['bssid'] not in ev:
1406 raise Exception("Unexpected reassociation target: " + ev)
1408 def test_wnm_bss_tm_reject(dev, apdev):
1409 """WNM BSS Transition Management request getting rejected"""
1412 params = { "ssid": "test-wnm",
1413 "country_code": "FI",
1417 "bss_transition": "1" }
1418 hapd = hostapd.add_ap(apdev[0], params)
1420 id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1421 addr = dev[0].own_addr()
1422 dev[0].dump_monitor()
1424 if "OK" not in dev[0].request("SET reject_btm_req_reason 123"):
1425 raise Exception("Failed to set reject_btm_req_reason")
1427 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " disassoc_timer=1"):
1428 raise Exception("BSS_TM_REQ command failed")
1429 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1431 raise Exception("No BSS Transition Management Response")
1433 raise Exception("Unexpected BSS Transition Management Response address")
1434 if "status_code=123" not in ev:
1435 raise Exception("Unexpected BSS Transition Management Response status: " + ev)
1436 dev[0].wait_disconnected()
1438 dev[0].request("DISCONNECT")
1440 hapd.request("DISABLE")
1441 subprocess.call(['iw', 'reg', 'set', '00'])
1442 dev[0].flush_scan_cache()