rx_mgmt.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169
  1. /*
  2. * Received Management frame processing
  3. * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "utils/includes.h"
  9. #include "utils/common.h"
  10. #include "common/ieee802_11_defs.h"
  11. #include "common/ieee802_11_common.h"
  12. #include "crypto/aes_wrap.h"
  13. #include "wlantest.h"
  14. static const char * mgmt_stype(u16 stype)
  15. {
  16. switch (stype) {
  17. case WLAN_FC_STYPE_ASSOC_REQ:
  18. return "ASSOC-REQ";
  19. case WLAN_FC_STYPE_ASSOC_RESP:
  20. return "ASSOC-RESP";
  21. case WLAN_FC_STYPE_REASSOC_REQ:
  22. return "REASSOC-REQ";
  23. case WLAN_FC_STYPE_REASSOC_RESP:
  24. return "REASSOC-RESP";
  25. case WLAN_FC_STYPE_PROBE_REQ:
  26. return "PROBE-REQ";
  27. case WLAN_FC_STYPE_PROBE_RESP:
  28. return "PROBE-RESP";
  29. case WLAN_FC_STYPE_BEACON:
  30. return "BEACON";
  31. case WLAN_FC_STYPE_ATIM:
  32. return "ATIM";
  33. case WLAN_FC_STYPE_DISASSOC:
  34. return "DISASSOC";
  35. case WLAN_FC_STYPE_AUTH:
  36. return "AUTH";
  37. case WLAN_FC_STYPE_DEAUTH:
  38. return "DEAUTH";
  39. case WLAN_FC_STYPE_ACTION:
  40. return "ACTION";
  41. }
  42. return "??";
  43. }
  44. static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len)
  45. {
  46. const struct ieee80211_mgmt *mgmt;
  47. struct wlantest_bss *bss;
  48. struct ieee802_11_elems elems;
  49. mgmt = (const struct ieee80211_mgmt *) data;
  50. bss = bss_get(wt, mgmt->bssid);
  51. if (bss == NULL)
  52. return;
  53. if (bss->proberesp_seen)
  54. return; /* do not override with Beacon data */
  55. bss->capab_info = le_to_host16(mgmt->u.beacon.capab_info);
  56. if (ieee802_11_parse_elems(mgmt->u.beacon.variable,
  57. len - (mgmt->u.beacon.variable - data),
  58. &elems, 0) == ParseFailed) {
  59. if (bss->parse_error_reported)
  60. return;
  61. wpa_printf(MSG_INFO, "Invalid IEs in a Beacon frame from "
  62. MACSTR, MAC2STR(mgmt->sa));
  63. bss->parse_error_reported = 1;
  64. return;
  65. }
  66. bss_update(wt, bss, &elems);
  67. }
  68. static void rx_mgmt_probe_resp(struct wlantest *wt, const u8 *data, size_t len)
  69. {
  70. const struct ieee80211_mgmt *mgmt;
  71. struct wlantest_bss *bss;
  72. struct ieee802_11_elems elems;
  73. mgmt = (const struct ieee80211_mgmt *) data;
  74. bss = bss_get(wt, mgmt->bssid);
  75. if (bss == NULL)
  76. return;
  77. bss->capab_info = le_to_host16(mgmt->u.probe_resp.capab_info);
  78. if (ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
  79. len - (mgmt->u.probe_resp.variable - data),
  80. &elems, 0) == ParseFailed) {
  81. if (bss->parse_error_reported)
  82. return;
  83. wpa_printf(MSG_INFO, "Invalid IEs in a Probe Response frame "
  84. "from " MACSTR, MAC2STR(mgmt->sa));
  85. bss->parse_error_reported = 1;
  86. return;
  87. }
  88. bss_update(wt, bss, &elems);
  89. }
  90. static void rx_mgmt_auth(struct wlantest *wt, const u8 *data, size_t len)
  91. {
  92. const struct ieee80211_mgmt *mgmt;
  93. struct wlantest_bss *bss;
  94. struct wlantest_sta *sta;
  95. u16 alg, trans, status;
  96. mgmt = (const struct ieee80211_mgmt *) data;
  97. bss = bss_get(wt, mgmt->bssid);
  98. if (bss == NULL)
  99. return;
  100. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
  101. sta = sta_get(bss, mgmt->da);
  102. else
  103. sta = sta_get(bss, mgmt->sa);
  104. if (sta == NULL)
  105. return;
  106. if (len < 24 + 6) {
  107. wpa_printf(MSG_INFO, "Too short Authentication frame from "
  108. MACSTR, MAC2STR(mgmt->sa));
  109. return;
  110. }
  111. alg = le_to_host16(mgmt->u.auth.auth_alg);
  112. trans = le_to_host16(mgmt->u.auth.auth_transaction);
  113. status = le_to_host16(mgmt->u.auth.status_code);
  114. wpa_printf(MSG_DEBUG, "AUTH " MACSTR " -> " MACSTR
  115. " (alg=%u trans=%u status=%u)",
  116. MAC2STR(mgmt->sa), MAC2STR(mgmt->da), alg, trans, status);
  117. if (alg == 0 && trans == 2 && status == 0) {
  118. if (sta->state == STATE1) {
  119. wpa_printf(MSG_DEBUG, "STA " MACSTR
  120. " moved to State 2 with " MACSTR,
  121. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  122. sta->state = STATE2;
  123. }
  124. }
  125. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
  126. sta->counters[WLANTEST_STA_COUNTER_AUTH_RX]++;
  127. else
  128. sta->counters[WLANTEST_STA_COUNTER_AUTH_TX]++;
  129. }
  130. static void deauth_all_stas(struct wlantest_bss *bss)
  131. {
  132. struct wlantest_sta *sta;
  133. dl_list_for_each(sta, &bss->sta, struct wlantest_sta, list) {
  134. if (sta->state == STATE1)
  135. continue;
  136. wpa_printf(MSG_DEBUG, "STA " MACSTR
  137. " moved to State 1 with " MACSTR,
  138. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  139. sta->state = STATE1;
  140. }
  141. }
  142. static void tdls_link_down(struct wlantest_bss *bss, struct wlantest_sta *sta)
  143. {
  144. struct wlantest_tdls *tdls;
  145. dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) {
  146. if ((tdls->init == sta || tdls->resp == sta) && tdls->link_up)
  147. {
  148. wpa_printf(MSG_DEBUG, "TDLS: Set link down based on "
  149. "STA deauth/disassoc");
  150. tdls->link_up = 0;
  151. }
  152. }
  153. }
  154. static void rx_mgmt_deauth(struct wlantest *wt, const u8 *data, size_t len,
  155. int valid)
  156. {
  157. const struct ieee80211_mgmt *mgmt;
  158. struct wlantest_bss *bss;
  159. struct wlantest_sta *sta;
  160. u16 fc, reason;
  161. mgmt = (const struct ieee80211_mgmt *) data;
  162. bss = bss_get(wt, mgmt->bssid);
  163. if (bss == NULL)
  164. return;
  165. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
  166. sta = sta_get(bss, mgmt->da);
  167. else
  168. sta = sta_get(bss, mgmt->sa);
  169. if (len < 24 + 2) {
  170. wpa_printf(MSG_INFO, "Too short Deauthentication frame from "
  171. MACSTR, MAC2STR(mgmt->sa));
  172. return;
  173. }
  174. reason = le_to_host16(mgmt->u.deauth.reason_code);
  175. wpa_printf(MSG_DEBUG, "DEAUTH " MACSTR " -> " MACSTR
  176. " (reason=%u) (valid=%d)",
  177. MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
  178. reason, valid);
  179. wpa_hexdump(MSG_MSGDUMP, "DEAUTH payload", data + 24, len - 24);
  180. if (sta == NULL) {
  181. if (valid && mgmt->da[0] == 0xff)
  182. deauth_all_stas(bss);
  183. return;
  184. }
  185. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
  186. sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DEAUTH_RX :
  187. WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX]++;
  188. if (sta->pwrmgt && !sta->pspoll)
  189. sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_ASLEEP]++;
  190. else
  191. sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_AWAKE]++;
  192. fc = le_to_host16(mgmt->frame_control);
  193. if (!(fc & WLAN_FC_ISWEP) && reason == 6)
  194. sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_RC6]++;
  195. else if (!(fc & WLAN_FC_ISWEP) && reason == 7)
  196. sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_RC7]++;
  197. } else
  198. sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DEAUTH_TX :
  199. WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX]++;
  200. if (!valid) {
  201. wpa_printf(MSG_INFO, "Do not change STA " MACSTR " State "
  202. "since Disassociation frame was not protected "
  203. "correctly", MAC2STR(sta->addr));
  204. return;
  205. }
  206. if (sta->state != STATE1) {
  207. wpa_printf(MSG_DEBUG, "STA " MACSTR
  208. " moved to State 1 with " MACSTR,
  209. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  210. sta->state = STATE1;
  211. }
  212. tdls_link_down(bss, sta);
  213. }
  214. static void rx_mgmt_assoc_req(struct wlantest *wt, const u8 *data, size_t len)
  215. {
  216. const struct ieee80211_mgmt *mgmt;
  217. struct wlantest_bss *bss;
  218. struct wlantest_sta *sta;
  219. struct ieee802_11_elems elems;
  220. mgmt = (const struct ieee80211_mgmt *) data;
  221. bss = bss_get(wt, mgmt->bssid);
  222. if (bss == NULL)
  223. return;
  224. sta = sta_get(bss, mgmt->sa);
  225. if (sta == NULL)
  226. return;
  227. if (len < 24 + 4) {
  228. wpa_printf(MSG_INFO, "Too short Association Request frame "
  229. "from " MACSTR, MAC2STR(mgmt->sa));
  230. return;
  231. }
  232. wpa_printf(MSG_DEBUG, "ASSOCREQ " MACSTR " -> " MACSTR
  233. " (capab=0x%x listen_int=%u)",
  234. MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
  235. le_to_host16(mgmt->u.assoc_req.capab_info),
  236. le_to_host16(mgmt->u.assoc_req.listen_interval));
  237. sta->counters[WLANTEST_STA_COUNTER_ASSOCREQ_TX]++;
  238. if (ieee802_11_parse_elems(mgmt->u.assoc_req.variable,
  239. len - (mgmt->u.assoc_req.variable - data),
  240. &elems, 0) == ParseFailed) {
  241. wpa_printf(MSG_INFO, "Invalid IEs in Association Request "
  242. "frame from " MACSTR, MAC2STR(mgmt->sa));
  243. return;
  244. }
  245. sta->assocreq_capab_info = le_to_host16(mgmt->u.assoc_req.capab_info);
  246. sta->assocreq_listen_int =
  247. le_to_host16(mgmt->u.assoc_req.listen_interval);
  248. os_free(sta->assocreq_ies);
  249. sta->assocreq_ies_len = len - (mgmt->u.assoc_req.variable - data);
  250. sta->assocreq_ies = os_malloc(sta->assocreq_ies_len);
  251. if (sta->assocreq_ies)
  252. os_memcpy(sta->assocreq_ies, mgmt->u.assoc_req.variable,
  253. sta->assocreq_ies_len);
  254. sta_update_assoc(sta, &elems);
  255. }
  256. static void rx_mgmt_assoc_resp(struct wlantest *wt, const u8 *data, size_t len)
  257. {
  258. const struct ieee80211_mgmt *mgmt;
  259. struct wlantest_bss *bss;
  260. struct wlantest_sta *sta;
  261. u16 capab, status, aid;
  262. mgmt = (const struct ieee80211_mgmt *) data;
  263. bss = bss_get(wt, mgmt->bssid);
  264. if (bss == NULL)
  265. return;
  266. sta = sta_get(bss, mgmt->da);
  267. if (sta == NULL)
  268. return;
  269. if (len < 24 + 6) {
  270. wpa_printf(MSG_INFO, "Too short Association Response frame "
  271. "from " MACSTR, MAC2STR(mgmt->sa));
  272. return;
  273. }
  274. capab = le_to_host16(mgmt->u.assoc_resp.capab_info);
  275. status = le_to_host16(mgmt->u.assoc_resp.status_code);
  276. aid = le_to_host16(mgmt->u.assoc_resp.aid);
  277. wpa_printf(MSG_DEBUG, "ASSOCRESP " MACSTR " -> " MACSTR
  278. " (capab=0x%x status=%u aid=%u)",
  279. MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status,
  280. aid & 0x3fff);
  281. if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
  282. struct ieee802_11_elems elems;
  283. const u8 *ies = mgmt->u.assoc_resp.variable;
  284. size_t ies_len = len - (mgmt->u.assoc_resp.variable - data);
  285. if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) ==
  286. ParseFailed) {
  287. wpa_printf(MSG_INFO, "Failed to parse IEs in "
  288. "AssocResp from " MACSTR,
  289. MAC2STR(mgmt->sa));
  290. } else if (elems.timeout_int == NULL ||
  291. elems.timeout_int_len != 5 ||
  292. elems.timeout_int[0] !=
  293. WLAN_TIMEOUT_ASSOC_COMEBACK) {
  294. wpa_printf(MSG_INFO, "No valid Timeout Interval IE "
  295. "with Assoc Comeback time in AssocResp "
  296. "(status=30) from " MACSTR,
  297. MAC2STR(mgmt->sa));
  298. } else {
  299. sta->counters[
  300. WLANTEST_STA_COUNTER_ASSOCRESP_COMEBACK]++;
  301. }
  302. }
  303. if (status)
  304. return;
  305. if ((aid & 0xc000) != 0xc000) {
  306. wpa_printf(MSG_DEBUG, "Two MSBs of the AID were not set to 1 "
  307. "in Association Response from " MACSTR,
  308. MAC2STR(mgmt->sa));
  309. }
  310. sta->aid = aid & 0xc000;
  311. if (sta->state < STATE2) {
  312. wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 when "
  313. "getting associated", MAC2STR(sta->addr));
  314. }
  315. if (sta->state < STATE3) {
  316. wpa_printf(MSG_DEBUG, "STA " MACSTR
  317. " moved to State 3 with " MACSTR,
  318. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  319. sta->state = STATE3;
  320. }
  321. }
  322. static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data,
  323. size_t len)
  324. {
  325. const struct ieee80211_mgmt *mgmt;
  326. struct wlantest_bss *bss;
  327. struct wlantest_sta *sta;
  328. struct ieee802_11_elems elems;
  329. mgmt = (const struct ieee80211_mgmt *) data;
  330. bss = bss_get(wt, mgmt->bssid);
  331. if (bss == NULL)
  332. return;
  333. sta = sta_get(bss, mgmt->sa);
  334. if (sta == NULL)
  335. return;
  336. if (len < 24 + 4 + ETH_ALEN) {
  337. wpa_printf(MSG_INFO, "Too short Reassociation Request frame "
  338. "from " MACSTR, MAC2STR(mgmt->sa));
  339. return;
  340. }
  341. wpa_printf(MSG_DEBUG, "REASSOCREQ " MACSTR " -> " MACSTR
  342. " (capab=0x%x listen_int=%u current_ap=" MACSTR ")",
  343. MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
  344. le_to_host16(mgmt->u.reassoc_req.capab_info),
  345. le_to_host16(mgmt->u.reassoc_req.listen_interval),
  346. MAC2STR(mgmt->u.reassoc_req.current_ap));
  347. sta->counters[WLANTEST_STA_COUNTER_REASSOCREQ_TX]++;
  348. if (ieee802_11_parse_elems(mgmt->u.reassoc_req.variable,
  349. len - (mgmt->u.reassoc_req.variable - data),
  350. &elems, 0) == ParseFailed) {
  351. wpa_printf(MSG_INFO, "Invalid IEs in Reassociation Request "
  352. "frame from " MACSTR, MAC2STR(mgmt->sa));
  353. return;
  354. }
  355. sta->assocreq_capab_info =
  356. le_to_host16(mgmt->u.reassoc_req.capab_info);
  357. sta->assocreq_listen_int =
  358. le_to_host16(mgmt->u.reassoc_req.listen_interval);
  359. os_free(sta->assocreq_ies);
  360. sta->assocreq_ies_len = len - (mgmt->u.reassoc_req.variable - data);
  361. sta->assocreq_ies = os_malloc(sta->assocreq_ies_len);
  362. if (sta->assocreq_ies)
  363. os_memcpy(sta->assocreq_ies, mgmt->u.reassoc_req.variable,
  364. sta->assocreq_ies_len);
  365. sta_update_assoc(sta, &elems);
  366. }
  367. static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data,
  368. size_t len)
  369. {
  370. const struct ieee80211_mgmt *mgmt;
  371. struct wlantest_bss *bss;
  372. struct wlantest_sta *sta;
  373. u16 capab, status, aid;
  374. mgmt = (const struct ieee80211_mgmt *) data;
  375. bss = bss_get(wt, mgmt->bssid);
  376. if (bss == NULL)
  377. return;
  378. sta = sta_get(bss, mgmt->da);
  379. if (sta == NULL)
  380. return;
  381. if (len < 24 + 6) {
  382. wpa_printf(MSG_INFO, "Too short Reassociation Response frame "
  383. "from " MACSTR, MAC2STR(mgmt->sa));
  384. return;
  385. }
  386. capab = le_to_host16(mgmt->u.reassoc_resp.capab_info);
  387. status = le_to_host16(mgmt->u.reassoc_resp.status_code);
  388. aid = le_to_host16(mgmt->u.reassoc_resp.aid);
  389. wpa_printf(MSG_DEBUG, "REASSOCRESP " MACSTR " -> " MACSTR
  390. " (capab=0x%x status=%u aid=%u)",
  391. MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status,
  392. aid & 0x3fff);
  393. if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
  394. struct ieee802_11_elems elems;
  395. const u8 *ies = mgmt->u.reassoc_resp.variable;
  396. size_t ies_len = len - (mgmt->u.reassoc_resp.variable - data);
  397. if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) ==
  398. ParseFailed) {
  399. wpa_printf(MSG_INFO, "Failed to parse IEs in "
  400. "ReassocResp from " MACSTR,
  401. MAC2STR(mgmt->sa));
  402. } else if (elems.timeout_int == NULL ||
  403. elems.timeout_int_len != 5 ||
  404. elems.timeout_int[0] !=
  405. WLAN_TIMEOUT_ASSOC_COMEBACK) {
  406. wpa_printf(MSG_INFO, "No valid Timeout Interval IE "
  407. "with Assoc Comeback time in ReassocResp "
  408. "(status=30) from " MACSTR,
  409. MAC2STR(mgmt->sa));
  410. } else {
  411. sta->counters[
  412. WLANTEST_STA_COUNTER_REASSOCRESP_COMEBACK]++;
  413. }
  414. }
  415. if (status)
  416. return;
  417. if ((aid & 0xc000) != 0xc000) {
  418. wpa_printf(MSG_DEBUG, "Two MSBs of the AID were not set to 1 "
  419. "in Reassociation Response from " MACSTR,
  420. MAC2STR(mgmt->sa));
  421. }
  422. sta->aid = aid & 0xc000;
  423. if (sta->state < STATE2) {
  424. wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 when "
  425. "getting associated", MAC2STR(sta->addr));
  426. }
  427. if (sta->state < STATE3) {
  428. wpa_printf(MSG_DEBUG, "STA " MACSTR
  429. " moved to State 3 with " MACSTR,
  430. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  431. sta->state = STATE3;
  432. }
  433. }
  434. static void disassoc_all_stas(struct wlantest_bss *bss)
  435. {
  436. struct wlantest_sta *sta;
  437. dl_list_for_each(sta, &bss->sta, struct wlantest_sta, list) {
  438. if (sta->state <= STATE2)
  439. continue;
  440. wpa_printf(MSG_DEBUG, "STA " MACSTR
  441. " moved to State 2 with " MACSTR,
  442. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  443. sta->state = STATE2;
  444. }
  445. }
  446. static void rx_mgmt_disassoc(struct wlantest *wt, const u8 *data, size_t len,
  447. int valid)
  448. {
  449. const struct ieee80211_mgmt *mgmt;
  450. struct wlantest_bss *bss;
  451. struct wlantest_sta *sta;
  452. u16 fc, reason;
  453. mgmt = (const struct ieee80211_mgmt *) data;
  454. bss = bss_get(wt, mgmt->bssid);
  455. if (bss == NULL)
  456. return;
  457. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
  458. sta = sta_get(bss, mgmt->da);
  459. else
  460. sta = sta_get(bss, mgmt->sa);
  461. if (len < 24 + 2) {
  462. wpa_printf(MSG_INFO, "Too short Disassociation frame from "
  463. MACSTR, MAC2STR(mgmt->sa));
  464. return;
  465. }
  466. reason = le_to_host16(mgmt->u.disassoc.reason_code);
  467. wpa_printf(MSG_DEBUG, "DISASSOC " MACSTR " -> " MACSTR
  468. " (reason=%u) (valid=%d)",
  469. MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
  470. reason, valid);
  471. wpa_hexdump(MSG_MSGDUMP, "DISASSOC payload", data + 24, len - 24);
  472. if (sta == NULL) {
  473. if (valid && mgmt->da[0] == 0xff)
  474. disassoc_all_stas(bss);
  475. return;
  476. }
  477. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
  478. sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DISASSOC_RX :
  479. WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX]++;
  480. if (sta->pwrmgt && !sta->pspoll)
  481. sta->counters[
  482. WLANTEST_STA_COUNTER_DISASSOC_RX_ASLEEP]++;
  483. else
  484. sta->counters[
  485. WLANTEST_STA_COUNTER_DISASSOC_RX_AWAKE]++;
  486. fc = le_to_host16(mgmt->frame_control);
  487. if (!(fc & WLAN_FC_ISWEP) && reason == 6)
  488. sta->counters[WLANTEST_STA_COUNTER_DISASSOC_RX_RC6]++;
  489. else if (!(fc & WLAN_FC_ISWEP) && reason == 7)
  490. sta->counters[WLANTEST_STA_COUNTER_DISASSOC_RX_RC7]++;
  491. } else
  492. sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DISASSOC_TX :
  493. WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX]++;
  494. if (!valid) {
  495. wpa_printf(MSG_INFO, "Do not change STA " MACSTR " State "
  496. "since Disassociation frame was not protected "
  497. "correctly", MAC2STR(sta->addr));
  498. return;
  499. }
  500. if (sta->state < STATE2) {
  501. wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 or 3 "
  502. "when getting disassociated", MAC2STR(sta->addr));
  503. }
  504. if (sta->state > STATE2) {
  505. wpa_printf(MSG_DEBUG, "STA " MACSTR
  506. " moved to State 2 with " MACSTR,
  507. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  508. sta->state = STATE2;
  509. }
  510. tdls_link_down(bss, sta);
  511. }
  512. static void rx_mgmt_action_sa_query_req(struct wlantest *wt,
  513. struct wlantest_sta *sta,
  514. const struct ieee80211_mgmt *mgmt,
  515. size_t len, int valid)
  516. {
  517. const u8 *rx_id;
  518. u8 *id;
  519. rx_id = (const u8 *) mgmt->u.action.u.sa_query_req.trans_id;
  520. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
  521. id = sta->ap_sa_query_tr;
  522. else
  523. id = sta->sta_sa_query_tr;
  524. wpa_printf(MSG_INFO, "SA Query Request " MACSTR " -> " MACSTR
  525. " (trans_id=%02x%02x)%s",
  526. MAC2STR(mgmt->sa), MAC2STR(mgmt->da), rx_id[0], rx_id[1],
  527. valid ? "" : " (invalid protection)");
  528. os_memcpy(id, mgmt->u.action.u.sa_query_req.trans_id, 2);
  529. if (os_memcmp(mgmt->sa, sta->addr, ETH_ALEN) == 0)
  530. sta->counters[valid ?
  531. WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX :
  532. WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX]++;
  533. else
  534. sta->counters[valid ?
  535. WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX :
  536. WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX]++;
  537. }
  538. static void rx_mgmt_action_sa_query_resp(struct wlantest *wt,
  539. struct wlantest_sta *sta,
  540. const struct ieee80211_mgmt *mgmt,
  541. size_t len, int valid)
  542. {
  543. const u8 *rx_id;
  544. u8 *id;
  545. int match;
  546. rx_id = (const u8 *) mgmt->u.action.u.sa_query_resp.trans_id;
  547. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
  548. id = sta->sta_sa_query_tr;
  549. else
  550. id = sta->ap_sa_query_tr;
  551. match = os_memcmp(rx_id, id, 2) == 0;
  552. wpa_printf(MSG_INFO, "SA Query Response " MACSTR " -> " MACSTR
  553. " (trans_id=%02x%02x; %s)%s",
  554. MAC2STR(mgmt->sa), MAC2STR(mgmt->da), rx_id[0], rx_id[1],
  555. match ? "match" : "mismatch",
  556. valid ? "" : " (invalid protection)");
  557. if (os_memcmp(mgmt->sa, sta->addr, ETH_ALEN) == 0)
  558. sta->counters[(valid && match) ?
  559. WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX :
  560. WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX]++;
  561. else
  562. sta->counters[(valid && match) ?
  563. WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX :
  564. WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX]++;
  565. }
  566. static void rx_mgmt_action_sa_query(struct wlantest *wt,
  567. struct wlantest_sta *sta,
  568. const struct ieee80211_mgmt *mgmt,
  569. size_t len, int valid)
  570. {
  571. if (len < 24 + 2 + WLAN_SA_QUERY_TR_ID_LEN) {
  572. wpa_printf(MSG_INFO, "Too short SA Query frame from " MACSTR,
  573. MAC2STR(mgmt->sa));
  574. return;
  575. }
  576. if (len > 24 + 2 + WLAN_SA_QUERY_TR_ID_LEN) {
  577. size_t elen = len - (24 + 2 + WLAN_SA_QUERY_TR_ID_LEN);
  578. wpa_printf(MSG_INFO, "Unexpected %u octets of extra data at "
  579. "the end of SA Query frame from " MACSTR,
  580. (unsigned) elen, MAC2STR(mgmt->sa));
  581. wpa_hexdump(MSG_INFO, "SA Query extra data",
  582. ((const u8 *) mgmt) + len - elen, elen);
  583. }
  584. switch (mgmt->u.action.u.sa_query_req.action) {
  585. case WLAN_SA_QUERY_REQUEST:
  586. rx_mgmt_action_sa_query_req(wt, sta, mgmt, len, valid);
  587. break;
  588. case WLAN_SA_QUERY_RESPONSE:
  589. rx_mgmt_action_sa_query_resp(wt, sta, mgmt, len, valid);
  590. break;
  591. default:
  592. wpa_printf(MSG_INFO, "Unexpected SA Query action value %u "
  593. "from " MACSTR,
  594. mgmt->u.action.u.sa_query_req.action,
  595. MAC2STR(mgmt->sa));
  596. }
  597. }
  598. static void rx_mgmt_action(struct wlantest *wt, const u8 *data, size_t len,
  599. int valid)
  600. {
  601. const struct ieee80211_mgmt *mgmt;
  602. struct wlantest_bss *bss;
  603. struct wlantest_sta *sta;
  604. mgmt = (const struct ieee80211_mgmt *) data;
  605. if (mgmt->da[0] & 0x01) {
  606. wpa_printf(MSG_DEBUG, "Group addressed Action frame: DA="
  607. MACSTR " SA=" MACSTR " BSSID=" MACSTR
  608. " category=%u",
  609. MAC2STR(mgmt->da), MAC2STR(mgmt->sa),
  610. MAC2STR(mgmt->bssid), mgmt->u.action.category);
  611. return; /* Ignore group addressed Action frames for now */
  612. }
  613. bss = bss_get(wt, mgmt->bssid);
  614. if (bss == NULL)
  615. return;
  616. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
  617. sta = sta_get(bss, mgmt->da);
  618. else
  619. sta = sta_get(bss, mgmt->sa);
  620. if (sta == NULL)
  621. return;
  622. if (len < 24 + 1) {
  623. wpa_printf(MSG_INFO, "Too short Action frame from "
  624. MACSTR, MAC2STR(mgmt->sa));
  625. return;
  626. }
  627. wpa_printf(MSG_DEBUG, "ACTION " MACSTR " -> " MACSTR
  628. " (category=%u) (valid=%d)",
  629. MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
  630. mgmt->u.action.category, valid);
  631. wpa_hexdump(MSG_MSGDUMP, "ACTION payload", data + 24, len - 24);
  632. if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
  633. sta->state < STATE3) {
  634. wpa_printf(MSG_INFO, "Action frame sent when STA is not in "
  635. "State 3 (SA=" MACSTR " DATA=" MACSTR ")",
  636. MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
  637. }
  638. switch (mgmt->u.action.category) {
  639. case WLAN_ACTION_SA_QUERY:
  640. rx_mgmt_action_sa_query(wt, sta, mgmt, len, valid);
  641. break;
  642. }
  643. }
  644. static int check_mmie_mic(const u8 *igtk, const u8 *data, size_t len)
  645. {
  646. u8 *buf;
  647. u8 mic[16];
  648. u16 fc;
  649. const struct ieee80211_hdr *hdr;
  650. buf = os_malloc(len + 20 - 24);
  651. if (buf == NULL)
  652. return -1;
  653. /* BIP AAD: FC(masked) A1 A2 A3 */
  654. hdr = (const struct ieee80211_hdr *) data;
  655. fc = le_to_host16(hdr->frame_control);
  656. fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA);
  657. WPA_PUT_LE16(buf, fc);
  658. os_memcpy(buf + 2, hdr->addr1, 3 * ETH_ALEN);
  659. /* Frame body with MMIE MIC masked to zero */
  660. os_memcpy(buf + 20, data + 24, len - 24 - 8);
  661. os_memset(buf + 20 + len - 24 - 8, 0, 8);
  662. wpa_hexdump(MSG_MSGDUMP, "BIP: AAD|Body(masked)", buf, len + 20 - 24);
  663. /* MIC = L(AES-128-CMAC(AAD || Frame Body(masked)), 0, 64) */
  664. if (omac1_aes_128(igtk, buf, len + 20 - 24, mic) < 0) {
  665. os_free(buf);
  666. return -1;
  667. }
  668. os_free(buf);
  669. if (os_memcmp(data + len - 8, mic, 8) != 0)
  670. return -1;
  671. return 0;
  672. }
  673. static int check_bip(struct wlantest *wt, const u8 *data, size_t len)
  674. {
  675. const struct ieee80211_mgmt *mgmt;
  676. u16 fc, stype;
  677. const u8 *mmie;
  678. u16 keyid;
  679. struct wlantest_bss *bss;
  680. mgmt = (const struct ieee80211_mgmt *) data;
  681. fc = le_to_host16(mgmt->frame_control);
  682. stype = WLAN_FC_GET_STYPE(fc);
  683. if (stype == WLAN_FC_STYPE_ACTION) {
  684. if (len < 24 + 1)
  685. return 0;
  686. if (mgmt->u.action.category == WLAN_ACTION_PUBLIC)
  687. return 0; /* Not a robust management frame */
  688. }
  689. bss = bss_get(wt, mgmt->bssid);
  690. if (bss == NULL)
  691. return 0; /* No key known yet */
  692. if (len < 24 + 18 || data[len - 18] != WLAN_EID_MMIE ||
  693. data[len - 17] != 16) {
  694. /* No MMIE */
  695. if (bss->rsn_capab & WPA_CAPABILITY_MFPC) {
  696. wpa_printf(MSG_INFO, "Robust group-addressed "
  697. "management frame sent without BIP by "
  698. MACSTR, MAC2STR(mgmt->sa));
  699. bss->counters[WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE]++;
  700. return -1;
  701. }
  702. return 0;
  703. }
  704. mmie = data + len - 16;
  705. keyid = WPA_GET_LE16(mmie);
  706. if (keyid & 0xf000) {
  707. wpa_printf(MSG_INFO, "MMIE KeyID reserved bits not zero "
  708. "(%04x) from " MACSTR, keyid, MAC2STR(mgmt->sa));
  709. keyid &= 0x0fff;
  710. }
  711. if (keyid < 4 || keyid > 5) {
  712. wpa_printf(MSG_INFO, "Unexpected MMIE KeyID %u from " MACSTR,
  713. keyid, MAC2STR(mgmt->sa));
  714. bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++;
  715. return 0;
  716. }
  717. wpa_printf(MSG_DEBUG, "MMIE KeyID %u", keyid);
  718. wpa_hexdump(MSG_MSGDUMP, "MMIE IPN", mmie + 2, 6);
  719. wpa_hexdump(MSG_MSGDUMP, "MMIE MIC", mmie + 8, 8);
  720. if (!bss->igtk_set[keyid]) {
  721. wpa_printf(MSG_DEBUG, "No IGTK known to validate BIP frame");
  722. return 0;
  723. }
  724. if (os_memcmp(mmie + 2, bss->ipn[keyid], 6) <= 0) {
  725. wpa_printf(MSG_INFO, "BIP replay detected: SA=" MACSTR,
  726. MAC2STR(mgmt->sa));
  727. wpa_hexdump(MSG_INFO, "RX IPN", mmie + 2, 6);
  728. wpa_hexdump(MSG_INFO, "Last RX IPN", bss->ipn[keyid], 6);
  729. }
  730. if (check_mmie_mic(bss->igtk[keyid], data, len) < 0) {
  731. wpa_printf(MSG_INFO, "Invalid MMIE MIC in a frame from "
  732. MACSTR, MAC2STR(mgmt->sa));
  733. bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++;
  734. return -1;
  735. }
  736. wpa_printf(MSG_DEBUG, "Valid MMIE MIC");
  737. os_memcpy(bss->ipn[keyid], mmie + 2, 6);
  738. bss->counters[WLANTEST_BSS_COUNTER_VALID_BIP_MMIE]++;
  739. if (stype == WLAN_FC_STYPE_DEAUTH)
  740. bss->counters[WLANTEST_BSS_COUNTER_BIP_DEAUTH]++;
  741. else if (stype == WLAN_FC_STYPE_DISASSOC)
  742. bss->counters[WLANTEST_BSS_COUNTER_BIP_DISASSOC]++;
  743. return 0;
  744. }
  745. static u8 * mgmt_ccmp_decrypt(struct wlantest *wt, const u8 *data, size_t len,
  746. size_t *dlen)
  747. {
  748. struct wlantest_bss *bss;
  749. struct wlantest_sta *sta;
  750. const struct ieee80211_hdr *hdr;
  751. int keyid;
  752. u8 *decrypted, *frame = NULL;
  753. u8 pn[6], *rsc;
  754. hdr = (const struct ieee80211_hdr *) data;
  755. bss = bss_get(wt, hdr->addr3);
  756. if (bss == NULL)
  757. return NULL;
  758. if (os_memcmp(hdr->addr1, hdr->addr3, ETH_ALEN) == 0)
  759. sta = sta_get(bss, hdr->addr2);
  760. else
  761. sta = sta_get(bss, hdr->addr1);
  762. if (sta == NULL || !sta->ptk_set) {
  763. wpa_printf(MSG_MSGDUMP, "No PTK known to decrypt the frame");
  764. return NULL;
  765. }
  766. if (len < 24 + 4)
  767. return NULL;
  768. if (!(data[24 + 3] & 0x20)) {
  769. wpa_printf(MSG_INFO, "Expected CCMP frame from " MACSTR
  770. " did not have ExtIV bit set to 1",
  771. MAC2STR(hdr->addr2));
  772. return NULL;
  773. }
  774. if (data[24 + 2] != 0 || (data[24 + 3] & 0x1f) != 0) {
  775. wpa_printf(MSG_INFO, "CCMP mgmt frame from " MACSTR " used "
  776. "non-zero reserved bit", MAC2STR(hdr->addr2));
  777. }
  778. keyid = data[24 + 3] >> 6;
  779. if (keyid != 0) {
  780. wpa_printf(MSG_INFO, "Unexpected non-zero KeyID %d in "
  781. "individually addressed Management frame from "
  782. MACSTR, keyid, MAC2STR(hdr->addr2));
  783. }
  784. if (os_memcmp(hdr->addr1, hdr->addr3, ETH_ALEN) == 0)
  785. rsc = sta->rsc_tods[16];
  786. else
  787. rsc = sta->rsc_fromds[16];
  788. ccmp_get_pn(pn, data + 24);
  789. if (os_memcmp(pn, rsc, 6) <= 0) {
  790. u16 seq_ctrl = le_to_host16(hdr->seq_ctrl);
  791. wpa_printf(MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR
  792. " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u",
  793. MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
  794. MAC2STR(hdr->addr3),
  795. WLAN_GET_SEQ_SEQ(seq_ctrl),
  796. WLAN_GET_SEQ_FRAG(seq_ctrl));
  797. wpa_hexdump(MSG_INFO, "RX PN", pn, 6);
  798. wpa_hexdump(MSG_INFO, "RSC", rsc, 6);
  799. }
  800. decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data + 24, len - 24, dlen);
  801. if (decrypted) {
  802. os_memcpy(rsc, pn, 6);
  803. frame = os_malloc(24 + *dlen);
  804. if (frame) {
  805. os_memcpy(frame, data, 24);
  806. os_memcpy(frame + 24, decrypted, *dlen);
  807. *dlen += 24;
  808. }
  809. }
  810. os_free(decrypted);
  811. return frame;
  812. }
  813. static int check_mgmt_ccmp(struct wlantest *wt, const u8 *data, size_t len)
  814. {
  815. const struct ieee80211_mgmt *mgmt;
  816. u16 fc;
  817. struct wlantest_bss *bss;
  818. struct wlantest_sta *sta;
  819. mgmt = (const struct ieee80211_mgmt *) data;
  820. fc = le_to_host16(mgmt->frame_control);
  821. if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
  822. if (len > 24 &&
  823. mgmt->u.action.category == WLAN_ACTION_PUBLIC)
  824. return 0; /* Not a robust management frame */
  825. }
  826. bss = bss_get(wt, mgmt->bssid);
  827. if (bss == NULL)
  828. return 0;
  829. if (os_memcmp(mgmt->da, mgmt->bssid, ETH_ALEN) == 0)
  830. sta = sta_get(bss, mgmt->sa);
  831. else
  832. sta = sta_get(bss, mgmt->da);
  833. if (sta == NULL)
  834. return 0;
  835. if ((sta->rsn_capab & WPA_CAPABILITY_MFPC) &&
  836. (sta->state == STATE3 ||
  837. WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION)) {
  838. wpa_printf(MSG_INFO, "Robust individually-addressed "
  839. "management frame sent without CCMP by "
  840. MACSTR, MAC2STR(mgmt->sa));
  841. return -1;
  842. }
  843. return 0;
  844. }
  845. void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
  846. {
  847. const struct ieee80211_hdr *hdr;
  848. u16 fc, stype;
  849. int valid = 1;
  850. u8 *decrypted = NULL;
  851. size_t dlen;
  852. if (len < 24)
  853. return;
  854. hdr = (const struct ieee80211_hdr *) data;
  855. fc = le_to_host16(hdr->frame_control);
  856. wt->rx_mgmt++;
  857. stype = WLAN_FC_GET_STYPE(fc);
  858. if ((hdr->addr1[0] & 0x01) &&
  859. (stype == WLAN_FC_STYPE_DEAUTH ||
  860. stype == WLAN_FC_STYPE_DISASSOC ||
  861. stype == WLAN_FC_STYPE_ACTION)) {
  862. if (check_bip(wt, data, len) < 0)
  863. valid = 0;
  864. }
  865. wpa_printf((stype == WLAN_FC_STYPE_BEACON ||
  866. stype == WLAN_FC_STYPE_PROBE_RESP ||
  867. stype == WLAN_FC_STYPE_PROBE_REQ) ?
  868. MSG_EXCESSIVE : MSG_MSGDUMP,
  869. "MGMT %s%s%s DA=" MACSTR " SA=" MACSTR " BSSID=" MACSTR,
  870. mgmt_stype(stype),
  871. fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
  872. fc & WLAN_FC_ISWEP ? " Prot" : "",
  873. MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
  874. MAC2STR(hdr->addr3));
  875. if ((fc & WLAN_FC_ISWEP) &&
  876. !(hdr->addr1[0] & 0x01) &&
  877. (stype == WLAN_FC_STYPE_DEAUTH ||
  878. stype == WLAN_FC_STYPE_DISASSOC ||
  879. stype == WLAN_FC_STYPE_ACTION)) {
  880. decrypted = mgmt_ccmp_decrypt(wt, data, len, &dlen);
  881. if (decrypted) {
  882. write_pcap_decrypted(wt, decrypted, dlen, NULL, 0);
  883. data = decrypted;
  884. len = dlen;
  885. } else
  886. valid = 0;
  887. }
  888. if (!(fc & WLAN_FC_ISWEP) &&
  889. !(hdr->addr1[0] & 0x01) &&
  890. (stype == WLAN_FC_STYPE_DEAUTH ||
  891. stype == WLAN_FC_STYPE_DISASSOC ||
  892. stype == WLAN_FC_STYPE_ACTION)) {
  893. if (check_mgmt_ccmp(wt, data, len) < 0)
  894. valid = 0;
  895. }
  896. switch (stype) {
  897. case WLAN_FC_STYPE_BEACON:
  898. rx_mgmt_beacon(wt, data, len);
  899. break;
  900. case WLAN_FC_STYPE_PROBE_RESP:
  901. rx_mgmt_probe_resp(wt, data, len);
  902. break;
  903. case WLAN_FC_STYPE_AUTH:
  904. rx_mgmt_auth(wt, data, len);
  905. break;
  906. case WLAN_FC_STYPE_DEAUTH:
  907. rx_mgmt_deauth(wt, data, len, valid);
  908. break;
  909. case WLAN_FC_STYPE_ASSOC_REQ:
  910. rx_mgmt_assoc_req(wt, data, len);
  911. break;
  912. case WLAN_FC_STYPE_ASSOC_RESP:
  913. rx_mgmt_assoc_resp(wt, data, len);
  914. break;
  915. case WLAN_FC_STYPE_REASSOC_REQ:
  916. rx_mgmt_reassoc_req(wt, data, len);
  917. break;
  918. case WLAN_FC_STYPE_REASSOC_RESP:
  919. rx_mgmt_reassoc_resp(wt, data, len);
  920. break;
  921. case WLAN_FC_STYPE_DISASSOC:
  922. rx_mgmt_disassoc(wt, data, len, valid);
  923. break;
  924. case WLAN_FC_STYPE_ACTION:
  925. rx_mgmt_action(wt, data, len, valid);
  926. break;
  927. }
  928. os_free(decrypted);
  929. wt->last_mgmt_valid = valid;
  930. }
  931. static void rx_mgmt_deauth_ack(struct wlantest *wt,
  932. const struct ieee80211_hdr *hdr)
  933. {
  934. const struct ieee80211_mgmt *mgmt;
  935. struct wlantest_bss *bss;
  936. struct wlantest_sta *sta;
  937. mgmt = (const struct ieee80211_mgmt *) hdr;
  938. bss = bss_get(wt, mgmt->bssid);
  939. if (bss == NULL)
  940. return;
  941. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
  942. sta = sta_get(bss, mgmt->da);
  943. else
  944. sta = sta_get(bss, mgmt->sa);
  945. if (sta == NULL)
  946. return;
  947. wpa_printf(MSG_DEBUG, "DEAUTH from " MACSTR " acknowledged by " MACSTR,
  948. MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
  949. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
  950. int c;
  951. c = wt->last_mgmt_valid ?
  952. WLANTEST_STA_COUNTER_VALID_DEAUTH_RX_ACK :
  953. WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX_ACK;
  954. sta->counters[c]++;
  955. }
  956. }
  957. static void rx_mgmt_disassoc_ack(struct wlantest *wt,
  958. const struct ieee80211_hdr *hdr)
  959. {
  960. const struct ieee80211_mgmt *mgmt;
  961. struct wlantest_bss *bss;
  962. struct wlantest_sta *sta;
  963. mgmt = (const struct ieee80211_mgmt *) hdr;
  964. bss = bss_get(wt, mgmt->bssid);
  965. if (bss == NULL)
  966. return;
  967. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
  968. sta = sta_get(bss, mgmt->da);
  969. else
  970. sta = sta_get(bss, mgmt->sa);
  971. if (sta == NULL)
  972. return;
  973. wpa_printf(MSG_DEBUG, "DISASSOC from " MACSTR " acknowledged by "
  974. MACSTR, MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
  975. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
  976. int c;
  977. c = wt->last_mgmt_valid ?
  978. WLANTEST_STA_COUNTER_VALID_DISASSOC_RX_ACK :
  979. WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX_ACK;
  980. sta->counters[c]++;
  981. }
  982. }
  983. void rx_mgmt_ack(struct wlantest *wt, const struct ieee80211_hdr *hdr)
  984. {
  985. u16 fc, stype;
  986. fc = le_to_host16(hdr->frame_control);
  987. stype = WLAN_FC_GET_STYPE(fc);
  988. wpa_printf(MSG_MSGDUMP, "MGMT ACK: stype=%u a1=" MACSTR " a2=" MACSTR
  989. " a3=" MACSTR,
  990. stype, MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
  991. MAC2STR(hdr->addr3));
  992. switch (stype) {
  993. case WLAN_FC_STYPE_DEAUTH:
  994. rx_mgmt_deauth_ack(wt, hdr);
  995. break;
  996. case WLAN_FC_STYPE_DISASSOC:
  997. rx_mgmt_disassoc_ack(wt, hdr);
  998. break;
  999. }
  1000. }