test_wnm.py 50 KB

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