tests: Do not use tabs for indentation
[mech_eap.git] / tests / hwsim / test_wnm.py
1 # WNM tests
2 # Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi>
3 #
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
6
7 import binascii
8 import struct
9 import time
10 import logging
11 logger = logging.getLogger()
12 import subprocess
13
14 import hostapd
15 from wpasupplicant import WpaSupplicant
16 from utils import alloc_fail, wait_fail_trigger
17 from wlantest import Wlantest
18
19 def test_wnm_bss_transition_mgmt(dev, apdev):
20     """WNM BSS Transition Management"""
21     params = { "ssid": "test-wnm",
22                "time_advertisement": "2",
23                "time_zone": "EST5",
24                "wnm_sleep_mode": "1",
25                "bss_transition": "1" }
26     hostapd.add_ap(apdev[0], params)
27
28     dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
29     dev[0].request("WNM_BSS_QUERY 0")
30
31 def test_wnm_disassoc_imminent(dev, apdev):
32     """WNM Disassociation Imminent"""
33     params = { "ssid": "test-wnm",
34                "time_advertisement": "2",
35                "time_zone": "EST5",
36                "wnm_sleep_mode": "1",
37                "bss_transition": "1" }
38     hapd = hostapd.add_ap(apdev[0], params)
39
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"])
44     if ev is None:
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"])
49     if ev is None:
50         raise Exception("Timeout while waiting for re-connection scan")
51
52 def test_wnm_ess_disassoc_imminent(dev, apdev):
53     """WNM ESS Disassociation Imminent"""
54     params = { "ssid": "test-wnm",
55                "time_advertisement": "2",
56                "time_zone": "EST5",
57                "wnm_sleep_mode": "1",
58                "bss_transition": "1" }
59     hapd = hostapd.add_ap(apdev[0], params)
60
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"])
65     if ev is None:
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"])
70     if ev is None:
71         raise Exception("Timeout while waiting for re-connection scan")
72
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)
80
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"])
86     if ev is None:
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"])
91     if ev is None:
92         raise Exception("Timeout while waiting for re-connection scan")
93
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")
99
100     logger.info("Going to WNM Sleep Mode")
101     extra = ""
102     if interval is not None:
103         extra += " interval=" + str(interval)
104     if tfs_req:
105         extra += " tfs_req=" + tfs_req
106     if "OK" not in dev.request("WNM_SLEEP enter" + extra):
107         raise Exception("WNM_SLEEP failed")
108     ok = False
109     for i in range(20):
110         time.sleep(0.1)
111         sta = hapd.get_sta(addr)
112         if "[WNM_SLEEP_MODE]" in sta['flags']:
113             ok = True
114             break
115     if not ok:
116         raise Exception("Station failed to enter WNM-Sleep Mode")
117
118     logger.info("Waking up from WNM Sleep Mode")
119     ok = False
120     dev.request("WNM_SLEEP exit")
121     for i in range(20):
122         time.sleep(0.1)
123         sta = hapd.get_sta(addr)
124         if "[WNM_SLEEP_MODE]" not in sta['flags']:
125             ok = True
126             break
127     if not ok:
128         raise Exception("Station failed to exit WNM-Sleep Mode")
129
130 def test_wnm_sleep_mode_open(dev, apdev):
131     """WNM Sleep Mode - open"""
132     params = { "ssid": "test-wnm",
133                "time_advertisement": "2",
134                "time_zone": "EST5",
135                "wnm_sleep_mode": "1",
136                "bss_transition": "1" }
137     hapd = hostapd.add_ap(apdev[0], params)
138
139     dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
140     ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
141     if ev is None:
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")
146
147     cmds = [ "foo",
148              "exit tfs_req=123 interval=10",
149              "enter tfs_req=qq interval=10" ]
150     for cmd in cmds:
151         if "FAIL" not in dev[0].request("WNM_SLEEP " + cmd):
152             raise Exception("Invalid WNM_SLEEP accepted")
153
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)
162
163     dev[0].connect("test-wnm-rsn", psk="12345678", scan_freq="2412")
164     ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
165     if ev is None:
166         raise Exception("No connection event received from hostapd")
167     check_wnm_sleep_mode_enter_exit(hapd, dev[0])
168
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)
174
175     dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
176     ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
177     if ev is None:
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")
185
186 def test_wnm_sleep_mode_rsn_pmf(dev, apdev):
187     """WNM Sleep Mode - RSN with PMF"""
188     wt = Wlantest()
189     wt.flush()
190     wt.add_passphrase("12345678")
191     params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
192     params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
193     params["ieee80211w"] = "2";
194     params["time_advertisement"] = "2"
195     params["time_zone"] = "EST5"
196     params["wnm_sleep_mode"] = "1"
197     params["bss_transition"] = "1"
198     hapd = hostapd.add_ap(apdev[0], params)
199
200     dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
201                    key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
202     ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
203     if ev is None:
204         raise Exception("No connection event received from hostapd")
205     check_wnm_sleep_mode_enter_exit(hapd, dev[0])
206
207 MGMT_SUBTYPE_ACTION = 13
208 ACTION_CATEG_WNM = 10
209 WNM_ACT_BSS_TM_REQ = 7
210 WNM_ACT_BSS_TM_RESP = 8
211 WNM_ACT_SLEEP_MODE_REQ = 16
212 WNM_ACT_SLEEP_MODE_RESP = 17
213 WNM_ACT_NOTIFICATION_REQ = 26
214 WNM_ACT_NOTIFICATION_RESP = 27
215 WNM_NOTIF_TYPE_FW_UPGRADE = 0
216 WNM_NOTIF_TYPE_WFA = 1
217 WLAN_EID_TFS_RESP = 92
218 WLAN_EID_WNMSLEEP = 93
219 WNM_SLEEP_MODE_ENTER = 0
220 WNM_SLEEP_MODE_EXIT = 1
221 WNM_STATUS_SLEEP_ACCEPT = 0
222 WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE = 1
223 WNM_STATUS_DENIED_ACTION = 2
224 WNM_STATUS_DENIED_TMP = 3
225 WNM_STATUS_DENIED_KEY = 4
226 WNM_STATUS_DENIED_OTHER_WNM_SERVICE = 5
227 WNM_SLEEP_SUBELEM_GTK = 0
228 WNM_SLEEP_SUBELEM_IGTK = 1
229
230 def bss_tm_req(dst, src, dialog_token=1, req_mode=0, disassoc_timer=0,
231                validity_interval=1):
232     msg = {}
233     msg['fc'] = MGMT_SUBTYPE_ACTION << 4
234     msg['da'] = dst
235     msg['sa'] = src
236     msg['bssid'] = src
237     msg['payload'] = struct.pack("<BBBBHB",
238                                  ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
239                                  dialog_token, req_mode, disassoc_timer,
240                                  validity_interval)
241     return msg
242
243 def rx_bss_tm_resp(hapd, expect_dialog=None, expect_status=None):
244     for i in range(0, 100):
245         resp = hapd.mgmt_rx()
246         if resp is None:
247             raise Exception("No BSS TM Response received")
248         if resp['subtype'] == MGMT_SUBTYPE_ACTION:
249             break
250     if i == 99:
251         raise Exception("Not an Action frame")
252     payload = resp['payload']
253     if len(payload) < 2 + 3:
254         raise Exception("Too short payload")
255     (category, action) = struct.unpack('BB', payload[0:2])
256     if category != ACTION_CATEG_WNM or action != WNM_ACT_BSS_TM_RESP:
257         raise Exception("Not a BSS TM Response")
258     pos = payload[2:]
259     (dialog, status, bss_term_delay) = struct.unpack('BBB', pos[0:3])
260     resp['dialog'] = dialog
261     resp['status'] = status
262     resp['bss_term_delay'] = bss_term_delay
263     pos = pos[3:]
264     if len(pos) >= 6 and status == 0:
265         resp['target_bssid'] = binascii.hexlify(pos[0:6])
266         pos = pos[6:]
267     resp['candidates'] = pos
268     if expect_dialog is not None and dialog != expect_dialog:
269         raise Exception("Unexpected dialog token")
270     if expect_status is not None and status != expect_status:
271         raise Exception("Unexpected status code %d" % status)
272     return resp
273
274 def expect_ack(hapd):
275     ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
276     if ev is None:
277         raise Exception("Missing TX status")
278     if "ok=1" not in ev:
279         raise Exception("Action frame not acknowledged")
280
281 def test_wnm_bss_tm_req(dev, apdev):
282     """BSS Transition Management Request"""
283     params = { "ssid": "test-wnm", "bss_transition": "1" }
284     hapd = hostapd.add_ap(apdev[0], params)
285     dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
286     hapd2 = hostapd.add_ap(apdev[1], params)
287
288     hapd.set("ext_mgmt_frame_handling", "1")
289
290     # truncated BSS TM Request
291     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
292                      req_mode=0x08)
293     req['payload'] = struct.pack("<BBBBH",
294                                  ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
295                                  1, 0, 0)
296     hapd.mgmt_tx(req)
297     expect_ack(hapd)
298
299     # no disassociation and no candidate list
300     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
301                      dialog_token=2)
302     hapd.mgmt_tx(req)
303     resp = rx_bss_tm_resp(hapd, expect_dialog=2, expect_status=1)
304
305     # truncated BSS Termination Duration
306     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
307                      req_mode=0x08)
308     hapd.mgmt_tx(req)
309     expect_ack(hapd)
310
311     # BSS Termination Duration with TSF=0 and Duration=10
312     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
313                      req_mode=0x08, dialog_token=3)
314     req['payload'] += struct.pack("<BBQH", 4, 10, 0, 10)
315     hapd.mgmt_tx(req)
316     resp = rx_bss_tm_resp(hapd, expect_dialog=3, expect_status=1)
317
318     # truncated Session Information URL
319     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
320                      req_mode=0x10)
321     hapd.mgmt_tx(req)
322     expect_ack(hapd)
323     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
324                      req_mode=0x10)
325     req['payload'] += struct.pack("<BBB", 3, 65, 66)
326     hapd.mgmt_tx(req)
327     expect_ack(hapd)
328
329     # Session Information URL
330     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
331                      req_mode=0x10, dialog_token=4)
332     req['payload'] += struct.pack("<BBB", 2, 65, 66)
333     hapd.mgmt_tx(req)
334     resp = rx_bss_tm_resp(hapd, expect_dialog=4, expect_status=0)
335
336     # Preferred Candidate List without any entries
337     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
338                      req_mode=0x01, dialog_token=5)
339     hapd.mgmt_tx(req)
340     resp = rx_bss_tm_resp(hapd, expect_dialog=5, expect_status=7)
341
342     # Preferred Candidate List with a truncated entry
343     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
344                      req_mode=0x01)
345     req['payload'] += struct.pack("<BB", 52, 1)
346     hapd.mgmt_tx(req)
347     expect_ack(hapd)
348
349     # Preferred Candidate List with a too short entry
350     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
351                      req_mode=0x01, dialog_token=6)
352     req['payload'] += struct.pack("<BB", 52, 0)
353     hapd.mgmt_tx(req)
354     resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
355
356     # Preferred Candidate List with a non-matching entry
357     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
358                      req_mode=0x01, dialog_token=6)
359     req['payload'] += struct.pack("<BB6BLBBB", 52, 13,
360                                   1, 2, 3, 4, 5, 6,
361                                   0, 81, 1, 7)
362     hapd.mgmt_tx(req)
363     resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
364
365     # Preferred Candidate List with a truncated subelement
366     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
367                      req_mode=0x01, dialog_token=7)
368     req['payload'] += struct.pack("<BB6BLBBBBB", 52, 13 + 2,
369                                   1, 2, 3, 4, 5, 6,
370                                   0, 81, 1, 7,
371                                   1, 1)
372     hapd.mgmt_tx(req)
373     resp = rx_bss_tm_resp(hapd, expect_dialog=7, expect_status=7)
374
375     # Preferred Candidate List with lots of invalid optional subelements
376     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
377                      req_mode=0x01, dialog_token=8)
378     subelems = struct.pack("<BBHB", 1, 3, 0, 100)
379     subelems += struct.pack("<BBB", 2, 1, 65)
380     subelems += struct.pack("<BB", 3, 0)
381     subelems += struct.pack("<BBQB", 4, 9, 0, 10)
382     subelems += struct.pack("<BBHLB", 5, 7, 0, 0, 0)
383     subelems += struct.pack("<BB", 66, 0)
384     subelems += struct.pack("<BBBBBB", 70, 4, 0, 0, 0, 0)
385     subelems += struct.pack("<BB", 71, 0)
386     req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
387                                   1, 2, 3, 4, 5, 6,
388                                   0, 81, 1, 7) + subelems
389     hapd.mgmt_tx(req)
390     resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
391
392     # Preferred Candidate List with lots of valid optional subelements (twice)
393     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
394                      req_mode=0x01, dialog_token=8)
395     # TSF Information
396     subelems = struct.pack("<BBHH", 1, 4, 0, 100)
397     # Condensed Country String
398     subelems += struct.pack("<BBBB", 2, 2, 65, 66)
399     # BSS Transition Candidate Preference
400     subelems += struct.pack("<BBB", 3, 1, 100)
401     # BSS Termination Duration
402     subelems += struct.pack("<BBQH", 4, 10, 0, 10)
403     # Bearing
404     subelems += struct.pack("<BBHLH", 5, 8, 0, 0, 0)
405     # Measurement Pilot Transmission
406     subelems += struct.pack("<BBBBB", 66, 3, 0, 0, 0)
407     # RM Enabled Capabilities
408     subelems += struct.pack("<BBBBBBB", 70, 5, 0, 0, 0, 0, 0)
409     # Multiple BSSID
410     subelems += struct.pack("<BBBB", 71, 2, 0, 0)
411     req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems) * 2,
412                                   1, 2, 3, 4, 5, 6,
413                                   0, 81, 1, 7) + subelems + subelems
414     hapd.mgmt_tx(req)
415     resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
416
417     # Preferred Candidate List followed by vendor element
418     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
419                      req_mode=0x01, dialog_token=8)
420     subelems = ""
421     req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
422                                   1, 2, 3, 4, 5, 6,
423                                   0, 81, 1, 7) + subelems
424     req['payload'] += binascii.unhexlify("DD0411223344")
425     hapd.mgmt_tx(req)
426     resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
427
428 def test_wnm_bss_keep_alive(dev, apdev):
429     """WNM keep-alive"""
430     params = { "ssid": "test-wnm",
431                "ap_max_inactivity": "1" }
432     hapd = hostapd.add_ap(apdev[0], params)
433
434     addr = dev[0].p2p_interface_addr()
435     dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
436     start = hapd.get_sta(addr)
437     ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=2)
438     if ev is not None:
439         raise Exception("Unexpected disconnection")
440     end = hapd.get_sta(addr)
441     if int(end['rx_packets']) <= int(start['rx_packets']):
442         raise Exception("No keep-alive packets received")
443     try:
444         # Disable client keep-alive so that hostapd will verify connection
445         # with client poll
446         dev[0].request("SET no_keep_alive 1")
447         for i in range(60):
448             sta = hapd.get_sta(addr)
449             logger.info("timeout_next=%s rx_packets=%s tx_packets=%s" % (sta['timeout_next'], sta['rx_packets'], sta['tx_packets']))
450             if i > 1 and sta['timeout_next'] != "NULLFUNC POLL" and int(sta['tx_packets']) > int(end['tx_packets']):
451                 break
452             ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
453             if ev is not None:
454                 raise Exception("Unexpected disconnection (client poll expected)")
455     finally:
456         dev[0].request("SET no_keep_alive 0")
457     if int(sta['tx_packets']) <= int(end['tx_packets']):
458         raise Exception("No client poll packet seen")
459
460 def test_wnm_bss_tm(dev, apdev):
461     """WNM BSS Transition Management"""
462     try:
463         hapd = None
464         hapd2 = None
465         params = { "ssid": "test-wnm",
466                    "country_code": "FI",
467                    "ieee80211d": "1",
468                    "hw_mode": "g",
469                    "channel": "1",
470                    "bss_transition": "1" }
471         hapd = hostapd.add_ap(apdev[0], params)
472
473         id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
474         dev[0].set_network(id, "scan_freq", "")
475
476         params = { "ssid": "test-wnm",
477                    "country_code": "FI",
478                    "ieee80211d": "1",
479                    "hw_mode": "a",
480                    "channel": "36",
481                    "bss_transition": "1" }
482         hapd2 = hostapd.add_ap(apdev[1], params)
483
484         addr = dev[0].p2p_interface_addr()
485         dev[0].dump_monitor()
486
487         logger.info("No neighbor list entries")
488         if "OK" not in hapd.request("BSS_TM_REQ " + addr):
489             raise Exception("BSS_TM_REQ command failed")
490         ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
491         if ev is None:
492             raise Exception("No BSS Transition Management Response")
493         if addr not in ev:
494             raise Exception("Unexpected BSS Transition Management Response address")
495         if "status_code=0" in ev:
496             raise Exception("BSS transition accepted unexpectedly")
497         dev[0].dump_monitor()
498
499         logger.info("Neighbor list entry, but not claimed as Preferred Candidate List")
500         if "OK" not in hapd.request("BSS_TM_REQ " + addr + " neighbor=11:22:33:44:55:66,0x0000,81,3,7"):
501             raise Exception("BSS_TM_REQ command failed")
502         ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
503         if ev is None:
504             raise Exception("No BSS Transition Management Response")
505         if "status_code=0" in ev:
506             raise Exception("BSS transition accepted unexpectedly")
507         dev[0].dump_monitor()
508
509         logger.info("Preferred Candidate List (no matching neighbor) without Disassociation Imminent")
510         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"):
511             raise Exception("BSS_TM_REQ command failed")
512         ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
513         if ev is None:
514             raise Exception("No BSS Transition Management Response")
515         if "status_code=0" in ev:
516             raise Exception("BSS transition accepted unexpectedly")
517         ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
518         if ev is None:
519             raise Exception("No scan started")
520         dev[0].dump_monitor()
521
522         logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
523         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"):
524             raise Exception("BSS_TM_REQ command failed")
525         ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
526         if ev is None:
527             raise Exception("No BSS Transition Management Response")
528         if "status_code=0" not in ev:
529             raise Exception("BSS transition request was not accepted: " + ev)
530         if "target_bssid=" + apdev[1]['bssid'] not in ev:
531             raise Exception("Unexpected target BSS: " + ev)
532         dev[0].wait_connected(timeout=15, error="No reassociation seen")
533         if apdev[1]['bssid'] not in ev:
534             raise Exception("Unexpected reassociation target: " + ev)
535         ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
536         if ev is not None:
537             raise Exception("Unexpected scan started")
538         dev[0].dump_monitor()
539
540         logger.info("Preferred Candidate List with two matches, no roam needed")
541         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"):
542             raise Exception("BSS_TM_REQ command failed")
543         ev = hapd2.wait_event(['BSS-TM-RESP'], timeout=10)
544         if ev is None:
545             raise Exception("No BSS Transition Management Response")
546         if "status_code=0" not in ev:
547             raise Exception("BSS transition request was not accepted: " + ev)
548         if "target_bssid=" + apdev[1]['bssid'] not in ev:
549             raise Exception("Unexpected target BSS: " + ev)
550         ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
551         if ev is not None:
552             raise Exception("Unexpected scan started")
553         ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
554         if ev is not None:
555             raise Exception("Unexpected reassociation");
556     finally:
557         dev[0].request("DISCONNECT")
558         if hapd:
559             hapd.request("DISABLE")
560         if hapd2:
561             hapd2.request("DISABLE")
562         subprocess.call(['iw', 'reg', 'set', '00'])
563         dev[0].flush_scan_cache()
564
565 def test_wnm_bss_tm_scan_not_needed(dev, apdev):
566     """WNM BSS Transition Management and scan not needed"""
567     run_wnm_bss_tm_scan_not_needed(dev, apdev)
568
569 def test_wnm_bss_tm_nei_vht(dev, apdev):
570     """WNM BSS Transition Management and VHT neighbor"""
571     run_wnm_bss_tm_scan_not_needed(dev, apdev, vht=True, nei_info="115,36,9")
572
573 def test_wnm_bss_tm_nei_11a(dev, apdev):
574     """WNM BSS Transition Management and 11a neighbor"""
575     run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, nei_info="115,36,4")
576
577 def test_wnm_bss_tm_nei_11g(dev, apdev):
578     """WNM BSS Transition Management and 11g neighbor"""
579     run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, hwmode='g',
580                                    channel='2', freq=2417, nei_info="81,2,6")
581
582 def test_wnm_bss_tm_nei_11b(dev, apdev):
583     """WNM BSS Transition Management and 11g neighbor"""
584     run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, hwmode='b',
585                                    channel='3', freq=2422, nei_info="81,2,5")
586
587 def run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=True, vht=False, hwmode='a',
588                                    channel='36', freq=5180,
589                                    nei_info="115,36,7,0301ff"):
590     try:
591         hapd = None
592         hapd2 = None
593         params = { "ssid": "test-wnm",
594                    "country_code": "FI",
595                    "ieee80211d": "1",
596                    "hw_mode": "g",
597                    "channel": "1",
598                    "bss_transition": "1" }
599         hapd = hostapd.add_ap(apdev[0], params)
600
601         params = { "ssid": "test-wnm",
602                    "country_code": "FI",
603                    "ieee80211d": "1",
604                    "hw_mode": hwmode,
605                    "channel": channel,
606                    "bss_transition": "1" }
607         if not ht:
608             params['ieee80211n'] = '0'
609         if vht:
610             params['ieee80211ac'] = "1"
611             params["vht_oper_chwidth"] = "0"
612             params["vht_oper_centr_freq_seg0_idx"] = "0"
613
614         hapd2 = hostapd.add_ap(apdev[1], params)
615
616         dev[0].scan_for_bss(apdev[1]['bssid'], freq)
617
618         id = dev[0].connect("test-wnm", key_mgmt="NONE",
619                             bssid=apdev[0]['bssid'], scan_freq="2412")
620         dev[0].set_network(id, "scan_freq", "")
621         dev[0].set_network(id, "bssid", "")
622
623         addr = dev[0].own_addr()
624         dev[0].dump_monitor()
625
626         logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
627         if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000," + nei_info):
628             raise Exception("BSS_TM_REQ command failed")
629         ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
630         if ev is None:
631             raise Exception("No BSS Transition Management Response")
632         if "status_code=0" not in ev:
633             raise Exception("BSS transition request was not accepted: " + ev)
634         if "target_bssid=" + apdev[1]['bssid'] not in ev:
635             raise Exception("Unexpected target BSS: " + ev)
636         dev[0].wait_connected(timeout=15, error="No reassociation seen")
637         if apdev[1]['bssid'] not in ev:
638             raise Exception("Unexpected reassociation target: " + ev)
639         ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
640         if ev is not None:
641             raise Exception("Unexpected scan started")
642         dev[0].dump_monitor()
643     finally:
644         dev[0].request("DISCONNECT")
645         if hapd:
646             hapd.request("DISABLE")
647         if hapd2:
648             hapd2.request("DISABLE")
649         subprocess.call(['iw', 'reg', 'set', '00'])
650         dev[0].flush_scan_cache()
651
652 def test_wnm_bss_tm_scan_needed(dev, apdev):
653     """WNM BSS Transition Management and scan needed"""
654     try:
655         hapd = None
656         hapd2 = None
657         params = { "ssid": "test-wnm",
658                    "country_code": "FI",
659                    "ieee80211d": "1",
660                    "hw_mode": "g",
661                    "channel": "1",
662                    "bss_transition": "1" }
663         hapd = hostapd.add_ap(apdev[0], params)
664
665         params = { "ssid": "test-wnm",
666                    "country_code": "FI",
667                    "ieee80211d": "1",
668                    "hw_mode": "a",
669                    "channel": "36",
670                    "bss_transition": "1" }
671         hapd2 = hostapd.add_ap(apdev[1], params)
672
673         dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
674
675         id = dev[0].connect("test-wnm", key_mgmt="NONE",
676                             bssid=apdev[0]['bssid'], scan_freq="2412")
677         dev[0].set_network(id, "scan_freq", "")
678         dev[0].set_network(id, "bssid", "")
679
680         addr = dev[0].own_addr()
681         dev[0].dump_monitor()
682
683         logger.info("Wait 11 seconds for the last scan result to be too old, but still present in BSS table")
684         time.sleep(11)
685         logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
686         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"):
687             raise Exception("BSS_TM_REQ command failed")
688         ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
689         if ev is None:
690             raise Exception("No BSS Transition Management Response")
691         if "status_code=0" not in ev:
692             raise Exception("BSS transition request was not accepted: " + ev)
693         if "target_bssid=" + apdev[1]['bssid'] not in ev:
694             raise Exception("Unexpected target BSS: " + ev)
695         dev[0].wait_connected(timeout=15, error="No reassociation seen")
696         if apdev[1]['bssid'] not in ev:
697             raise Exception("Unexpected reassociation target: " + ev)
698         ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
699         if ev is not None:
700             raise Exception("Unexpected scan started")
701         dev[0].dump_monitor()
702     finally:
703         dev[0].request("DISCONNECT")
704         if hapd:
705             hapd.request("DISABLE")
706         if hapd2:
707             hapd2.request("DISABLE")
708         subprocess.call(['iw', 'reg', 'set', '00'])
709         dev[0].flush_scan_cache()
710
711 def start_wnm_tm(ap, country, dev):
712     params = { "ssid": "test-wnm",
713                "country_code": country,
714                "ieee80211d": "1",
715                "hw_mode": "g",
716                "channel": "1",
717                "bss_transition": "1" }
718     hapd = hostapd.add_ap(ap, params)
719     id = dev.connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
720     dev.dump_monitor()
721     dev.set_network(id, "scan_freq", "")
722     return hapd, id
723
724 def stop_wnm_tm(hapd, dev):
725     dev.request("DISCONNECT")
726     try:
727         dev.wait_disconnected()
728     except:
729         pass
730     if hapd:
731         hapd.request("DISABLE")
732     subprocess.call(['iw', 'reg', 'set', '00'])
733     dev.flush_scan_cache()
734
735 def wnm_bss_tm_check(hapd, dev, data):
736     addr = dev.p2p_interface_addr()
737     if "OK" not in hapd.request("BSS_TM_REQ " + addr + " " + data):
738         raise Exception("BSS_TM_REQ command failed")
739     ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
740     if ev is None:
741         raise Exception("No scan started")
742     ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
743     if ev is None:
744         raise Exception("Scan did not complete")
745
746     ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
747     if ev is None:
748         raise Exception("No BSS Transition Management Response")
749     if "status_code=7" not in ev:
750         raise Exception("Unexpected response: " + ev)
751
752 def test_wnm_bss_tm_country_us(dev, apdev):
753     """WNM BSS Transition Management (US)"""
754     try:
755         hapd = None
756         hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
757
758         logger.info("Preferred Candidate List (no matching neighbor, known channels)")
759         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")
760
761         # Make the test take less time by limiting full scans
762         dev[0].set_network(id, "scan_freq", "2412")
763         logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
764         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")
765
766         logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
767         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")
768     finally:
769         stop_wnm_tm(hapd, dev[0])
770
771 def test_wnm_bss_tm_country_fi(dev, apdev):
772     """WNM BSS Transition Management (FI)"""
773     addr = dev[0].p2p_interface_addr()
774     try:
775         hapd = None
776         hapd, id = start_wnm_tm(apdev[0], "FI", dev[0])
777
778         logger.info("Preferred Candidate List (no matching neighbor, known channels)")
779         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")
780
781         # Make the test take less time by limiting full scans
782         dev[0].set_network(id, "scan_freq", "2412")
783         logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
784         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")
785
786         logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
787         wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,0,0,7")
788     finally:
789         stop_wnm_tm(hapd, dev[0])
790
791 def test_wnm_bss_tm_country_jp(dev, apdev):
792     """WNM BSS Transition Management (JP)"""
793     addr = dev[0].p2p_interface_addr()
794     try:
795         hapd = None
796         hapd, id = start_wnm_tm(apdev[0], "JP", dev[0])
797
798         logger.info("Preferred Candidate List (no matching neighbor, known channels)")
799         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")
800
801         # Make the test take less time by limiting full scans
802         dev[0].set_network(id, "scan_freq", "2412")
803         logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
804         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")
805     finally:
806         stop_wnm_tm(hapd, dev[0])
807
808 def test_wnm_bss_tm_country_cn(dev, apdev):
809     """WNM BSS Transition Management (CN)"""
810     addr = dev[0].p2p_interface_addr()
811     try:
812         hapd = None
813         hapd, id = start_wnm_tm(apdev[0], "CN", dev[0])
814
815         logger.info("Preferred Candidate List (no matching neighbor, known channels)")
816         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")
817
818         # Make the test take less time by limiting full scans
819         dev[0].set_network(id, "scan_freq", "2412")
820         logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
821         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")
822     finally:
823         stop_wnm_tm(hapd, dev[0])
824
825 def test_wnm_bss_tm_global(dev, apdev):
826     """WNM BSS Transition Management (global)"""
827     addr = dev[0].p2p_interface_addr()
828     try:
829         hapd = None
830         hapd, id = start_wnm_tm(apdev[0], "XX", dev[0])
831
832         logger.info("Preferred Candidate List (no matching neighbor, known channels)")
833         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")
834
835         # Make the test take less time by limiting full scans
836         dev[0].set_network(id, "scan_freq", "2412")
837         logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
838         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")
839
840         logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
841         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")
842     finally:
843         stop_wnm_tm(hapd, dev[0])
844
845 def test_wnm_bss_tm_op_class_0(dev, apdev):
846     """WNM BSS Transition Management with invalid operating class"""
847     try:
848         hapd = None
849         hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
850
851         logger.info("Preferred Candidate List (no matching neighbor, invalid op class specified for channels)")
852         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")
853     finally:
854         stop_wnm_tm(hapd, dev[0])
855
856 def test_wnm_action_proto(dev, apdev):
857     """WNM Action protocol testing"""
858     params = { "ssid": "test-wnm" }
859     params['wnm_sleep_mode'] = '1'
860     hapd = hostapd.add_ap(apdev[0], params)
861     bssid = apdev[0]['bssid']
862     dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
863     dev[0].request("WNM_SLEEP enter")
864     time.sleep(0.1)
865     hapd.set("ext_mgmt_frame_handling", "1")
866
867     msg = {}
868     msg['fc'] = MGMT_SUBTYPE_ACTION << 4
869     msg['da'] = dev[0].own_addr()
870     msg['sa'] = bssid
871     msg['bssid'] = bssid
872
873     dialog_token = 1
874
875     logger.debug("Unexpected WNM-Notification Response")
876     # Note: This is actually not registered for user space processing in
877     # driver_nl80211.c nl80211_mgmt_subscribe_non_ap() and as such, won't make
878     # it to wpa_supplicant.
879     msg['payload'] = struct.pack("<BBBB",
880                                  ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_RESP,
881                                  dialog_token, 0)
882     hapd.mgmt_tx(msg)
883     expect_ack(hapd)
884
885     logger.debug("Truncated WNM-Notification Request (no Type field)")
886     msg['payload'] = struct.pack("<BBB",
887                                  ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
888                                  dialog_token)
889     hapd.mgmt_tx(msg)
890     expect_ack(hapd)
891
892     logger.debug("WFA WNM-Notification Request with truncated IE (min)")
893     msg['payload'] = struct.pack("<BBBBBB",
894                                  ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
895                                  dialog_token, WNM_NOTIF_TYPE_WFA, 0, 1)
896     hapd.mgmt_tx(msg)
897     expect_ack(hapd)
898
899     logger.debug("WFA WNM-Notification Request with truncated IE (max)")
900     msg['payload'] = struct.pack("<BBBBBB",
901                                  ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
902                                  dialog_token, WNM_NOTIF_TYPE_WFA, 0, 255)
903     hapd.mgmt_tx(msg)
904     expect_ack(hapd)
905
906     logger.debug("WFA WNM-Notification Request with too short IE")
907     msg['payload'] = struct.pack("<BBBBBB",
908                                  ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
909                                  dialog_token, WNM_NOTIF_TYPE_WFA, 0, 0)
910     hapd.mgmt_tx(msg)
911     expect_ack(hapd)
912
913     logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL")
914     msg['payload'] = struct.pack(">BBBBBBLB",
915                                  ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
916                                  dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
917                                  0x506f9a00, 1)
918     hapd.mgmt_tx(msg)
919     expect_ack(hapd)
920
921     logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(2)")
922     msg['payload'] = struct.pack(">BBBBBBLBB",
923                                  ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
924                                  dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 6,
925                                  0x506f9a00, 1, 0)
926     hapd.mgmt_tx(msg)
927     expect_ack(hapd)
928
929     logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(3)")
930     msg['payload'] = struct.pack(">BBBBBBLB",
931                                  ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
932                                  dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
933                                  0x506f9a00, 0xff)
934     hapd.mgmt_tx(msg)
935     expect_ack(hapd)
936
937     logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(min)")
938     msg['payload'] = struct.pack(">BBBBBBLBHB",
939                                  ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
940                                  dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
941                                  0x506f9a01, 0, 0, 1)
942     hapd.mgmt_tx(msg)
943     expect_ack(hapd)
944
945     logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(max)")
946     msg['payload'] = struct.pack(">BBBBBBLBHB",
947                                  ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
948                                  dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
949                                  0x506f9a01, 0, 0, 0xff)
950     hapd.mgmt_tx(msg)
951     expect_ack(hapd)
952
953     logger.debug("WFA WNM-Notification Request with unsupported IE")
954     msg['payload'] = struct.pack("<BBBBBBL",
955                                  ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
956                                  dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 4, 0)
957     hapd.mgmt_tx(msg)
958     expect_ack(hapd)
959
960     logger.debug("WNM-Notification Request with unknown WNM-Notification type 0")
961     msg['payload'] = struct.pack("<BBBB",
962                                  ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
963                                  dialog_token, WNM_NOTIF_TYPE_FW_UPGRADE)
964     hapd.mgmt_tx(msg)
965     expect_ack(hapd)
966
967     logger.debug("Truncated WNM Sleep Mode Response - no Dialog Token")
968     msg['payload'] = struct.pack("<BB",
969                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP)
970     hapd.mgmt_tx(msg)
971     expect_ack(hapd)
972
973     logger.debug("Truncated WNM Sleep Mode Response - no Key Data Length")
974     msg['payload'] = struct.pack("<BBB",
975                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0)
976     hapd.mgmt_tx(msg)
977     expect_ack(hapd)
978
979     logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (min)")
980     msg['payload'] = struct.pack("<BBBH",
981                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
982                                  1)
983     hapd.mgmt_tx(msg)
984     expect_ack(hapd)
985
986     logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (max)")
987     msg['payload'] = struct.pack("<BBBH",
988                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
989                                  0xffff)
990     hapd.mgmt_tx(msg)
991     expect_ack(hapd)
992
993     logger.debug("WNM Sleep Mode Response - truncated IE header")
994     msg['payload'] = struct.pack("<BBBHB",
995                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
996                                  0, 0)
997     hapd.mgmt_tx(msg)
998     expect_ack(hapd)
999
1000     logger.debug("WNM Sleep Mode Response - truncated IE")
1001     msg['payload'] = struct.pack("<BBBHBB",
1002                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1003                                  0, 0, 1)
1004     hapd.mgmt_tx(msg)
1005     expect_ack(hapd)
1006
1007     logger.debug("WNM Sleep Mode Response - Empty TFS Response")
1008     msg['payload'] = struct.pack("<BBBHBB",
1009                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1010                                  0, WLAN_EID_TFS_RESP, 0)
1011     hapd.mgmt_tx(msg)
1012     expect_ack(hapd)
1013
1014     logger.debug("WNM Sleep Mode Response - EID 0 not recognized")
1015     msg['payload'] = struct.pack("<BBBHBB",
1016                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1017                                  0, 0, 0)
1018     hapd.mgmt_tx(msg)
1019     expect_ack(hapd)
1020
1021     logger.debug("WNM Sleep Mode Response - Empty WNM Sleep Mode element and TFS Response element")
1022     msg['payload'] = struct.pack("<BBBHBBBB",
1023                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1024                                  0, WLAN_EID_WNMSLEEP, 0, WLAN_EID_TFS_RESP, 0)
1025     hapd.mgmt_tx(msg)
1026     expect_ack(hapd)
1027
1028     logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element and empty TFS Response element")
1029     msg['payload'] = struct.pack("<BBBHBBBBHBB",
1030                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1031                                  0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1032                                  WNM_STATUS_SLEEP_ACCEPT, 0,
1033                                  WLAN_EID_TFS_RESP, 0)
1034     hapd.mgmt_tx(msg)
1035     expect_ack(hapd)
1036
1037     logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(exit, deny key) and empty TFS Response element")
1038     msg['payload'] = struct.pack("<BBBHBBBBHBB",
1039                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1040                                  0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1041                                  WNM_STATUS_DENIED_KEY, 0,
1042                                  WLAN_EID_TFS_RESP, 0)
1043     hapd.mgmt_tx(msg)
1044     expect_ack(hapd)
1045
1046     logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(enter, deny key) and empty TFS Response element")
1047     msg['payload'] = struct.pack("<BBBHBBBBHBB",
1048                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1049                                  0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1050                                  WNM_STATUS_DENIED_KEY, 0,
1051                                  WLAN_EID_TFS_RESP, 0)
1052     hapd.mgmt_tx(msg)
1053     expect_ack(hapd)
1054
1055 def test_wnm_action_proto_pmf(dev, apdev):
1056     """WNM Action protocol testing (PMF enabled)"""
1057     ssid = "test-wnm-pmf"
1058     params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1059     params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1060     params["ieee80211w"] = "2"
1061     params['wnm_sleep_mode'] = '1'
1062     hapd = hostapd.add_ap(apdev[0], params)
1063     bssid = apdev[0]['bssid']
1064     dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
1065                    proto="WPA2", ieee80211w="2", scan_freq="2412")
1066     dev[0].request("WNM_SLEEP enter")
1067     time.sleep(0.1)
1068     hapd.set("ext_mgmt_frame_handling", "1")
1069
1070     msg = {}
1071     msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1072     msg['da'] = dev[0].own_addr()
1073     msg['sa'] = bssid
1074     msg['bssid'] = bssid
1075
1076     logger.debug("WNM Sleep Mode Response - Invalid Key Data element length")
1077     keydata = struct.pack("<BB", 0, 1)
1078     msg['payload'] = struct.pack("<BBBH",
1079                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1080                                  len(keydata))
1081     msg['payload'] += keydata
1082     msg['payload'] += struct.pack("<BBBBHBB",
1083                                   WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1084                                   WNM_STATUS_SLEEP_ACCEPT, 0,
1085                                   WLAN_EID_TFS_RESP, 0)
1086     hapd.mgmt_tx(msg)
1087     expect_ack(hapd)
1088
1089     logger.debug("WNM Sleep Mode Response - Too short GTK subelem")
1090     keydata = struct.pack("<BB", WNM_SLEEP_SUBELEM_GTK, 0)
1091     msg['payload'] = struct.pack("<BBBH",
1092                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1093                                  len(keydata))
1094     msg['payload'] += keydata
1095     msg['payload'] += struct.pack("<BBBBHBB",
1096                                   WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1097                                   WNM_STATUS_SLEEP_ACCEPT, 0,
1098                                   WLAN_EID_TFS_RESP, 0)
1099     hapd.mgmt_tx(msg)
1100     expect_ack(hapd)
1101
1102     logger.debug("WNM Sleep Mode Response - Invalid GTK subelem")
1103     keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1104                           0, 17, 0, 0, 0, 0, 0, 0)
1105     msg['payload'] = struct.pack("<BBBH",
1106                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1107                                  len(keydata))
1108     msg['payload'] += keydata
1109     msg['payload'] += struct.pack("<BBBBHBB",
1110                                   WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1111                                   WNM_STATUS_SLEEP_ACCEPT, 0,
1112                                   WLAN_EID_TFS_RESP, 0)
1113     hapd.mgmt_tx(msg)
1114     expect_ack(hapd)
1115
1116     logger.debug("WNM Sleep Mode Response - Invalid GTK subelem (2)")
1117     keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1118                           0, 0, 0, 0, 0, 0, 0, 0)
1119     msg['payload'] = struct.pack("<BBBH",
1120                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1121                                  len(keydata))
1122     msg['payload'] += keydata
1123     msg['payload'] += struct.pack("<BBBBHBB",
1124                                   WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1125                                   WNM_STATUS_SLEEP_ACCEPT, 0,
1126                                   WLAN_EID_TFS_RESP, 0)
1127     hapd.mgmt_tx(msg)
1128     expect_ack(hapd)
1129
1130     logger.debug("WNM Sleep Mode Response - GTK subelem and too short IGTK subelem")
1131     keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1132     keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1133                            0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1134     keydata += struct.pack("<BB", WNM_SLEEP_SUBELEM_IGTK, 0)
1135     msg['payload'] = struct.pack("<BBBH",
1136                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1137                                  len(keydata))
1138     msg['payload'] += keydata
1139     msg['payload'] += struct.pack("<BBBBHBB",
1140                                   WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1141                                   WNM_STATUS_SLEEP_ACCEPT, 0,
1142                                   WLAN_EID_TFS_RESP, 0)
1143     hapd.mgmt_tx(msg)
1144     expect_ack(hapd)
1145
1146     logger.debug("WNM Sleep Mode Response - Unknown subelem")
1147     keydata = struct.pack("<BB", 255, 0)
1148     msg['payload'] = struct.pack("<BBBH",
1149                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1150                                  len(keydata))
1151     msg['payload'] += keydata
1152     msg['payload'] += struct.pack("<BBBBHBB",
1153                                   WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1154                                   WNM_STATUS_SLEEP_ACCEPT, 0,
1155                                   WLAN_EID_TFS_RESP, 0)
1156     hapd.mgmt_tx(msg)
1157     expect_ack(hapd)
1158
1159 def test_wnm_action_proto_no_pmf(dev, apdev):
1160     """WNM Action protocol testing (PMF disabled)"""
1161     ssid = "test-wnm-no-pmf"
1162     params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1163     params['wnm_sleep_mode'] = '1'
1164     hapd = hostapd.add_ap(apdev[0], params)
1165     bssid = apdev[0]['bssid']
1166     dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1167                    proto="WPA2", ieee80211w="0", scan_freq="2412")
1168     dev[0].request("WNM_SLEEP enter")
1169     time.sleep(0.1)
1170     hapd.set("ext_mgmt_frame_handling", "1")
1171
1172     msg = {}
1173     msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1174     msg['da'] = dev[0].own_addr()
1175     msg['sa'] = bssid
1176     msg['bssid'] = bssid
1177
1178     logger.debug("WNM Sleep Mode Response - GTK subelem and IGTK subelem")
1179     keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1180     keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1181                            0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1182     keydata += struct.pack("<BBHLH4L", WNM_SLEEP_SUBELEM_IGTK, 2 + 6 + 16, 0,
1183                            0x10203040, 0x5060,
1184                            0xf1f2f3f4, 0xf5f6f7f8, 0xf9f0fafb, 0xfcfdfeff)
1185     msg['payload'] = struct.pack("<BBBH",
1186                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1187                                  len(keydata))
1188     msg['payload'] += keydata
1189     msg['payload'] += struct.pack("<BBBBHBB",
1190                                   WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1191                                   WNM_STATUS_SLEEP_ACCEPT, 0,
1192                                   WLAN_EID_TFS_RESP, 0)
1193     hapd.mgmt_tx(msg)
1194     expect_ack(hapd)
1195
1196     ev = dev[0].wait_event(["WNM: Ignore Key Data"], timeout=5)
1197     if ev is None:
1198         raise Exception("Key Data not ignored")
1199
1200 def test_wnm_bss_tm_req_with_mbo_ie(dev, apdev):
1201     """WNM BSS transition request with MBO IE and reassociation delay attribute"""
1202     ssid = "test-wnm-mbo"
1203     params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1204     hapd = hostapd.add_ap(apdev[0], params)
1205     bssid = apdev[0]['bssid']
1206     if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
1207         raise Exception("Failed to set STA as cellular data capable")
1208
1209     dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1210                    proto="WPA2", ieee80211w="0", scan_freq="2412")
1211
1212     logger.debug("BTM request with MBO reassociation delay when disassoc imminent is not set")
1213     if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=3:2:1"):
1214         raise Exception("BSS transition management succeeded unexpectedly")
1215
1216     logger.debug("BTM request with invalid MBO transition reason code")
1217     if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=10:2:1"):
1218         raise Exception("BSS transition management succeeded unexpectedly")
1219
1220     logger.debug("BTM request with MBO reassociation retry delay of 5 seconds")
1221     if 'OK' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " disassoc_imminent=1 disassoc_timer=3 mbo=3:5:1"):
1222         raise Exception("BSS transition management command failed")
1223
1224     ev = dev[0].wait_event(['MBO-CELL-PREFERENCE'], 1)
1225     if ev is None or "preference=1" not in ev:
1226         raise Exception("Timeout waiting for MBO-CELL-PREFERENCE event")
1227
1228     ev = dev[0].wait_event(['MBO-TRANSITION-REASON'], 1)
1229     if ev is None or "reason=3" not in ev:
1230         raise Exception("Timeout waiting for MBO-TRANSITION-REASON event")
1231
1232     ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1233     if ev is None:
1234         raise Exception("No BSS Transition Management Response")
1235     if dev[0].own_addr() not in ev:
1236         raise Exception("Unexpected BSS Transition Management Response address")
1237
1238     ev = dev[0].wait_event(['CTRL-EVENT-DISCONNECTED'], 5)
1239     if ev is None:
1240         raise Exception("Station did not disconnect although disassoc imminent was set")
1241
1242     # Set the scan interval to make dev[0] look for connections
1243     if 'OK' not in dev[0].request("SCAN_INTERVAL 1"):
1244         raise Exception("Failed to set scan interval")
1245
1246     # Make sure no connection is made during the retry delay
1247     ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1248     if ev is not None:
1249         raise Exception("Station connected before assoc retry delay was over")
1250
1251     # After the assoc retry delay is over, we can reconnect
1252     ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1253     if ev is None:
1254         raise Exception("Station did not connect after assoc retry delay is over")
1255
1256     if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
1257         raise Exception("Failed to set STA as cellular data not-capable")
1258
1259 def test_wnm_bss_transition_mgmt_query(dev, apdev):
1260     """WNM BSS Transition Management query"""
1261     params = { "ssid": "test-wnm",
1262                "bss_transition": "1" }
1263     hapd = hostapd.add_ap(apdev[0], params)
1264     params = { "ssid": "another" }
1265     hapd2 = hostapd.add_ap(apdev[1], params)
1266
1267     dev[0].scan_for_bss(apdev[1]['bssid'], 2412)
1268     dev[0].scan_for_bss(apdev[0]['bssid'], 2412)
1269
1270     dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1271     dev[0].request("WNM_BSS_QUERY 0 list")
1272
1273     ev = dev[0].wait_event(["WNM: BSS Transition Management Request"],
1274                            timeout=5)
1275     if ev is None:
1276         raise Exception("No BSS Transition Management Request frame seen")
1277
1278     ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1279     if ev is None:
1280         raise Exception("No BSS Transition Management Response frame seen")
1281
1282 def test_wnm_bss_tm_security_mismatch(dev, apdev):
1283     """WNM BSS Transition Management and security mismatch"""
1284     params = { "ssid": "test-wnm",
1285                "wpa": "2",
1286                "wpa_key_mgmt": "WPA-PSK",
1287                "rsn_pairwise": "CCMP",
1288                "wpa_passphrase": "12345678",
1289                "hw_mode": "g",
1290                "channel": "1",
1291                "bss_transition": "1" }
1292     hapd = hostapd.add_ap(apdev[0], params)
1293
1294     params = { "ssid": "test-wnm",
1295                "hw_mode": "g",
1296                "channel": "11",
1297                "bss_transition": "1" }
1298     hapd2 = hostapd.add_ap(apdev[1], params)
1299
1300     dev[0].scan_for_bss(apdev[1]['bssid'], 2462)
1301
1302     id = dev[0].connect("test-wnm", psk="12345678",
1303                         bssid=apdev[0]['bssid'], scan_freq="2412")
1304     dev[0].set_network(id, "scan_freq", "")
1305     dev[0].set_network(id, "bssid", "")
1306
1307     addr = dev[0].own_addr()
1308     dev[0].dump_monitor()
1309
1310     logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1311     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"):
1312         raise Exception("BSS_TM_REQ command failed")
1313     ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1314     if ev is None:
1315         raise Exception("No BSS Transition Management Response")
1316     if "status_code=7" not in ev:
1317         raise Exception("Unexpected BSS transition request response: " + ev)
1318
1319 def test_wnm_bss_tm_connect_cmd(dev, apdev):
1320     """WNM BSS Transition Management and cfg80211 connect command"""
1321     params = { "ssid": "test-wnm",
1322                "hw_mode": "g",
1323                "channel": "1",
1324                "bss_transition": "1" }
1325     hapd = hostapd.add_ap(apdev[0], params)
1326
1327     params = { "ssid": "test-wnm",
1328                "hw_mode": "g",
1329                "channel": "11",
1330                "bss_transition": "1" }
1331     hapd2 = hostapd.add_ap(apdev[1], params)
1332
1333     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1334     wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
1335
1336     wpas.scan_for_bss(apdev[1]['bssid'], 2462)
1337
1338     id = wpas.connect("test-wnm", key_mgmt="NONE",
1339                       bssid=apdev[0]['bssid'], scan_freq="2412")
1340     wpas.set_network(id, "scan_freq", "")
1341     wpas.set_network(id, "bssid", "")
1342
1343     addr = wpas.own_addr()
1344     wpas.dump_monitor()
1345
1346     logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1347     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"):
1348         raise Exception("BSS_TM_REQ command failed")
1349     ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1350     if ev is None:
1351         raise Exception("No BSS Transition Management Response")
1352     if "status_code=0" not in ev:
1353         raise Exception("BSS transition request was not accepted: " + ev)
1354     if "target_bssid=" + apdev[1]['bssid'] not in ev:
1355         raise Exception("Unexpected target BSS: " + ev)
1356     ev = wpas.wait_event(["CTRL-EVENT-CONNECTED",
1357                           "CTRL-EVENT-DISCONNECTED"], timeout=10)
1358     if ev is None:
1359         raise Exception("No reassociation seen")
1360     if "CTRL-EVENT-DISCONNECTED" in ev:
1361         #TODO: Uncomment this once kernel side changes for Connect command
1362         #reassociation are in upstream.
1363         #raise Exception("Unexpected disconnection reported")
1364         logger.info("Unexpected disconnection reported")
1365         ev = wpas.wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
1366         if ev is None:
1367             raise Exception("No reassociation seen")
1368     if apdev[1]['bssid'] not in ev:
1369         raise Exception("Unexpected reassociation target: " + ev)