test_wnm.py 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  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_bss_tm_op_class_0(dev, apdev):
  603. """WNM BSS Transition Management with invalid operating class"""
  604. try:
  605. hapd = None
  606. hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
  607. logger.info("Preferred Candidate List (no matching neighbor, invalid op class specified for channels)")
  608. 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")
  609. finally:
  610. stop_wnm_tm(hapd, dev[0])
  611. def test_wnm_action_proto(dev, apdev):
  612. """WNM Action protocol testing"""
  613. params = { "ssid": "test-wnm" }
  614. params['wnm_sleep_mode'] = '1'
  615. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  616. bssid = apdev[0]['bssid']
  617. dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
  618. dev[0].request("WNM_SLEEP enter")
  619. time.sleep(0.1)
  620. hapd.set("ext_mgmt_frame_handling", "1")
  621. msg = {}
  622. msg['fc'] = MGMT_SUBTYPE_ACTION << 4
  623. msg['da'] = dev[0].own_addr()
  624. msg['sa'] = bssid
  625. msg['bssid'] = bssid
  626. dialog_token = 1
  627. logger.debug("Unexpected WNM-Notification Response")
  628. # Note: This is actually not registered for user space processing in
  629. # driver_nl80211.c nl80211_mgmt_subscribe_non_ap() and as such, won't make
  630. # it to wpa_supplicant.
  631. msg['payload'] = struct.pack("<BBBB",
  632. ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_RESP,
  633. dialog_token, 0)
  634. hapd.mgmt_tx(msg)
  635. expect_ack(hapd)
  636. logger.debug("Truncated WNM-Notification Request (no Type field)")
  637. msg['payload'] = struct.pack("<BBB",
  638. ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
  639. dialog_token)
  640. hapd.mgmt_tx(msg)
  641. expect_ack(hapd)
  642. logger.debug("WFA WNM-Notification Request with truncated IE (min)")
  643. msg['payload'] = struct.pack("<BBBBBB",
  644. ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
  645. dialog_token, WNM_NOTIF_TYPE_WFA, 0, 1)
  646. hapd.mgmt_tx(msg)
  647. expect_ack(hapd)
  648. logger.debug("WFA WNM-Notification Request with truncated IE (max)")
  649. msg['payload'] = struct.pack("<BBBBBB",
  650. ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
  651. dialog_token, WNM_NOTIF_TYPE_WFA, 0, 255)
  652. hapd.mgmt_tx(msg)
  653. expect_ack(hapd)
  654. logger.debug("WFA WNM-Notification Request with too short IE")
  655. msg['payload'] = struct.pack("<BBBBBB",
  656. ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
  657. dialog_token, WNM_NOTIF_TYPE_WFA, 0, 0)
  658. hapd.mgmt_tx(msg)
  659. expect_ack(hapd)
  660. logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL")
  661. msg['payload'] = struct.pack(">BBBBBBLB",
  662. ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
  663. dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
  664. 0x506f9a00, 1)
  665. hapd.mgmt_tx(msg)
  666. expect_ack(hapd)
  667. logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(2)")
  668. msg['payload'] = struct.pack(">BBBBBBLBB",
  669. ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
  670. dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 6,
  671. 0x506f9a00, 1, 0)
  672. hapd.mgmt_tx(msg)
  673. expect_ack(hapd)
  674. logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(3)")
  675. msg['payload'] = struct.pack(">BBBBBBLB",
  676. ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
  677. dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
  678. 0x506f9a00, 0xff)
  679. hapd.mgmt_tx(msg)
  680. expect_ack(hapd)
  681. logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(min)")
  682. msg['payload'] = struct.pack(">BBBBBBLBHB",
  683. ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
  684. dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
  685. 0x506f9a01, 0, 0, 1)
  686. hapd.mgmt_tx(msg)
  687. expect_ack(hapd)
  688. logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(max)")
  689. msg['payload'] = struct.pack(">BBBBBBLBHB",
  690. ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
  691. dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
  692. 0x506f9a01, 0, 0, 0xff)
  693. hapd.mgmt_tx(msg)
  694. expect_ack(hapd)
  695. logger.debug("WFA WNM-Notification Request with unsupported IE")
  696. msg['payload'] = struct.pack("<BBBBBBL",
  697. ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
  698. dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 4, 0)
  699. hapd.mgmt_tx(msg)
  700. expect_ack(hapd)
  701. logger.debug("WNM-Notification Request with unknown WNM-Notification type 0")
  702. msg['payload'] = struct.pack("<BBBB",
  703. ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
  704. dialog_token, WNM_NOTIF_TYPE_FW_UPGRADE)
  705. hapd.mgmt_tx(msg)
  706. expect_ack(hapd)
  707. logger.debug("Truncated WNM Sleep Mode Response - no Dialog Token")
  708. msg['payload'] = struct.pack("<BB",
  709. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP)
  710. hapd.mgmt_tx(msg)
  711. expect_ack(hapd)
  712. logger.debug("Truncated WNM Sleep Mode Response - no Key Data Length")
  713. msg['payload'] = struct.pack("<BBB",
  714. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0)
  715. hapd.mgmt_tx(msg)
  716. expect_ack(hapd)
  717. logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (min)")
  718. msg['payload'] = struct.pack("<BBBH",
  719. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  720. 1)
  721. hapd.mgmt_tx(msg)
  722. expect_ack(hapd)
  723. logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (max)")
  724. msg['payload'] = struct.pack("<BBBH",
  725. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  726. 0xffff)
  727. hapd.mgmt_tx(msg)
  728. expect_ack(hapd)
  729. logger.debug("WNM Sleep Mode Response - truncated IE header")
  730. msg['payload'] = struct.pack("<BBBHB",
  731. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  732. 0, 0)
  733. hapd.mgmt_tx(msg)
  734. expect_ack(hapd)
  735. logger.debug("WNM Sleep Mode Response - truncated IE")
  736. msg['payload'] = struct.pack("<BBBHBB",
  737. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  738. 0, 0, 1)
  739. hapd.mgmt_tx(msg)
  740. expect_ack(hapd)
  741. logger.debug("WNM Sleep Mode Response - Empty TFS Response")
  742. msg['payload'] = struct.pack("<BBBHBB",
  743. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  744. 0, WLAN_EID_TFS_RESP, 0)
  745. hapd.mgmt_tx(msg)
  746. expect_ack(hapd)
  747. logger.debug("WNM Sleep Mode Response - EID 0 not recognized")
  748. msg['payload'] = struct.pack("<BBBHBB",
  749. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  750. 0, 0, 0)
  751. hapd.mgmt_tx(msg)
  752. expect_ack(hapd)
  753. logger.debug("WNM Sleep Mode Response - Empty WNM Sleep Mode element and TFS Response element")
  754. msg['payload'] = struct.pack("<BBBHBBBB",
  755. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  756. 0, WLAN_EID_WNMSLEEP, 0, WLAN_EID_TFS_RESP, 0)
  757. hapd.mgmt_tx(msg)
  758. expect_ack(hapd)
  759. logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element and empty TFS Response element")
  760. msg['payload'] = struct.pack("<BBBHBBBBHBB",
  761. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  762. 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
  763. WNM_STATUS_SLEEP_ACCEPT, 0,
  764. WLAN_EID_TFS_RESP, 0)
  765. hapd.mgmt_tx(msg)
  766. expect_ack(hapd)
  767. logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(exit, deny key) and empty TFS Response element")
  768. msg['payload'] = struct.pack("<BBBHBBBBHBB",
  769. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  770. 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
  771. WNM_STATUS_DENIED_KEY, 0,
  772. 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(enter, deny key) 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_DENIED_KEY, 0,
  780. WLAN_EID_TFS_RESP, 0)
  781. hapd.mgmt_tx(msg)
  782. expect_ack(hapd)
  783. def test_wnm_action_proto_pmf(dev, apdev):
  784. """WNM Action protocol testing (PMF enabled)"""
  785. ssid = "test-wnm-pmf"
  786. params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
  787. params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
  788. params["ieee80211w"] = "2"
  789. params['wnm_sleep_mode'] = '1'
  790. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  791. bssid = apdev[0]['bssid']
  792. dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
  793. proto="WPA2", ieee80211w="2", scan_freq="2412")
  794. dev[0].request("WNM_SLEEP enter")
  795. time.sleep(0.1)
  796. hapd.set("ext_mgmt_frame_handling", "1")
  797. msg = {}
  798. msg['fc'] = MGMT_SUBTYPE_ACTION << 4
  799. msg['da'] = dev[0].own_addr()
  800. msg['sa'] = bssid
  801. msg['bssid'] = bssid
  802. logger.debug("WNM Sleep Mode Response - Invalid Key Data element length")
  803. keydata = struct.pack("<BB", 0, 1)
  804. msg['payload'] = struct.pack("<BBBH",
  805. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  806. len(keydata))
  807. msg['payload'] += keydata
  808. msg['payload'] += struct.pack("<BBBBHBB",
  809. WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
  810. WNM_STATUS_SLEEP_ACCEPT, 0,
  811. WLAN_EID_TFS_RESP, 0)
  812. hapd.mgmt_tx(msg)
  813. expect_ack(hapd)
  814. logger.debug("WNM Sleep Mode Response - Too short GTK subelem")
  815. keydata = struct.pack("<BB", WNM_SLEEP_SUBELEM_GTK, 0)
  816. msg['payload'] = struct.pack("<BBBH",
  817. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  818. len(keydata))
  819. msg['payload'] += keydata
  820. msg['payload'] += struct.pack("<BBBBHBB",
  821. WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
  822. WNM_STATUS_SLEEP_ACCEPT, 0,
  823. WLAN_EID_TFS_RESP, 0)
  824. hapd.mgmt_tx(msg)
  825. expect_ack(hapd)
  826. logger.debug("WNM Sleep Mode Response - Invalid GTK subelem")
  827. keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
  828. 0, 17, 0, 0, 0, 0, 0, 0)
  829. msg['payload'] = struct.pack("<BBBH",
  830. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  831. len(keydata))
  832. msg['payload'] += keydata
  833. msg['payload'] += struct.pack("<BBBBHBB",
  834. WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
  835. WNM_STATUS_SLEEP_ACCEPT, 0,
  836. WLAN_EID_TFS_RESP, 0)
  837. hapd.mgmt_tx(msg)
  838. expect_ack(hapd)
  839. logger.debug("WNM Sleep Mode Response - Invalid GTK subelem (2)")
  840. keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
  841. 0, 0, 0, 0, 0, 0, 0, 0)
  842. msg['payload'] = struct.pack("<BBBH",
  843. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  844. len(keydata))
  845. msg['payload'] += keydata
  846. msg['payload'] += struct.pack("<BBBBHBB",
  847. WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
  848. WNM_STATUS_SLEEP_ACCEPT, 0,
  849. WLAN_EID_TFS_RESP, 0)
  850. hapd.mgmt_tx(msg)
  851. expect_ack(hapd)
  852. logger.debug("WNM Sleep Mode Response - GTK subelem and too short IGTK subelem")
  853. keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
  854. keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
  855. 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
  856. keydata += struct.pack("<BB", WNM_SLEEP_SUBELEM_IGTK, 0)
  857. msg['payload'] = struct.pack("<BBBH",
  858. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  859. len(keydata))
  860. msg['payload'] += keydata
  861. msg['payload'] += struct.pack("<BBBBHBB",
  862. WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
  863. WNM_STATUS_SLEEP_ACCEPT, 0,
  864. WLAN_EID_TFS_RESP, 0)
  865. hapd.mgmt_tx(msg)
  866. expect_ack(hapd)
  867. logger.debug("WNM Sleep Mode Response - Unknown subelem")
  868. keydata = struct.pack("<BB", 255, 0)
  869. msg['payload'] = struct.pack("<BBBH",
  870. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  871. len(keydata))
  872. msg['payload'] += keydata
  873. msg['payload'] += struct.pack("<BBBBHBB",
  874. WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
  875. WNM_STATUS_SLEEP_ACCEPT, 0,
  876. WLAN_EID_TFS_RESP, 0)
  877. hapd.mgmt_tx(msg)
  878. expect_ack(hapd)
  879. def test_wnm_action_proto_no_pmf(dev, apdev):
  880. """WNM Action protocol testing (PMF disabled)"""
  881. ssid = "test-wnm-no-pmf"
  882. params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
  883. params['wnm_sleep_mode'] = '1'
  884. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  885. bssid = apdev[0]['bssid']
  886. dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
  887. proto="WPA2", ieee80211w="0", scan_freq="2412")
  888. dev[0].request("WNM_SLEEP enter")
  889. time.sleep(0.1)
  890. hapd.set("ext_mgmt_frame_handling", "1")
  891. msg = {}
  892. msg['fc'] = MGMT_SUBTYPE_ACTION << 4
  893. msg['da'] = dev[0].own_addr()
  894. msg['sa'] = bssid
  895. msg['bssid'] = bssid
  896. logger.debug("WNM Sleep Mode Response - GTK subelem and IGTK subelem")
  897. keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
  898. keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
  899. 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
  900. keydata += struct.pack("<BBHLH4L", WNM_SLEEP_SUBELEM_IGTK, 2 + 6 + 16, 0,
  901. 0x10203040, 0x5060,
  902. 0xf1f2f3f4, 0xf5f6f7f8, 0xf9f0fafb, 0xfcfdfeff)
  903. msg['payload'] = struct.pack("<BBBH",
  904. ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
  905. len(keydata))
  906. msg['payload'] += keydata
  907. msg['payload'] += struct.pack("<BBBBHBB",
  908. WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
  909. WNM_STATUS_SLEEP_ACCEPT, 0,
  910. WLAN_EID_TFS_RESP, 0)
  911. hapd.mgmt_tx(msg)
  912. expect_ack(hapd)
  913. ev = dev[0].wait_event(["WNM: Ignore Key Data"], timeout=5)
  914. if ev is None:
  915. raise Exception("Key Data not ignored")