tests: Add support for wlantest for remote hwsim tests
[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     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)
196
197     Wlantest.setup(hapd)
198     wt = Wlantest()
199     wt.flush()
200     wt.add_passphrase("12345678")
201
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)
205     if ev is None:
206         raise Exception("No connection event received from hostapd")
207     check_wnm_sleep_mode_enter_exit(hapd, dev[0])
208
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
231
232 def bss_tm_req(dst, src, dialog_token=1, req_mode=0, disassoc_timer=0,
233                validity_interval=1):
234     msg = {}
235     msg['fc'] = MGMT_SUBTYPE_ACTION << 4
236     msg['da'] = dst
237     msg['sa'] = src
238     msg['bssid'] = src
239     msg['payload'] = struct.pack("<BBBBHB",
240                                  ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
241                                  dialog_token, req_mode, disassoc_timer,
242                                  validity_interval)
243     return msg
244
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()
248         if resp is None:
249             raise Exception("No BSS TM Response received")
250         if resp['subtype'] == MGMT_SUBTYPE_ACTION:
251             break
252     if i == 99:
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")
260     pos = payload[2:]
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
265     pos = pos[3:]
266     if len(pos) >= 6 and status == 0:
267         resp['target_bssid'] = binascii.hexlify(pos[0:6])
268         pos = pos[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)
274     return resp
275
276 def expect_ack(hapd):
277     ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
278     if ev is None:
279         raise Exception("Missing TX status")
280     if "ok=1" not in ev:
281         raise Exception("Action frame not acknowledged")
282
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)
289
290     hapd.set("ext_mgmt_frame_handling", "1")
291
292     # truncated BSS TM Request
293     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
294                      req_mode=0x08)
295     req['payload'] = struct.pack("<BBBBH",
296                                  ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
297                                  1, 0, 0)
298     hapd.mgmt_tx(req)
299     expect_ack(hapd)
300
301     # no disassociation and no candidate list
302     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
303                      dialog_token=2)
304     hapd.mgmt_tx(req)
305     resp = rx_bss_tm_resp(hapd, expect_dialog=2, expect_status=1)
306
307     # truncated BSS Termination Duration
308     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
309                      req_mode=0x08)
310     hapd.mgmt_tx(req)
311     expect_ack(hapd)
312
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)
317     hapd.mgmt_tx(req)
318     resp = rx_bss_tm_resp(hapd, expect_dialog=3, expect_status=1)
319
320     # truncated Session Information URL
321     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
322                      req_mode=0x10)
323     hapd.mgmt_tx(req)
324     expect_ack(hapd)
325     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
326                      req_mode=0x10)
327     req['payload'] += struct.pack("<BBB", 3, 65, 66)
328     hapd.mgmt_tx(req)
329     expect_ack(hapd)
330
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)
335     hapd.mgmt_tx(req)
336     resp = rx_bss_tm_resp(hapd, expect_dialog=4, expect_status=0)
337
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)
341     hapd.mgmt_tx(req)
342     resp = rx_bss_tm_resp(hapd, expect_dialog=5, expect_status=7)
343
344     # Preferred Candidate List with a truncated entry
345     req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
346                      req_mode=0x01)
347     req['payload'] += struct.pack("<BB", 52, 1)
348     hapd.mgmt_tx(req)
349     expect_ack(hapd)
350
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)
355     hapd.mgmt_tx(req)
356     resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
357
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,
362                                   1, 2, 3, 4, 5, 6,
363                                   0, 81, 1, 7)
364     hapd.mgmt_tx(req)
365     resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
366
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,
371                                   1, 2, 3, 4, 5, 6,
372                                   0, 81, 1, 7,
373                                   1, 1)
374     hapd.mgmt_tx(req)
375     resp = rx_bss_tm_resp(hapd, expect_dialog=7, expect_status=7)
376
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),
389                                   1, 2, 3, 4, 5, 6,
390                                   0, 81, 1, 7) + subelems
391     hapd.mgmt_tx(req)
392     resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
393
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)
397     # TSF Information
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)
405     # Bearing
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)
411     # Multiple BSSID
412     subelems += struct.pack("<BBBB", 71, 2, 0, 0)
413     req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems) * 2,
414                                   1, 2, 3, 4, 5, 6,
415                                   0, 81, 1, 7) + subelems + subelems
416     hapd.mgmt_tx(req)
417     resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
418
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)
422     subelems = ""
423     req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
424                                   1, 2, 3, 4, 5, 6,
425                                   0, 81, 1, 7) + subelems
426     req['payload'] += binascii.unhexlify("DD0411223344")
427     hapd.mgmt_tx(req)
428     resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
429
430 def test_wnm_bss_keep_alive(dev, apdev):
431     """WNM keep-alive"""
432     params = { "ssid": "test-wnm",
433                "ap_max_inactivity": "1" }
434     hapd = hostapd.add_ap(apdev[0], params)
435
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)
440     if ev is not None:
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")
445     try:
446         # Disable client keep-alive so that hostapd will verify connection
447         # with client poll
448         dev[0].request("SET no_keep_alive 1")
449         for i in range(60):
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']):
453                 break
454             ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
455             if ev is not None:
456                 raise Exception("Unexpected disconnection (client poll expected)")
457     finally:
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")
461
462 def test_wnm_bss_tm(dev, apdev):
463     """WNM BSS Transition Management"""
464     try:
465         hapd = None
466         hapd2 = None
467         params = { "ssid": "test-wnm",
468                    "country_code": "FI",
469                    "ieee80211d": "1",
470                    "hw_mode": "g",
471                    "channel": "1",
472                    "bss_transition": "1" }
473         hapd = hostapd.add_ap(apdev[0], params)
474
475         id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
476         dev[0].set_network(id, "scan_freq", "")
477
478         params = { "ssid": "test-wnm",
479                    "country_code": "FI",
480                    "ieee80211d": "1",
481                    "hw_mode": "a",
482                    "channel": "36",
483                    "bss_transition": "1" }
484         hapd2 = hostapd.add_ap(apdev[1], params)
485
486         addr = dev[0].p2p_interface_addr()
487         dev[0].dump_monitor()
488
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)
493         if ev is None:
494             raise Exception("No BSS Transition Management Response")
495         if addr not in ev:
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()
500
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)
505         if ev is None:
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()
510
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)
515         if ev is None:
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)
520         if ev is None:
521             raise Exception("No scan started")
522         dev[0].dump_monitor()
523
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)
528         if ev is None:
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)
538         if ev is not None:
539             raise Exception("Unexpected scan started")
540         dev[0].dump_monitor()
541
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)
546         if ev is None:
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)
553         if ev is not None:
554             raise Exception("Unexpected scan started")
555         ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
556         if ev is not None:
557             raise Exception("Unexpected reassociation");
558     finally:
559         dev[0].request("DISCONNECT")
560         if hapd:
561             hapd.request("DISABLE")
562         if hapd2:
563             hapd2.request("DISABLE")
564         subprocess.call(['iw', 'reg', 'set', '00'])
565         dev[0].flush_scan_cache()
566
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)
570
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")
574
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")
578
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")
583
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")
588
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"):
592     try:
593         hapd = None
594         hapd2 = None
595         params = { "ssid": "test-wnm",
596                    "country_code": "FI",
597                    "ieee80211d": "1",
598                    "hw_mode": "g",
599                    "channel": "1",
600                    "bss_transition": "1" }
601         hapd = hostapd.add_ap(apdev[0], params)
602
603         params = { "ssid": "test-wnm",
604                    "country_code": "FI",
605                    "ieee80211d": "1",
606                    "hw_mode": hwmode,
607                    "channel": channel,
608                    "bss_transition": "1" }
609         if not ht:
610             params['ieee80211n'] = '0'
611         if vht:
612             params['ieee80211ac'] = "1"
613             params["vht_oper_chwidth"] = "0"
614             params["vht_oper_centr_freq_seg0_idx"] = "0"
615
616         hapd2 = hostapd.add_ap(apdev[1], params)
617
618         dev[0].scan_for_bss(apdev[1]['bssid'], freq)
619
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", "")
624
625         addr = dev[0].own_addr()
626         dev[0].dump_monitor()
627
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)
632         if ev is None:
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)
642         if ev is not None:
643             raise Exception("Unexpected scan started")
644         dev[0].dump_monitor()
645     finally:
646         dev[0].request("DISCONNECT")
647         if hapd:
648             hapd.request("DISABLE")
649         if hapd2:
650             hapd2.request("DISABLE")
651         subprocess.call(['iw', 'reg', 'set', '00'])
652         dev[0].flush_scan_cache()
653
654 def test_wnm_bss_tm_scan_needed(dev, apdev):
655     """WNM BSS Transition Management and scan needed"""
656     try:
657         hapd = None
658         hapd2 = None
659         params = { "ssid": "test-wnm",
660                    "country_code": "FI",
661                    "ieee80211d": "1",
662                    "hw_mode": "g",
663                    "channel": "1",
664                    "bss_transition": "1" }
665         hapd = hostapd.add_ap(apdev[0], params)
666
667         params = { "ssid": "test-wnm",
668                    "country_code": "FI",
669                    "ieee80211d": "1",
670                    "hw_mode": "a",
671                    "channel": "36",
672                    "bss_transition": "1" }
673         hapd2 = hostapd.add_ap(apdev[1], params)
674
675         dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
676
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", "")
681
682         addr = dev[0].own_addr()
683         dev[0].dump_monitor()
684
685         logger.info("Wait 11 seconds for the last scan result to be too old, but still present in BSS table")
686         time.sleep(11)
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)
691         if ev is None:
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)
701         if ev is not None:
702             raise Exception("Unexpected scan started")
703         dev[0].dump_monitor()
704     finally:
705         dev[0].request("DISCONNECT")
706         if hapd:
707             hapd.request("DISABLE")
708         if hapd2:
709             hapd2.request("DISABLE")
710         subprocess.call(['iw', 'reg', 'set', '00'])
711         dev[0].flush_scan_cache()
712
713 def start_wnm_tm(ap, country, dev):
714     params = { "ssid": "test-wnm",
715                "country_code": country,
716                "ieee80211d": "1",
717                "hw_mode": "g",
718                "channel": "1",
719                "bss_transition": "1" }
720     hapd = hostapd.add_ap(ap, params)
721     id = dev.connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
722     dev.dump_monitor()
723     dev.set_network(id, "scan_freq", "")
724     return hapd, id
725
726 def stop_wnm_tm(hapd, dev):
727     dev.request("DISCONNECT")
728     try:
729         dev.wait_disconnected()
730     except:
731         pass
732     if hapd:
733         hapd.request("DISABLE")
734     subprocess.call(['iw', 'reg', 'set', '00'])
735     dev.flush_scan_cache()
736
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)
742     if ev is None:
743         raise Exception("No scan started")
744     ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
745     if ev is None:
746         raise Exception("Scan did not complete")
747
748     ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
749     if ev is None:
750         raise Exception("No BSS Transition Management Response")
751     if "status_code=7" not in ev:
752         raise Exception("Unexpected response: " + ev)
753
754 def test_wnm_bss_tm_country_us(dev, apdev):
755     """WNM BSS Transition Management (US)"""
756     try:
757         hapd = None
758         hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
759
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")
762
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")
767
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")
770     finally:
771         stop_wnm_tm(hapd, dev[0])
772
773 def test_wnm_bss_tm_country_fi(dev, apdev):
774     """WNM BSS Transition Management (FI)"""
775     addr = dev[0].p2p_interface_addr()
776     try:
777         hapd = None
778         hapd, id = start_wnm_tm(apdev[0], "FI", dev[0])
779
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")
782
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")
787
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")
790     finally:
791         stop_wnm_tm(hapd, dev[0])
792
793 def test_wnm_bss_tm_country_jp(dev, apdev):
794     """WNM BSS Transition Management (JP)"""
795     addr = dev[0].p2p_interface_addr()
796     try:
797         hapd = None
798         hapd, id = start_wnm_tm(apdev[0], "JP", dev[0])
799
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")
802
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")
807     finally:
808         stop_wnm_tm(hapd, dev[0])
809
810 def test_wnm_bss_tm_country_cn(dev, apdev):
811     """WNM BSS Transition Management (CN)"""
812     addr = dev[0].p2p_interface_addr()
813     try:
814         hapd = None
815         hapd, id = start_wnm_tm(apdev[0], "CN", dev[0])
816
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")
819
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")
824     finally:
825         stop_wnm_tm(hapd, dev[0])
826
827 def test_wnm_bss_tm_global(dev, apdev):
828     """WNM BSS Transition Management (global)"""
829     addr = dev[0].p2p_interface_addr()
830     try:
831         hapd = None
832         hapd, id = start_wnm_tm(apdev[0], "XX", dev[0])
833
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")
836
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")
841
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")
844     finally:
845         stop_wnm_tm(hapd, dev[0])
846
847 def test_wnm_bss_tm_op_class_0(dev, apdev):
848     """WNM BSS Transition Management with invalid operating class"""
849     try:
850         hapd = None
851         hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
852
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")
855     finally:
856         stop_wnm_tm(hapd, dev[0])
857
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")
866     time.sleep(0.1)
867     hapd.set("ext_mgmt_frame_handling", "1")
868
869     msg = {}
870     msg['fc'] = MGMT_SUBTYPE_ACTION << 4
871     msg['da'] = dev[0].own_addr()
872     msg['sa'] = bssid
873     msg['bssid'] = bssid
874
875     dialog_token = 1
876
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,
883                                  dialog_token, 0)
884     hapd.mgmt_tx(msg)
885     expect_ack(hapd)
886
887     logger.debug("Truncated WNM-Notification Request (no Type field)")
888     msg['payload'] = struct.pack("<BBB",
889                                  ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
890                                  dialog_token)
891     hapd.mgmt_tx(msg)
892     expect_ack(hapd)
893
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)
898     hapd.mgmt_tx(msg)
899     expect_ack(hapd)
900
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)
905     hapd.mgmt_tx(msg)
906     expect_ack(hapd)
907
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)
912     hapd.mgmt_tx(msg)
913     expect_ack(hapd)
914
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,
919                                  0x506f9a00, 1)
920     hapd.mgmt_tx(msg)
921     expect_ack(hapd)
922
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,
927                                  0x506f9a00, 1, 0)
928     hapd.mgmt_tx(msg)
929     expect_ack(hapd)
930
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,
935                                  0x506f9a00, 0xff)
936     hapd.mgmt_tx(msg)
937     expect_ack(hapd)
938
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,
943                                  0x506f9a01, 0, 0, 1)
944     hapd.mgmt_tx(msg)
945     expect_ack(hapd)
946
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)
952     hapd.mgmt_tx(msg)
953     expect_ack(hapd)
954
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)
959     hapd.mgmt_tx(msg)
960     expect_ack(hapd)
961
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)
966     hapd.mgmt_tx(msg)
967     expect_ack(hapd)
968
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)
972     hapd.mgmt_tx(msg)
973     expect_ack(hapd)
974
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)
978     hapd.mgmt_tx(msg)
979     expect_ack(hapd)
980
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,
984                                  1)
985     hapd.mgmt_tx(msg)
986     expect_ack(hapd)
987
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,
991                                  0xffff)
992     hapd.mgmt_tx(msg)
993     expect_ack(hapd)
994
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,
998                                  0, 0)
999     hapd.mgmt_tx(msg)
1000     expect_ack(hapd)
1001
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,
1005                                  0, 0, 1)
1006     hapd.mgmt_tx(msg)
1007     expect_ack(hapd)
1008
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)
1013     hapd.mgmt_tx(msg)
1014     expect_ack(hapd)
1015
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,
1019                                  0, 0, 0)
1020     hapd.mgmt_tx(msg)
1021     expect_ack(hapd)
1022
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)
1027     hapd.mgmt_tx(msg)
1028     expect_ack(hapd)
1029
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)
1036     hapd.mgmt_tx(msg)
1037     expect_ack(hapd)
1038
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)
1045     hapd.mgmt_tx(msg)
1046     expect_ack(hapd)
1047
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)
1054     hapd.mgmt_tx(msg)
1055     expect_ack(hapd)
1056
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")
1069     time.sleep(0.1)
1070     hapd.set("ext_mgmt_frame_handling", "1")
1071
1072     msg = {}
1073     msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1074     msg['da'] = dev[0].own_addr()
1075     msg['sa'] = bssid
1076     msg['bssid'] = bssid
1077
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,
1082                                  len(keydata))
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)
1088     hapd.mgmt_tx(msg)
1089     expect_ack(hapd)
1090
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,
1095                                  len(keydata))
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)
1101     hapd.mgmt_tx(msg)
1102     expect_ack(hapd)
1103
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,
1109                                  len(keydata))
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)
1115     hapd.mgmt_tx(msg)
1116     expect_ack(hapd)
1117
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,
1123                                  len(keydata))
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)
1129     hapd.mgmt_tx(msg)
1130     expect_ack(hapd)
1131
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,
1139                                  len(keydata))
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)
1145     hapd.mgmt_tx(msg)
1146     expect_ack(hapd)
1147
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,
1152                                  len(keydata))
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)
1158     hapd.mgmt_tx(msg)
1159     expect_ack(hapd)
1160
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")
1171     time.sleep(0.1)
1172     hapd.set("ext_mgmt_frame_handling", "1")
1173
1174     msg = {}
1175     msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1176     msg['da'] = dev[0].own_addr()
1177     msg['sa'] = bssid
1178     msg['bssid'] = bssid
1179
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,
1185                            0x10203040, 0x5060,
1186                            0xf1f2f3f4, 0xf5f6f7f8, 0xf9f0fafb, 0xfcfdfeff)
1187     msg['payload'] = struct.pack("<BBBH",
1188                                  ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1189                                  len(keydata))
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)
1195     hapd.mgmt_tx(msg)
1196     expect_ack(hapd)
1197
1198     ev = dev[0].wait_event(["WNM: Ignore Key Data"], timeout=5)
1199     if ev is None:
1200         raise Exception("Key Data not ignored")
1201
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")
1210
1211     dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1212                    proto="WPA2", ieee80211w="0", scan_freq="2412")
1213
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")
1217
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")
1221
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")
1225
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")
1229
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")
1233
1234     ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1235     if ev is None:
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")
1239
1240     ev = dev[0].wait_event(['CTRL-EVENT-DISCONNECTED'], 5)
1241     if ev is None:
1242         raise Exception("Station did not disconnect although disassoc imminent was set")
1243
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")
1247
1248     # Make sure no connection is made during the retry delay
1249     ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1250     if ev is not None:
1251         raise Exception("Station connected before assoc retry delay was over")
1252
1253     # After the assoc retry delay is over, we can reconnect
1254     ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1255     if ev is None:
1256         raise Exception("Station did not connect after assoc retry delay is over")
1257
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")
1260
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)
1268
1269     dev[0].scan_for_bss(apdev[1]['bssid'], 2412)
1270     dev[0].scan_for_bss(apdev[0]['bssid'], 2412)
1271
1272     dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1273     dev[0].request("WNM_BSS_QUERY 0 list")
1274
1275     ev = dev[0].wait_event(["WNM: BSS Transition Management Request"],
1276                            timeout=5)
1277     if ev is None:
1278         raise Exception("No BSS Transition Management Request frame seen")
1279
1280     ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1281     if ev is None:
1282         raise Exception("No BSS Transition Management Response frame seen")
1283
1284 def test_wnm_bss_tm_security_mismatch(dev, apdev):
1285     """WNM BSS Transition Management and security mismatch"""
1286     params = { "ssid": "test-wnm",
1287                "wpa": "2",
1288                "wpa_key_mgmt": "WPA-PSK",
1289                "rsn_pairwise": "CCMP",
1290                "wpa_passphrase": "12345678",
1291                "hw_mode": "g",
1292                "channel": "1",
1293                "bss_transition": "1" }
1294     hapd = hostapd.add_ap(apdev[0], params)
1295
1296     params = { "ssid": "test-wnm",
1297                "hw_mode": "g",
1298                "channel": "11",
1299                "bss_transition": "1" }
1300     hapd2 = hostapd.add_ap(apdev[1], params)
1301
1302     dev[0].scan_for_bss(apdev[1]['bssid'], 2462)
1303
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", "")
1308
1309     addr = dev[0].own_addr()
1310     dev[0].dump_monitor()
1311
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)
1316     if ev is None:
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)
1320
1321 def test_wnm_bss_tm_connect_cmd(dev, apdev):
1322     """WNM BSS Transition Management and cfg80211 connect command"""
1323     params = { "ssid": "test-wnm",
1324                "hw_mode": "g",
1325                "channel": "1",
1326                "bss_transition": "1" }
1327     hapd = hostapd.add_ap(apdev[0], params)
1328
1329     params = { "ssid": "test-wnm",
1330                "hw_mode": "g",
1331                "channel": "11",
1332                "bss_transition": "1" }
1333     hapd2 = hostapd.add_ap(apdev[1], params)
1334
1335     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1336     wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
1337
1338     wpas.scan_for_bss(apdev[1]['bssid'], 2462)
1339
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", "")
1344
1345     addr = wpas.own_addr()
1346     wpas.dump_monitor()
1347
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)
1352     if ev is None:
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)
1360     if ev is None:
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)
1368         if ev is None:
1369             raise Exception("No reassociation seen")
1370     if apdev[1]['bssid'] not in ev:
1371         raise Exception("Unexpected reassociation target: " + ev)