test_wnm.py 61 KB

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