2 # Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi>
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
11 logger = logging.getLogger()
15 from wpasupplicant import WpaSupplicant
16 from utils import alloc_fail, wait_fail_trigger
17 from wlantest import Wlantest
19 def test_wnm_bss_transition_mgmt(dev, apdev):
20 """WNM BSS Transition Management"""
21 params = { "ssid": "test-wnm",
22 "time_advertisement": "2",
24 "wnm_sleep_mode": "1",
25 "bss_transition": "1" }
26 hostapd.add_ap(apdev[0], params)
28 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
29 dev[0].request("WNM_BSS_QUERY 0")
31 def test_wnm_disassoc_imminent(dev, apdev):
32 """WNM Disassociation Imminent"""
33 params = { "ssid": "test-wnm",
34 "time_advertisement": "2",
36 "wnm_sleep_mode": "1",
37 "bss_transition": "1" }
38 hapd = hostapd.add_ap(apdev[0], params)
40 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
41 addr = dev[0].p2p_interface_addr()
42 hapd.request("DISASSOC_IMMINENT " + addr + " 10")
43 ev = dev[0].wait_event(["WNM: Disassociation Imminent"])
45 raise Exception("Timeout while waiting for disassociation imminent")
46 if "Disassociation Timer 10" not in ev:
47 raise Exception("Unexpected disassociation imminent contents")
48 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
50 raise Exception("Timeout while waiting for re-connection scan")
52 def test_wnm_ess_disassoc_imminent(dev, apdev):
53 """WNM ESS Disassociation Imminent"""
54 params = { "ssid": "test-wnm",
55 "time_advertisement": "2",
57 "wnm_sleep_mode": "1",
58 "bss_transition": "1" }
59 hapd = hostapd.add_ap(apdev[0], params)
61 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
62 addr = dev[0].p2p_interface_addr()
63 hapd.request("ESS_DISASSOC " + addr + " 10 http://example.com/session-info")
64 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"])
66 raise Exception("Timeout while waiting for ESS disassociation imminent")
67 if "0 1024 http://example.com/session-info" not in ev:
68 raise Exception("Unexpected ESS disassociation imminent message contents")
69 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
71 raise Exception("Timeout while waiting for re-connection scan")
73 def test_wnm_ess_disassoc_imminent_pmf(dev, apdev):
74 """WNM ESS Disassociation Imminent"""
75 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
76 params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
77 params["ieee80211w"] = "2";
78 params["bss_transition"] = "1"
79 hapd = hostapd.add_ap(apdev[0], params)
81 dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
82 key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
83 addr = dev[0].p2p_interface_addr()
84 hapd.request("ESS_DISASSOC " + addr + " 10 http://example.com/session-info")
85 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"])
87 raise Exception("Timeout while waiting for ESS disassociation imminent")
88 if "1 1024 http://example.com/session-info" not in ev:
89 raise Exception("Unexpected ESS disassociation imminent message contents")
90 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
92 raise Exception("Timeout while waiting for re-connection scan")
94 def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None):
95 addr = dev.p2p_interface_addr()
96 sta = hapd.get_sta(addr)
97 if "[WNM_SLEEP_MODE]" in sta['flags']:
98 raise Exception("Station unexpectedly in WNM-Sleep Mode")
100 logger.info("Going to WNM Sleep Mode")
102 if interval is not None:
103 extra += " interval=" + str(interval)
105 extra += " tfs_req=" + tfs_req
106 if "OK" not in dev.request("WNM_SLEEP enter" + extra):
107 raise Exception("WNM_SLEEP failed")
111 sta = hapd.get_sta(addr)
112 if "[WNM_SLEEP_MODE]" in sta['flags']:
116 raise Exception("Station failed to enter WNM-Sleep Mode")
118 logger.info("Waking up from WNM Sleep Mode")
120 dev.request("WNM_SLEEP exit")
123 sta = hapd.get_sta(addr)
124 if "[WNM_SLEEP_MODE]" not in sta['flags']:
128 raise Exception("Station failed to exit WNM-Sleep Mode")
130 def test_wnm_sleep_mode_open(dev, apdev):
131 """WNM Sleep Mode - open"""
132 params = { "ssid": "test-wnm",
133 "time_advertisement": "2",
135 "wnm_sleep_mode": "1",
136 "bss_transition": "1" }
137 hapd = hostapd.add_ap(apdev[0], params)
139 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
140 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
142 raise Exception("No connection event received from hostapd")
143 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
144 check_wnm_sleep_mode_enter_exit(hapd, dev[0], interval=100)
145 check_wnm_sleep_mode_enter_exit(hapd, dev[0], tfs_req="5b17010001130e110000071122334455661122334455661234")
148 "exit tfs_req=123 interval=10",
149 "enter tfs_req=qq interval=10" ]
151 if "FAIL" not in dev[0].request("WNM_SLEEP " + cmd):
152 raise Exception("Invalid WNM_SLEEP accepted")
154 def test_wnm_sleep_mode_rsn(dev, apdev):
155 """WNM Sleep Mode - RSN"""
156 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
157 params["time_advertisement"] = "2"
158 params["time_zone"] = "EST5"
159 params["wnm_sleep_mode"] = "1"
160 params["bss_transition"] = "1"
161 hapd = hostapd.add_ap(apdev[0], params)
163 dev[0].connect("test-wnm-rsn", psk="12345678", scan_freq="2412")
164 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
166 raise Exception("No connection event received from hostapd")
167 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
169 def test_wnm_sleep_mode_ap_oom(dev, apdev):
170 """WNM Sleep Mode - AP side OOM"""
171 params = { "ssid": "test-wnm",
172 "wnm_sleep_mode": "1" }
173 hapd = hostapd.add_ap(apdev[0], params)
175 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
176 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
178 raise Exception("No connection event received from hostapd")
179 with alloc_fail(hapd, 1, "ieee802_11_send_wnmsleep_resp"):
180 dev[0].request("WNM_SLEEP enter")
181 wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
182 with alloc_fail(hapd, 2, "ieee802_11_send_wnmsleep_resp"):
183 dev[0].request("WNM_SLEEP exit")
184 wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
186 def test_wnm_sleep_mode_rsn_pmf(dev, apdev):
187 """WNM Sleep Mode - RSN with PMF"""
188 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
189 params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
190 params["ieee80211w"] = "2";
191 params["time_advertisement"] = "2"
192 params["time_zone"] = "EST5"
193 params["wnm_sleep_mode"] = "1"
194 params["bss_transition"] = "1"
195 hapd = hostapd.add_ap(apdev[0], params)
200 wt.add_passphrase("12345678")
202 dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
203 key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
204 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
206 raise Exception("No connection event received from hostapd")
207 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
209 MGMT_SUBTYPE_ACTION = 13
210 ACTION_CATEG_WNM = 10
211 WNM_ACT_BSS_TM_REQ = 7
212 WNM_ACT_BSS_TM_RESP = 8
213 WNM_ACT_SLEEP_MODE_REQ = 16
214 WNM_ACT_SLEEP_MODE_RESP = 17
215 WNM_ACT_NOTIFICATION_REQ = 26
216 WNM_ACT_NOTIFICATION_RESP = 27
217 WNM_NOTIF_TYPE_FW_UPGRADE = 0
218 WNM_NOTIF_TYPE_WFA = 1
219 WLAN_EID_TFS_RESP = 92
220 WLAN_EID_WNMSLEEP = 93
221 WNM_SLEEP_MODE_ENTER = 0
222 WNM_SLEEP_MODE_EXIT = 1
223 WNM_STATUS_SLEEP_ACCEPT = 0
224 WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE = 1
225 WNM_STATUS_DENIED_ACTION = 2
226 WNM_STATUS_DENIED_TMP = 3
227 WNM_STATUS_DENIED_KEY = 4
228 WNM_STATUS_DENIED_OTHER_WNM_SERVICE = 5
229 WNM_SLEEP_SUBELEM_GTK = 0
230 WNM_SLEEP_SUBELEM_IGTK = 1
232 def bss_tm_req(dst, src, dialog_token=1, req_mode=0, disassoc_timer=0,
233 validity_interval=1):
235 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
239 msg['payload'] = struct.pack("<BBBBHB",
240 ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
241 dialog_token, req_mode, disassoc_timer,
245 def rx_bss_tm_resp(hapd, expect_dialog=None, expect_status=None):
246 for i in range(0, 100):
247 resp = hapd.mgmt_rx()
249 raise Exception("No BSS TM Response received")
250 if resp['subtype'] == MGMT_SUBTYPE_ACTION:
253 raise Exception("Not an Action frame")
254 payload = resp['payload']
255 if len(payload) < 2 + 3:
256 raise Exception("Too short payload")
257 (category, action) = struct.unpack('BB', payload[0:2])
258 if category != ACTION_CATEG_WNM or action != WNM_ACT_BSS_TM_RESP:
259 raise Exception("Not a BSS TM Response")
261 (dialog, status, bss_term_delay) = struct.unpack('BBB', pos[0:3])
262 resp['dialog'] = dialog
263 resp['status'] = status
264 resp['bss_term_delay'] = bss_term_delay
266 if len(pos) >= 6 and status == 0:
267 resp['target_bssid'] = binascii.hexlify(pos[0:6])
269 resp['candidates'] = pos
270 if expect_dialog is not None and dialog != expect_dialog:
271 raise Exception("Unexpected dialog token")
272 if expect_status is not None and status != expect_status:
273 raise Exception("Unexpected status code %d" % status)
276 def expect_ack(hapd):
277 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
279 raise Exception("Missing TX status")
281 raise Exception("Action frame not acknowledged")
283 def test_wnm_bss_tm_req(dev, apdev):
284 """BSS Transition Management Request"""
285 params = { "ssid": "test-wnm", "bss_transition": "1" }
286 hapd = hostapd.add_ap(apdev[0], params)
287 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
288 hapd2 = hostapd.add_ap(apdev[1], params)
290 hapd.set("ext_mgmt_frame_handling", "1")
292 # truncated BSS TM Request
293 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
295 req['payload'] = struct.pack("<BBBBH",
296 ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
301 # no disassociation and no candidate list
302 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
305 resp = rx_bss_tm_resp(hapd, expect_dialog=2, expect_status=1)
307 # truncated BSS Termination Duration
308 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
313 # BSS Termination Duration with TSF=0 and Duration=10
314 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
315 req_mode=0x08, dialog_token=3)
316 req['payload'] += struct.pack("<BBQH", 4, 10, 0, 10)
318 resp = rx_bss_tm_resp(hapd, expect_dialog=3, expect_status=1)
320 # truncated Session Information URL
321 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
325 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
327 req['payload'] += struct.pack("<BBB", 3, 65, 66)
331 # Session Information URL
332 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
333 req_mode=0x10, dialog_token=4)
334 req['payload'] += struct.pack("<BBB", 2, 65, 66)
336 resp = rx_bss_tm_resp(hapd, expect_dialog=4, expect_status=0)
338 # Preferred Candidate List without any entries
339 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
340 req_mode=0x01, dialog_token=5)
342 resp = rx_bss_tm_resp(hapd, expect_dialog=5, expect_status=7)
344 # Preferred Candidate List with a truncated entry
345 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
347 req['payload'] += struct.pack("<BB", 52, 1)
351 # Preferred Candidate List with a too short entry
352 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
353 req_mode=0x01, dialog_token=6)
354 req['payload'] += struct.pack("<BB", 52, 0)
356 resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
358 # Preferred Candidate List with a non-matching entry
359 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
360 req_mode=0x01, dialog_token=6)
361 req['payload'] += struct.pack("<BB6BLBBB", 52, 13,
365 resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
367 # Preferred Candidate List with a truncated subelement
368 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
369 req_mode=0x01, dialog_token=7)
370 req['payload'] += struct.pack("<BB6BLBBBBB", 52, 13 + 2,
375 resp = rx_bss_tm_resp(hapd, expect_dialog=7, expect_status=7)
377 # Preferred Candidate List with lots of invalid optional subelements
378 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
379 req_mode=0x01, dialog_token=8)
380 subelems = struct.pack("<BBHB", 1, 3, 0, 100)
381 subelems += struct.pack("<BBB", 2, 1, 65)
382 subelems += struct.pack("<BB", 3, 0)
383 subelems += struct.pack("<BBQB", 4, 9, 0, 10)
384 subelems += struct.pack("<BBHLB", 5, 7, 0, 0, 0)
385 subelems += struct.pack("<BB", 66, 0)
386 subelems += struct.pack("<BBBBBB", 70, 4, 0, 0, 0, 0)
387 subelems += struct.pack("<BB", 71, 0)
388 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
390 0, 81, 1, 7) + subelems
392 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
394 # Preferred Candidate List with lots of valid optional subelements (twice)
395 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
396 req_mode=0x01, dialog_token=8)
398 subelems = struct.pack("<BBHH", 1, 4, 0, 100)
399 # Condensed Country String
400 subelems += struct.pack("<BBBB", 2, 2, 65, 66)
401 # BSS Transition Candidate Preference
402 subelems += struct.pack("<BBB", 3, 1, 100)
403 # BSS Termination Duration
404 subelems += struct.pack("<BBQH", 4, 10, 0, 10)
406 subelems += struct.pack("<BBHLH", 5, 8, 0, 0, 0)
407 # Measurement Pilot Transmission
408 subelems += struct.pack("<BBBBB", 66, 3, 0, 0, 0)
409 # RM Enabled Capabilities
410 subelems += struct.pack("<BBBBBBB", 70, 5, 0, 0, 0, 0, 0)
412 subelems += struct.pack("<BBBB", 71, 2, 0, 0)
413 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems) * 2,
415 0, 81, 1, 7) + subelems + subelems
417 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
419 # Preferred Candidate List followed by vendor element
420 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
421 req_mode=0x01, dialog_token=8)
423 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
425 0, 81, 1, 7) + subelems
426 req['payload'] += binascii.unhexlify("DD0411223344")
428 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
430 def test_wnm_bss_keep_alive(dev, apdev):
432 params = { "ssid": "test-wnm",
433 "ap_max_inactivity": "1" }
434 hapd = hostapd.add_ap(apdev[0], params)
436 addr = dev[0].p2p_interface_addr()
437 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
438 start = hapd.get_sta(addr)
439 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=2)
441 raise Exception("Unexpected disconnection")
442 end = hapd.get_sta(addr)
443 if int(end['rx_packets']) <= int(start['rx_packets']):
444 raise Exception("No keep-alive packets received")
446 # Disable client keep-alive so that hostapd will verify connection
448 dev[0].request("SET no_keep_alive 1")
450 sta = hapd.get_sta(addr)
451 logger.info("timeout_next=%s rx_packets=%s tx_packets=%s" % (sta['timeout_next'], sta['rx_packets'], sta['tx_packets']))
452 if i > 1 and sta['timeout_next'] != "NULLFUNC POLL" and int(sta['tx_packets']) > int(end['tx_packets']):
454 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
456 raise Exception("Unexpected disconnection (client poll expected)")
458 dev[0].request("SET no_keep_alive 0")
459 if int(sta['tx_packets']) <= int(end['tx_packets']):
460 raise Exception("No client poll packet seen")
462 def test_wnm_bss_tm(dev, apdev):
463 """WNM BSS Transition Management"""
467 params = { "ssid": "test-wnm",
468 "country_code": "FI",
472 "bss_transition": "1" }
473 hapd = hostapd.add_ap(apdev[0], params)
475 id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
476 dev[0].set_network(id, "scan_freq", "")
478 params = { "ssid": "test-wnm",
479 "country_code": "FI",
483 "bss_transition": "1" }
484 hapd2 = hostapd.add_ap(apdev[1], params)
486 addr = dev[0].p2p_interface_addr()
487 dev[0].dump_monitor()
489 logger.info("No neighbor list entries")
490 if "OK" not in hapd.request("BSS_TM_REQ " + addr):
491 raise Exception("BSS_TM_REQ command failed")
492 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
494 raise Exception("No BSS Transition Management Response")
496 raise Exception("Unexpected BSS Transition Management Response address")
497 if "status_code=0" in ev:
498 raise Exception("BSS transition accepted unexpectedly")
499 dev[0].dump_monitor()
501 logger.info("Neighbor list entry, but not claimed as Preferred Candidate List")
502 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " neighbor=11:22:33:44:55:66,0x0000,81,3,7"):
503 raise Exception("BSS_TM_REQ command failed")
504 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
506 raise Exception("No BSS Transition Management Response")
507 if "status_code=0" in ev:
508 raise Exception("BSS transition accepted unexpectedly")
509 dev[0].dump_monitor()
511 logger.info("Preferred Candidate List (no matching neighbor) without Disassociation Imminent")
512 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"):
513 raise Exception("BSS_TM_REQ command failed")
514 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
516 raise Exception("No BSS Transition Management Response")
517 if "status_code=0" in ev:
518 raise Exception("BSS transition accepted unexpectedly")
519 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
521 raise Exception("No scan started")
522 dev[0].dump_monitor()
524 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
525 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"):
526 raise Exception("BSS_TM_REQ command failed")
527 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
529 raise Exception("No BSS Transition Management Response")
530 if "status_code=0" not in ev:
531 raise Exception("BSS transition request was not accepted: " + ev)
532 if "target_bssid=" + apdev[1]['bssid'] not in ev:
533 raise Exception("Unexpected target BSS: " + ev)
534 dev[0].wait_connected(timeout=15, error="No reassociation seen")
535 if apdev[1]['bssid'] not in ev:
536 raise Exception("Unexpected reassociation target: " + ev)
537 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
539 raise Exception("Unexpected scan started")
540 dev[0].dump_monitor()
542 logger.info("Preferred Candidate List with two matches, no roam needed")
543 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"):
544 raise Exception("BSS_TM_REQ command failed")
545 ev = hapd2.wait_event(['BSS-TM-RESP'], timeout=10)
547 raise Exception("No BSS Transition Management Response")
548 if "status_code=0" not in ev:
549 raise Exception("BSS transition request was not accepted: " + ev)
550 if "target_bssid=" + apdev[1]['bssid'] not in ev:
551 raise Exception("Unexpected target BSS: " + ev)
552 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
554 raise Exception("Unexpected scan started")
555 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
557 raise Exception("Unexpected reassociation");
559 dev[0].request("DISCONNECT")
561 hapd.request("DISABLE")
563 hapd2.request("DISABLE")
564 subprocess.call(['iw', 'reg', 'set', '00'])
565 dev[0].flush_scan_cache()
567 def test_wnm_bss_tm_scan_not_needed(dev, apdev):
568 """WNM BSS Transition Management and scan not needed"""
569 run_wnm_bss_tm_scan_not_needed(dev, apdev)
571 def test_wnm_bss_tm_nei_vht(dev, apdev):
572 """WNM BSS Transition Management and VHT neighbor"""
573 run_wnm_bss_tm_scan_not_needed(dev, apdev, vht=True, nei_info="115,36,9")
575 def test_wnm_bss_tm_nei_11a(dev, apdev):
576 """WNM BSS Transition Management and 11a neighbor"""
577 run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, nei_info="115,36,4")
579 def test_wnm_bss_tm_nei_11g(dev, apdev):
580 """WNM BSS Transition Management and 11g neighbor"""
581 run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, hwmode='g',
582 channel='2', freq=2417, nei_info="81,2,6")
584 def test_wnm_bss_tm_nei_11b(dev, apdev):
585 """WNM BSS Transition Management and 11g neighbor"""
586 run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, hwmode='b',
587 channel='3', freq=2422, nei_info="81,2,5")
589 def run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=True, vht=False, hwmode='a',
590 channel='36', freq=5180,
591 nei_info="115,36,7,0301ff"):
595 params = { "ssid": "test-wnm",
596 "country_code": "FI",
600 "bss_transition": "1" }
601 hapd = hostapd.add_ap(apdev[0], params)
603 params = { "ssid": "test-wnm",
604 "country_code": "FI",
608 "bss_transition": "1" }
610 params['ieee80211n'] = '0'
612 params['ieee80211ac'] = "1"
613 params["vht_oper_chwidth"] = "0"
614 params["vht_oper_centr_freq_seg0_idx"] = "0"
616 hapd2 = hostapd.add_ap(apdev[1], params)
618 dev[0].scan_for_bss(apdev[1]['bssid'], freq)
620 id = dev[0].connect("test-wnm", key_mgmt="NONE",
621 bssid=apdev[0]['bssid'], scan_freq="2412")
622 dev[0].set_network(id, "scan_freq", "")
623 dev[0].set_network(id, "bssid", "")
625 addr = dev[0].own_addr()
626 dev[0].dump_monitor()
628 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
629 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000," + nei_info):
630 raise Exception("BSS_TM_REQ command failed")
631 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
633 raise Exception("No BSS Transition Management Response")
634 if "status_code=0" not in ev:
635 raise Exception("BSS transition request was not accepted: " + ev)
636 if "target_bssid=" + apdev[1]['bssid'] not in ev:
637 raise Exception("Unexpected target BSS: " + ev)
638 dev[0].wait_connected(timeout=15, error="No reassociation seen")
639 if apdev[1]['bssid'] not in ev:
640 raise Exception("Unexpected reassociation target: " + ev)
641 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
643 raise Exception("Unexpected scan started")
644 dev[0].dump_monitor()
646 dev[0].request("DISCONNECT")
648 hapd.request("DISABLE")
650 hapd2.request("DISABLE")
651 subprocess.call(['iw', 'reg', 'set', '00'])
652 dev[0].flush_scan_cache()
654 def test_wnm_bss_tm_scan_needed(dev, apdev):
655 """WNM BSS Transition Management and scan needed"""
659 params = { "ssid": "test-wnm",
660 "country_code": "FI",
664 "bss_transition": "1" }
665 hapd = hostapd.add_ap(apdev[0], params)
667 params = { "ssid": "test-wnm",
668 "country_code": "FI",
672 "bss_transition": "1" }
673 hapd2 = hostapd.add_ap(apdev[1], params)
675 dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
677 id = dev[0].connect("test-wnm", key_mgmt="NONE",
678 bssid=apdev[0]['bssid'], scan_freq="2412")
679 dev[0].set_network(id, "scan_freq", "")
680 dev[0].set_network(id, "bssid", "")
682 addr = dev[0].own_addr()
683 dev[0].dump_monitor()
685 logger.info("Wait 11 seconds for the last scan result to be too old, but still present in BSS table")
687 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
688 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"):
689 raise Exception("BSS_TM_REQ command failed")
690 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
692 raise Exception("No BSS Transition Management Response")
693 if "status_code=0" not in ev:
694 raise Exception("BSS transition request was not accepted: " + ev)
695 if "target_bssid=" + apdev[1]['bssid'] not in ev:
696 raise Exception("Unexpected target BSS: " + ev)
697 dev[0].wait_connected(timeout=15, error="No reassociation seen")
698 if apdev[1]['bssid'] not in ev:
699 raise Exception("Unexpected reassociation target: " + ev)
700 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
702 raise Exception("Unexpected scan started")
703 dev[0].dump_monitor()
705 dev[0].request("DISCONNECT")
707 hapd.request("DISABLE")
709 hapd2.request("DISABLE")
710 subprocess.call(['iw', 'reg', 'set', '00'])
711 dev[0].flush_scan_cache()
713 def start_wnm_tm(ap, country, dev):
714 params = { "ssid": "test-wnm",
715 "country_code": country,
719 "bss_transition": "1" }
720 hapd = hostapd.add_ap(ap, params)
721 id = dev.connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
723 dev.set_network(id, "scan_freq", "")
726 def stop_wnm_tm(hapd, dev):
727 dev.request("DISCONNECT")
729 dev.wait_disconnected()
733 hapd.request("DISABLE")
734 subprocess.call(['iw', 'reg', 'set', '00'])
735 dev.flush_scan_cache()
737 def wnm_bss_tm_check(hapd, dev, data):
738 addr = dev.p2p_interface_addr()
739 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " " + data):
740 raise Exception("BSS_TM_REQ command failed")
741 ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
743 raise Exception("No scan started")
744 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
746 raise Exception("Scan did not complete")
748 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
750 raise Exception("No BSS Transition Management Response")
751 if "status_code=7" not in ev:
752 raise Exception("Unexpected response: " + ev)
754 def test_wnm_bss_tm_country_us(dev, apdev):
755 """WNM BSS Transition Management (US)"""
758 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
760 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
761 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")
763 # Make the test take less time by limiting full scans
764 dev[0].set_network(id, "scan_freq", "2412")
765 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
766 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")
768 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
769 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")
771 stop_wnm_tm(hapd, dev[0])
773 def test_wnm_bss_tm_country_fi(dev, apdev):
774 """WNM BSS Transition Management (FI)"""
775 addr = dev[0].p2p_interface_addr()
778 hapd, id = start_wnm_tm(apdev[0], "FI", dev[0])
780 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
781 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")
783 # Make the test take less time by limiting full scans
784 dev[0].set_network(id, "scan_freq", "2412")
785 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
786 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")
788 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
789 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,0,0,7")
791 stop_wnm_tm(hapd, dev[0])
793 def test_wnm_bss_tm_country_jp(dev, apdev):
794 """WNM BSS Transition Management (JP)"""
795 addr = dev[0].p2p_interface_addr()
798 hapd, id = start_wnm_tm(apdev[0], "JP", dev[0])
800 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
801 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")
803 # Make the test take less time by limiting full scans
804 dev[0].set_network(id, "scan_freq", "2412")
805 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
806 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")
808 stop_wnm_tm(hapd, dev[0])
810 def test_wnm_bss_tm_country_cn(dev, apdev):
811 """WNM BSS Transition Management (CN)"""
812 addr = dev[0].p2p_interface_addr()
815 hapd, id = start_wnm_tm(apdev[0], "CN", dev[0])
817 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
818 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")
820 # Make the test take less time by limiting full scans
821 dev[0].set_network(id, "scan_freq", "2412")
822 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
823 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")
825 stop_wnm_tm(hapd, dev[0])
827 def test_wnm_bss_tm_global(dev, apdev):
828 """WNM BSS Transition Management (global)"""
829 addr = dev[0].p2p_interface_addr()
832 hapd, id = start_wnm_tm(apdev[0], "XX", dev[0])
834 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
835 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")
837 # Make the test take less time by limiting full scans
838 dev[0].set_network(id, "scan_freq", "2412")
839 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
840 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")
842 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
843 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")
845 stop_wnm_tm(hapd, dev[0])
847 def test_wnm_bss_tm_op_class_0(dev, apdev):
848 """WNM BSS Transition Management with invalid operating class"""
851 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
853 logger.info("Preferred Candidate List (no matching neighbor, invalid op class specified for channels)")
854 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")
856 stop_wnm_tm(hapd, dev[0])
858 def test_wnm_action_proto(dev, apdev):
859 """WNM Action protocol testing"""
860 params = { "ssid": "test-wnm" }
861 params['wnm_sleep_mode'] = '1'
862 hapd = hostapd.add_ap(apdev[0], params)
863 bssid = apdev[0]['bssid']
864 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
865 dev[0].request("WNM_SLEEP enter")
867 hapd.set("ext_mgmt_frame_handling", "1")
870 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
871 msg['da'] = dev[0].own_addr()
877 logger.debug("Unexpected WNM-Notification Response")
878 # Note: This is actually not registered for user space processing in
879 # driver_nl80211.c nl80211_mgmt_subscribe_non_ap() and as such, won't make
880 # it to wpa_supplicant.
881 msg['payload'] = struct.pack("<BBBB",
882 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_RESP,
887 logger.debug("Truncated WNM-Notification Request (no Type field)")
888 msg['payload'] = struct.pack("<BBB",
889 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
894 logger.debug("WFA WNM-Notification Request with truncated IE (min)")
895 msg['payload'] = struct.pack("<BBBBBB",
896 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
897 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 1)
901 logger.debug("WFA WNM-Notification Request with truncated IE (max)")
902 msg['payload'] = struct.pack("<BBBBBB",
903 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
904 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 255)
908 logger.debug("WFA WNM-Notification Request with too short IE")
909 msg['payload'] = struct.pack("<BBBBBB",
910 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
911 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 0)
915 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL")
916 msg['payload'] = struct.pack(">BBBBBBLB",
917 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
918 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
923 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(2)")
924 msg['payload'] = struct.pack(">BBBBBBLBB",
925 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
926 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 6,
931 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(3)")
932 msg['payload'] = struct.pack(">BBBBBBLB",
933 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
934 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
939 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(min)")
940 msg['payload'] = struct.pack(">BBBBBBLBHB",
941 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
942 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
947 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(max)")
948 msg['payload'] = struct.pack(">BBBBBBLBHB",
949 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
950 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
951 0x506f9a01, 0, 0, 0xff)
955 logger.debug("WFA WNM-Notification Request with unsupported IE")
956 msg['payload'] = struct.pack("<BBBBBBL",
957 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
958 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 4, 0)
962 logger.debug("WNM-Notification Request with unknown WNM-Notification type 0")
963 msg['payload'] = struct.pack("<BBBB",
964 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
965 dialog_token, WNM_NOTIF_TYPE_FW_UPGRADE)
969 logger.debug("Truncated WNM Sleep Mode Response - no Dialog Token")
970 msg['payload'] = struct.pack("<BB",
971 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP)
975 logger.debug("Truncated WNM Sleep Mode Response - no Key Data Length")
976 msg['payload'] = struct.pack("<BBB",
977 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0)
981 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (min)")
982 msg['payload'] = struct.pack("<BBBH",
983 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
988 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (max)")
989 msg['payload'] = struct.pack("<BBBH",
990 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
995 logger.debug("WNM Sleep Mode Response - truncated IE header")
996 msg['payload'] = struct.pack("<BBBHB",
997 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1002 logger.debug("WNM Sleep Mode Response - truncated IE")
1003 msg['payload'] = struct.pack("<BBBHBB",
1004 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1009 logger.debug("WNM Sleep Mode Response - Empty TFS Response")
1010 msg['payload'] = struct.pack("<BBBHBB",
1011 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1012 0, WLAN_EID_TFS_RESP, 0)
1016 logger.debug("WNM Sleep Mode Response - EID 0 not recognized")
1017 msg['payload'] = struct.pack("<BBBHBB",
1018 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1023 logger.debug("WNM Sleep Mode Response - Empty WNM Sleep Mode element and TFS Response element")
1024 msg['payload'] = struct.pack("<BBBHBBBB",
1025 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1026 0, WLAN_EID_WNMSLEEP, 0, WLAN_EID_TFS_RESP, 0)
1030 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element and empty TFS Response element")
1031 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1032 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1033 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1034 WNM_STATUS_SLEEP_ACCEPT, 0,
1035 WLAN_EID_TFS_RESP, 0)
1039 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(exit, deny key) and empty TFS Response element")
1040 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1041 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1042 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1043 WNM_STATUS_DENIED_KEY, 0,
1044 WLAN_EID_TFS_RESP, 0)
1048 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(enter, deny key) and empty TFS Response element")
1049 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1050 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1051 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1052 WNM_STATUS_DENIED_KEY, 0,
1053 WLAN_EID_TFS_RESP, 0)
1057 def test_wnm_action_proto_pmf(dev, apdev):
1058 """WNM Action protocol testing (PMF enabled)"""
1059 ssid = "test-wnm-pmf"
1060 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1061 params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1062 params["ieee80211w"] = "2"
1063 params['wnm_sleep_mode'] = '1'
1064 hapd = hostapd.add_ap(apdev[0], params)
1065 bssid = apdev[0]['bssid']
1066 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
1067 proto="WPA2", ieee80211w="2", scan_freq="2412")
1068 dev[0].request("WNM_SLEEP enter")
1070 hapd.set("ext_mgmt_frame_handling", "1")
1073 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1074 msg['da'] = dev[0].own_addr()
1076 msg['bssid'] = bssid
1078 logger.debug("WNM Sleep Mode Response - Invalid Key Data element length")
1079 keydata = struct.pack("<BB", 0, 1)
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 - Too short GTK subelem")
1092 keydata = struct.pack("<BB", WNM_SLEEP_SUBELEM_GTK, 0)
1093 msg['payload'] = struct.pack("<BBBH",
1094 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1096 msg['payload'] += keydata
1097 msg['payload'] += struct.pack("<BBBBHBB",
1098 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1099 WNM_STATUS_SLEEP_ACCEPT, 0,
1100 WLAN_EID_TFS_RESP, 0)
1104 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem")
1105 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1106 0, 17, 0, 0, 0, 0, 0, 0)
1107 msg['payload'] = struct.pack("<BBBH",
1108 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1110 msg['payload'] += keydata
1111 msg['payload'] += struct.pack("<BBBBHBB",
1112 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1113 WNM_STATUS_SLEEP_ACCEPT, 0,
1114 WLAN_EID_TFS_RESP, 0)
1118 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem (2)")
1119 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1120 0, 0, 0, 0, 0, 0, 0, 0)
1121 msg['payload'] = struct.pack("<BBBH",
1122 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1124 msg['payload'] += keydata
1125 msg['payload'] += struct.pack("<BBBBHBB",
1126 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1127 WNM_STATUS_SLEEP_ACCEPT, 0,
1128 WLAN_EID_TFS_RESP, 0)
1132 logger.debug("WNM Sleep Mode Response - GTK subelem and too short IGTK subelem")
1133 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1134 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1135 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1136 keydata += struct.pack("<BB", WNM_SLEEP_SUBELEM_IGTK, 0)
1137 msg['payload'] = struct.pack("<BBBH",
1138 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1140 msg['payload'] += keydata
1141 msg['payload'] += struct.pack("<BBBBHBB",
1142 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1143 WNM_STATUS_SLEEP_ACCEPT, 0,
1144 WLAN_EID_TFS_RESP, 0)
1148 logger.debug("WNM Sleep Mode Response - Unknown subelem")
1149 keydata = struct.pack("<BB", 255, 0)
1150 msg['payload'] = struct.pack("<BBBH",
1151 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1153 msg['payload'] += keydata
1154 msg['payload'] += struct.pack("<BBBBHBB",
1155 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1156 WNM_STATUS_SLEEP_ACCEPT, 0,
1157 WLAN_EID_TFS_RESP, 0)
1161 def test_wnm_action_proto_no_pmf(dev, apdev):
1162 """WNM Action protocol testing (PMF disabled)"""
1163 ssid = "test-wnm-no-pmf"
1164 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1165 params['wnm_sleep_mode'] = '1'
1166 hapd = hostapd.add_ap(apdev[0], params)
1167 bssid = apdev[0]['bssid']
1168 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1169 proto="WPA2", ieee80211w="0", scan_freq="2412")
1170 dev[0].request("WNM_SLEEP enter")
1172 hapd.set("ext_mgmt_frame_handling", "1")
1175 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1176 msg['da'] = dev[0].own_addr()
1178 msg['bssid'] = bssid
1180 logger.debug("WNM Sleep Mode Response - GTK subelem and IGTK subelem")
1181 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1182 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1183 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1184 keydata += struct.pack("<BBHLH4L", WNM_SLEEP_SUBELEM_IGTK, 2 + 6 + 16, 0,
1186 0xf1f2f3f4, 0xf5f6f7f8, 0xf9f0fafb, 0xfcfdfeff)
1187 msg['payload'] = struct.pack("<BBBH",
1188 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1190 msg['payload'] += keydata
1191 msg['payload'] += struct.pack("<BBBBHBB",
1192 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1193 WNM_STATUS_SLEEP_ACCEPT, 0,
1194 WLAN_EID_TFS_RESP, 0)
1198 ev = dev[0].wait_event(["WNM: Ignore Key Data"], timeout=5)
1200 raise Exception("Key Data not ignored")
1202 def test_wnm_bss_tm_req_with_mbo_ie(dev, apdev):
1203 """WNM BSS transition request with MBO IE and reassociation delay attribute"""
1204 ssid = "test-wnm-mbo"
1205 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1206 hapd = hostapd.add_ap(apdev[0], params)
1207 bssid = apdev[0]['bssid']
1208 if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
1209 raise Exception("Failed to set STA as cellular data capable")
1211 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1212 proto="WPA2", ieee80211w="0", scan_freq="2412")
1214 logger.debug("BTM request with MBO reassociation delay when disassoc imminent is not set")
1215 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=3:2:1"):
1216 raise Exception("BSS transition management succeeded unexpectedly")
1218 logger.debug("BTM request with invalid MBO transition reason code")
1219 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=10:2:1"):
1220 raise Exception("BSS transition management succeeded unexpectedly")
1222 logger.debug("BTM request with MBO reassociation retry delay of 5 seconds")
1223 if 'OK' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " disassoc_imminent=1 disassoc_timer=3 mbo=3:5:1"):
1224 raise Exception("BSS transition management command failed")
1226 ev = dev[0].wait_event(['MBO-CELL-PREFERENCE'], 1)
1227 if ev is None or "preference=1" not in ev:
1228 raise Exception("Timeout waiting for MBO-CELL-PREFERENCE event")
1230 ev = dev[0].wait_event(['MBO-TRANSITION-REASON'], 1)
1231 if ev is None or "reason=3" not in ev:
1232 raise Exception("Timeout waiting for MBO-TRANSITION-REASON event")
1234 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1236 raise Exception("No BSS Transition Management Response")
1237 if dev[0].own_addr() not in ev:
1238 raise Exception("Unexpected BSS Transition Management Response address")
1240 ev = dev[0].wait_event(['CTRL-EVENT-DISCONNECTED'], 5)
1242 raise Exception("Station did not disconnect although disassoc imminent was set")
1244 # Set the scan interval to make dev[0] look for connections
1245 if 'OK' not in dev[0].request("SCAN_INTERVAL 1"):
1246 raise Exception("Failed to set scan interval")
1248 # Make sure no connection is made during the retry delay
1249 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1251 raise Exception("Station connected before assoc retry delay was over")
1253 # After the assoc retry delay is over, we can reconnect
1254 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1256 raise Exception("Station did not connect after assoc retry delay is over")
1258 if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
1259 raise Exception("Failed to set STA as cellular data not-capable")
1261 def test_wnm_bss_transition_mgmt_query(dev, apdev):
1262 """WNM BSS Transition Management query"""
1263 params = { "ssid": "test-wnm",
1264 "bss_transition": "1" }
1265 hapd = hostapd.add_ap(apdev[0], params)
1266 params = { "ssid": "another" }
1267 hapd2 = hostapd.add_ap(apdev[1], params)
1269 dev[0].scan_for_bss(apdev[1]['bssid'], 2412)
1270 dev[0].scan_for_bss(apdev[0]['bssid'], 2412)
1272 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1273 dev[0].request("WNM_BSS_QUERY 0 list")
1275 ev = dev[0].wait_event(["WNM: BSS Transition Management Request"],
1278 raise Exception("No BSS Transition Management Request frame seen")
1280 ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1282 raise Exception("No BSS Transition Management Response frame seen")
1284 def test_wnm_bss_tm_security_mismatch(dev, apdev):
1285 """WNM BSS Transition Management and security mismatch"""
1286 params = { "ssid": "test-wnm",
1288 "wpa_key_mgmt": "WPA-PSK",
1289 "rsn_pairwise": "CCMP",
1290 "wpa_passphrase": "12345678",
1293 "bss_transition": "1" }
1294 hapd = hostapd.add_ap(apdev[0], params)
1296 params = { "ssid": "test-wnm",
1299 "bss_transition": "1" }
1300 hapd2 = hostapd.add_ap(apdev[1], params)
1302 dev[0].scan_for_bss(apdev[1]['bssid'], 2462)
1304 id = dev[0].connect("test-wnm", psk="12345678",
1305 bssid=apdev[0]['bssid'], scan_freq="2412")
1306 dev[0].set_network(id, "scan_freq", "")
1307 dev[0].set_network(id, "bssid", "")
1309 addr = dev[0].own_addr()
1310 dev[0].dump_monitor()
1312 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1313 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"):
1314 raise Exception("BSS_TM_REQ command failed")
1315 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1317 raise Exception("No BSS Transition Management Response")
1318 if "status_code=7" not in ev:
1319 raise Exception("Unexpected BSS transition request response: " + ev)
1321 def test_wnm_bss_tm_connect_cmd(dev, apdev):
1322 """WNM BSS Transition Management and cfg80211 connect command"""
1323 params = { "ssid": "test-wnm",
1326 "bss_transition": "1" }
1327 hapd = hostapd.add_ap(apdev[0], params)
1329 params = { "ssid": "test-wnm",
1332 "bss_transition": "1" }
1333 hapd2 = hostapd.add_ap(apdev[1], params)
1335 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1336 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
1338 wpas.scan_for_bss(apdev[1]['bssid'], 2462)
1340 id = wpas.connect("test-wnm", key_mgmt="NONE",
1341 bssid=apdev[0]['bssid'], scan_freq="2412")
1342 wpas.set_network(id, "scan_freq", "")
1343 wpas.set_network(id, "bssid", "")
1345 addr = wpas.own_addr()
1348 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1349 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"):
1350 raise Exception("BSS_TM_REQ command failed")
1351 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1353 raise Exception("No BSS Transition Management Response")
1354 if "status_code=0" not in ev:
1355 raise Exception("BSS transition request was not accepted: " + ev)
1356 if "target_bssid=" + apdev[1]['bssid'] not in ev:
1357 raise Exception("Unexpected target BSS: " + ev)
1358 ev = wpas.wait_event(["CTRL-EVENT-CONNECTED",
1359 "CTRL-EVENT-DISCONNECTED"], timeout=10)
1361 raise Exception("No reassociation seen")
1362 if "CTRL-EVENT-DISCONNECTED" in ev:
1363 #TODO: Uncomment this once kernel side changes for Connect command
1364 #reassociation are in upstream.
1365 #raise Exception("Unexpected disconnection reported")
1366 logger.info("Unexpected disconnection reported")
1367 ev = wpas.wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
1369 raise Exception("No reassociation seen")
1370 if apdev[1]['bssid'] not in ev:
1371 raise Exception("Unexpected reassociation target: " + ev)