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