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