test_wnm.py 46 KB

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