]> git.ipfire.org Git - thirdparty/hostap.git/blame - tests/hwsim/test_wnm.py
WNM: Fix candidates count in BSS Transition Management Request
[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 558
13a17a77
JM
559def test_wnm_bss_tm_scan_not_needed(dev, apdev):
560 """WNM BSS Transition Management and scan not needed"""
561 try:
562 hapd = None
563 hapd2 = None
564 params = { "ssid": "test-wnm",
565 "country_code": "FI",
566 "ieee80211d": "1",
567 "hw_mode": "g",
568 "channel": "1",
569 "bss_transition": "1" }
570 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
571
572 params = { "ssid": "test-wnm",
573 "country_code": "FI",
574 "ieee80211d": "1",
575 "hw_mode": "a",
576 "channel": "36",
577 "bss_transition": "1" }
578 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
579
580 dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
581
582 id = dev[0].connect("test-wnm", key_mgmt="NONE",
583 bssid=apdev[0]['bssid'], scan_freq="2412")
584 dev[0].set_network(id, "scan_freq", "")
585 dev[0].set_network(id, "bssid", "")
586
587 addr = dev[0].own_addr()
588 dev[0].dump_monitor()
589
590 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
591 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"):
592 raise Exception("BSS_TM_REQ command failed")
593 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
594 if ev is None:
595 raise Exception("No BSS Transition Management Response")
596 if "status_code=0" not in ev:
597 raise Exception("BSS transition request was not accepted: " + ev)
598 if "target_bssid=" + apdev[1]['bssid'] not in ev:
599 raise Exception("Unexpected target BSS: " + ev)
600 dev[0].wait_connected(timeout=15, error="No reassociation seen")
601 if apdev[1]['bssid'] not in ev:
602 raise Exception("Unexpected reassociation target: " + ev)
603 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
604 if ev is not None:
605 raise Exception("Unexpected scan started")
606 dev[0].dump_monitor()
607 finally:
608 dev[0].request("DISCONNECT")
609 if hapd:
610 hapd.request("DISABLE")
611 if hapd2:
612 hapd2.request("DISABLE")
613 subprocess.call(['iw', 'reg', 'set', '00'])
614 dev[0].flush_scan_cache()
615
616def test_wnm_bss_tm_scan_needed(dev, apdev):
617 """WNM BSS Transition Management and scan needed"""
618 try:
619 hapd = None
620 hapd2 = None
621 params = { "ssid": "test-wnm",
622 "country_code": "FI",
623 "ieee80211d": "1",
624 "hw_mode": "g",
625 "channel": "1",
626 "bss_transition": "1" }
627 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
628
629 params = { "ssid": "test-wnm",
630 "country_code": "FI",
631 "ieee80211d": "1",
632 "hw_mode": "a",
633 "channel": "36",
634 "bss_transition": "1" }
635 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
636
637 dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
638
639 id = dev[0].connect("test-wnm", key_mgmt="NONE",
640 bssid=apdev[0]['bssid'], scan_freq="2412")
641 dev[0].set_network(id, "scan_freq", "")
642 dev[0].set_network(id, "bssid", "")
643
644 addr = dev[0].own_addr()
645 dev[0].dump_monitor()
646
647 logger.info("Wait 11 seconds for the last scan result to be too old, but still present in BSS table")
648 time.sleep(11)
649 logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
650 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"):
651 raise Exception("BSS_TM_REQ command failed")
652 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
653 if ev is None:
654 raise Exception("No BSS Transition Management Response")
655 if "status_code=0" not in ev:
656 raise Exception("BSS transition request was not accepted: " + ev)
657 if "target_bssid=" + apdev[1]['bssid'] not in ev:
658 raise Exception("Unexpected target BSS: " + ev)
659 dev[0].wait_connected(timeout=15, error="No reassociation seen")
660 if apdev[1]['bssid'] not in ev:
661 raise Exception("Unexpected reassociation target: " + ev)
662 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
663 if ev is not None:
664 raise Exception("Unexpected scan started")
665 dev[0].dump_monitor()
666 finally:
667 dev[0].request("DISCONNECT")
668 if hapd:
669 hapd.request("DISABLE")
670 if hapd2:
671 hapd2.request("DISABLE")
672 subprocess.call(['iw', 'reg', 'set', '00'])
673 dev[0].flush_scan_cache()
674
8cc9bc07
JM
675def start_wnm_tm(ap, country, dev):
676 params = { "ssid": "test-wnm",
677 "country_code": country,
678 "ieee80211d": "1",
679 "hw_mode": "g",
680 "channel": "1",
681 "bss_transition": "1" }
682 hapd = hostapd.add_ap(ap['ifname'], params)
683 id = dev.connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
684 dev.dump_monitor()
685 dev.set_network(id, "scan_freq", "")
686 return hapd, id
687
688def stop_wnm_tm(hapd, dev):
689 dev.request("DISCONNECT")
690 try:
691 dev.wait_disconnected()
692 except:
693 pass
694 if hapd:
695 hapd.request("DISABLE")
696 subprocess.call(['iw', 'reg', 'set', '00'])
697 dev.flush_scan_cache()
698
699def wnm_bss_tm_check(hapd, dev, data):
700 addr = dev.p2p_interface_addr()
701 if "OK" not in hapd.request("BSS_TM_REQ " + addr + " " + data):
702 raise Exception("BSS_TM_REQ command failed")
703 ev = dev.wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
704 if ev is None:
705 raise Exception("No scan started")
706 ev = dev.wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
707 if ev is None:
708 raise Exception("Scan did not complete")
709
710 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
711 if ev is None:
712 raise Exception("No BSS Transition Management Response")
713 if "status_code=7" not in ev:
714 raise Exception("Unexpected response: " + ev)
715
716def test_wnm_bss_tm_country_us(dev, apdev):
717 """WNM BSS Transition Management (US)"""
718 try:
719 hapd = None
720 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
721
722 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
723 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")
724
725 # Make the test take less time by limiting full scans
726 dev[0].set_network(id, "scan_freq", "2412")
727 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
728 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")
729
730 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
731 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")
732 finally:
733 stop_wnm_tm(hapd, dev[0])
734
735def test_wnm_bss_tm_country_fi(dev, apdev):
736 """WNM BSS Transition Management (FI)"""
737 addr = dev[0].p2p_interface_addr()
738 try:
739 hapd = None
740 hapd, id = start_wnm_tm(apdev[0], "FI", dev[0])
741
742 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
743 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")
744
745 # Make the test take less time by limiting full scans
746 dev[0].set_network(id, "scan_freq", "2412")
747 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
748 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")
749
750 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
751 wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,0,0,7")
752 finally:
753 stop_wnm_tm(hapd, dev[0])
754
755def test_wnm_bss_tm_country_jp(dev, apdev):
756 """WNM BSS Transition Management (JP)"""
757 addr = dev[0].p2p_interface_addr()
758 try:
759 hapd = None
760 hapd, id = start_wnm_tm(apdev[0], "JP", dev[0])
761
762 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
763 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")
764
765 # Make the test take less time by limiting full scans
766 dev[0].set_network(id, "scan_freq", "2412")
767 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
768 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")
769 finally:
770 stop_wnm_tm(hapd, dev[0])
771
772def test_wnm_bss_tm_country_cn(dev, apdev):
773 """WNM BSS Transition Management (CN)"""
774 addr = dev[0].p2p_interface_addr()
775 try:
776 hapd = None
777 hapd, id = start_wnm_tm(apdev[0], "CN", dev[0])
778
779 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
780 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")
781
782 # Make the test take less time by limiting full scans
783 dev[0].set_network(id, "scan_freq", "2412")
784 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
785 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")
786 finally:
787 stop_wnm_tm(hapd, dev[0])
788
789def test_wnm_bss_tm_global(dev, apdev):
790 """WNM BSS Transition Management (global)"""
791 addr = dev[0].p2p_interface_addr()
792 try:
793 hapd = None
794 hapd, id = start_wnm_tm(apdev[0], "XX", dev[0])
795
796 logger.info("Preferred Candidate List (no matching neighbor, known channels)")
797 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")
798
799 # Make the test take less time by limiting full scans
800 dev[0].set_network(id, "scan_freq", "2412")
801 logger.info("Preferred Candidate List (no matching neighbor, unknown channels)")
802 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")
803
804 logger.info("Preferred Candidate List (no matching neighbor, unknown channels 2)")
805 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")
806 finally:
807 stop_wnm_tm(hapd, dev[0])
c4082f78 808
56153620
JM
809def test_wnm_bss_tm_op_class_0(dev, apdev):
810 """WNM BSS Transition Management with invalid operating class"""
811 try:
812 hapd = None
813 hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
814
815 logger.info("Preferred Candidate List (no matching neighbor, invalid op class specified for channels)")
816 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")
817 finally:
818 stop_wnm_tm(hapd, dev[0])
819
c4082f78
JM
820def test_wnm_action_proto(dev, apdev):
821 """WNM Action protocol testing"""
822 params = { "ssid": "test-wnm" }
8823178c 823 params['wnm_sleep_mode'] = '1'
c4082f78
JM
824 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
825 bssid = apdev[0]['bssid']
826 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
8823178c
JM
827 dev[0].request("WNM_SLEEP enter")
828 time.sleep(0.1)
c4082f78
JM
829 hapd.set("ext_mgmt_frame_handling", "1")
830
831 msg = {}
832 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
833 msg['da'] = dev[0].own_addr()
834 msg['sa'] = bssid
835 msg['bssid'] = bssid
836
837 dialog_token = 1
838
839 logger.debug("Unexpected WNM-Notification Response")
840 # Note: This is actually not registered for user space processing in
841 # driver_nl80211.c nl80211_mgmt_subscribe_non_ap() and as such, won't make
842 # it to wpa_supplicant.
843 msg['payload'] = struct.pack("<BBBB",
844 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_RESP,
845 dialog_token, 0)
846 hapd.mgmt_tx(msg)
847 expect_ack(hapd)
848
849 logger.debug("Truncated WNM-Notification Request (no Type field)")
850 msg['payload'] = struct.pack("<BBB",
851 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
852 dialog_token)
853 hapd.mgmt_tx(msg)
854 expect_ack(hapd)
855
856 logger.debug("WFA WNM-Notification Request with truncated IE (min)")
857 msg['payload'] = struct.pack("<BBBBBB",
858 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
859 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 1)
860 hapd.mgmt_tx(msg)
861 expect_ack(hapd)
862
863 logger.debug("WFA WNM-Notification Request with truncated IE (max)")
864 msg['payload'] = struct.pack("<BBBBBB",
865 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
866 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 255)
867 hapd.mgmt_tx(msg)
868 expect_ack(hapd)
869
870 logger.debug("WFA WNM-Notification Request with too short IE")
871 msg['payload'] = struct.pack("<BBBBBB",
872 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
873 dialog_token, WNM_NOTIF_TYPE_WFA, 0, 0)
874 hapd.mgmt_tx(msg)
875 expect_ack(hapd)
876
877 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL")
878 msg['payload'] = struct.pack(">BBBBBBLB",
879 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
880 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
881 0x506f9a00, 1)
882 hapd.mgmt_tx(msg)
883 expect_ack(hapd)
884
885 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(2)")
886 msg['payload'] = struct.pack(">BBBBBBLBB",
887 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
888 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 6,
889 0x506f9a00, 1, 0)
890 hapd.mgmt_tx(msg)
891 expect_ack(hapd)
892
893 logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(3)")
894 msg['payload'] = struct.pack(">BBBBBBLB",
895 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
896 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
897 0x506f9a00, 0xff)
898 hapd.mgmt_tx(msg)
899 expect_ack(hapd)
900
901 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(min)")
902 msg['payload'] = struct.pack(">BBBBBBLBHB",
903 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
904 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
905 0x506f9a01, 0, 0, 1)
906 hapd.mgmt_tx(msg)
907 expect_ack(hapd)
908
909 logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(max)")
910 msg['payload'] = struct.pack(">BBBBBBLBHB",
911 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
912 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
913 0x506f9a01, 0, 0, 0xff)
914 hapd.mgmt_tx(msg)
915 expect_ack(hapd)
916
917 logger.debug("WFA WNM-Notification Request with unsupported IE")
918 msg['payload'] = struct.pack("<BBBBBBL",
919 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
920 dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 4, 0)
921 hapd.mgmt_tx(msg)
922 expect_ack(hapd)
923
924 logger.debug("WNM-Notification Request with unknown WNM-Notification type 0")
925 msg['payload'] = struct.pack("<BBBB",
926 ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
927 dialog_token, WNM_NOTIF_TYPE_FW_UPGRADE)
928 hapd.mgmt_tx(msg)
929 expect_ack(hapd)
930
931 logger.debug("Truncated WNM Sleep Mode Response - no Dialog Token")
932 msg['payload'] = struct.pack("<BB",
933 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP)
934 hapd.mgmt_tx(msg)
935 expect_ack(hapd)
936
937 logger.debug("Truncated WNM Sleep Mode Response - no Key Data Length")
938 msg['payload'] = struct.pack("<BBB",
939 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0)
940 hapd.mgmt_tx(msg)
941 expect_ack(hapd)
942
943 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (min)")
944 msg['payload'] = struct.pack("<BBBH",
945 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
946 1)
947 hapd.mgmt_tx(msg)
948 expect_ack(hapd)
949
950 logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (max)")
951 msg['payload'] = struct.pack("<BBBH",
952 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
953 0xffff)
954 hapd.mgmt_tx(msg)
955 expect_ack(hapd)
956
957 logger.debug("WNM Sleep Mode Response - truncated IE header")
958 msg['payload'] = struct.pack("<BBBHB",
959 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
960 0, 0)
961 hapd.mgmt_tx(msg)
962 expect_ack(hapd)
963
964 logger.debug("WNM Sleep Mode Response - truncated IE")
965 msg['payload'] = struct.pack("<BBBHBB",
966 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
967 0, 0, 1)
968 hapd.mgmt_tx(msg)
969 expect_ack(hapd)
970
971 logger.debug("WNM Sleep Mode Response - Empty TFS Response")
972 msg['payload'] = struct.pack("<BBBHBB",
973 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
974 0, WLAN_EID_TFS_RESP, 0)
975 hapd.mgmt_tx(msg)
976 expect_ack(hapd)
977
978 logger.debug("WNM Sleep Mode Response - EID 0 not recognized")
979 msg['payload'] = struct.pack("<BBBHBB",
980 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
981 0, 0, 0)
982 hapd.mgmt_tx(msg)
983 expect_ack(hapd)
984
985 logger.debug("WNM Sleep Mode Response - Empty WNM Sleep Mode element and TFS Response element")
986 msg['payload'] = struct.pack("<BBBHBBBB",
987 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
988 0, WLAN_EID_WNMSLEEP, 0, WLAN_EID_TFS_RESP, 0)
989 hapd.mgmt_tx(msg)
990 expect_ack(hapd)
991
992 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element and empty TFS Response element")
993 msg['payload'] = struct.pack("<BBBHBBBBHBB",
994 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
995 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
996 WNM_STATUS_SLEEP_ACCEPT, 0,
997 WLAN_EID_TFS_RESP, 0)
998 hapd.mgmt_tx(msg)
999 expect_ack(hapd)
1000
1001 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(exit, deny key) and empty TFS Response element")
1002 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1003 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1004 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1005 WNM_STATUS_DENIED_KEY, 0,
1006 WLAN_EID_TFS_RESP, 0)
1007 hapd.mgmt_tx(msg)
1008 expect_ack(hapd)
1009
1010 logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(enter, deny key) and empty TFS Response element")
1011 msg['payload'] = struct.pack("<BBBHBBBBHBB",
1012 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1013 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
1014 WNM_STATUS_DENIED_KEY, 0,
1015 WLAN_EID_TFS_RESP, 0)
1016 hapd.mgmt_tx(msg)
1017 expect_ack(hapd)
1018
1019def test_wnm_action_proto_pmf(dev, apdev):
1020 """WNM Action protocol testing (PMF enabled)"""
1021 ssid = "test-wnm-pmf"
1022 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1023 params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1024 params["ieee80211w"] = "2"
8823178c 1025 params['wnm_sleep_mode'] = '1'
c4082f78
JM
1026 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1027 bssid = apdev[0]['bssid']
1028 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
1029 proto="WPA2", ieee80211w="2", scan_freq="2412")
8823178c
JM
1030 dev[0].request("WNM_SLEEP enter")
1031 time.sleep(0.1)
c4082f78
JM
1032 hapd.set("ext_mgmt_frame_handling", "1")
1033
1034 msg = {}
1035 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1036 msg['da'] = dev[0].own_addr()
1037 msg['sa'] = bssid
1038 msg['bssid'] = bssid
1039
1040 logger.debug("WNM Sleep Mode Response - Invalid Key Data element length")
1041 keydata = struct.pack("<BB", 0, 1)
1042 msg['payload'] = struct.pack("<BBBH",
1043 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1044 len(keydata))
1045 msg['payload'] += keydata
1046 msg['payload'] += struct.pack("<BBBBHBB",
1047 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1048 WNM_STATUS_SLEEP_ACCEPT, 0,
1049 WLAN_EID_TFS_RESP, 0)
1050 hapd.mgmt_tx(msg)
1051 expect_ack(hapd)
1052
1053 logger.debug("WNM Sleep Mode Response - Too short GTK subelem")
1054 keydata = struct.pack("<BB", WNM_SLEEP_SUBELEM_GTK, 0)
1055 msg['payload'] = struct.pack("<BBBH",
1056 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1057 len(keydata))
1058 msg['payload'] += keydata
1059 msg['payload'] += struct.pack("<BBBBHBB",
1060 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1061 WNM_STATUS_SLEEP_ACCEPT, 0,
1062 WLAN_EID_TFS_RESP, 0)
1063 hapd.mgmt_tx(msg)
1064 expect_ack(hapd)
1065
1066 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem")
1067 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1068 0, 17, 0, 0, 0, 0, 0, 0)
1069 msg['payload'] = struct.pack("<BBBH",
1070 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1071 len(keydata))
1072 msg['payload'] += keydata
1073 msg['payload'] += struct.pack("<BBBBHBB",
1074 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1075 WNM_STATUS_SLEEP_ACCEPT, 0,
1076 WLAN_EID_TFS_RESP, 0)
1077 hapd.mgmt_tx(msg)
1078 expect_ack(hapd)
1079
1080 logger.debug("WNM Sleep Mode Response - Invalid GTK subelem (2)")
1081 keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
1082 0, 0, 0, 0, 0, 0, 0, 0)
1083 msg['payload'] = struct.pack("<BBBH",
1084 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1085 len(keydata))
1086 msg['payload'] += keydata
1087 msg['payload'] += struct.pack("<BBBBHBB",
1088 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1089 WNM_STATUS_SLEEP_ACCEPT, 0,
1090 WLAN_EID_TFS_RESP, 0)
1091 hapd.mgmt_tx(msg)
1092 expect_ack(hapd)
1093
1094 logger.debug("WNM Sleep Mode Response - GTK subelem and too short IGTK subelem")
1095 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1096 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1097 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1098 keydata += struct.pack("<BB", WNM_SLEEP_SUBELEM_IGTK, 0)
1099 msg['payload'] = struct.pack("<BBBH",
1100 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1101 len(keydata))
1102 msg['payload'] += keydata
1103 msg['payload'] += struct.pack("<BBBBHBB",
1104 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1105 WNM_STATUS_SLEEP_ACCEPT, 0,
1106 WLAN_EID_TFS_RESP, 0)
1107 hapd.mgmt_tx(msg)
1108 expect_ack(hapd)
1109
1110 logger.debug("WNM Sleep Mode Response - Unknown subelem")
1111 keydata = struct.pack("<BB", 255, 0)
1112 msg['payload'] = struct.pack("<BBBH",
1113 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1114 len(keydata))
1115 msg['payload'] += keydata
1116 msg['payload'] += struct.pack("<BBBBHBB",
1117 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1118 WNM_STATUS_SLEEP_ACCEPT, 0,
1119 WLAN_EID_TFS_RESP, 0)
1120 hapd.mgmt_tx(msg)
1121 expect_ack(hapd)
63a19e56
JM
1122
1123def test_wnm_action_proto_no_pmf(dev, apdev):
1124 """WNM Action protocol testing (PMF disabled)"""
1125 ssid = "test-wnm-no-pmf"
1126 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
8823178c 1127 params['wnm_sleep_mode'] = '1'
63a19e56
JM
1128 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1129 bssid = apdev[0]['bssid']
1130 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1131 proto="WPA2", ieee80211w="0", scan_freq="2412")
8823178c
JM
1132 dev[0].request("WNM_SLEEP enter")
1133 time.sleep(0.1)
63a19e56
JM
1134 hapd.set("ext_mgmt_frame_handling", "1")
1135
1136 msg = {}
1137 msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1138 msg['da'] = dev[0].own_addr()
1139 msg['sa'] = bssid
1140 msg['bssid'] = bssid
1141
1142 logger.debug("WNM Sleep Mode Response - GTK subelem and IGTK subelem")
1143 keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
1144 keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
1145 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
1146 keydata += struct.pack("<BBHLH4L", WNM_SLEEP_SUBELEM_IGTK, 2 + 6 + 16, 0,
1147 0x10203040, 0x5060,
1148 0xf1f2f3f4, 0xf5f6f7f8, 0xf9f0fafb, 0xfcfdfeff)
1149 msg['payload'] = struct.pack("<BBBH",
1150 ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
1151 len(keydata))
1152 msg['payload'] += keydata
1153 msg['payload'] += struct.pack("<BBBBHBB",
1154 WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
1155 WNM_STATUS_SLEEP_ACCEPT, 0,
1156 WLAN_EID_TFS_RESP, 0)
1157 hapd.mgmt_tx(msg)
1158 expect_ack(hapd)
1159
1160 ev = dev[0].wait_event(["WNM: Ignore Key Data"], timeout=5)
1161 if ev is None:
1162 raise Exception("Key Data not ignored")
85cc109e
AS
1163
1164def test_wnm_bss_tm_req_with_mbo_ie(dev, apdev):
1165 """WNM BSS transition request with MBO IE and reassociation delay attribute"""
1166 ssid = "test-wnm-mbo"
1167 params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1168 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1169 bssid = apdev[0]['bssid']
1170 if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
1171 raise Exception("Failed to set STA as cellular data capable")
1172
1173 dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
1174 proto="WPA2", ieee80211w="0", scan_freq="2412")
1175
1176 logger.debug("BTM request with MBO reassociation delay when disassoc imminent is not set")
1177 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=3:2:1"):
1178 raise Exception("BSS transition management succeeded unexpectedly")
1179
1180 logger.debug("BTM request with invalid MBO transition reason code")
1181 if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=10:2:1"):
1182 raise Exception("BSS transition management succeeded unexpectedly")
1183
1184 logger.debug("BTM request with MBO reassociation retry delay of 5 seconds")
1185 if 'OK' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " disassoc_imminent=1 disassoc_timer=3 mbo=3:5:1"):
1186 raise Exception("BSS transition management command failed")
1187
1188 ev = dev[0].wait_event(['MBO-CELL-PREFERENCE'], 1)
1189 if ev is None or "preference=1" not in ev:
1190 raise Exception("Timeout waiting for MBO-CELL-PREFERENCE event")
1191
1192 ev = dev[0].wait_event(['MBO-TRANSITION-REASON'], 1)
1193 if ev is None or "reason=3" not in ev:
1194 raise Exception("Timeout waiting for MBO-TRANSITION-REASON event")
1195
1196 ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
1197 if ev is None:
1198 raise Exception("No BSS Transition Management Response")
1199 if dev[0].own_addr() not in ev:
1200 raise Exception("Unexpected BSS Transition Management Response address")
1201
1202 ev = dev[0].wait_event(['CTRL-EVENT-DISCONNECTED'], 5)
1203 if ev is None:
1204 raise Exception("Station did not disconnect although disassoc imminent was set")
1205
1206 # Set the scan interval to make dev[0] look for connections
1207 if 'OK' not in dev[0].request("SCAN_INTERVAL 1"):
1208 raise Exception("Failed to set scan interval")
1209
1210 # Make sure no connection is made during the retry delay
1211 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1212 if ev is not None:
1213 raise Exception("Station connected before assoc retry delay was over")
1214
1215 # After the assoc retry delay is over, we can reconnect
1216 ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
1217 if ev is None:
1218 raise Exception("Station did not connect after assoc retry delay is over")
1219
1220 if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
1221 raise Exception("Failed to set STA as cellular data not-capable")
c24c144f
JM
1222
1223def test_wnm_bss_transition_mgmt_query(dev, apdev):
1224 """WNM BSS Transition Management query"""
1225 params = { "ssid": "test-wnm",
1226 "bss_transition": "1" }
1227 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1228 params = { "ssid": "another" }
1229 hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
1230
1231 dev[0].scan_for_bss(apdev[1]['bssid'], 2412)
1232 dev[0].scan_for_bss(apdev[0]['bssid'], 2412)
1233
1234 dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
1235 dev[0].request("WNM_BSS_QUERY 0 list")
1236
1237 ev = dev[0].wait_event(["WNM: BSS Transition Management Request"],
1238 timeout=5)
1239 if ev is None:
1240 raise Exception("No BSS Transition Management Request frame seen")
1241
1242 ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
1243 if ev is None:
1244 raise Exception("No BSS Transition Management Response frame seen")