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