]> git.ipfire.org Git - thirdparty/hostap.git/blame - tests/hwsim/test_wnm.py
WNM: Optimize a single BSS transition management candidate scan
[thirdparty/hostap.git] / tests / hwsim / test_wnm.py
CommitLineData
6435799b 1# WNM tests
2de01c9d 2# Copyright (c) 2013-2014, 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
2de01c9d
JM
7import binascii
8import struct
6435799b
JM
9import time
10import logging
11logger = logging.getLogger()
13f8d51e 12import subprocess
6435799b
JM
13
14import hostapd
cd54a3ed 15from utils import alloc_fail, wait_fail_trigger
b2edaa43 16from wlantest import Wlantest
6435799b
JM
17
18def test_wnm_bss_transition_mgmt(dev, apdev):
19 """WNM BSS Transition Management"""
20 params = { "ssid": "test-wnm",
21 "time_advertisement": "2",
22 "time_zone": "EST5",
23 "wnm_sleep_mode": "1",
24 "bss_transition": "1" }
25 hostapd.add_ap(apdev[0]['ifname'], params)
26
27 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
28 dev[0].request("WNM_BSS_QUERY 0")
29
30def test_wnm_disassoc_imminent(dev, apdev):
31 """WNM Disassociation Imminent"""
32 params = { "ssid": "test-wnm",
33 "time_advertisement": "2",
34 "time_zone": "EST5",
35 "wnm_sleep_mode": "1",
36 "bss_transition": "1" }
37 hostapd.add_ap(apdev[0]['ifname'], params)
38 hapd = hostapd.Hostapd(apdev[0]['ifname'])
39
40 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
41 addr = dev[0].p2p_interface_addr()
42 hapd.request("DISASSOC_IMMINENT " + addr + " 10")
43 ev = dev[0].wait_event(["WNM: Disassociation Imminent"])
44 if ev is None:
45 raise Exception("Timeout while waiting for disassociation imminent")
46 if "Disassociation Timer 10" not in ev:
47 raise Exception("Unexpected disassociation imminent contents")
48 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
49 if ev is None:
50 raise Exception("Timeout while waiting for re-connection scan")
51
52def test_wnm_ess_disassoc_imminent(dev, apdev):
53 """WNM ESS Disassociation Imminent"""
54 params = { "ssid": "test-wnm",
55 "time_advertisement": "2",
56 "time_zone": "EST5",
57 "wnm_sleep_mode": "1",
58 "bss_transition": "1" }
59 hostapd.add_ap(apdev[0]['ifname'], params)
60 hapd = hostapd.Hostapd(apdev[0]['ifname'])
61
62 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
63 addr = dev[0].p2p_interface_addr()
64 hapd.request("ESS_DISASSOC " + addr + " 10 http://example.com/session-info")
65 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"])
66 if ev is None:
67 raise Exception("Timeout while waiting for ESS disassociation imminent")
68 if "0 1024 http://example.com/session-info" not in ev:
69 raise Exception("Unexpected ESS disassociation imminent message contents")
70 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
71 if ev is None:
72 raise Exception("Timeout while waiting for re-connection scan")
73
74def test_wnm_ess_disassoc_imminent_pmf(dev, apdev):
75 """WNM ESS Disassociation Imminent"""
76 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
77 params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
78 params["ieee80211w"] = "2";
79 params["bss_transition"] = "1"
80 hostapd.add_ap(apdev[0]['ifname'], params)
81 hapd = hostapd.Hostapd(apdev[0]['ifname'])
82
83 dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
84 key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
85 addr = dev[0].p2p_interface_addr()
86 hapd.request("ESS_DISASSOC " + addr + " 10 http://example.com/session-info")
87 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"])
88 if ev is None:
89 raise Exception("Timeout while waiting for ESS disassociation imminent")
90 if "1 1024 http://example.com/session-info" not in ev:
91 raise Exception("Unexpected ESS disassociation imminent message contents")
92 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
93 if ev is None:
94 raise Exception("Timeout while waiting for re-connection scan")
95
a27f9f7a 96def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None):
6435799b
JM
97 addr = dev.p2p_interface_addr()
98 sta = hapd.get_sta(addr)
99 if "[WNM_SLEEP_MODE]" in sta['flags']:
100 raise Exception("Station unexpectedly in WNM-Sleep Mode")
7f08b2f9 101
6435799b 102 logger.info("Going to WNM Sleep Mode")
a27f9f7a
JM
103 extra = ""
104 if interval is not None:
105 extra += " interval=" + str(interval)
106 if tfs_req:
107 extra += " tfs_req=" + tfs_req
108 if "OK" not in dev.request("WNM_SLEEP enter" + extra):
109 raise Exception("WNM_SLEEP failed")
7f08b2f9
JM
110 ok = False
111 for i in range(20):
112 time.sleep(0.1)
113 sta = hapd.get_sta(addr)
114 if "[WNM_SLEEP_MODE]" in sta['flags']:
115 ok = True
116 break
117 if not ok:
6435799b 118 raise Exception("Station failed to enter WNM-Sleep Mode")
7f08b2f9 119
6435799b 120 logger.info("Waking up from WNM Sleep Mode")
7f08b2f9 121 ok = False
6435799b 122 dev.request("WNM_SLEEP exit")
7f08b2f9
JM
123 for i in range(20):
124 time.sleep(0.1)
125 sta = hapd.get_sta(addr)
126 if "[WNM_SLEEP_MODE]" not in sta['flags']:
127 ok = True
128 break
129 if not ok:
6435799b
JM
130 raise Exception("Station failed to exit WNM-Sleep Mode")
131
132def test_wnm_sleep_mode_open(dev, apdev):
133 """WNM Sleep Mode - open"""
134 params = { "ssid": "test-wnm",
135 "time_advertisement": "2",
136 "time_zone": "EST5",
137 "wnm_sleep_mode": "1",
138 "bss_transition": "1" }
139 hostapd.add_ap(apdev[0]['ifname'], params)
140 hapd = hostapd.Hostapd(apdev[0]['ifname'])
141
142 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
7f08b2f9
JM
143 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
144 if ev is None:
145 raise Exception("No connection event received from hostapd")
6435799b 146 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
a27f9f7a
JM
147 check_wnm_sleep_mode_enter_exit(hapd, dev[0], interval=100)
148 check_wnm_sleep_mode_enter_exit(hapd, dev[0], tfs_req="5b17010001130e110000071122334455661122334455661234")
6435799b 149
f8423317
JM
150 cmds = [ "foo",
151 "exit tfs_req=123 interval=10",
152 "enter tfs_req=qq interval=10" ]
153 for cmd in cmds:
154 if "FAIL" not in dev[0].request("WNM_SLEEP " + cmd):
155 raise Exception("Invalid WNM_SLEEP accepted")
156
6435799b
JM
157def test_wnm_sleep_mode_rsn(dev, apdev):
158 """WNM Sleep Mode - RSN"""
159 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
160 params["time_advertisement"] = "2"
161 params["time_zone"] = "EST5"
162 params["wnm_sleep_mode"] = "1"
163 params["bss_transition"] = "1"
164 hostapd.add_ap(apdev[0]['ifname'], params)
165 hapd = hostapd.Hostapd(apdev[0]['ifname'])
166
167 dev[0].connect("test-wnm-rsn", psk="12345678", scan_freq="2412")
7f08b2f9
JM
168 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
169 if ev is None:
170 raise Exception("No connection event received from hostapd")
6435799b
JM
171 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
172
cd54a3ed
JM
173def test_wnm_sleep_mode_ap_oom(dev, apdev):
174 """WNM Sleep Mode - AP side OOM"""
175 params = { "ssid": "test-wnm",
176 "wnm_sleep_mode": "1" }
177 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
178
179 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
180 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
181 if ev is None:
182 raise Exception("No connection event received from hostapd")
183 with alloc_fail(hapd, 1, "ieee802_11_send_wnmsleep_resp"):
184 dev[0].request("WNM_SLEEP enter")
185 wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
186 with alloc_fail(hapd, 2, "ieee802_11_send_wnmsleep_resp"):
187 dev[0].request("WNM_SLEEP exit")
188 wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
189
6435799b
JM
190def test_wnm_sleep_mode_rsn_pmf(dev, apdev):
191 """WNM Sleep Mode - RSN with PMF"""
b2edaa43
JM
192 wt = Wlantest()
193 wt.flush()
194 wt.add_passphrase("12345678")
6435799b
JM
195 params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
196 params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
197 params["ieee80211w"] = "2";
198 params["time_advertisement"] = "2"
199 params["time_zone"] = "EST5"
200 params["wnm_sleep_mode"] = "1"
201 params["bss_transition"] = "1"
202 hostapd.add_ap(apdev[0]['ifname'], params)
203 hapd = hostapd.Hostapd(apdev[0]['ifname'])
204
205 dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
206 key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
7f08b2f9
JM
207 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
208 if ev is None:
209 raise Exception("No connection event received from hostapd")
6435799b 210 check_wnm_sleep_mode_enter_exit(hapd, dev[0])
2de01c9d
JM
211
212MGMT_SUBTYPE_ACTION = 13
213ACTION_CATEG_WNM = 10
214WNM_ACT_BSS_TM_REQ = 7
215WNM_ACT_BSS_TM_RESP = 8
c4082f78
JM
216WNM_ACT_SLEEP_MODE_REQ = 16
217WNM_ACT_SLEEP_MODE_RESP = 17
218WNM_ACT_NOTIFICATION_REQ = 26
219WNM_ACT_NOTIFICATION_RESP = 27
220WNM_NOTIF_TYPE_FW_UPGRADE = 0
221WNM_NOTIF_TYPE_WFA = 1
222WLAN_EID_TFS_RESP = 92
223WLAN_EID_WNMSLEEP = 93
224WNM_SLEEP_MODE_ENTER = 0
225WNM_SLEEP_MODE_EXIT = 1
226WNM_STATUS_SLEEP_ACCEPT = 0
227WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE = 1
228WNM_STATUS_DENIED_ACTION = 2
229WNM_STATUS_DENIED_TMP = 3
230WNM_STATUS_DENIED_KEY = 4
231WNM_STATUS_DENIED_OTHER_WNM_SERVICE = 5
232WNM_SLEEP_SUBELEM_GTK = 0
233WNM_SLEEP_SUBELEM_IGTK = 1
2de01c9d
JM
234
235def bss_tm_req(dst, src, dialog_token=1, req_mode=0, disassoc_timer=0,
236 validity_interval=1):
237 msg = {}
238 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
239 msg['da'] = dst
240 msg['sa'] = src
241 msg['bssid'] = src
242 msg['payload'] = struct.pack("<BBBBHB",
243 ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
244 dialog_token, req_mode, disassoc_timer,
245 validity_interval)
246 return msg
247
248def rx_bss_tm_resp(hapd, expect_dialog=None, expect_status=None):
249 for i in range(0, 100):
250 resp = hapd.mgmt_rx()
251 if resp is None:
252 raise Exception("No BSS TM Response received")
253 if resp['subtype'] == MGMT_SUBTYPE_ACTION:
254 break
255 if i == 99:
256 raise Exception("Not an Action frame")
257 payload = resp['payload']
258 if len(payload) < 2 + 3:
259 raise Exception("Too short payload")
260 (category, action) = struct.unpack('BB', payload[0:2])
261 if category != ACTION_CATEG_WNM or action != WNM_ACT_BSS_TM_RESP:
262 raise Exception("Not a BSS TM Response")
263 pos = payload[2:]
264 (dialog, status, bss_term_delay) = struct.unpack('BBB', pos[0:3])
265 resp['dialog'] = dialog
266 resp['status'] = status
267 resp['bss_term_delay'] = bss_term_delay
268 pos = pos[3:]
269 if len(pos) >= 6 and status == 0:
270 resp['target_bssid'] = binascii.hexlify(pos[0:6])
271 pos = pos[6:]
272 resp['candidates'] = pos
273 if expect_dialog is not None and dialog != expect_dialog:
274 raise Exception("Unexpected dialog token")
275 if expect_status is not None and status != expect_status:
276 raise Exception("Unexpected status code %d" % status)
277 return resp
278
73360424 279def expect_ack(hapd):
2de01c9d
JM
280 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
281 if ev is None:
282 raise Exception("Missing TX status")
283 if "ok=1" not in ev:
284 raise Exception("Action frame not acknowledged")
285
286def test_wnm_bss_tm_req(dev, apdev):
287 """BSS Transition Management Request"""
288 params = { "ssid": "test-wnm", "bss_transition": "1" }
289 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
290 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
291 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
292
293 hapd.set("ext_mgmt_frame_handling", "1")
294
295 # truncated BSS TM Request
296 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
297 req_mode=0x08)
298 req['payload'] = struct.pack("<BBBBH",
299 ACTION_CATEG_WNM, WNM_ACT_BSS_TM_REQ,
300 1, 0, 0)
301 hapd.mgmt_tx(req)
73360424 302 expect_ack(hapd)
2de01c9d
JM
303
304 # no disassociation and no candidate list
305 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
306 dialog_token=2)
307 hapd.mgmt_tx(req)
308 resp = rx_bss_tm_resp(hapd, expect_dialog=2, expect_status=1)
309
310 # truncated BSS Termination Duration
311 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
312 req_mode=0x08)
313 hapd.mgmt_tx(req)
73360424 314 expect_ack(hapd)
2de01c9d
JM
315
316 # BSS Termination Duration with TSF=0 and Duration=10
317 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
318 req_mode=0x08, dialog_token=3)
319 req['payload'] += struct.pack("<BBQH", 4, 10, 0, 10)
320 hapd.mgmt_tx(req)
321 resp = rx_bss_tm_resp(hapd, expect_dialog=3, expect_status=1)
322
323 # truncated Session Information URL
324 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
325 req_mode=0x10)
326 hapd.mgmt_tx(req)
73360424 327 expect_ack(hapd)
2de01c9d
JM
328 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
329 req_mode=0x10)
330 req['payload'] += struct.pack("<BBB", 3, 65, 66)
331 hapd.mgmt_tx(req)
73360424 332 expect_ack(hapd)
2de01c9d
JM
333
334 # Session Information URL
335 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
336 req_mode=0x10, dialog_token=4)
337 req['payload'] += struct.pack("<BBB", 2, 65, 66)
338 hapd.mgmt_tx(req)
339 resp = rx_bss_tm_resp(hapd, expect_dialog=4, expect_status=0)
340
341 # Preferred Candidate List without any entries
342 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
343 req_mode=0x01, dialog_token=5)
344 hapd.mgmt_tx(req)
ab4ee343 345 resp = rx_bss_tm_resp(hapd, expect_dialog=5, expect_status=7)
2de01c9d
JM
346
347 # Preferred Candidate List with a truncated entry
348 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
349 req_mode=0x01)
350 req['payload'] += struct.pack("<BB", 52, 1)
351 hapd.mgmt_tx(req)
73360424 352 expect_ack(hapd)
2de01c9d
JM
353
354 # Preferred Candidate List with a too short entry
355 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
356 req_mode=0x01, dialog_token=6)
357 req['payload'] += struct.pack("<BB", 52, 0)
358 hapd.mgmt_tx(req)
ab4ee343 359 resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
2de01c9d
JM
360
361 # Preferred Candidate List with a non-matching entry
362 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
363 req_mode=0x01, dialog_token=6)
364 req['payload'] += struct.pack("<BB6BLBBB", 52, 13,
365 1, 2, 3, 4, 5, 6,
366 0, 81, 1, 7)
367 hapd.mgmt_tx(req)
ab4ee343 368 resp = rx_bss_tm_resp(hapd, expect_dialog=6, expect_status=7)
d8e0013e
JM
369
370 # Preferred Candidate List with a truncated subelement
371 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
372 req_mode=0x01, dialog_token=7)
373 req['payload'] += struct.pack("<BB6BLBBBBB", 52, 13 + 2,
374 1, 2, 3, 4, 5, 6,
375 0, 81, 1, 7,
376 1, 1)
377 hapd.mgmt_tx(req)
ab4ee343 378 resp = rx_bss_tm_resp(hapd, expect_dialog=7, expect_status=7)
d8e0013e
JM
379
380 # Preferred Candidate List with lots of invalid optional subelements
381 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
382 req_mode=0x01, dialog_token=8)
383 subelems = struct.pack("<BBHB", 1, 3, 0, 100)
384 subelems += struct.pack("<BBB", 2, 1, 65)
385 subelems += struct.pack("<BB", 3, 0)
386 subelems += struct.pack("<BBQB", 4, 9, 0, 10)
387 subelems += struct.pack("<BBHLB", 5, 7, 0, 0, 0)
388 subelems += struct.pack("<BB", 66, 0)
389 subelems += struct.pack("<BBBBBB", 70, 4, 0, 0, 0, 0)
390 subelems += struct.pack("<BB", 71, 0)
391 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
392 1, 2, 3, 4, 5, 6,
393 0, 81, 1, 7) + subelems
394 hapd.mgmt_tx(req)
ab4ee343 395 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
d8e0013e
JM
396
397 # Preferred Candidate List with lots of valid optional subelements (twice)
398 req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
399 req_mode=0x01, dialog_token=8)
400 # TSF Information
401 subelems = struct.pack("<BBHH", 1, 4, 0, 100)
402 # Condensed Country String
403 subelems += struct.pack("<BBBB", 2, 2, 65, 66)
404 # BSS Transition Candidate Preference
405 subelems += struct.pack("<BBB", 3, 1, 100)
406 # BSS Termination Duration
407 subelems += struct.pack("<BBQH", 4, 10, 0, 10)
408 # Bearing
409 subelems += struct.pack("<BBHLH", 5, 8, 0, 0, 0)
410 # Measurement Pilot Transmission
411 subelems += struct.pack("<BBBBB", 66, 3, 0, 0, 0)
412 # RM Enabled Capabilities
413 subelems += struct.pack("<BBBBBBB", 70, 5, 0, 0, 0, 0, 0)
414 # Multiple BSSID
415 subelems += struct.pack("<BBBB", 71, 2, 0, 0)
416 req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems) * 2,
417 1, 2, 3, 4, 5, 6,
418 0, 81, 1, 7) + subelems + subelems
419 hapd.mgmt_tx(req)
ab4ee343 420 resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
519c3f70
JM
421
422def test_wnm_bss_keep_alive(dev, apdev):
423 """WNM keep-alive"""
424 params = { "ssid": "test-wnm",
425 "ap_max_inactivity": "1" }
e61f9087 426 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
519c3f70 427
e61f9087 428 addr = dev[0].p2p_interface_addr()
519c3f70 429 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
e61f9087
JM
430 start = hapd.get_sta(addr)
431 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=2)
432 if ev is not None:
433 raise Exception("Unexpected disconnection")
434 end = hapd.get_sta(addr)
435 if int(end['rx_packets']) <= int(start['rx_packets']):
436 raise Exception("No keep-alive packets received")
437 try:
438 # Disable client keep-alive so that hostapd will verify connection
439 # with client poll
440 dev[0].request("SET no_keep_alive 1")
441 for i in range(60):
442 sta = hapd.get_sta(addr)
443 logger.info("timeout_next=%s rx_packets=%s tx_packets=%s" % (sta['timeout_next'], sta['rx_packets'], sta['tx_packets']))
444 if i > 1 and sta['timeout_next'] != "NULLFUNC POLL" and int(sta['tx_packets']) > int(end['tx_packets']):
445 break
446 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
447 if ev is not None:
448 raise Exception("Unexpected disconnection (client poll expected)")
449 finally:
450 dev[0].request("SET no_keep_alive 0")
451 if int(sta['tx_packets']) <= int(end['tx_packets']):
452 raise Exception("No client poll packet seen")
13f8d51e
JM
453
454def test_wnm_bss_tm(dev, apdev):
455 """WNM BSS Transition Management"""
456 try:
9d7fdac5
JM
457 hapd = None
458 hapd2 = None
13f8d51e
JM
459 params = { "ssid": "test-wnm",
460 "country_code": "FI",
df4733df 461 "ieee80211d": "1",
13f8d51e
JM
462 "hw_mode": "g",
463 "channel": "1",
464 "bss_transition": "1" }
465 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
466
467 id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
468 dev[0].set_network(id, "scan_freq", "")
469
470 params = { "ssid": "test-wnm",
471 "country_code": "FI",
df4733df 472 "ieee80211d": "1",
13f8d51e
JM
473 "hw_mode": "a",
474 "channel": "36",
475 "bss_transition": "1" }
476 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
477
478 addr = dev[0].p2p_interface_addr()
479 dev[0].dump_monitor()
480
481 logger.info("No neighbor list entries")
482 if "OK" not in hapd.request("BSS_TM_REQ " + addr):
483 raise Exception("BSS_TM_REQ command failed")
484 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
485 if ev is None:
486 raise Exception("No BSS Transition Management Response")
487 if addr not in ev:
488 raise Exception("Unexpected BSS Transition Management Response address")
489 if "status_code=0" in ev:
490 raise Exception("BSS transition accepted unexpectedly")
491 dev[0].dump_monitor()
492
493 logger.info("Neighbor list entry, but not claimed as Preferred Candidate List")
494 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " neighbor=11:22:33:44:55:66,0x0000,81,3,7"):
495 raise Exception("BSS_TM_REQ command failed")
496 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
497 if ev is None:
498 raise Exception("No BSS Transition Management Response")
499 if "status_code=0" in ev:
500 raise Exception("BSS transition accepted unexpectedly")
501 dev[0].dump_monitor()
502
503 logger.info("Preferred Candidate List (no matching neighbor) without Disassociation Imminent")
df4733df 504 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
505 raise Exception("BSS_TM_REQ command failed")
506 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
507 if ev is None:
508 raise Exception("No BSS Transition Management Response")
509 if "status_code=0" in ev:
510 raise Exception("BSS transition accepted unexpectedly")
511 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
512 if ev is None:
513 raise Exception("No scan started")
514 dev[0].dump_monitor()
515
516 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
517 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"):
518 raise Exception("BSS_TM_REQ command failed")
519 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
520 if ev is None:
521 raise Exception("No BSS Transition Management Response")
522 if "status_code=0" not in ev:
523 raise Exception("BSS transition request was not accepted: " + ev)
524 if "target_bssid=" + apdev[1]['bssid'] not in ev:
525 raise Exception("Unexpected target BSS: " + ev)
5f35a5e2 526 dev[0].wait_connected(timeout=15, error="No reassociation seen")
13f8d51e
JM
527 if apdev[1]['bssid'] not in ev:
528 raise Exception("Unexpected reassociation target: " + ev)
529 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
530 if ev is not None:
531 raise Exception("Unexpected scan started")
532 dev[0].dump_monitor()
533
534 logger.info("Preferred Candidate List with two matches, no roam needed")
535 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"):
536 raise Exception("BSS_TM_REQ command failed")
537 ev = hapd2.wait_event(['BSS-TM-RESP'], timeout=10)
538 if ev is None:
539 raise Exception("No BSS Transition Management Response")
540 if "status_code=0" not in ev:
541 raise Exception("BSS transition request was not accepted: " + ev)
542 if "target_bssid=" + apdev[1]['bssid'] not in ev:
543 raise Exception("Unexpected target BSS: " + ev)
544 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
545 if ev is not None:
546 raise Exception("Unexpected scan started")
547 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
548 if ev is not None:
549 raise Exception("Unexpected reassociation");
550 finally:
9d7fdac5
JM
551 dev[0].request("DISCONNECT")
552 if hapd:
553 hapd.request("DISABLE")
554 if hapd2:
555 hapd2.request("DISABLE")
13f8d51e 556 subprocess.call(['iw', 'reg', 'set', '00'])
9d7fdac5 557 dev[0].flush_scan_cache()
8cc9bc07
JM
558
559def start_wnm_tm(ap, country, dev):
560 params = { "ssid": "test-wnm",
561 "country_code": country,
562 "ieee80211d": "1",
563 "hw_mode": "g",
564 "channel": "1",
565 "bss_transition": "1" }
566 hapd = hostapd.add_ap(ap['ifname'], params)
567 id = dev.connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
568 dev.dump_monitor()
569 dev.set_network(id, "scan_freq", "")
570 return hapd, id
571
572def stop_wnm_tm(hapd, dev):
573 dev.request("DISCONNECT")
574 try:
575 dev.wait_disconnected()
576 except:
577 pass
578 if hapd:
579 hapd.request("DISABLE")
580 subprocess.call(['iw', 'reg', 'set', '00'])
581 dev.flush_scan_cache()
582
583def wnm_bss_tm_check(hapd, dev, data):
584 addr = dev.p2p_interface_addr()
585 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " " + data):
586 raise Exception("BSS_TM_REQ command failed")
587 ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
588 if ev is None:
589 raise Exception("No scan started")
590 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
591 if ev is None:
592 raise Exception("Scan did not complete")
593
594 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
595 if ev is None:
596 raise Exception("No BSS Transition Management Response")
597 if "status_code=7" not in ev:
598 raise Exception("Unexpected response: " + ev)
599
600def test_wnm_bss_tm_country_us(dev, apdev):
601 """WNM BSS Transition Management (US)"""
602 try:
603 hapd = None
604 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
605
606 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
607 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")
608
609 # Make the test take less time by limiting full scans
610 dev[0].set_network(id, "scan_freq", "2412")
611 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
612 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")
613
614 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
615 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")
616 finally:
617 stop_wnm_tm(hapd, dev[0])
618
619def test_wnm_bss_tm_country_fi(dev, apdev):
620 """WNM BSS Transition Management (FI)"""
621 addr = dev[0].p2p_interface_addr()
622 try:
623 hapd = None
624 hapd, id = start_wnm_tm(apdev[0], "FI", dev[0])
625
626 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
627 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")
628
629 # Make the test take less time by limiting full scans
630 dev[0].set_network(id, "scan_freq", "2412")
631 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
632 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")
633
634 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
635 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,0,0,7")
636 finally:
637 stop_wnm_tm(hapd, dev[0])
638
639def test_wnm_bss_tm_country_jp(dev, apdev):
640 """WNM BSS Transition Management (JP)"""
641 addr = dev[0].p2p_interface_addr()
642 try:
643 hapd = None
644 hapd, id = start_wnm_tm(apdev[0], "JP", dev[0])
645
646 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
647 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")
648
649 # Make the test take less time by limiting full scans
650 dev[0].set_network(id, "scan_freq", "2412")
651 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
652 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")
653 finally:
654 stop_wnm_tm(hapd, dev[0])
655
656def test_wnm_bss_tm_country_cn(dev, apdev):
657 """WNM BSS Transition Management (CN)"""
658 addr = dev[0].p2p_interface_addr()
659 try:
660 hapd = None
661 hapd, id = start_wnm_tm(apdev[0], "CN", dev[0])
662
663 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
664 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")
665
666 # Make the test take less time by limiting full scans
667 dev[0].set_network(id, "scan_freq", "2412")
668 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
669 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")
670 finally:
671 stop_wnm_tm(hapd, dev[0])
672
673def test_wnm_bss_tm_global(dev, apdev):
674 """WNM BSS Transition Management (global)"""
675 addr = dev[0].p2p_interface_addr()
676 try:
677 hapd = None
678 hapd, id = start_wnm_tm(apdev[0], "XX", dev[0])
679
680 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
681 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")
682
683 # Make the test take less time by limiting full scans
684 dev[0].set_network(id, "scan_freq", "2412")
685 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
686 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")
687
688 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
689 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")
690 finally:
691 stop_wnm_tm(hapd, dev[0])
c4082f78 692
56153620
JM
693def test_wnm_bss_tm_op_class_0(dev, apdev):
694 """WNM BSS Transition Management with invalid operating class"""
695 try:
696 hapd = None
697 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
698
699 logger.info("Preferred Candidate List (no matching neighbor, invalid op class specified for channels)")
700 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")
701 finally:
702 stop_wnm_tm(hapd, dev[0])
703
c4082f78
JM
704def test_wnm_action_proto(dev, apdev):
705 """WNM Action protocol testing"""
706 params = { "ssid": "test-wnm" }
8823178c 707 params['wnm_sleep_mode'] = '1'
c4082f78
JM
708 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
709 bssid = apdev[0]['bssid']
710 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
8823178c
JM
711 dev[0].request("WNM_SLEEP enter")
712 time.sleep(0.1)
c4082f78
JM
713 hapd.set("ext_mgmt_frame_handling", "1")
714
715 msg = {}
716 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
717 msg['da'] = dev[0].own_addr()
718 msg['sa'] = bssid
719 msg['bssid'] = bssid
720
721 dialog_token = 1
722
723 logger.debug("Unexpected WNM-Notification Response")
724 # Note: This is actually not registered for user space processing in
725 # driver_nl80211.c nl80211_mgmt_subscribe_non_ap() and as such, won't make
726 # it to wpa_supplicant.
727 msg['payload'] = struct.pack("<BBBB",
728 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_RESP,
729 dialog_token, 0)
730 hapd.mgmt_tx(msg)
731 expect_ack(hapd)
732
733 logger.debug("Truncated WNM-Notification Request (no Type field)")
734 msg['payload'] = struct.pack("<BBB",
735 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
736 dialog_token)
737 hapd.mgmt_tx(msg)
738 expect_ack(hapd)
739
740 logger.debug("WFA WNM-Notification Request with truncated IE (min)")
741 msg['payload'] = struct.pack("<BBBBBB",
742 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
743 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 1)
744 hapd.mgmt_tx(msg)
745 expect_ack(hapd)
746
747 logger.debug("WFA WNM-Notification Request with truncated IE (max)")
748 msg['payload'] = struct.pack("<BBBBBB",
749 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
750 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 255)
751 hapd.mgmt_tx(msg)
752 expect_ack(hapd)
753
754 logger.debug("WFA WNM-Notification Request with too short IE")
755 msg['payload'] = struct.pack("<BBBBBB",
756 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
757 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 0)
758 hapd.mgmt_tx(msg)
759 expect_ack(hapd)
760
761 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL")
762 msg['payload'] = struct.pack(">BBBBBBLB",
763 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
764 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
765 0x506f9a00, 1)
766 hapd.mgmt_tx(msg)
767 expect_ack(hapd)
768
769 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(2)")
770 msg['payload'] = struct.pack(">BBBBBBLBB",
771 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
772 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 6,
773 0x506f9a00, 1, 0)
774 hapd.mgmt_tx(msg)
775 expect_ack(hapd)
776
777 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(3)")
778 msg['payload'] = struct.pack(">BBBBBBLB",
779 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
780 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
781 0x506f9a00, 0xff)
782 hapd.mgmt_tx(msg)
783 expect_ack(hapd)
784
785 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(min)")
786 msg['payload'] = struct.pack(">BBBBBBLBHB",
787 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
788 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
789 0x506f9a01, 0, 0, 1)
790 hapd.mgmt_tx(msg)
791 expect_ack(hapd)
792
793 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(max)")
794 msg['payload'] = struct.pack(">BBBBBBLBHB",
795 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
796 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
797 0x506f9a01, 0, 0, 0xff)
798 hapd.mgmt_tx(msg)
799 expect_ack(hapd)
800
801 logger.debug("WFA WNM-Notification Request with unsupported IE")
802 msg['payload'] = struct.pack("<BBBBBBL",
803 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
804 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 4, 0)
805 hapd.mgmt_tx(msg)
806 expect_ack(hapd)
807
808 logger.debug("WNM-Notification Request with unknown WNM-Notification type 0")
809 msg['payload'] = struct.pack("<BBBB",
810 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
811 dialog_token, WNM_NOTIF_TYPE_FW_UPGRADE)
812 hapd.mgmt_tx(msg)
813 expect_ack(hapd)
814
815 logger.debug("Truncated WNM Sleep Mode Response - no Dialog Token")
816 msg['payload'] = struct.pack("<BB",
817 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP)
818 hapd.mgmt_tx(msg)
819 expect_ack(hapd)
820
821 logger.debug("Truncated WNM Sleep Mode Response - no Key Data Length")
822 msg['payload'] = struct.pack("<BBB",
823 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0)
824 hapd.mgmt_tx(msg)
825 expect_ack(hapd)
826
827 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (min)")
828 msg['payload'] = struct.pack("<BBBH",
829 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
830 1)
831 hapd.mgmt_tx(msg)
832 expect_ack(hapd)
833
834 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (max)")
835 msg['payload'] = struct.pack("<BBBH",
836 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
837 0xffff)
838 hapd.mgmt_tx(msg)
839 expect_ack(hapd)
840
841 logger.debug("WNM Sleep Mode Response - truncated IE header")
842 msg['payload'] = struct.pack("<BBBHB",
843 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
844 0, 0)
845 hapd.mgmt_tx(msg)
846 expect_ack(hapd)
847
848 logger.debug("WNM Sleep Mode Response - truncated IE")
849 msg['payload'] = struct.pack("<BBBHBB",
850 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
851 0, 0, 1)
852 hapd.mgmt_tx(msg)
853 expect_ack(hapd)
854
855 logger.debug("WNM Sleep Mode Response - Empty TFS Response")
856 msg['payload'] = struct.pack("<BBBHBB",
857 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
858 0, WLAN_EID_TFS_RESP, 0)
859 hapd.mgmt_tx(msg)
860 expect_ack(hapd)
861
862 logger.debug("WNM Sleep Mode Response - EID 0 not recognized")
863 msg['payload'] = struct.pack("<BBBHBB",
864 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
865 0, 0, 0)
866 hapd.mgmt_tx(msg)
867 expect_ack(hapd)
868
869 logger.debug("WNM Sleep Mode Response - Empty WNM Sleep Mode element and TFS Response element")
870 msg['payload'] = struct.pack("<BBBHBBBB",
871 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
872 0, WLAN_EID_WNMSLEEP, 0, WLAN_EID_TFS_RESP, 0)
873 hapd.mgmt_tx(msg)
874 expect_ack(hapd)
875
876 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element and empty TFS Response element")
877 msg['payload'] = struct.pack("<BBBHBBBBHBB",
878 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
879 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
880 WNM_STATUS_SLEEP_ACCEPT, 0,
881 WLAN_EID_TFS_RESP, 0)
882 hapd.mgmt_tx(msg)
883 expect_ack(hapd)
884
885 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(exit, deny key) and empty TFS Response element")
886 msg['payload'] = struct.pack("<BBBHBBBBHBB",
887 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
888 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
889 WNM_STATUS_DENIED_KEY, 0,
890 WLAN_EID_TFS_RESP, 0)
891 hapd.mgmt_tx(msg)
892 expect_ack(hapd)
893
894 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(enter, deny key) and empty TFS Response element")
895 msg['payload'] = struct.pack("<BBBHBBBBHBB",
896 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
897 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
898 WNM_STATUS_DENIED_KEY, 0,
899 WLAN_EID_TFS_RESP, 0)
900 hapd.mgmt_tx(msg)
901 expect_ack(hapd)
902
903def test_wnm_action_proto_pmf(dev, apdev):
904 """WNM Action protocol testing (PMF enabled)"""
905 ssid = "test-wnm-pmf"
906 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
907 params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
908 params["ieee80211w"] = "2"
8823178c 909 params['wnm_sleep_mode'] = '1'
c4082f78
JM
910 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
911 bssid = apdev[0]['bssid']
912 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
913 proto="WPA2", ieee80211w="2", scan_freq="2412")
8823178c
JM
914 dev[0].request("WNM_SLEEP enter")
915 time.sleep(0.1)
c4082f78
JM
916 hapd.set("ext_mgmt_frame_handling", "1")
917
918 msg = {}
919 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
920 msg['da'] = dev[0].own_addr()
921 msg['sa'] = bssid
922 msg['bssid'] = bssid
923
924 logger.debug("WNM Sleep Mode Response - Invalid Key Data element length")
925 keydata = struct.pack("<BB", 0, 1)
926 msg['payload'] = struct.pack("<BBBH",
927 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
928 len(keydata))
929 msg['payload'] += keydata
930 msg['payload'] += struct.pack("<BBBBHBB",
931 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
932 WNM_STATUS_SLEEP_ACCEPT, 0,
933 WLAN_EID_TFS_RESP, 0)
934 hapd.mgmt_tx(msg)
935 expect_ack(hapd)
936
937 logger.debug("WNM Sleep Mode Response - Too short GTK subelem")
938 keydata = struct.pack("<BB", WNM_SLEEP_SUBELEM_GTK, 0)
939 msg['payload'] = struct.pack("<BBBH",
940 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
941 len(keydata))
942 msg['payload'] += keydata
943 msg['payload'] += struct.pack("<BBBBHBB",
944 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
945 WNM_STATUS_SLEEP_ACCEPT, 0,
946 WLAN_EID_TFS_RESP, 0)
947 hapd.mgmt_tx(msg)
948 expect_ack(hapd)
949
950 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem")
951 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
952 0, 17, 0, 0, 0, 0, 0, 0)
953 msg['payload'] = struct.pack("<BBBH",
954 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
955 len(keydata))
956 msg['payload'] += keydata
957 msg['payload'] += struct.pack("<BBBBHBB",
958 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
959 WNM_STATUS_SLEEP_ACCEPT, 0,
960 WLAN_EID_TFS_RESP, 0)
961 hapd.mgmt_tx(msg)
962 expect_ack(hapd)
963
964 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem (2)")
965 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
966 0, 0, 0, 0, 0, 0, 0, 0)
967 msg['payload'] = struct.pack("<BBBH",
968 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
969 len(keydata))
970 msg['payload'] += keydata
971 msg['payload'] += struct.pack("<BBBBHBB",
972 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
973 WNM_STATUS_SLEEP_ACCEPT, 0,
974 WLAN_EID_TFS_RESP, 0)
975 hapd.mgmt_tx(msg)
976 expect_ack(hapd)
977
978 logger.debug("WNM Sleep Mode Response - GTK subelem and too short IGTK subelem")
979 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
980 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
981 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
982 keydata += struct.pack("<BB", WNM_SLEEP_SUBELEM_IGTK, 0)
983 msg['payload'] = struct.pack("<BBBH",
984 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
985 len(keydata))
986 msg['payload'] += keydata
987 msg['payload'] += struct.pack("<BBBBHBB",
988 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
989 WNM_STATUS_SLEEP_ACCEPT, 0,
990 WLAN_EID_TFS_RESP, 0)
991 hapd.mgmt_tx(msg)
992 expect_ack(hapd)
993
994 logger.debug("WNM Sleep Mode Response - Unknown subelem")
995 keydata = struct.pack("<BB", 255, 0)
996 msg['payload'] = struct.pack("<BBBH",
997 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
998 len(keydata))
999 msg['payload'] += keydata
1000 msg['payload'] += struct.pack("<BBBBHBB",
1001 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1002 WNM_STATUS_SLEEP_ACCEPT, 0,
1003 WLAN_EID_TFS_RESP, 0)
1004 hapd.mgmt_tx(msg)
1005 expect_ack(hapd)
63a19e56
JM
1006
1007def test_wnm_action_proto_no_pmf(dev, apdev):
1008 """WNM Action protocol testing (PMF disabled)"""
1009 ssid = "test-wnm-no-pmf"
1010 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
8823178c 1011 params['wnm_sleep_mode'] = '1'
63a19e56
JM
1012 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1013 bssid = apdev[0]['bssid']
1014 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1015 proto="WPA2", ieee80211w="0", scan_freq="2412")
8823178c
JM
1016 dev[0].request("WNM_SLEEP enter")
1017 time.sleep(0.1)
63a19e56
JM
1018 hapd.set("ext_mgmt_frame_handling", "1")
1019
1020 msg = {}
1021 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1022 msg['da'] = dev[0].own_addr()
1023 msg['sa'] = bssid
1024 msg['bssid'] = bssid
1025
1026 logger.debug("WNM Sleep Mode Response - GTK subelem and IGTK subelem")
1027 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1028 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1029 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1030 keydata += struct.pack("<BBHLH4L", WNM_SLEEP_SUBELEM_IGTK, 2 + 6 + 16, 0,
1031 0x10203040, 0x5060,
1032 0xf1f2f3f4, 0xf5f6f7f8, 0xf9f0fafb, 0xfcfdfeff)
1033 msg['payload'] = struct.pack("<BBBH",
1034 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1035 len(keydata))
1036 msg['payload'] += keydata
1037 msg['payload'] += struct.pack("<BBBBHBB",
1038 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1039 WNM_STATUS_SLEEP_ACCEPT, 0,
1040 WLAN_EID_TFS_RESP, 0)
1041 hapd.mgmt_tx(msg)
1042 expect_ack(hapd)
1043
1044 ev = dev[0].wait_event(["WNM: Ignore Key Data"], timeout=5)
1045 if ev is None:
1046 raise Exception("Key Data not ignored")
85cc109e
AS
1047
1048def test_wnm_bss_tm_req_with_mbo_ie(dev, apdev):
1049 """WNM BSS transition request with MBO IE and reassociation delay attribute"""
1050 ssid = "test-wnm-mbo"
1051 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1052 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1053 bssid = apdev[0]['bssid']
1054 if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
1055 raise Exception("Failed to set STA as cellular data capable")
1056
1057 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1058 proto="WPA2", ieee80211w="0", scan_freq="2412")
1059
1060 logger.debug("BTM request with MBO reassociation delay when disassoc imminent is not set")
1061 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=3:2:1"):
1062 raise Exception("BSS transition management succeeded unexpectedly")
1063
1064 logger.debug("BTM request with invalid MBO transition reason code")
1065 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=10:2:1"):
1066 raise Exception("BSS transition management succeeded unexpectedly")
1067
1068 logger.debug("BTM request with MBO reassociation retry delay of 5 seconds")
1069 if 'OK' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " disassoc_imminent=1 disassoc_timer=3 mbo=3:5:1"):
1070 raise Exception("BSS transition management command failed")
1071
1072 ev = dev[0].wait_event(['MBO-CELL-PREFERENCE'], 1)
1073 if ev is None or "preference=1" not in ev:
1074 raise Exception("Timeout waiting for MBO-CELL-PREFERENCE event")
1075
1076 ev = dev[0].wait_event(['MBO-TRANSITION-REASON'], 1)
1077 if ev is None or "reason=3" not in ev:
1078 raise Exception("Timeout waiting for MBO-TRANSITION-REASON event")
1079
1080 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1081 if ev is None:
1082 raise Exception("No BSS Transition Management Response")
1083 if dev[0].own_addr() not in ev:
1084 raise Exception("Unexpected BSS Transition Management Response address")
1085
1086 ev = dev[0].wait_event(['CTRL-EVENT-DISCONNECTED'], 5)
1087 if ev is None:
1088 raise Exception("Station did not disconnect although disassoc imminent was set")
1089
1090 # Set the scan interval to make dev[0] look for connections
1091 if 'OK' not in dev[0].request("SCAN_INTERVAL 1"):
1092 raise Exception("Failed to set scan interval")
1093
1094 # Make sure no connection is made during the retry delay
1095 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1096 if ev is not None:
1097 raise Exception("Station connected before assoc retry delay was over")
1098
1099 # After the assoc retry delay is over, we can reconnect
1100 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1101 if ev is None:
1102 raise Exception("Station did not connect after assoc retry delay is over")
1103
1104 if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
1105 raise Exception("Failed to set STA as cellular data not-capable")
c24c144f
JM
1106
1107def test_wnm_bss_transition_mgmt_query(dev, apdev):
1108 """WNM BSS Transition Management query"""
1109 params = { "ssid": "test-wnm",
1110 "bss_transition": "1" }
1111 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1112 params = { "ssid": "another" }
1113 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
1114
1115 dev[0].scan_for_bss(apdev[1]['bssid'], 2412)
1116 dev[0].scan_for_bss(apdev[0]['bssid'], 2412)
1117
1118 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1119 dev[0].request("WNM_BSS_QUERY 0 list")
1120
1121 ev = dev[0].wait_event(["WNM: BSS Transition Management Request"],
1122 timeout=5)
1123 if ev is None:
1124 raise Exception("No BSS Transition Management Request frame seen")
1125
1126 ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1127 if ev is None:
1128 raise Exception("No BSS Transition Management Response frame seen")