1# WNM tests
2# Copyright (c) 2013-2019, 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
7from remotehost import remote_compatible
8import binascii
9import struct
10import time
11import logging
12logger = logging.getLogger()
13import subprocess
14
15import hostapd
16from wpasupplicant import WpaSupplicant
17from utils import *
18from wlantest import Wlantest
19from datetime import datetime
20
21def clear_regdom_state(dev, hapd, hapd2):
22    for i in range(0, 3):
23        ev = dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5)
24        if ev is None or "init=COUNTRY_IE" in ev:
25            break
26    if hapd:
27        hapd.request("DISABLE")
28    if hapd2:
29        hapd2.request("DISABLE")
30    subprocess.call(['iw', 'reg', 'set', '00'])
31    dev[0].disconnect_and_stop_scan()
32    subprocess.call(['iw', 'reg', 'set', '00'])
33    dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5)
34    dev[0].flush_scan_cache()
35
36def start_wnm_ap(apdev, bss_transition=True, time_adv=False, ssid=None,
37                 wnm_sleep_mode=False, wnm_sleep_mode_no_keys=False, rsn=False,
38                 ocv=False, ap_max_inactivity=0, coloc_intf_reporting=False,
39                 hw_mode=None, channel=None, country_code=None, country3=None,
40                 pmf=True, passphrase=None, ht=True, vht=False, mbo=False,
41                 beacon_prot=False, he=False, bss_max_idle=None,
42                 wpa_group_rekey=None, no_disconnect_on_group_keyerror=False,
43                 max_acceptable_idle_period=None):
44    if rsn:
45        if not ssid:
46            ssid = "test-wnm-rsn"
47        if not passphrase:
48            passphrase = "12345678"
49        params = hostapd.wpa2_params(ssid, passphrase)
50        if pmf:
51            params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
52            params["ieee80211w"] = "2"
53            if beacon_prot:
54                params["beacon_prot"] = "1"
55    else:
56        params = {"ssid": "test-wnm"}
57    if bss_transition:
58        params["bss_transition"] = "1"
59    if time_adv:
60        params["time_advertisement"] = "2"
61        params["time_zone"] = "EST5"
62    if wnm_sleep_mode:
63        params["wnm_sleep_mode"] = "1"
64    if wnm_sleep_mode_no_keys:
65        params["wnm_sleep_mode_no_keys"] = "1"
66    if ocv:
67        params["ocv"] = "1"
68    if ap_max_inactivity:
69        params["ap_max_inactivity"] = str(ap_max_inactivity)
70    if coloc_intf_reporting:
71        params["coloc_intf_reporting"] = "1"
72    if hw_mode:
73        params["hw_mode"] = hw_mode
74    if channel:
75        params["channel"] = channel
76    if country_code:
77        params["country_code"] = country_code
78        params["ieee80211d"] = "1"
79    if country3:
80        params["country3"] = country3
81    if not ht:
82        params['ieee80211n'] = '0'
83    if vht:
84        params['ieee80211ac'] = "1"
85        params["vht_oper_chwidth"] = "0"
86        params["vht_oper_centr_freq_seg0_idx"] = "0"
87    if he:
88        params["ieee80211ax"] = "1"
89        params["he_bss_color"] = "42"
90    if mbo:
91        params["mbo"] = "1"
92    if bss_max_idle is not None:
93        params["bss_max_idle"] = str(bss_max_idle)
94    if wpa_group_rekey:
95        params["wpa_group_rekey"] = str(wpa_group_rekey)
96    if no_disconnect_on_group_keyerror:
97        params["no_disconnect_on_group_keyerror"] = "1"
98    if max_acceptable_idle_period is not None:
99        params["max_acceptable_idle_period"] = str(max_acceptable_idle_period)
100    try:
101        hapd = hostapd.add_ap(apdev, params)
102    except Exception as e:
103        if "Failed to set hostapd parameter ocv" in str(e):
104            raise HwsimSkip("OCV not supported")
105        raise
106    if rsn:
107        Wlantest.setup(hapd)
108        wt = Wlantest()
109        wt.flush()
110        wt.add_passphrase("12345678")
111    return hapd
112
113@remote_compatible
114def test_wnm_bss_transition_mgmt(dev, apdev):
115    """WNM BSS Transition Management"""
116    start_wnm_ap(apdev[0], time_adv=True, wnm_sleep_mode=True)
117    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
118    dev[0].request("WNM_BSS_QUERY 0")
119
120def test_wnm_bss_transition_mgmt_oom(dev, apdev):
121    """WNM BSS Transition Management OOM"""
122    hapd = start_wnm_ap(apdev[0])
123    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
124    with alloc_fail(hapd, 1, "ieee802_11_send_bss_trans_mgmt_request"):
125        dev[0].request("WNM_BSS_QUERY 0")
126        wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
127
128@remote_compatible
129def test_wnm_disassoc_imminent(dev, apdev):
130    """WNM Disassociation Imminent"""
131    hapd = start_wnm_ap(apdev[0], time_adv=True, wnm_sleep_mode=True)
132    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
133    addr = dev[0].p2p_interface_addr()
134    hapd.request("DISASSOC_IMMINENT " + addr + " 10")
135    ev = dev[0].wait_event(["WNM: Disassociation Imminent"])
136    if ev is None:
137        raise Exception("Timeout while waiting for disassociation imminent")
138    if "Disassociation Timer 10" not in ev:
139        raise Exception("Unexpected disassociation imminent contents")
140    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
141    if ev is None:
142        raise Exception("Timeout while waiting for re-connection scan")
143
144def test_wnm_disassoc_imminent_bssid_set(dev, apdev):
145    """WNM Disassociation Imminent and bssid set"""
146    hapd = start_wnm_ap(apdev[0], time_adv=True, wnm_sleep_mode=True)
147    hapd2 = start_wnm_ap(apdev[1], time_adv=True, wnm_sleep_mode=True)
148    dev[0].connect("test-wnm", key_mgmt="NONE", bssid=hapd.own_addr(),
149                   scan_freq="2412")
150    addr = dev[0].own_addr()
151    cmd = "BSS_TM_REQ " + addr + " pref=1 disassoc_imminent=1 disassoc_timer=100 neighbor=" + apdev[1]['bssid'] + ",0x0000," + "81,1,7,0301ff"
152    if "OK" not in hapd.request(cmd):
153        raise Exception("BSS_TM_REQ command failed")
154
155    ev = dev[0].wait_event(["WNM: Disassociation Imminent"])
156    if ev is None:
157        raise Exception("Timeout while waiting for disassociation imminent")
158    if "Disassociation Timer 100" not in ev:
159        raise Exception("Unexpected disassociation imminent contents")
160
161    ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
162    if ev is None:
163        raise Exception("No BSS Transition Management Response")
164    if "status_code=7" not in ev:
165        raise Exception("Unexpected BSS TM response status: " + ev)
166
167    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=2)
168    if ev is not None:
169        raise Exception("Unexpected scan started")
170
171    dev[0].request("DISCONNECT")
172    dev[0].wait_disconnected()
173
174def test_wnm_disassoc_imminent_fail(dev, apdev):
175    """WNM Disassociation Imminent failure"""
176    hapd = start_wnm_ap(apdev[0])
177    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
178    addr = dev[0].own_addr()
179    with fail_test(hapd, 1, "wnm_send_disassoc_imminent"):
180        if "FAIL" not in hapd.request("DISASSOC_IMMINENT " + addr + " 10"):
181            raise Exception("DISASSOC_IMMINENT succeeded during failure testing")
182
183@remote_compatible
184def test_wnm_ess_disassoc_imminent(dev, apdev):
185    """WNM ESS Disassociation Imminent"""
186    hapd = start_wnm_ap(apdev[0], time_adv=True, wnm_sleep_mode=True)
187    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
188    addr = dev[0].p2p_interface_addr()
189    hapd.request("ESS_DISASSOC " + addr + " 10 http://example.com/session-info")
190    ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"])
191    if ev is None:
192        raise Exception("Timeout while waiting for ESS disassociation imminent")
193    if "0 1024 http://example.com/session-info" not in ev:
194        raise Exception("Unexpected ESS disassociation imminent message contents")
195    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
196    if ev is None:
197        raise Exception("Timeout while waiting for re-connection scan")
198
199def test_wnm_ess_disassoc_imminent_fail(dev, apdev):
200    """WNM ESS Disassociation Imminent failure"""
201    hapd = start_wnm_ap(apdev[0])
202    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
203    addr = dev[0].own_addr()
204    if "FAIL" not in hapd.request("ESS_DISASSOC " + addr + " 10 http://" + 256*'a'):
205        raise Exception("Invalid ESS_DISASSOC URL accepted")
206    with fail_test(hapd, 1, "wnm_send_ess_disassoc_imminent"):
207        if "FAIL" not in hapd.request("ESS_DISASSOC " + addr + " 10 http://example.com/session-info"):
208            raise Exception("ESS_DISASSOC succeeded during failure testing")
209
210def test_wnm_ess_disassoc_imminent_reject(dev, apdev):
211    """WNM ESS Disassociation Imminent getting rejected"""
212    hapd = start_wnm_ap(apdev[0])
213    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
214    addr = dev[0].own_addr()
215    if "OK" not in dev[0].request("SET reject_btm_req_reason 123"):
216        raise Exception("Failed to set reject_btm_req_reason")
217
218    hapd.request("ESS_DISASSOC " + addr + " 1 http://example.com/session-info")
219    ev = hapd.wait_event(["BSS-TM-RESP"], timeout=10)
220    if ev is None:
221        raise Exception("BSS-TM-RESP not seen")
222    if "status_code=123" not in ev:
223        raise Exception("Unexpected response status: " + ev)
224    dev[0].wait_disconnected()
225    dev[0].request("DISCONNECT")
226
227@remote_compatible
228def test_wnm_ess_disassoc_imminent_pmf(dev, apdev):
229    """WNM ESS Disassociation Imminent"""
230    hapd = start_wnm_ap(apdev[0], rsn=True)
231    dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
232                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
233    addr = dev[0].p2p_interface_addr()
234    hapd.wait_sta(wait_4way_hs=True)
235    hapd.request("ESS_DISASSOC " + addr + " 10 http://example.com/session-info")
236    ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"])
237    if ev is None:
238        raise Exception("Timeout while waiting for ESS disassociation imminent")
239    if "1 1024 http://example.com/session-info" not in ev:
240        raise Exception("Unexpected ESS disassociation imminent message contents")
241    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
242    if ev is None:
243        raise Exception("Timeout while waiting for re-connection scan")
244
245def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None,
246                                    rekey=False):
247    addr = dev.p2p_interface_addr()
248    sta = hapd.get_sta(addr)
249    if "[WNM_SLEEP_MODE]" in sta['flags']:
250        raise Exception("Station unexpectedly in WNM-Sleep Mode")
251
252    logger.info("Going to WNM Sleep Mode")
253    extra = ""
254    if interval is not None:
255        extra += " interval=" + str(interval)
256    if tfs_req:
257        extra += " tfs_req=" + tfs_req
258    if "OK" not in dev.request("WNM_SLEEP enter" + extra):
259        raise Exception("WNM_SLEEP failed")
260    ok = False
261    for i in range(20):
262        time.sleep(0.1)
263        sta = hapd.get_sta(addr)
264        if "[WNM_SLEEP_MODE]" in sta['flags']:
265            ok = True
266            break
267    if not ok:
268        raise Exception("Station failed to enter WNM-Sleep Mode")
269
270    if rekey:
271        time.sleep(0.1)
272        if "OK" not in hapd.request("REKEY_GTK"):
273            raise Exception("REKEY_GTK failed")
274        ev = dev.wait_event(["RSN: Group rekeying completed"], timeout=0.1)
275        if ev is not None:
276                raise Exception("Unexpected report of GTK rekey during WNM-Sleep Mode")
277
278    logger.info("Waking up from WNM Sleep Mode")
279    ok = False
280    dev.request("WNM_SLEEP exit")
281    for i in range(20):
282        time.sleep(0.1)
283        sta = hapd.get_sta(addr)
284        if "[WNM_SLEEP_MODE]" not in sta['flags']:
285            ok = True
286            break
287    if not ok:
288        raise Exception("Station failed to exit WNM-Sleep Mode")
289
290    if rekey:
291        time.sleep(0.1)
292        if "OK" not in hapd.request("REKEY_GTK"):
293            raise Exception("REKEY_GTK failed")
294        ev = dev.wait_event(["RSN: Group rekeying completed"], timeout=2)
295        if ev is None:
296                raise Exception("GTK rekey timed out")
297
298@remote_compatible
299def test_wnm_sleep_mode_open(dev, apdev):
300    """WNM Sleep Mode - open"""
301    hapd = start_wnm_ap(apdev[0], time_adv=True, wnm_sleep_mode=True)
302    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
303    ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5)
304    if ev is None:
305        raise Exception("No connection event received from hostapd")
306    check_wnm_sleep_mode_enter_exit(hapd, dev[0])
307    check_wnm_sleep_mode_enter_exit(hapd, dev[0], interval=100)
308    check_wnm_sleep_mode_enter_exit(hapd, dev[0], tfs_req="5b17010001130e110000071122334455661122334455661234")
309
310    cmds = ["foo",
311            "exit tfs_req=123 interval=10",
312            "enter tfs_req=qq interval=10"]
313    for cmd in cmds:
314        if "FAIL" not in dev[0].request("WNM_SLEEP " + cmd):
315            raise Exception("Invalid WNM_SLEEP accepted")
316
317def test_wnm_sleep_mode_open_fail(dev, apdev):
318    """WNM Sleep Mode - open (fail)"""
319    hapd = start_wnm_ap(apdev[0], wnm_sleep_mode=True)
320    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
321    with fail_test(hapd, 1, "nl80211_send_frame_cmd;ieee802_11_send_wnmsleep_resp"):
322        dev[0].request("WNM_SLEEP enter")
323        wait_fail_trigger(hapd, "GET_FAIL")
324
325def test_wnm_sleep_mode_disabled_on_ap(dev, apdev):
326    """WNM Sleep Mode disabled on AP"""
327    hapd = start_wnm_ap(apdev[0], wnm_sleep_mode=False)
328    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
329    # Ignore WNM-Sleep Mode Request from 02:00:00:00:00:00 since WNM-Sleep Mode is disabled
330    dev[0].request("WNM_SLEEP enter")
331    time.sleep(0.1)
332
333@remote_compatible
334def test_wnm_sleep_mode_rsn(dev, apdev):
335    """WNM Sleep Mode - RSN"""
336    hapd = start_wnm_ap(apdev[0], time_adv=True, wnm_sleep_mode=True, rsn=True,
337                        pmf=False)
338    dev[0].connect("test-wnm-rsn", psk="12345678", scan_freq="2412")
339    ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5)
340    if ev is None:
341        raise Exception("No connection event received from hostapd")
342    check_wnm_sleep_mode_enter_exit(hapd, dev[0])
343
344@remote_compatible
345def test_wnm_sleep_mode_ap_oom(dev, apdev):
346    """WNM Sleep Mode - AP side OOM"""
347    hapd = start_wnm_ap(apdev[0], bss_transition=False, wnm_sleep_mode=True)
348    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
349    ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5)
350    if ev is None:
351        raise Exception("No connection event received from hostapd")
352    with alloc_fail(hapd, 1, "ieee802_11_send_wnmsleep_resp"):
353        dev[0].request("WNM_SLEEP enter")
354        wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
355    with alloc_fail(hapd, 2, "ieee802_11_send_wnmsleep_resp"):
356        dev[0].request("WNM_SLEEP exit")
357        wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
358
359@remote_compatible
360def test_wnm_sleep_mode_rsn_pmf(dev, apdev):
361    """WNM Sleep Mode - RSN with PMF"""
362    hapd = start_wnm_ap(apdev[0], rsn=True, wnm_sleep_mode=True, time_adv=True)
363    dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
364                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
365    ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5)
366    if ev is None:
367        raise Exception("No connection event received from hostapd")
368    check_wnm_sleep_mode_enter_exit(hapd, dev[0])
369
370def test_wnm_sleep_mode_rsn_beacon_prot(dev, apdev):
371    """WNM Sleep Mode - RSN with PMF and beacon protection"""
372    hapd = start_wnm_ap(apdev[0], rsn=True, wnm_sleep_mode=True, time_adv=True,
373                        beacon_prot=True)
374    dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
375                   beacon_prot="1",
376                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
377    ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5)
378    if ev is None:
379        raise Exception("No connection event received from hostapd")
380    check_wnm_sleep_mode_enter_exit(hapd, dev[0])
381    check_wnm_sleep_mode_enter_exit(hapd, dev[0], rekey=True)
382
383@remote_compatible
384def test_wnm_sleep_mode_rsn_ocv(dev, apdev):
385    """WNM Sleep Mode - RSN with OCV"""
386    hapd = start_wnm_ap(apdev[0], rsn=True, wnm_sleep_mode=True,
387                        time_adv=True, ocv=True)
388
389    dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2", ocv="1",
390                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
391    ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5)
392    if ev is None:
393        raise Exception("No connection event received from hostapd")
394    check_wnm_sleep_mode_enter_exit(hapd, dev[0])
395
396    # Check if OCV succeeded or failed
397    ev = dev[0].wait_event(["OCV failed"], timeout=1)
398    if ev is not None:
399        raise Exception("OCI verification failed: " + ev)
400
401@remote_compatible
402def test_wnm_sleep_mode_rsn_badocv(dev, apdev):
403    """WNM Sleep Mode - RSN with OCV and bad OCI elements"""
404    ssid = "test-wnm-rsn"
405    hapd = start_wnm_ap(apdev[0], rsn=True, wnm_sleep_mode=True, ocv=True)
406    bssid = apdev[0]['bssid']
407    dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256", ocv="1",
408                   proto="WPA2", ieee80211w="2", scan_freq="2412")
409    dev[0].request("WNM_SLEEP enter")
410    time.sleep(0.1)
411
412    msg = {'fc': MGMT_SUBTYPE_ACTION << 4,
413           'da': bssid,
414           'sa': dev[0].own_addr(),
415           'bssid': bssid}
416
417    logger.debug("WNM Sleep Mode Request - Missing OCI element")
418    msg['payload'] = struct.pack("<BBBBBBBHBB",
419                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_REQ, 0,
420                                 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT, 0, 0,
421                                 WLAN_EID_TFS_REQ, 0)
422    mgmt_tx(dev[0], "MGMT_TX {} {} freq=2412 wait_time=200 no_cck=1 action={}".format(
423        msg['da'], msg['bssid'], binascii.hexlify(msg['payload']).decode()))
424    ev = hapd.wait_event(["OCV failed"], timeout=5)
425    if ev is None:
426        raise Exception("AP did not report missing OCI element")
427
428    logger.debug("WNM Sleep Mode Request - Bad OCI element")
429    msg['payload'] = struct.pack("<BBBBBBBHBB",
430                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_REQ, 0,
431                                 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT, 0,
432                                 0,
433                                 WLAN_EID_TFS_REQ, 0)
434    oci_ie = struct.pack("<BBB", 81, 2, 0)
435    msg['payload'] += struct.pack("<BBB", WLAN_EID_EXTENSION, 1 + len(oci_ie),
436                                  WLAN_EID_EXT_OCV_OCI) + oci_ie
437    mgmt_tx(dev[0], "MGMT_TX {} {} freq=2412 wait_time=200 no_cck=1 action={}".format(
438        msg['da'], msg['bssid'], binascii.hexlify(msg['payload']).decode()))
439    ev = hapd.wait_event(["OCV failed"], timeout=5)
440    if ev is None:
441        raise Exception("AP did not report bad OCI element")
442
443    msg = {'fc': MGMT_SUBTYPE_ACTION << 4,
444           'da': dev[0].own_addr(),
445           'sa': bssid,
446           'bssid': bssid}
447    hapd.set("ext_mgmt_frame_handling", "1")
448
449    logger.debug("WNM Sleep Mode Response - Missing OCI element")
450    msg['payload'] = struct.pack("<BBBHBBBBHBB",
451                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
452                                 0,
453                                 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
454                                 WNM_STATUS_SLEEP_ACCEPT, 0,
455                                 WLAN_EID_TFS_RESP, 0)
456    dev[0].request("WNM_SLEEP exit")
457    hapd.mgmt_tx(msg)
458    expect_ack(hapd)
459    ev = dev[0].wait_event(["OCV failed"], timeout=5)
460    if ev is None:
461        raise Exception("STA did not report missing OCI element")
462
463    logger.debug("WNM Sleep Mode Response - Bad OCI element")
464    msg['payload'] = struct.pack("<BBBHBBBBHBB",
465                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
466                                 0,
467                                 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
468                                 WNM_STATUS_SLEEP_ACCEPT, 0,
469                                 WLAN_EID_TFS_RESP, 0)
470    oci_ie = struct.pack("<BBB", 81, 2, 0)
471    msg['payload'] += struct.pack("<BBB", WLAN_EID_EXTENSION, 1 + len(oci_ie),
472                                  WLAN_EID_EXT_OCV_OCI) + oci_ie
473    hapd.mgmt_tx(msg)
474    expect_ack(hapd)
475    ev = dev[0].wait_event(["OCV failed"], timeout=5)
476    if ev is None:
477        raise Exception("STA did not report bad OCI element")
478
479def test_wnm_sleep_mode_rsn_ocv_failure(dev, apdev):
480    """WNM Sleep Mode - RSN with OCV - local failure"""
481    hapd = start_wnm_ap(apdev[0], rsn=True, wnm_sleep_mode=True,
482                        time_adv=True, ocv=True)
483
484    dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2", ocv="1",
485                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
486    hapd.wait_sta()
487    # Failed to allocate buffer for OCI element in WNM-Sleep Mode frame
488    with alloc_fail(hapd, 2, "ieee802_11_send_wnmsleep_resp"):
489            if "OK" not in dev[0].request("WNM_SLEEP enter"):
490                    raise Exception("WNM_SLEEP failed")
491            wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
492
493def test_wnm_sleep_mode_rsn_pmf_key_workaround(dev, apdev):
494    """WNM Sleep Mode - RSN with PMF and GTK/IGTK workaround"""
495    hapd = start_wnm_ap(apdev[0], rsn=True, wnm_sleep_mode=True,
496                        wnm_sleep_mode_no_keys=True,
497                        time_adv=True, ocv=True)
498    dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
499                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
500    ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5)
501    if ev is None:
502        raise Exception("No connection event received from hostapd")
503    check_wnm_sleep_mode_enter_exit(hapd, dev[0])
504
505def test_wnm_sleep_mode_proto(dev, apdev):
506    """WNM Sleep Mode - protocol testing"""
507    hapd = start_wnm_ap(apdev[0], wnm_sleep_mode=True, bss_transition=False)
508    bssid = hapd.own_addr()
509    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
510    addr = dev[0].own_addr()
511
512    hdr = "d0003a01" + bssid.replace(':', '') + addr.replace(':', '') + bssid.replace(':', '') + "1000"
513    hapd.set("ext_mgmt_frame_handling", "1")
514    tests = ["0a10",
515             "0a1001",
516             "0a10015d00",
517             "0a10015d01",
518             "0a10015d0400000000",
519             "0a1001" + 7*("5bff" + 255*"00") + "5d00",
520             "0a1001ff00"]
521    for t in tests:
522        if "OK" not in hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + t):
523            raise Exception("MGMT_RX_PROCESS failed")
524
525    hapd.set("ext_mgmt_frame_handling", "0")
526
527MGMT_SUBTYPE_ACTION = 13
528ACTION_CATEG_WNM = 10
529WNM_ACT_EVENT_REPORT = 1
530WNM_ACT_BSS_TM_REQ = 7
531WNM_ACT_BSS_TM_RESP = 8
532WNM_ACT_SLEEP_MODE_REQ = 16
533WNM_ACT_SLEEP_MODE_RESP = 17
534WNM_ACT_NOTIFICATION_REQ = 26
535WNM_ACT_NOTIFICATION_RESP = 27
536WNM_NOTIF_TYPE_FW_UPGRADE = 0
537WNM_NOTIF_TYPE_WFA = 1
538WLAN_EID_EVENT_REPORT = 79
539WLAN_EID_TFS_REQ = 91
540WLAN_EID_TFS_RESP = 92
541WLAN_EID_WNMSLEEP = 93
542WLAN_EID_EXTENSION = 255
543WLAN_EID_EXT_OCV_OCI = 54
544WNM_SLEEP_MODE_ENTER = 0
545WNM_SLEEP_MODE_EXIT = 1
546WNM_STATUS_SLEEP_ACCEPT = 0
547WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE = 1
548WNM_STATUS_DENIED_ACTION = 2
549WNM_STATUS_DENIED_TMP = 3
550WNM_STATUS_DENIED_KEY = 4
551WNM_STATUS_DENIED_OTHER_WNM_SERVICE = 5
552WNM_SLEEP_SUBELEM_GTK = 0
553WNM_SLEEP_SUBELEM_IGTK = 1
554
555def bss_tm_req(dst, src, dialog_token=1, req_mode=0, disassoc_timer=0,
556               validity_interval=1):
557    msg = {}
558    msg['fc'] = MGMT_SUBTYPE_ACTION << 4
559    msg['da'] = dst
560    msg['sa'] = src
561    msg['bssid'] = src
562    msg['payload'] = struct.pack("<BBBBHB",
563                                 ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
564                                 dialog_token, req_mode, disassoc_timer,
565                                 validity_interval)
566    return msg
567
568def rx_bss_tm_resp(hapd, expect_dialog=None, expect_status=None):
569    for i in range(0, 100):
570        resp = hapd.mgmt_rx()
571        if resp is None:
572            raise Exception("No BSS TM Response received")
573        if resp['subtype'] == MGMT_SUBTYPE_ACTION:
574            break
575    if i == 99:
576        raise Exception("Not an Action frame")
577    payload = resp['payload']
578    if len(payload) < 2 + 3:
579        raise Exception("Too short payload")
580    (category, action) = struct.unpack('BB', payload[0:2])
581    if category != ACTION_CATEG_WNM or action != WNM_ACT_BSS_TM_RESP:
582        raise Exception("Not a BSS TM Response")
583    pos = payload[2:]
584    (dialog, status, bss_term_delay) = struct.unpack('BBB', pos[0:3])
585    resp['dialog'] = dialog
586    resp['status'] = status
587    resp['bss_term_delay'] = bss_term_delay
588    pos = pos[3:]
589    if len(pos) >= 6 and status == 0:
590        resp['target_bssid'] = binascii.hexlify(pos[0:6])
591        pos = pos[6:]
592    resp['candidates'] = pos
593    if expect_dialog is not None and dialog != expect_dialog:
594        raise Exception("Unexpected dialog token")
595    if expect_status is not None and status != expect_status:
596        raise Exception("Unexpected status code %d" % status)
597    return resp
598
599def expect_ack(hapd):
600    ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
601    if ev is None:
602        raise Exception("Missing TX status")
603    if "ok=1" not in ev:
604        raise Exception("Action frame not acknowledged")
605
606def mgmt_tx(dev, msg):
607    if "FAIL" in dev.request(msg):
608        raise Exception("Failed to send Action frame")
609    ev = dev.wait_event(["MGMT-TX-STATUS"], timeout=10)
610    if ev is None:
611        raise Exception("Timeout on MGMT-TX-STATUS")
612    if "result=SUCCESS" not in ev:
613        raise Exception("Peer did not ack Action frame")
614
615@remote_compatible
616def test_wnm_bss_tm_req(dev, apdev):
617    """BSS Transition Management Request"""
618    hapd = start_wnm_ap(apdev[0])
619    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
620    addr = dev[0].own_addr()
621
622    hapd.set("ext_mgmt_frame_handling", "1")
623
624    # truncated BSS TM Request
625    req = bss_tm_req(addr, apdev[0]['bssid'],
626                     req_mode=0x08)
627    req['payload'] = struct.pack("<BBBBH",
628                                 ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
629                                 1, 0, 0)
630    hapd.mgmt_tx(req)
631    expect_ack(hapd)
632    dev[0].dump_monitor()
633
634    # no disassociation and no candidate list
635    req = bss_tm_req(addr, apdev[0]['bssid'],
636                     dialog_token=2)
637    hapd.mgmt_tx(req)
638    resp = rx_bss_tm_resp(hapd, expect_dialog=2, expect_status=1)
639    dev[0].dump_monitor()
640
641    # truncated BSS Termination Duration
642    req = bss_tm_req(addr, apdev[0]['bssid'],
643                     req_mode=0x08)
644    hapd.mgmt_tx(req)
645    expect_ack(hapd)
646    dev[0].dump_monitor()
647
648    # BSS Termination Duration with TSF=0 and Duration=10
649    req = bss_tm_req(addr, apdev[0]['bssid'],
650                     req_mode=0x08, dialog_token=3)
651    req['payload'] += struct.pack("<BBQH", 4, 10, 0, 10)
652    hapd.mgmt_tx(req)
653    resp = rx_bss_tm_resp(hapd, expect_dialog=3, expect_status=1)
654    dev[0].dump_monitor()
655
656    # truncated Session Information URL
657    req = bss_tm_req(addr, apdev[0]['bssid'],
658                     req_mode=0x10)
659    hapd.mgmt_tx(req)
660    expect_ack(hapd)
661    req = bss_tm_req(addr, apdev[0]['bssid'],
662                     req_mode=0x10)
663    req['payload'] += struct.pack("<BBB", 3, 65, 66)
664    hapd.mgmt_tx(req)
665    expect_ack(hapd)
666    dev[0].dump_monitor()
667
668    # Session Information URL
669    req = bss_tm_req(addr, apdev[0]['bssid'],
670                     req_mode=0x10, dialog_token=4)
671    req['payload'] += struct.pack("<BBB", 2, 65, 66)
672    hapd.mgmt_tx(req)
673    resp = rx_bss_tm_resp(hapd, expect_dialog=4, expect_status=0)
674    dev[0].dump_monitor()
675
676    # Preferred Candidate List without any entries
677    req = bss_tm_req(addr, apdev[0]['bssid'],
678                     req_mode=0x01, dialog_token=5)
679    hapd.mgmt_tx(req)
680    resp = rx_bss_tm_resp(hapd, expect_dialog=5, expect_status=7)
681    dev[0].dump_monitor()
682
683    # Preferred Candidate List with a truncated entry
684    req = bss_tm_req(addr, apdev[0]['bssid'],
685                     req_mode=0x01)
686    req['payload'] += struct.pack("<BB", 52, 1)
687    hapd.mgmt_tx(req)
688    expect_ack(hapd)
689    dev[0].dump_monitor()
690
691    # Preferred Candidate List with a too short entry
692    req = bss_tm_req(addr, apdev[0]['bssid'],
693                     req_mode=0x01, dialog_token=6)
694    req['payload'] += struct.pack("<BB", 52, 0)
695    hapd.mgmt_tx(req)
696    resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
697    dev[0].dump_monitor()
698
699    # Preferred Candidate List with a non-matching entry
700    req = bss_tm_req(addr, apdev[0]['bssid'],
701                     req_mode=0x01, dialog_token=6)
702    req['payload'] += struct.pack("<BB6BLBBB", 52, 13,
703                                  1, 2, 3, 4, 5, 6,
704                                  0, 81, 1, 7)
705    hapd.mgmt_tx(req)
706    resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
707    dev[0].dump_monitor()
708
709    # Preferred Candidate List with a truncated subelement
710    req = bss_tm_req(addr, apdev[0]['bssid'],
711                     req_mode=0x01, dialog_token=7)
712    req['payload'] += struct.pack("<BB6BLBBBBB", 52, 13 + 2,
713                                  1, 2, 3, 4, 5, 6,
714                                  0, 81, 1, 7,
715                                  1, 1)
716    hapd.mgmt_tx(req)
717    resp = rx_bss_tm_resp(hapd, expect_dialog=7, expect_status=7)
718    dev[0].dump_monitor()
719
720    # Preferred Candidate List with lots of invalid optional subelements
721    req = bss_tm_req(addr, apdev[0]['bssid'],
722                     req_mode=0x01, dialog_token=8)
723    subelems = struct.pack("<BBHB", 1, 3, 0, 100)
724    subelems += struct.pack("<BBB", 2, 1, 65)
725    subelems += struct.pack("<BB", 3, 0)
726    subelems += struct.pack("<BBQB", 4, 9, 0, 10)
727    subelems += struct.pack("<BBHLB", 5, 7, 0, 0, 0)
728    subelems += struct.pack("<BB", 66, 0)
729    subelems += struct.pack("<BBBBBB", 70, 4, 0, 0, 0, 0)
730    subelems += struct.pack("<BB", 71, 0)
731    req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
732                                  1, 2, 3, 4, 5, 6,
733                                  0, 81, 1, 7) + subelems
734    hapd.mgmt_tx(req)
735    resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
736    dev[0].dump_monitor()
737
738    # Preferred Candidate List with lots of valid optional subelements (twice)
739    req = bss_tm_req(addr, apdev[0]['bssid'],
740                     req_mode=0x01, dialog_token=8)
741    # TSF Information
742    subelems = struct.pack("<BBHH", 1, 4, 0, 100)
743    # Condensed Country String
744    subelems += struct.pack("<BBBB", 2, 2, 65, 66)
745    # BSS Transition Candidate Preference
746    subelems += struct.pack("<BBB", 3, 1, 100)
747    # BSS Termination Duration
748    subelems += struct.pack("<BBQH", 4, 10, 0, 10)
749    # Bearing
750    subelems += struct.pack("<BBHLH", 5, 8, 0, 0, 0)
751    # Measurement Pilot Transmission
752    subelems += struct.pack("<BBBBB", 66, 3, 0, 0, 0)
753    # RM Enabled Capabilities
754    subelems += struct.pack("<BBBBBBB", 70, 5, 0, 0, 0, 0, 0)
755    # Multiple BSSID
756    subelems += struct.pack("<BBBB", 71, 2, 0, 0)
757    req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems) * 2,
758                                  1, 2, 3, 4, 5, 6,
759                                  0, 81, 1, 7) + subelems + subelems
760    hapd.mgmt_tx(req)
761    resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
762    dev[0].dump_monitor()
763
764    # Preferred Candidate List with truncated BSS Termination Duration
765    # WNM: Too short BSS termination duration
766    req = bss_tm_req(addr, apdev[0]['bssid'],
767                     req_mode=0x01, dialog_token=8)
768    # BSS Termination Duration (truncated)
769    subelems = struct.pack("<BBQB", 4, 9, 0, 10)
770    req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
771                                  1, 2, 3, 4, 5, 6,
772                                  0, 81, 1, 7) + subelems
773    hapd.mgmt_tx(req)
774    resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
775    dev[0].dump_monitor()
776
777    # Preferred Candidate List followed by vendor element
778    req = bss_tm_req(addr, apdev[0]['bssid'],
779                     req_mode=0x01, dialog_token=8)
780    subelems = b''
781    req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
782                                  1, 2, 3, 4, 5, 6,
783                                  0, 81, 1, 7) + subelems
784    req['payload'] += binascii.unhexlify("DD0411223344")
785    hapd.mgmt_tx(req)
786    resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
787    dev[0].dump_monitor()
788
789@remote_compatible
790@disable_ipv6
791def test_wnm_bss_keep_alive(dev, apdev):
792    """WNM keep-alive"""
793    run_wnm_bss_keep_alive(dev, apdev, False)
794
795def test_wnm_bss_protected_keep_alive(dev, apdev):
796    """WNM protected keep-alive"""
797    run_wnm_bss_keep_alive(dev, apdev, True)
798
799def run_wnm_bss_keep_alive(dev, apdev, protected):
800    hapd = start_wnm_ap(apdev[0], bss_transition=False, ap_max_inactivity=1,
801                        bss_max_idle=2 if protected else 1, rsn=True)
802    addr = dev[0].p2p_interface_addr()
803    dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
804                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
805    start = hapd.get_sta(addr)
806    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=2)
807    if ev is not None:
808        raise Exception("Unexpected disconnection")
809    end = hapd.get_sta(addr)
810    if int(end['rx_packets']) <= int(start['rx_packets']):
811        raise Exception("No keep-alive packets received")
812    try:
813        # Disable client keep-alive so that hostapd will verify connection
814        # with client poll
815        dev[0].request("SET no_keep_alive 1")
816        for i in range(60):
817            sta = hapd.get_sta(addr)
818            logger.info("timeout_next=%s rx_packets=%s tx_packets=%s" % (sta['timeout_next'], sta['rx_packets'], sta['tx_packets']))
819            if i > 1 and sta['timeout_next'] != "NULLFUNC POLL" and int(sta['tx_packets']) > int(end['tx_packets']):
820                break
821            ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
822            if ev is not None:
823                raise Exception("Unexpected disconnection (client poll expected)")
824    finally:
825        dev[0].request("SET no_keep_alive 0")
826    if int(sta['tx_packets']) <= int(end['tx_packets']):
827        raise Exception("No client poll packet seen")
828
829def test_wnm_bss_max_idle_period_management(dev, apdev):
830    """WNM BSS max idle period management"""
831    hapd = start_wnm_ap(apdev[0], bss_transition=False, ap_max_inactivity=10,
832                        max_acceptable_idle_period=1000, rsn=True)
833    addr = dev[0].own_addr()
834    dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
835                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412",
836                   max_idle="1500")
837    addr1 = dev[1].own_addr()
838    dev[1].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
839                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
840
841    ap_val = hapd.get_sta(addr)['max_idle_period']
842    if ap_val != '1000':
843        raise Exception("AP reported unexpected value: " + ap_val)
844
845    sta_val = dev[0].get_status_field("bss_max_idle_period")
846    if sta_val != '1000':
847        raise Exception("STA reported unexpected value: " + sta_val)
848
849    sta = hapd.get_sta(addr1)
850    if 'max_idle_period' in sta:
851        raise Exception("AP reported unexpected value(2): " + sta['max_idle_period'])
852
853    sta_val = dev[1].get_status_field("bss_max_idle_period")
854    if sta_val != '9':
855        raise Exception("STA reported unexpected value(2): " + sta_val)
856
857def test_wnm_bss_group_rekey(dev, apdev):
858    """WNM BSS max idle period and group rekey"""
859    hapd = start_wnm_ap(apdev[0], bss_transition=False, ap_max_inactivity=100,
860                        wpa_group_rekey=2, rsn=True)
861    addr = dev[0].own_addr()
862    dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
863                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
864    start = hapd.get_sta(addr)
865    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED",
866                            "RSN: Group rekeying completed"], timeout=3)
867    if ev is None:
868        raise Exception("No group rekeying")
869    if "CTRL-EVENT-DISCONNECTED" in ev:
870        raise Exception("Unexpected disconnection")
871
872    hapd.set("ext_eapol_frame_io", "1")
873    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED",
874                            "RSN: Group rekeying completed"], timeout=20)
875    if ev is None or "CTRL-EVENT-DISCONNECTED" not in ev:
876        raise Exception("No disconnection reported on missing group rekeying")
877    dev[0].request("DISCONNECT")
878
879def test_wnm_bss_group_rekey_skip(dev, apdev):
880    """WNM BSS max idle period and group rekey skip allowed"""
881    hapd = start_wnm_ap(apdev[0], bss_transition=False, ap_max_inactivity=100,
882                        wpa_group_rekey=2, rsn=True,
883                        no_disconnect_on_group_keyerror=True)
884    addr = dev[0].own_addr()
885    dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
886                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
887    start = hapd.get_sta(addr)
888    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED",
889                            "RSN: Group rekeying completed"], timeout=3)
890    if ev is None:
891        raise Exception("No group rekeying")
892    if "CTRL-EVENT-DISCONNECTED" in ev:
893        raise Exception("Unexpected disconnection")
894
895    hapd.set("ext_eapol_frame_io", "1")
896    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED",
897                            "RSN: Group rekeying completed"], timeout=20)
898    if ev:
899        raise Exception("Unexpected event reported: " + ev)
900    dev[0].request("DISCONNECT")
901
902def test_wnm_bss_tm(dev, apdev):
903    """WNM BSS Transition Management"""
904    try:
905        hapd = None
906        hapd2 = None
907        hapd = start_wnm_ap(apdev[0], country_code="FI")
908        dev[0].flush_scan_cache()
909        id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
910        dev[0].set_network(id, "scan_freq", "")
911
912        hapd2 = start_wnm_ap(apdev[1], country_code="FI", hw_mode="a",
913                             channel="36")
914
915        addr = dev[0].p2p_interface_addr()
916        dev[0].dump_monitor()
917
918        logger.info("No neighbor list entries")
919        if "OK" not in hapd.request("BSS_TM_REQ " + addr):
920            raise Exception("BSS_TM_REQ command failed")
921        ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
922        if ev is None:
923            raise Exception("No BSS Transition Management Response")
924        if addr not in ev:
925            raise Exception("Unexpected BSS Transition Management Response address")
926        if "status_code=0" in ev:
927            raise Exception("BSS transition accepted unexpectedly")
928        dev[0].dump_monitor()
929
930        logger.info("Neighbor list entry, but not claimed as Preferred Candidate List")
931        if "OK" not in hapd.request("BSS_TM_REQ " + addr + " dialog_token=123 neighbor=11:22:33:44:55:66,0x0000,81,3,7"):
932            raise Exception("BSS_TM_REQ command failed")
933        ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
934        if ev is None:
935            raise Exception("No BSS Transition Management Response")
936        if "status_code=0" in ev:
937            raise Exception("BSS transition accepted unexpectedly")
938        dev[0].dump_monitor()
939
940        logger.info("Preferred Candidate List (no matching neighbor) without Disassociation Imminent")
941        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,44,7 neighbor=00:11:22:33:44:55,0x0000,81,4,7,03010a"):
942            raise Exception("BSS_TM_REQ command failed")
943        ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
944        if ev is None:
945            raise Exception("No BSS Transition Management Response")
946        if "status_code=0" in ev:
947            raise Exception("BSS transition accepted unexpectedly")
948        ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
949        if ev is None:
950            raise Exception("No scan started")
951        dev[0].dump_monitor()
952
953        logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
954        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"):
955            raise Exception("BSS_TM_REQ command failed")
956        ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
957        if ev is None:
958            raise Exception("No BSS Transition Management Response")
959        if "status_code=0" not in ev:
960            raise Exception("BSS transition request was not accepted: " + ev)
961        if "target_bssid=" + apdev[1]['bssid'] not in ev:
962            raise Exception("Unexpected target BSS: " + ev)
963        dev[0].wait_connected(timeout=15, error="No reassociation seen")
964        if apdev[1]['bssid'] not in ev:
965            raise Exception("Unexpected reassociation target: " + ev)
966        ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
967        if ev is not None:
968            raise Exception("Unexpected scan started")
969        dev[0].dump_monitor()
970
971        logger.info("Preferred Candidate List with two matches, no roam needed")
972        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"):
973            raise Exception("BSS_TM_REQ command failed")
974        ev = hapd2.wait_event(['BSS-TM-RESP'], timeout=10)
975        if ev is None:
976            raise Exception("No BSS Transition Management Response")
977        if "status_code=0" not in ev:
978            raise Exception("BSS transition request was not accepted: " + ev)
979        if "target_bssid=" + apdev[1]['bssid'] not in ev:
980            raise Exception("Unexpected target BSS: " + ev)
981        ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
982        if ev is not None:
983            raise Exception("Unexpected scan started")
984        ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
985        if ev is not None:
986            raise Exception("Unexpected reassociation")
987
988        logger.info("Preferred Candidate List with two matches and extra frequency (160 MHz), no roam needed")
989        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" + ' neighbor=00:11:22:33:44:55,0x0000,129,36,7'):
990            raise Exception("BSS_TM_REQ command failed")
991        ev = hapd2.wait_event(['BSS-TM-RESP'], timeout=10)
992        if ev is None:
993            raise Exception("No BSS Transition Management Response")
994        if "status_code=0" not in ev:
995            raise Exception("BSS transition request was not accepted: " + ev)
996        if "target_bssid=" + apdev[1]['bssid'] not in ev:
997            raise Exception("Unexpected target BSS: " + ev)
998        ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
999        if ev is not None:
1000            raise Exception("Unexpected scan started")
1001        ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
1002        if ev is not None:
1003            raise Exception("Unexpected reassociation")
1004    finally:
1005        clear_regdom_state(dev, hapd, hapd2)
1006
1007def test_wnm_bss_tm_steering_timeout(dev, apdev):
1008    """WNM BSS Transition Management and steering timeout"""
1009    hapd = start_wnm_ap(apdev[0])
1010    dev[0].flush_scan_cache()
1011    id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1012    hapd2 = start_wnm_ap(apdev[1])
1013    dev[0].scan_for_bss(apdev[1]['bssid'], 2412)
1014    hapd2.disable()
1015    addr = dev[0].own_addr()
1016    if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000,81,1,7,0301ff"):
1017        raise Exception("BSS_TM_REQ command failed")
1018    ev = hapd.wait_event(['BSS-TM-RESP'], timeout=5)
1019    if ev is None:
1020        raise Exception("No BSS Transition Management Response")
1021    if "status_code=0" not in ev:
1022        raise Exception("BSS transition request was not accepted: " + ev)
1023    # Wait for the ap_sta_reset_steer_flag_timer timeout to occur
1024    # "Reset steering flag for STA 02:00:00:00:00:00"
1025    time.sleep(2.1)
1026
1027    ev = dev[0].wait_event(["Trying to authenticate"], timeout=5)
1028    if ev is None:
1029        raise Exception("No authentication attempt seen")
1030    if hapd2.own_addr() not in ev:
1031        raise Exception("Unexpected authentication target: " + ev)
1032    # Wait for return back to the previous AP
1033    dev[0].wait_connected()
1034
1035def test_wnm_bss_tm_errors(dev, apdev):
1036    """WNM BSS Transition Management errors"""
1037    hapd = start_wnm_ap(apdev[0])
1038    id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1039    addr = dev[0].own_addr()
1040
1041    tests = ["BSS_TM_REQ q",
1042             "BSS_TM_REQ 22:22:22:22:22:22",
1043             "BSS_TM_REQ %s disassoc_timer=-1" % addr,
1044             "BSS_TM_REQ %s disassoc_timer=65536" % addr,
1045             "BSS_TM_REQ %s bss_term=foo" % addr,
1046             "BSS_TM_REQ %s neighbor=q" % addr,
1047             "BSS_TM_REQ %s neighbor=02:11:22:33:44:55" % addr,
1048             "BSS_TM_REQ %s neighbor=02:11:22:33:44:55,0" % addr,
1049             "BSS_TM_REQ %s neighbor=02:11:22:33:44:55,0,0" % addr,
1050             "BSS_TM_REQ %s neighbor=02:11:22:33:44:55,0,0,0" % addr,
1051             "BSS_TM_REQ %s neighbor=02:11:22:33:44:55,0,0,0,0,q" % addr,
1052             "BSS_TM_REQ %s neighbor=02:11:22:33:44:55,0,0,0,0,0q" % addr,
1053             "BSS_TM_REQ " + addr + " url=" + 256*'a',
1054             "BSS_TM_REQ %s url=foo mbo=1:2" % addr,
1055             "BSS_TM_REQ %s url=foo mbo=100000:0:0" % addr,
1056             "BSS_TM_REQ %s url=foo mbo=0:0:254" % addr,
1057             "BSS_TM_REQ %s url=foo mbo=0:100000:0" % addr]
1058    for t in tests:
1059        if "FAIL" not in hapd.request(t):
1060            raise Exception("Invalid command accepted: %s" % t)
1061
1062    with alloc_fail(hapd, 1, "=hostapd_ctrl_iface_bss_tm_req"):
1063        if "FAIL" not in hapd.request("BSS_TM_REQ %s url=http://foo" % addr):
1064            raise Exception("BSS_TM_REQ accepted during OOM")
1065
1066    with alloc_fail(hapd, 1, "=wnm_send_bss_tm_req"):
1067        if "FAIL" not in hapd.request("BSS_TM_REQ %s url=http://foo" % addr):
1068            raise Exception("BSS_TM_REQ accepted during OOM")
1069
1070    with fail_test(hapd, 1, "wnm_send_bss_tm_req"):
1071        if "FAIL" not in hapd.request("BSS_TM_REQ %s url=http://foo" % addr):
1072            raise Exception("BSS_TM_REQ accepted during failure testing")
1073
1074def test_wnm_bss_tm_termination(dev, apdev):
1075    """WNM BSS Transition Management and BSS termination"""
1076    hapd = start_wnm_ap(apdev[0])
1077    id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1078    addr = dev[0].own_addr()
1079
1080    if "OK" not in hapd.request("BSS_TM_REQ %s bss_term=0,1" % addr):
1081        raise Exception("BSS_TM_REQ failed")
1082    ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1083    if ev is None:
1084        raise Exception("No BSS-TM-RESP event seen")
1085
1086    if "OK" not in hapd.request("BSS_TM_REQ %s url=http://example.com/" % addr):
1087        raise Exception("BSS_TM_REQ failed")
1088    ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1089    if ev is None:
1090        raise Exception("No BSS-TM-RESP event seen")
1091
1092def test_wnm_bss_tm_scan_not_needed(dev, apdev):
1093    """WNM BSS Transition Management and scan not needed"""
1094    run_wnm_bss_tm_scan_not_needed(dev, apdev)
1095
1096def test_wnm_bss_tm_nei_vht(dev, apdev):
1097    """WNM BSS Transition Management and VHT neighbor"""
1098    run_wnm_bss_tm_scan_not_needed(dev, apdev, vht=True, nei_info="115,36,9")
1099
1100def test_wnm_bss_tm_nei_11a(dev, apdev):
1101    """WNM BSS Transition Management and 11a neighbor"""
1102    run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, nei_info="115,36,4")
1103
1104def test_wnm_bss_tm_nei_11g(dev, apdev):
1105    """WNM BSS Transition Management and 11g neighbor"""
1106    run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, hwmode='g',
1107                                   channel='2', freq=2417, nei_info="81,2,6")
1108
1109def test_wnm_bss_tm_nei_11b(dev, apdev):
1110    """WNM BSS Transition Management and 11g neighbor"""
1111    run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, hwmode='b',
1112                                   channel='3', freq=2422, nei_info="81,2,5")
1113
1114def run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=True, vht=False, hwmode='a',
1115                                   channel='36', freq=5180,
1116                                   nei_info="115,36,7,0301ff"):
1117    try:
1118        hapd = None
1119        hapd2 = None
1120        hapd = start_wnm_ap(apdev[0], country_code="FI", hw_mode="g",
1121                            channel="1")
1122        hapd2 = start_wnm_ap(apdev[1], country_code="FI", hw_mode=hwmode,
1123                             channel=channel, ht=ht, vht=vht)
1124        dev[0].scan_for_bss(apdev[1]['bssid'], freq)
1125
1126        id = dev[0].connect("test-wnm", key_mgmt="NONE",
1127                            bssid=apdev[0]['bssid'], scan_freq="2412")
1128        dev[0].set_network(id, "scan_freq", "")
1129        dev[0].set_network(id, "bssid", "")
1130
1131        addr = dev[0].own_addr()
1132        dev[0].dump_monitor()
1133
1134        logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1135        if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000," + nei_info):
1136            raise Exception("BSS_TM_REQ command failed")
1137        ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1138        if ev is None:
1139            raise Exception("No BSS Transition Management Response")
1140        if "status_code=0" not in ev:
1141            raise Exception("BSS transition request was not accepted: " + ev)
1142        if "target_bssid=" + apdev[1]['bssid'] not in ev:
1143            raise Exception("Unexpected target BSS: " + ev)
1144        dev[0].wait_connected(timeout=15, error="No reassociation seen")
1145        if apdev[1]['bssid'] not in ev:
1146            raise Exception("Unexpected reassociation target: " + ev)
1147        ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
1148        if ev is not None:
1149            raise Exception("Unexpected scan started")
1150        dev[0].dump_monitor()
1151    finally:
1152        clear_regdom_state(dev, hapd, hapd2)
1153
1154def test_wnm_bss_tm_scan_needed(dev, apdev):
1155    """WNM BSS Transition Management and scan needed"""
1156    try:
1157        hapd = None
1158        hapd2 = None
1159        hapd = start_wnm_ap(apdev[0], country_code="FI", hw_mode="g",
1160                            channel="1")
1161        hapd2 = start_wnm_ap(apdev[1], country_code="FI", hw_mode="a",
1162                             channel="36")
1163
1164        dev[0].flush_scan_cache()
1165        dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
1166
1167        id = dev[0].connect("test-wnm", key_mgmt="NONE",
1168                            bssid=apdev[0]['bssid'], scan_freq="2412")
1169        dev[0].set_network(id, "scan_freq", "")
1170        dev[0].set_network(id, "bssid", "")
1171
1172        addr = dev[0].own_addr()
1173        dev[0].dump_monitor()
1174
1175        logger.info("Wait 11 seconds for the last scan result to be too old, but still present in BSS table")
1176        time.sleep(11)
1177        logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1178        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"):
1179            raise Exception("BSS_TM_REQ command failed")
1180        ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1181        if ev is None:
1182            raise Exception("No BSS Transition Management Response")
1183        if "status_code=0" not in ev:
1184            raise Exception("BSS transition request was not accepted: " + ev)
1185        if "target_bssid=" + apdev[1]['bssid'] not in ev:
1186            raise Exception("Unexpected target BSS: " + ev)
1187        dev[0].wait_connected(timeout=15, error="No reassociation seen")
1188        if apdev[1]['bssid'] not in ev:
1189            raise Exception("Unexpected reassociation target: " + ev)
1190        ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
1191        if ev is not None:
1192            raise Exception("Unexpected scan started")
1193        dev[0].dump_monitor()
1194    finally:
1195        clear_regdom_state(dev, hapd, hapd2)
1196
1197def test_wnm_bss_tm_scan_needed_e4(dev, apdev):
1198    """WNM BSS Transition Management and scan needed (Table E-4)"""
1199    try:
1200        hapd = None
1201        hapd2 = None
1202        hapd = start_wnm_ap(apdev[0], country_code="FI", country3="0x04",
1203                            hw_mode="g", channel="1")
1204        hapd2 = start_wnm_ap(apdev[1], country_code="FI", country3="0x04",
1205                             hw_mode="a", channel="36")
1206        dev[0].flush_scan_cache()
1207        id = dev[0].connect("test-wnm", key_mgmt="NONE",
1208                            bssid=apdev[0]['bssid'], scan_freq="2412")
1209        dev[0].set_network(id, "scan_freq", "")
1210        dev[0].set_network(id, "bssid", "")
1211
1212        addr = dev[0].own_addr()
1213        dev[0].dump_monitor()
1214
1215        logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1216        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"):
1217            raise Exception("BSS_TM_REQ command failed")
1218        ev = hapd.wait_event(['BSS-TM-RESP'], timeout=4)
1219        if ev is None:
1220            raise Exception("No BSS Transition Management Response seen quickly enough - did scan optimization fail?")
1221        if "status_code=0" not in ev:
1222            raise Exception("BSS transition request was not accepted: " + ev)
1223        dev[0].wait_connected(timeout=15, error="No reassociation seen")
1224        # Wait for regdom change due to country IE to avoid issues with that
1225        # processing happening only after the disconnection and cfg80211 ending
1226        # up intersecting regdoms when we try to clear state back to world (00)
1227        # regdom below.
1228        while True:
1229            ev = dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5)
1230            if not ev or "COUNTRY_IE" in ev:
1231                break
1232        dev[0].dump_monitor()
1233    finally:
1234        clear_regdom_state(dev, hapd, hapd2)
1235
1236def start_wnm_tm(ap, country, dev, country3=None):
1237    hapd = start_wnm_ap(ap, country_code=country, country3=country3)
1238    id = dev.connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1239    wait_regdom_changes(dev)
1240    dev.dump_monitor()
1241    dev.set_network(id, "scan_freq", "")
1242    return hapd, id
1243
1244def stop_wnm_tm(hapd, dev):
1245    if hapd:
1246        hapd.request("DISABLE")
1247        time.sleep(0.1)
1248    dev[0].disconnect_and_stop_scan()
1249    subprocess.call(['iw', 'reg', 'set', '00'])
1250    wait_regdom_changes(dev[0])
1251    country = dev[0].get_driver_status_field("country")
1252    logger.info("Country code at the end: " + country)
1253    if country != "00":
1254        clear_country(dev)
1255
1256    dev[0].flush_scan_cache()
1257
1258def wnm_bss_tm_check(hapd, dev, data):
1259    addr = dev.p2p_interface_addr()
1260    if "OK" not in hapd.request("BSS_TM_REQ " + addr + " " + data):
1261        raise Exception("BSS_TM_REQ command failed")
1262    ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
1263    if ev is None:
1264        raise Exception("No scan started")
1265    ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
1266    if ev is None:
1267        raise Exception("Scan did not complete")
1268
1269    ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1270    if ev is None:
1271        raise Exception("No BSS Transition Management Response")
1272    if "status_code=7" not in ev:
1273        raise Exception("Unexpected response: " + ev)
1274
1275def test_wnm_bss_tm_country_us(dev, apdev):
1276    """WNM BSS Transition Management (US)"""
1277    try:
1278        hapd = None
1279        hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
1280
1281        logger.info("Preferred Candidate List (no matching neighbor, known channels)")
1282        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")
1283
1284        # Make the test take less time by limiting full scans
1285        dev[0].set_network(id, "scan_freq", "2412")
1286        logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
1287        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")
1288
1289        logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
1290        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")
1291    finally:
1292        stop_wnm_tm(hapd, dev)
1293
1294def test_wnm_bss_tm_country_fi(dev, apdev):
1295    """WNM BSS Transition Management (FI)"""
1296    addr = dev[0].p2p_interface_addr()
1297    try:
1298        hapd = None
1299        hapd, id = start_wnm_tm(apdev[0], "FI", dev[0])
1300
1301        logger.info("Preferred Candidate List (no matching neighbor, known channels)")
1302        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")
1303
1304        # Make the test take less time by limiting full scans
1305        dev[0].set_network(id, "scan_freq", "2412")
1306        logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
1307        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")
1308
1309        logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
1310        wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,0,0,7")
1311    finally:
1312        stop_wnm_tm(hapd, dev)
1313
1314def test_wnm_bss_tm_country_jp(dev, apdev):
1315    """WNM BSS Transition Management (JP)"""
1316    addr = dev[0].p2p_interface_addr()
1317    try:
1318        hapd = None
1319        hapd, id = start_wnm_tm(apdev[0], "JP", dev[0])
1320
1321        logger.info("Preferred Candidate List (no matching neighbor, known channels)")
1322        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")
1323
1324        # Make the test take less time by limiting full scans
1325        dev[0].set_network(id, "scan_freq", "2412")
1326        logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
1327        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")
1328    finally:
1329        stop_wnm_tm(hapd, dev)
1330
1331def test_wnm_bss_tm_country_cn(dev, apdev):
1332    """WNM BSS Transition Management (CN)"""
1333    addr = dev[0].p2p_interface_addr()
1334    try:
1335        hapd = None
1336        hapd, id = start_wnm_tm(apdev[0], "CN", dev[0])
1337
1338        logger.info("Preferred Candidate List (no matching neighbor, known channels)")
1339        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")
1340
1341        # Make the test take less time by limiting full scans
1342        dev[0].set_network(id, "scan_freq", "2412")
1343        logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
1344        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")
1345    finally:
1346        stop_wnm_tm(hapd, dev)
1347
1348def test_wnm_bss_tm_global(dev, apdev):
1349    """WNM BSS Transition Management (global)"""
1350    run_wnm_bss_tm_global(dev, apdev, "XX", None)
1351
1352def test_wnm_bss_tm_global4(dev, apdev):
1353    """WNM BSS Transition Management (global; indicate table E-4)"""
1354    run_wnm_bss_tm_global(dev, apdev, "FI", "0x04")
1355
1356def run_wnm_bss_tm_global(dev, apdev, country, country3):
1357    addr = dev[0].p2p_interface_addr()
1358    try:
1359        hapd = None
1360        hapd, id = start_wnm_tm(apdev[0], country, dev[0], country3=country3)
1361
1362        logger.info("Preferred Candidate List (no matching neighbor, known channels)")
1363        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")
1364
1365        # Make the test take less time by limiting full scans
1366        dev[0].set_network(id, "scan_freq", "2412")
1367        logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
1368        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")
1369
1370        logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
1371        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")
1372    finally:
1373        stop_wnm_tm(hapd, dev)
1374
1375def test_wnm_bss_tm_op_class_0(dev, apdev):
1376    """WNM BSS Transition Management with invalid operating class"""
1377    try:
1378        hapd = None
1379        hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
1380
1381        logger.info("Preferred Candidate List (no matching neighbor, invalid op class specified for channels)")
1382        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")
1383    finally:
1384        stop_wnm_tm(hapd, dev)
1385
1386def test_wnm_bss_tm_rsn(dev, apdev):
1387    """WNM BSS Transition Management with RSN"""
1388    passphrase = "zxcvbnm,.-"
1389    try:
1390        hapd = None
1391        hapd2 = None
1392        hapd = start_wnm_ap(apdev[0], country_code="FI", hw_mode="g",
1393                            channel="1",
1394                            rsn=True, pmf=False, passphrase=passphrase)
1395        hapd2 = start_wnm_ap(apdev[1], country_code="FI", hw_mode="a",
1396                             channel="36",
1397                             rsn=True, pmf=False, passphrase=passphrase)
1398        dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
1399
1400        id = dev[0].connect("test-wnm-rsn", psk=passphrase,
1401                            bssid=apdev[0]['bssid'], scan_freq="2412")
1402        dev[0].set_network(id, "scan_freq", "")
1403        dev[0].set_network(id, "bssid", "")
1404
1405        addr = dev[0].own_addr()
1406        dev[0].dump_monitor()
1407
1408        time.sleep(0.5)
1409        logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1410        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"):
1411            raise Exception("BSS_TM_REQ command failed")
1412        ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1413        if ev is None:
1414            raise Exception("No BSS Transition Management Response")
1415        if "status_code=0" not in ev:
1416            raise Exception("BSS transition request was not accepted: " + ev)
1417        if "target_bssid=" + apdev[1]['bssid'] not in ev:
1418            raise Exception("Unexpected target BSS: " + ev)
1419        dev[0].wait_connected(timeout=15, error="No reassociation seen")
1420        if apdev[1]['bssid'] not in ev:
1421            raise Exception("Unexpected reassociation target: " + ev)
1422    finally:
1423        clear_regdom_state(dev, hapd, hapd2)
1424
1425def test_wnm_action_proto(dev, apdev):
1426    """WNM Action protocol testing"""
1427    hapd = start_wnm_ap(apdev[0], bss_transition=False, wnm_sleep_mode=True)
1428    bssid = apdev[0]['bssid']
1429    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1430    dev[0].request("WNM_SLEEP enter")
1431    time.sleep(0.1)
1432    hapd.set("ext_mgmt_frame_handling", "1")
1433
1434    msg = {}
1435    msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1436    msg['da'] = dev[0].own_addr()
1437    msg['sa'] = bssid
1438    msg['bssid'] = bssid
1439
1440    dialog_token = 1
1441
1442    logger.debug("Unexpected WNM-Notification Response")
1443    # Note: This is actually not registered for user space processing in
1444    # driver_nl80211.c nl80211_mgmt_subscribe_non_ap() and as such, won't make
1445    # it to wpa_supplicant.
1446    msg['payload'] = struct.pack("<BBBB",
1447                                 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_RESP,
1448                                 dialog_token, 0)
1449    hapd.mgmt_tx(msg)
1450    expect_ack(hapd)
1451
1452    logger.debug("Truncated WNM-Notification Request (no Type field)")
1453    msg['payload'] = struct.pack("<BBB",
1454                                 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
1455                                 dialog_token)
1456    hapd.mgmt_tx(msg)
1457    expect_ack(hapd)
1458
1459    logger.debug("WFA WNM-Notification Request with truncated IE (min)")
1460    msg['payload'] = struct.pack("<BBBBBB",
1461                                 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
1462                                 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 1)
1463    hapd.mgmt_tx(msg)
1464    expect_ack(hapd)
1465
1466    logger.debug("WFA WNM-Notification Request with truncated IE (max)")
1467    msg['payload'] = struct.pack("<BBBBBB",
1468                                 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
1469                                 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 255)
1470    hapd.mgmt_tx(msg)
1471    expect_ack(hapd)
1472
1473    logger.debug("WFA WNM-Notification Request with too short IE")
1474    msg['payload'] = struct.pack("<BBBBBB",
1475                                 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
1476                                 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 0)
1477    hapd.mgmt_tx(msg)
1478    expect_ack(hapd)
1479
1480    logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL")
1481    msg['payload'] = struct.pack(">BBBBBBLB",
1482                                 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
1483                                 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
1484                                 0x506f9a00, 1)
1485    hapd.mgmt_tx(msg)
1486    expect_ack(hapd)
1487
1488    logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(2)")
1489    msg['payload'] = struct.pack(">BBBBBBLBB",
1490                                 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
1491                                 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 6,
1492                                 0x506f9a00, 1, 0)
1493    hapd.mgmt_tx(msg)
1494    expect_ack(hapd)
1495
1496    logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(3)")
1497    msg['payload'] = struct.pack(">BBBBBBLB",
1498                                 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
1499                                 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
1500                                 0x506f9a00, 0xff)
1501    hapd.mgmt_tx(msg)
1502    expect_ack(hapd)
1503
1504    logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(min)")
1505    msg['payload'] = struct.pack(">BBBBBBLBHB",
1506                                 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
1507                                 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
1508                                 0x506f9a01, 0, 0, 1)
1509    hapd.mgmt_tx(msg)
1510    expect_ack(hapd)
1511
1512    logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(max)")
1513    msg['payload'] = struct.pack(">BBBBBBLBHB",
1514                                 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
1515                                 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
1516                                 0x506f9a01, 0, 0, 0xff)
1517    hapd.mgmt_tx(msg)
1518    expect_ack(hapd)
1519
1520    logger.debug("WFA WNM-Notification Request with unsupported IE")
1521    msg['payload'] = struct.pack("<BBBBBBL",
1522                                 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
1523                                 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 4, 0)
1524    hapd.mgmt_tx(msg)
1525    expect_ack(hapd)
1526
1527    logger.debug("WNM-Notification Request with unknown WNM-Notification type 0")
1528    msg['payload'] = struct.pack("<BBBB",
1529                                 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
1530                                 dialog_token, WNM_NOTIF_TYPE_FW_UPGRADE)
1531    hapd.mgmt_tx(msg)
1532    expect_ack(hapd)
1533
1534    logger.debug("Truncated WNM Sleep Mode Response - no Dialog Token")
1535    msg['payload'] = struct.pack("<BB",
1536                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP)
1537    hapd.mgmt_tx(msg)
1538    expect_ack(hapd)
1539
1540    logger.debug("Truncated WNM Sleep Mode Response - no Key Data Length")
1541    msg['payload'] = struct.pack("<BBB",
1542                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0)
1543    hapd.mgmt_tx(msg)
1544    expect_ack(hapd)
1545
1546    logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (min)")
1547    msg['payload'] = struct.pack("<BBBH",
1548                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1549                                 1)
1550    hapd.mgmt_tx(msg)
1551    expect_ack(hapd)
1552
1553    logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (max)")
1554    msg['payload'] = struct.pack("<BBBH",
1555                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1556                                 0xffff)
1557    hapd.mgmt_tx(msg)
1558    expect_ack(hapd)
1559
1560    logger.debug("WNM Sleep Mode Response - truncated IE header")
1561    msg['payload'] = struct.pack("<BBBHB",
1562                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1563                                 0, 0)
1564    hapd.mgmt_tx(msg)
1565    expect_ack(hapd)
1566
1567    logger.debug("WNM Sleep Mode Response - truncated IE")
1568    msg['payload'] = struct.pack("<BBBHBB",
1569                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1570                                 0, 0, 1)
1571    hapd.mgmt_tx(msg)
1572    expect_ack(hapd)
1573
1574    logger.debug("WNM Sleep Mode Response - Empty TFS Response")
1575    msg['payload'] = struct.pack("<BBBHBB",
1576                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1577                                 0, WLAN_EID_TFS_RESP, 0)
1578    hapd.mgmt_tx(msg)
1579    expect_ack(hapd)
1580
1581    logger.debug("WNM Sleep Mode Response - EID 0 not recognized")
1582    msg['payload'] = struct.pack("<BBBHBB",
1583                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1584                                 0, 0, 0)
1585    hapd.mgmt_tx(msg)
1586    expect_ack(hapd)
1587
1588    logger.debug("WNM Sleep Mode Response - Empty WNM Sleep Mode element and TFS Response element")
1589    msg['payload'] = struct.pack("<BBBHBBBB",
1590                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1591                                 0, WLAN_EID_WNMSLEEP, 0, WLAN_EID_TFS_RESP, 0)
1592    hapd.mgmt_tx(msg)
1593    expect_ack(hapd)
1594
1595    logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element and empty TFS Response element")
1596    msg['payload'] = struct.pack("<BBBHBBBBHBB",
1597                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1598                                 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1599                                 WNM_STATUS_SLEEP_ACCEPT, 0,
1600                                 WLAN_EID_TFS_RESP, 0)
1601    hapd.mgmt_tx(msg)
1602    expect_ack(hapd)
1603
1604    logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(exit, deny key) and empty TFS Response element")
1605    msg['payload'] = struct.pack("<BBBHBBBBHBB",
1606                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1607                                 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1608                                 WNM_STATUS_DENIED_KEY, 0,
1609                                 WLAN_EID_TFS_RESP, 0)
1610    hapd.mgmt_tx(msg)
1611    expect_ack(hapd)
1612
1613    logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(enter, deny key) and empty TFS Response element")
1614    msg['payload'] = struct.pack("<BBBHBBBBHBB",
1615                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1616                                 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1617                                 WNM_STATUS_DENIED_KEY, 0,
1618                                 WLAN_EID_TFS_RESP, 0)
1619    hapd.mgmt_tx(msg)
1620    expect_ack(hapd)
1621
1622@remote_compatible
1623def test_wnm_action_proto_pmf(dev, apdev):
1624    """WNM Action protocol testing (PMF enabled)"""
1625    ssid = "test-wnm-pmf"
1626    hapd = start_wnm_ap(apdev[0], rsn=True, wnm_sleep_mode=True, ssid=ssid)
1627    bssid = apdev[0]['bssid']
1628    dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
1629                   proto="WPA2", ieee80211w="2", scan_freq="2412")
1630    dev[0].request("WNM_SLEEP enter")
1631    time.sleep(0.1)
1632    hapd.set("ext_mgmt_frame_handling", "1")
1633
1634    msg = {}
1635    msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1636    msg['da'] = dev[0].own_addr()
1637    msg['sa'] = bssid
1638    msg['bssid'] = bssid
1639
1640    logger.debug("WNM Sleep Mode Response - Invalid Key Data element length")
1641    keydata = struct.pack("<BB", 0, 1)
1642    msg['payload'] = struct.pack("<BBBH",
1643                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1644                                 len(keydata))
1645    msg['payload'] += keydata
1646    msg['payload'] += struct.pack("<BBBBHBB",
1647                                  WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1648                                  WNM_STATUS_SLEEP_ACCEPT, 0,
1649                                  WLAN_EID_TFS_RESP, 0)
1650    hapd.mgmt_tx(msg)
1651    expect_ack(hapd)
1652
1653    logger.debug("WNM Sleep Mode Response - Too short GTK subelem")
1654    keydata = struct.pack("<BB", WNM_SLEEP_SUBELEM_GTK, 0)
1655    msg['payload'] = struct.pack("<BBBH",
1656                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1657                                 len(keydata))
1658    msg['payload'] += keydata
1659    msg['payload'] += struct.pack("<BBBBHBB",
1660                                  WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1661                                  WNM_STATUS_SLEEP_ACCEPT, 0,
1662                                  WLAN_EID_TFS_RESP, 0)
1663    hapd.mgmt_tx(msg)
1664    expect_ack(hapd)
1665
1666    logger.debug("WNM Sleep Mode Response - Invalid GTK subelem")
1667    keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1668                          0, 17, 0, 0, 0, 0, 0, 0)
1669    msg['payload'] = struct.pack("<BBBH",
1670                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1671                                 len(keydata))
1672    msg['payload'] += keydata
1673    msg['payload'] += struct.pack("<BBBBHBB",
1674                                  WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1675                                  WNM_STATUS_SLEEP_ACCEPT, 0,
1676                                  WLAN_EID_TFS_RESP, 0)
1677    hapd.mgmt_tx(msg)
1678    expect_ack(hapd)
1679
1680    logger.debug("WNM Sleep Mode Response - Invalid GTK subelem (2)")
1681    keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1682                          0, 0, 0, 0, 0, 0, 0, 0)
1683    msg['payload'] = struct.pack("<BBBH",
1684                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1685                                 len(keydata))
1686    msg['payload'] += keydata
1687    msg['payload'] += struct.pack("<BBBBHBB",
1688                                  WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1689                                  WNM_STATUS_SLEEP_ACCEPT, 0,
1690                                  WLAN_EID_TFS_RESP, 0)
1691    hapd.mgmt_tx(msg)
1692    expect_ack(hapd)
1693
1694    logger.debug("WNM Sleep Mode Response - GTK subelem and too short IGTK subelem")
1695    keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1696    keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1697                           0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1698    keydata += struct.pack("<BB", WNM_SLEEP_SUBELEM_IGTK, 0)
1699    msg['payload'] = struct.pack("<BBBH",
1700                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1701                                 len(keydata))
1702    msg['payload'] += keydata
1703    msg['payload'] += struct.pack("<BBBBHBB",
1704                                  WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1705                                  WNM_STATUS_SLEEP_ACCEPT, 0,
1706                                  WLAN_EID_TFS_RESP, 0)
1707    hapd.mgmt_tx(msg)
1708    expect_ack(hapd)
1709
1710    logger.debug("WNM Sleep Mode Response - Unknown subelem")
1711    keydata = struct.pack("<BB", 255, 0)
1712    msg['payload'] = struct.pack("<BBBH",
1713                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1714                                 len(keydata))
1715    msg['payload'] += keydata
1716    msg['payload'] += struct.pack("<BBBBHBB",
1717                                  WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1718                                  WNM_STATUS_SLEEP_ACCEPT, 0,
1719                                  WLAN_EID_TFS_RESP, 0)
1720    hapd.mgmt_tx(msg)
1721    expect_ack(hapd)
1722
1723@remote_compatible
1724def test_wnm_action_proto_no_pmf(dev, apdev):
1725    """WNM Action protocol testing (PMF disabled)"""
1726    ssid = "test-wnm-no-pmf"
1727    hapd = start_wnm_ap(apdev[0], rsn=True, pmf=False, bss_transition=False,
1728                        wnm_sleep_mode=True, ssid=ssid)
1729    bssid = apdev[0]['bssid']
1730    dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1731                   proto="WPA2", ieee80211w="0", scan_freq="2412")
1732    dev[0].request("WNM_SLEEP enter")
1733    time.sleep(0.1)
1734    hapd.set("ext_mgmt_frame_handling", "1")
1735    hapd.dump_monitor()
1736    dev[0].request("WNM_SLEEP exit")
1737    ev = hapd.wait_event(['MGMT-RX'], timeout=5)
1738    if ev is None:
1739        raise Exception("WNM-Sleep Mode Request not seen")
1740
1741    msg = {}
1742    msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1743    msg['da'] = dev[0].own_addr()
1744    msg['sa'] = bssid
1745    msg['bssid'] = bssid
1746
1747    logger.debug("WNM Sleep Mode Response - GTK subelem and IGTK subelem")
1748    keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1749    keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1750                           0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1751    keydata += struct.pack("<BBHLH4L", WNM_SLEEP_SUBELEM_IGTK, 2 + 6 + 16, 0,
1752                           0x10203040, 0x5060,
1753                           0xf1f2f3f4, 0xf5f6f7f8, 0xf9f0fafb, 0xfcfdfeff)
1754    msg['payload'] = struct.pack("<BBBH",
1755                                 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1756                                 len(keydata))
1757    msg['payload'] += keydata
1758    msg['payload'] += struct.pack("<BBBBHBB",
1759                                  WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1760                                  WNM_STATUS_SLEEP_ACCEPT, 0,
1761                                  WLAN_EID_TFS_RESP, 0)
1762    hapd.mgmt_tx(msg)
1763    expect_ack(hapd)
1764
1765    ev = dev[0].wait_event(["WNM: Ignore Key Data"], timeout=5)
1766    if ev is None:
1767        raise Exception("Key Data not ignored")
1768
1769def test_wnm_bss_tm_req_with_mbo_ie(dev, apdev):
1770    """WNM BSS transition request with MBO IE and reassociation delay attribute"""
1771    ssid = "test-wnm-mbo"
1772    hapd = start_wnm_ap(apdev[0], rsn=True, pmf=False, ssid=ssid)
1773    bssid = apdev[0]['bssid']
1774    if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
1775        raise Exception("Failed to set STA as cellular data capable")
1776
1777    dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1778                   proto="WPA2", ieee80211w="0", scan_freq="2412")
1779
1780    logger.debug("BTM request with MBO reassociation delay when disassoc imminent is not set")
1781    if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=3:2:1"):
1782        raise Exception("BSS transition management succeeded unexpectedly")
1783
1784    logger.debug("BTM request with invalid MBO transition reason code")
1785    if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=10:2:1"):
1786        raise Exception("BSS transition management succeeded unexpectedly")
1787
1788    logger.debug("BTM request with MBO reassociation retry delay of 5 seconds")
1789    if 'OK' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " disassoc_imminent=1 disassoc_timer=3 mbo=3:5:1"):
1790        raise Exception("BSS transition management command failed")
1791
1792    ev = dev[0].wait_event(['MBO-CELL-PREFERENCE'], 1)
1793    if ev is None or "preference=1" not in ev:
1794        raise Exception("Timeout waiting for MBO-CELL-PREFERENCE event")
1795
1796    ev = dev[0].wait_event(['MBO-TRANSITION-REASON'], 1)
1797    if ev is None or "reason=3" not in ev:
1798        raise Exception("Timeout waiting for MBO-TRANSITION-REASON event")
1799
1800    t0 = datetime.now()
1801
1802    ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1803    if ev is None:
1804        raise Exception("No BSS Transition Management Response")
1805    if dev[0].own_addr() not in ev:
1806        raise Exception("Unexpected BSS Transition Management Response address")
1807
1808    ev = dev[0].wait_event(['CTRL-EVENT-DISCONNECTED'], 5)
1809    if ev is None:
1810        raise Exception("Station did not disconnect although disassoc imminent was set")
1811
1812    # Set the scan interval to make dev[0] look for connections
1813    if 'OK' not in dev[0].request("SCAN_INTERVAL 1"):
1814        raise Exception("Failed to set scan interval")
1815
1816    # Wait until connected
1817    ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 10)
1818    if ev is None:
1819        raise Exception("Station did not connect")
1820
1821    # Make sure no connection is made during the retry delay
1822    time_diff = datetime.now() - t0
1823    if time_diff.total_seconds() < 5:
1824        raise Exception("Station connected before assoc retry delay was over")
1825
1826    if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
1827        raise Exception("Failed to set STA as cellular data not-capable")
1828
1829@remote_compatible
1830def test_wnm_bss_transition_mgmt_query(dev, apdev):
1831    """WNM BSS Transition Management query"""
1832    hapd = start_wnm_ap(apdev[0])
1833    params = {"ssid": "another"}
1834    hapd2 = hostapd.add_ap(apdev[1], params)
1835
1836    dev[0].scan_for_bss(apdev[1]['bssid'], 2412)
1837    dev[0].scan_for_bss(apdev[0]['bssid'], 2412)
1838
1839    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1840    dev[0].request("WNM_BSS_QUERY 0 list")
1841
1842    ev = dev[0].wait_event(["WNM: BSS Transition Management Request"],
1843                           timeout=5)
1844    if ev is None:
1845        raise Exception("No BSS Transition Management Request frame seen")
1846
1847    ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1848    if ev is None:
1849        raise Exception("No BSS Transition Management Response frame seen")
1850
1851def test_wnm_bss_transition_mgmt_query_disabled_on_ap(dev, apdev):
1852    """WNM BSS Transition Management query - TM disabled on AP"""
1853    hapd = start_wnm_ap(apdev[0], bss_transition=False)
1854    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1855    # Ignore BSS Transition Management Query from 02:00:00:00:00:00 since BSS Transition Management is disabled
1856    dev[0].request("WNM_BSS_QUERY 0 list")
1857    ev = hapd.wait_event(["BSS-TM-RESP"], timeout=0.1)
1858    if ev is not None:
1859        raise Exception("Unexpected BSS TM Response reported")
1860
1861def test_wnm_bss_transition_mgmt_query_mbo(dev, apdev):
1862    """WNM BSS Transition Management query - TM only due to MBO on AP"""
1863    hapd = start_wnm_ap(apdev[0], bss_transition=False, mbo=True)
1864    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1865    dev[0].request("WNM_BSS_QUERY 0 list")
1866    ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1867    if ev is None:
1868        raise Exception("No BSS TM Response reported")
1869
1870@remote_compatible
1871def test_wnm_bss_tm_security_mismatch(dev, apdev):
1872    """WNM BSS Transition Management and security mismatch"""
1873    hapd = start_wnm_ap(apdev[0], hw_mode="g", channel="1", ssid="test-wnm",
1874                        rsn=True, pmf=False)
1875    hapd2 = start_wnm_ap(apdev[1], hw_mode="g", channel="11")
1876    dev[0].scan_for_bss(apdev[1]['bssid'], 2462)
1877
1878    id = dev[0].connect("test-wnm", psk="12345678",
1879                        bssid=apdev[0]['bssid'], scan_freq="2412")
1880    dev[0].set_network(id, "scan_freq", "")
1881    dev[0].set_network(id, "bssid", "")
1882
1883    addr = dev[0].own_addr()
1884    dev[0].dump_monitor()
1885
1886    logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1887    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"):
1888        raise Exception("BSS_TM_REQ command failed")
1889    ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1890    if ev is None:
1891        raise Exception("No BSS Transition Management Response")
1892    if "status_code=7" not in ev:
1893        raise Exception("Unexpected BSS transition request response: " + ev)
1894
1895def test_wnm_bss_tm_connect_cmd(dev, apdev):
1896    """WNM BSS Transition Management and cfg80211 connect command"""
1897    hapd = start_wnm_ap(apdev[0], hw_mode="g", channel="1")
1898    hapd2 = start_wnm_ap(apdev[1], hw_mode="g", channel="11")
1899
1900    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1901    wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
1902
1903    wpas.scan_for_bss(apdev[1]['bssid'], 2462)
1904
1905    id = wpas.connect("test-wnm", key_mgmt="NONE",
1906                      bssid=apdev[0]['bssid'], scan_freq="2412")
1907    wpas.set_network(id, "scan_freq", "")
1908    wpas.set_network(id, "bssid", "")
1909
1910    addr = wpas.own_addr()
1911    wpas.dump_monitor()
1912
1913    logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
1914    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"):
1915        raise Exception("BSS_TM_REQ command failed")
1916    ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1917    if ev is None:
1918        raise Exception("No BSS Transition Management Response")
1919    if "status_code=0" not in ev:
1920        raise Exception("BSS transition request was not accepted: " + ev)
1921    if "target_bssid=" + apdev[1]['bssid'] not in ev:
1922        raise Exception("Unexpected target BSS: " + ev)
1923    ev = wpas.wait_event(["CTRL-EVENT-CONNECTED",
1924                          "CTRL-EVENT-DISCONNECTED"], timeout=10)
1925    if ev is None:
1926        raise Exception("No reassociation seen")
1927    if "CTRL-EVENT-DISCONNECTED" in ev:
1928        raise Exception("Unexpected disconnection reported")
1929    if apdev[1]['bssid'] not in ev:
1930        raise Exception("Unexpected reassociation target: " + ev)
1931
1932def test_wnm_bss_tm_reject(dev, apdev):
1933    """WNM BSS Transition Management request getting rejected"""
1934    try:
1935        hapd = None
1936        hapd = start_wnm_ap(apdev[0], country_code="FI", hw_mode="g",
1937                            channel="1")
1938        id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1939        addr = dev[0].own_addr()
1940        dev[0].dump_monitor()
1941
1942        if "OK" not in dev[0].request("SET reject_btm_req_reason 123"):
1943            raise Exception("Failed to set reject_btm_req_reason")
1944
1945        if "OK" not in hapd.request("BSS_TM_REQ " + addr + " disassoc_timer=1"):
1946            raise Exception("BSS_TM_REQ command failed")
1947        ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1948        if ev is None:
1949            raise Exception("No BSS Transition Management Response")
1950        if addr not in ev:
1951            raise Exception("Unexpected BSS Transition Management Response address")
1952        if "status_code=123" not in ev:
1953            raise Exception("Unexpected BSS Transition Management Response status: " + ev)
1954        dev[0].wait_disconnected()
1955        dev[0].wait_connected()
1956    finally:
1957        if hapd:
1958            hapd.request("DISABLE")
1959        dev[0].disconnect_and_stop_scan()
1960        subprocess.call(['iw', 'reg', 'set', '00'])
1961        dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5)
1962        dev[0].flush_scan_cache()
1963
1964def test_wnm_bss_tm_ap_proto(dev, apdev):
1965    """WNM BSS TM - protocol testing for AP message parsing"""
1966    hapd = start_wnm_ap(apdev[0])
1967    bssid = hapd.own_addr()
1968    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1969    addr = dev[0].own_addr()
1970
1971    hdr = "d0003a01" + bssid.replace(':', '') + addr.replace(':', '') + bssid.replace(':', '') + "1000"
1972    hapd.set("ext_mgmt_frame_handling", "1")
1973    tests = ["0a",
1974             "0a06",
1975             "0a0601",
1976             "0a060100",
1977             "0a080000",
1978             "0a08000000",
1979             "0a080000001122334455",
1980             "0a08000000112233445566",
1981             "0a08000000112233445566112233445566778899",
1982             "0a08ffffff",
1983             "0a08ffffff112233445566778899",
1984             "0a1a",
1985             "0a1a00",
1986             "0a1a0000",
1987             "0a0c016015007f0f000000000000000000000000000000000000",
1988             "0a0700",
1989             "0aff00",
1990             "0aff"]
1991    for t in tests:
1992        if "OK" not in hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + t):
1993            raise Exception("MGMT_RX_PROCESS failed")
1994
1995    hapd.set("ext_mgmt_frame_handling", "0")
1996
1997def test_wnm_bss_transition_mgmt_query_with_unknown_candidates(dev, apdev):
1998    """WNM BSS Transition Management query with unknown candidates"""
1999    hapd = start_wnm_ap(apdev[0])
2000    dev[0].scan_for_bss(apdev[0]['bssid'], 2412)
2001
2002    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
2003    dev[0].request("WNM_BSS_QUERY 0 neighbor=00:11:22:33:44:55,0,81,1,4")
2004
2005    ev = dev[0].wait_event(["WNM: BSS Transition Management Request"],
2006                           timeout=5)
2007    if ev is None:
2008        raise Exception("No BSS Transition Management Request frame seen")
2009
2010    ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
2011    if ev is None:
2012        raise Exception("No BSS Transition Management Response frame seen")
2013
2014def test_wnm_time_adv_without_time_zone(dev, apdev):
2015    """WNM Time Advertisement without time zone configuration"""
2016    params = {"ssid": "test-wnm",
2017              "time_advertisement": "2"}
2018    hostapd.add_ap(apdev[0], params)
2019
2020    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
2021
2022def test_wnm_coloc_intf_reporting(dev, apdev):
2023    """WNM Collocated Interference Reporting"""
2024    hapd = start_wnm_ap(apdev[0], bss_transition=False,
2025                        coloc_intf_reporting=True)
2026
2027    no_intf = struct.pack("<BBBBBLLLLH", 96, 21, 0, 127, 0x0f, 0, 0, 0, 0, 0)
2028
2029    try:
2030        dev[0].set("coloc_intf_reporting", "1")
2031        dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
2032        addr = dev[0].own_addr()
2033        if "OK" not in hapd.request("COLOC_INTF_REQ %s 1 5" % addr):
2034            raise Exception("Could not send Collocated Interference Request")
2035        ev = dev[0].wait_event(["COLOC-INTF-REQ"], timeout=2)
2036        if ev is None:
2037            raise Exception("No Collocated Interference Request frame seen")
2038        vals = ev.split(' ')
2039        if vals[2] != '1' or vals[3] != '5':
2040            raise Exception("Unexpected request values: " + ev)
2041        dev[0].set("coloc_intf_elems", binascii.hexlify(no_intf).decode())
2042        ev = hapd.wait_event(["COLOC-INTF-REPORT"], timeout=1)
2043        if ev is None:
2044            raise Exception("No Collocated Interference Report frame seen")
2045        if addr + " 1 " + binascii.hexlify(no_intf).decode() not in ev:
2046            raise Exception("Unexpected report values: " + ev)
2047
2048        if "OK" not in hapd.request("COLOC_INTF_REQ %s 0 0" % addr):
2049            raise Exception("Could not send Collocated Interference Request")
2050        ev = dev[0].wait_event(["COLOC-INTF-REQ"], timeout=2)
2051        if ev is None:
2052            raise Exception("No Collocated Interference Request frame seen")
2053        vals = ev.split(' ')
2054        if vals[2] != '0' or vals[3] != '0':
2055            raise Exception("Unexpected request values: " + ev)
2056
2057        res = dev[0].request("COLOC_INTF_REPORT " + binascii.hexlify(no_intf).decode())
2058        if "OK" not in res:
2059            raise Exception("Could not send unsolicited report")
2060        ev = hapd.wait_event(["COLOC-INTF-REPORT"], timeout=1)
2061        if ev is None:
2062            raise Exception("No Collocated Interference Report frame seen")
2063        if addr + " 0 " + binascii.hexlify(no_intf).decode() not in ev:
2064            raise Exception("Unexpected report values: " + ev)
2065
2066        if "FAIL" not in hapd.request("COLOC_INTF_REQ foo 1 5"):
2067            raise Exception("Invalid COLOC_INTF_REQ accepted")
2068        if "FAIL" not in hapd.request("COLOC_INTF_REQ 02:ff:ff:ff:ff:ff 1 5"):
2069            raise Exception("COLOC_INTF_REQ for unknown STA accepted")
2070        if "FAIL" not in hapd.request("COLOC_INTF_REQ %s 1" % addr):
2071            raise Exception("Invalid COLOC_INTF_REQ accepted")
2072        if "FAIL" not in hapd.request("COLOC_INTF_REQ %s" % addr):
2073            raise Exception("Invalid COLOC_INTF_REQ accepted")
2074    finally:
2075        dev[0].set("coloc_intf_reporting", "0")
2076        dev[0].set("coloc_intf_elems", "")
2077
2078def test_wnm_coloc_intf_reporting_errors(dev, apdev):
2079    """WNM Collocated Interference Reporting errors"""
2080    hapd = start_wnm_ap(apdev[0], bss_transition=False,
2081                        coloc_intf_reporting=True)
2082    bssid = hapd.own_addr()
2083    dev[0].set("coloc_intf_reporting", "1")
2084    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
2085    addr = dev[0].own_addr()
2086    if "FAIL" not in hapd.request("COLOC_INTF_REQ %s 4 5" % addr):
2087        raise Exception("Invalid Collocated Interference Request accepted")
2088    hdr = "d0003a01" + bssid.replace(':', '') + addr.replace(':', '') + bssid.replace(':', '') + "1000"
2089    hapd.set("ext_mgmt_frame_handling", "1")
2090    tests = ["0a0c016015007f0f000000000000000000000000000000000000",
2091             "0a0c"]
2092    with alloc_fail(hapd, 1, "ieee802_11_rx_wnm_coloc_intf_report"):
2093        for t in tests:
2094            if "OK" not in hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + t):
2095                raise Exception("MGMT_RX_PROCESS failed")
2096
2097    hapd.set("ext_mgmt_frame_handling", "0")
2098
2099def test_wnm_bss_transition_mgmt_disabled(dev, apdev):
2100    """WNM BSS Transition Management disabled"""
2101    hapd = start_wnm_ap(apdev[0])
2102    try:
2103        dev[0].set("disable_btm", "1")
2104        dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
2105        addr = dev[0].own_addr()
2106        hapd.request("BSS_TM_REQ " + addr)
2107        ev = hapd.wait_event(['BSS-TM-RESP'], timeout=0.5)
2108        if ev is not None:
2109            raise Exception("Unexpected BSS Transition Management Response")
2110    finally:
2111        dev[0].set("disable_btm", "0")
2112
2113def test_wnm_time_adv_restart(dev, apdev):
2114    """WNM time advertisement and interface restart"""
2115    hapd = start_wnm_ap(apdev[0], time_adv=True)
2116    hapd.disable()
2117    hapd.enable()
2118    dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
2119
2120def test_wnm_event_report(dev, apdev):
2121    """WNM event report"""
2122    ssid = "test-wnm-rsn"
2123    hapd = start_wnm_ap(apdev[0], rsn=True, he=True)
2124    bssid = apdev[0]['bssid']
2125    dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
2126                   proto="WPA2", ieee80211w="2", scan_freq="2412")
2127    hapd.wait_sta()
2128
2129    msg = {'fc': MGMT_SUBTYPE_ACTION << 4,
2130           'da': bssid,
2131           'sa': dev[0].own_addr(),
2132           'bssid': bssid}
2133    cmd = "MGMT_TX {} {} freq=2412 wait_time=200 no_cck=1=".format(bssid, bssid)
2134    cmd += " action="
2135
2136    for i in range(10):
2137        hapd.note("Event Type %d" % i)
2138        payload = struct.pack("<3B5B",
2139                              ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2140                              WLAN_EID_EVENT_REPORT, 3, 0, i, 0)
2141        mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2142
2143    hapd.note("Too short Event Report element")
2144    payload = struct.pack("<3B4B",
2145                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2146                          WLAN_EID_EVENT_REPORT, 2, 0, 0)
2147    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2148
2149    hapd.note("Truncated Event Report element")
2150    payload = struct.pack("<3B4B",
2151                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2152                          WLAN_EID_EVENT_REPORT, 3, 0, 0)
2153    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2154
2155    hapd.note("Request failed")
2156    payload = struct.pack("<3B5B",
2157                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2158                          WLAN_EID_EVENT_REPORT, 3, 0, 0, 1)
2159    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2160
2161    hapd.note("Unexpected element ID")
2162    payload = struct.pack("<3B5B",
2163                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2164                          WLAN_EID_EVENT_REPORT + 1, 3, 0, 0, 0)
2165    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2166
2167    hapd.note("Too short BSS color collision report")
2168    payload = struct.pack("<3B5B",
2169                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2170                          WLAN_EID_EVENT_REPORT, 3, 0, 4, 0)
2171    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2172
2173    hapd.note("Too short BSS color collision report")
2174    payload = struct.pack("<3B5BQ7B",
2175                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2176                          WLAN_EID_EVENT_REPORT, 3 + 8 + 7, 0, 4, 0, 0,
2177                          0, 0, 0, 0, 0, 0, 0)
2178    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2179
2180    hapd.note("BSS color collision report")
2181    payload = struct.pack("<3B5BQQ",
2182                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2183                          WLAN_EID_EVENT_REPORT, 3 + 8 + 8, 0, 4, 0,
2184                          0x1122334455667788, 0x123456789)
2185    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2186
2187    hapd.note("Too short BSS color in use report")
2188    payload = struct.pack("<3B5B",
2189                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2190                          WLAN_EID_EVENT_REPORT, 3, 0, 5, 0)
2191    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2192
2193    hapd.note("Too short BSS color in use report")
2194    payload = struct.pack("<3B5BQ",
2195                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2196                          WLAN_EID_EVENT_REPORT, 3 + 8, 0, 5, 0, 0)
2197    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2198
2199    hapd.note("BSS color in use report for color 1")
2200    payload = struct.pack("<3B5BQB",
2201                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2202                          WLAN_EID_EVENT_REPORT, 3 + 8 + 1, 0, 5, 0, 0, 1)
2203    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2204
2205    hapd.note("BSS color in use report for canceling")
2206    payload = struct.pack("<3B5BQB",
2207                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2208                          WLAN_EID_EVENT_REPORT, 3 + 8 + 1, 0, 5, 0, 0, 0)
2209    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2210
2211    hapd.note("BSS color in use report for invalid color")
2212    payload = struct.pack("<3B5BQB",
2213                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2214                          WLAN_EID_EVENT_REPORT, 3 + 8 + 1, 0, 5, 0, 0, 64)
2215    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2216
2217    time.sleep(51)
2218    hapd.note("BSS color collision report for more colors")
2219    payload = struct.pack("<3B5BQQ",
2220                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2221                          WLAN_EID_EVENT_REPORT, 3 + 8 + 8, 0, 4, 0,
2222                          0x1122334455667788, 0xfffffffffffffff0)
2223    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2224
2225    time.sleep(11)
2226    hapd.note("BSS color collision report")
2227    payload = struct.pack("<3B5BQQ",
2228                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2229                          WLAN_EID_EVENT_REPORT, 3 + 8 + 8, 0, 4, 0,
2230                          0x1122334455667788, 0xf)
2231    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2232
2233    time.sleep(51)
2234    hapd.note("BSS color collision report for all colors")
2235    payload = struct.pack("<3B5BQQ",
2236                          ACTION_CATEG_WNM, WNM_ACT_EVENT_REPORT, 0,
2237                          WLAN_EID_EVENT_REPORT, 3 + 8 + 8, 0, 4, 0,
2238                          0x1122334455667788, 0xffffffffffffffff)
2239    mgmt_tx(dev[0], cmd + binascii.hexlify(payload).decode())
2240
2241    time.sleep(11)
2242