rx_mgmt.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /*
  2. * Received Management frame processing
  3. * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "utils/includes.h"
  15. #include "utils/common.h"
  16. #include "common/ieee802_11_defs.h"
  17. #include "common/ieee802_11_common.h"
  18. #include "wlantest.h"
  19. static const char * mgmt_stype(u16 stype)
  20. {
  21. switch (stype) {
  22. case WLAN_FC_STYPE_ASSOC_REQ:
  23. return "ASSOC-REQ";
  24. case WLAN_FC_STYPE_ASSOC_RESP:
  25. return "ASSOC-RESP";
  26. case WLAN_FC_STYPE_REASSOC_REQ:
  27. return "REASSOC-REQ";
  28. case WLAN_FC_STYPE_REASSOC_RESP:
  29. return "REASSOC-RESP";
  30. case WLAN_FC_STYPE_PROBE_REQ:
  31. return "PROBE-REQ";
  32. case WLAN_FC_STYPE_PROBE_RESP:
  33. return "PROBE-RESP";
  34. case WLAN_FC_STYPE_BEACON:
  35. return "BEACON";
  36. case WLAN_FC_STYPE_ATIM:
  37. return "ATIM";
  38. case WLAN_FC_STYPE_DISASSOC:
  39. return "DISASSOC";
  40. case WLAN_FC_STYPE_AUTH:
  41. return "AUTH";
  42. case WLAN_FC_STYPE_DEAUTH:
  43. return "DEAUTH";
  44. case WLAN_FC_STYPE_ACTION:
  45. return "ACTION";
  46. }
  47. return "??";
  48. }
  49. static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len)
  50. {
  51. const struct ieee80211_mgmt *mgmt;
  52. struct wlantest_bss *bss;
  53. struct ieee802_11_elems elems;
  54. mgmt = (const struct ieee80211_mgmt *) data;
  55. bss = bss_get(wt, mgmt->bssid);
  56. if (bss == NULL)
  57. return;
  58. if (bss->proberesp_seen)
  59. return; /* do not override with Beacon data */
  60. bss->capab_info = le_to_host16(mgmt->u.beacon.capab_info);
  61. if (ieee802_11_parse_elems(mgmt->u.beacon.variable,
  62. len - (mgmt->u.beacon.variable - data),
  63. &elems, 0) == ParseFailed) {
  64. if (bss->parse_error_reported)
  65. return;
  66. wpa_printf(MSG_INFO, "Invalid IEs in a Beacon frame from "
  67. MACSTR, MAC2STR(mgmt->sa));
  68. bss->parse_error_reported = 1;
  69. return;
  70. }
  71. bss_update(wt, bss, &elems);
  72. }
  73. static void rx_mgmt_probe_resp(struct wlantest *wt, const u8 *data, size_t len)
  74. {
  75. const struct ieee80211_mgmt *mgmt;
  76. struct wlantest_bss *bss;
  77. struct ieee802_11_elems elems;
  78. mgmt = (const struct ieee80211_mgmt *) data;
  79. bss = bss_get(wt, mgmt->bssid);
  80. if (bss == NULL)
  81. return;
  82. bss->capab_info = le_to_host16(mgmt->u.probe_resp.capab_info);
  83. if (ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
  84. len - (mgmt->u.probe_resp.variable - data),
  85. &elems, 0) == ParseFailed) {
  86. if (bss->parse_error_reported)
  87. return;
  88. wpa_printf(MSG_INFO, "Invalid IEs in a Probe Response frame "
  89. "from " MACSTR, MAC2STR(mgmt->sa));
  90. bss->parse_error_reported = 1;
  91. return;
  92. }
  93. bss_update(wt, bss, &elems);
  94. }
  95. static void rx_mgmt_auth(struct wlantest *wt, const u8 *data, size_t len)
  96. {
  97. const struct ieee80211_mgmt *mgmt;
  98. struct wlantest_bss *bss;
  99. struct wlantest_sta *sta;
  100. u16 alg, trans, status;
  101. mgmt = (const struct ieee80211_mgmt *) data;
  102. bss = bss_get(wt, mgmt->bssid);
  103. if (bss == NULL)
  104. return;
  105. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
  106. sta = sta_get(bss, mgmt->da);
  107. else
  108. sta = sta_get(bss, mgmt->sa);
  109. if (sta == NULL)
  110. return;
  111. if (len < 24 + 6) {
  112. wpa_printf(MSG_INFO, "Too short Authentication frame from "
  113. MACSTR, MAC2STR(mgmt->sa));
  114. return;
  115. }
  116. alg = le_to_host16(mgmt->u.auth.auth_alg);
  117. trans = le_to_host16(mgmt->u.auth.auth_transaction);
  118. status = le_to_host16(mgmt->u.auth.status_code);
  119. wpa_printf(MSG_DEBUG, "AUTH " MACSTR " -> " MACSTR
  120. " (alg=%u trans=%u status=%u)",
  121. MAC2STR(mgmt->sa), MAC2STR(mgmt->da), alg, trans, status);
  122. if (alg == 0 && trans == 2 && status == 0) {
  123. if (sta->state == STATE1) {
  124. wpa_printf(MSG_DEBUG, "STA " MACSTR
  125. " moved to State 2 with " MACSTR,
  126. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  127. sta->state = STATE2;
  128. }
  129. }
  130. }
  131. static void rx_mgmt_deauth(struct wlantest *wt, const u8 *data, size_t len)
  132. {
  133. const struct ieee80211_mgmt *mgmt;
  134. struct wlantest_bss *bss;
  135. struct wlantest_sta *sta;
  136. mgmt = (const struct ieee80211_mgmt *) data;
  137. bss = bss_get(wt, mgmt->bssid);
  138. if (bss == NULL)
  139. return;
  140. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
  141. sta = sta_get(bss, mgmt->da);
  142. else
  143. sta = sta_get(bss, mgmt->sa);
  144. if (sta == NULL)
  145. return;
  146. if (len < 24 + 2) {
  147. wpa_printf(MSG_INFO, "Too short Deauthentication frame from "
  148. MACSTR, MAC2STR(mgmt->sa));
  149. return;
  150. }
  151. wpa_printf(MSG_DEBUG, "DEAUTH " MACSTR " -> " MACSTR
  152. " (reason=%u)",
  153. MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
  154. le_to_host16(mgmt->u.deauth.reason_code));
  155. if (sta->state != STATE1) {
  156. wpa_printf(MSG_DEBUG, "STA " MACSTR
  157. " moved to State 1 with " MACSTR,
  158. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  159. sta->state = STATE1;
  160. }
  161. }
  162. static void rx_mgmt_assoc_req(struct wlantest *wt, const u8 *data, size_t len)
  163. {
  164. const struct ieee80211_mgmt *mgmt;
  165. struct wlantest_bss *bss;
  166. struct wlantest_sta *sta;
  167. struct ieee802_11_elems elems;
  168. mgmt = (const struct ieee80211_mgmt *) data;
  169. bss = bss_get(wt, mgmt->bssid);
  170. if (bss == NULL)
  171. return;
  172. sta = sta_get(bss, mgmt->sa);
  173. if (sta == NULL)
  174. return;
  175. if (len < 24 + 4) {
  176. wpa_printf(MSG_INFO, "Too short Association Request frame "
  177. "from " MACSTR, MAC2STR(mgmt->sa));
  178. return;
  179. }
  180. wpa_printf(MSG_DEBUG, "ASSOCREQ " MACSTR " -> " MACSTR
  181. " (capab=0x%x listen_int=%u)",
  182. MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
  183. le_to_host16(mgmt->u.assoc_req.capab_info),
  184. le_to_host16(mgmt->u.assoc_req.listen_interval));
  185. if (ieee802_11_parse_elems(mgmt->u.assoc_req.variable,
  186. len - (mgmt->u.assoc_req.variable - data),
  187. &elems, 0) == ParseFailed) {
  188. wpa_printf(MSG_INFO, "Invalid IEs in Association Request "
  189. "frame from " MACSTR, MAC2STR(mgmt->sa));
  190. return;
  191. }
  192. sta_update_assoc(sta, &elems);
  193. }
  194. static void rx_mgmt_assoc_resp(struct wlantest *wt, const u8 *data, size_t len)
  195. {
  196. const struct ieee80211_mgmt *mgmt;
  197. struct wlantest_bss *bss;
  198. struct wlantest_sta *sta;
  199. u16 capab, status, aid;
  200. mgmt = (const struct ieee80211_mgmt *) data;
  201. bss = bss_get(wt, mgmt->bssid);
  202. if (bss == NULL)
  203. return;
  204. sta = sta_get(bss, mgmt->da);
  205. if (sta == NULL)
  206. return;
  207. if (len < 24 + 6) {
  208. wpa_printf(MSG_INFO, "Too short Association Response frame "
  209. "from " MACSTR, MAC2STR(mgmt->sa));
  210. return;
  211. }
  212. capab = le_to_host16(mgmt->u.assoc_resp.capab_info);
  213. status = le_to_host16(mgmt->u.assoc_resp.status_code);
  214. aid = le_to_host16(mgmt->u.assoc_resp.aid);
  215. wpa_printf(MSG_DEBUG, "ASSOCRESP " MACSTR " -> " MACSTR
  216. " (capab=0x%x status=%u aid=%u)",
  217. MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status,
  218. aid & 0x3fff);
  219. if (status)
  220. return;
  221. if ((aid & 0xc000) != 0xc000) {
  222. wpa_printf(MSG_DEBUG, "Two MSBs of the AID were not set to 1 "
  223. "in Association Response from " MACSTR,
  224. MAC2STR(mgmt->sa));
  225. }
  226. sta->aid = aid & 0xc000;
  227. if (sta->state < STATE2) {
  228. wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 when "
  229. "getting associated", MAC2STR(sta->addr));
  230. }
  231. if (sta->state < STATE3) {
  232. wpa_printf(MSG_DEBUG, "STA " MACSTR
  233. " moved to State 3 with " MACSTR,
  234. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  235. sta->state = STATE3;
  236. }
  237. }
  238. static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data,
  239. size_t len)
  240. {
  241. const struct ieee80211_mgmt *mgmt;
  242. struct wlantest_bss *bss;
  243. struct wlantest_sta *sta;
  244. struct ieee802_11_elems elems;
  245. mgmt = (const struct ieee80211_mgmt *) data;
  246. bss = bss_get(wt, mgmt->bssid);
  247. if (bss == NULL)
  248. return;
  249. sta = sta_get(bss, mgmt->sa);
  250. if (sta == NULL)
  251. return;
  252. if (len < 24 + 4 + ETH_ALEN) {
  253. wpa_printf(MSG_INFO, "Too short Reassociation Request frame "
  254. "from " MACSTR, MAC2STR(mgmt->sa));
  255. return;
  256. }
  257. wpa_printf(MSG_DEBUG, "REASSOCREQ " MACSTR " -> " MACSTR
  258. " (capab=0x%x listen_int=%u current_ap=" MACSTR ")",
  259. MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
  260. le_to_host16(mgmt->u.reassoc_req.capab_info),
  261. le_to_host16(mgmt->u.reassoc_req.listen_interval),
  262. MAC2STR(mgmt->u.reassoc_req.current_ap));
  263. if (ieee802_11_parse_elems(mgmt->u.reassoc_req.variable,
  264. len - (mgmt->u.reassoc_req.variable - data),
  265. &elems, 0) == ParseFailed) {
  266. wpa_printf(MSG_INFO, "Invalid IEs in Reassociation Request "
  267. "frame from " MACSTR, MAC2STR(mgmt->sa));
  268. return;
  269. }
  270. sta_update_assoc(sta, &elems);
  271. }
  272. static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data,
  273. size_t len)
  274. {
  275. const struct ieee80211_mgmt *mgmt;
  276. struct wlantest_bss *bss;
  277. struct wlantest_sta *sta;
  278. u16 capab, status, aid;
  279. mgmt = (const struct ieee80211_mgmt *) data;
  280. bss = bss_get(wt, mgmt->bssid);
  281. if (bss == NULL)
  282. return;
  283. sta = sta_get(bss, mgmt->da);
  284. if (sta == NULL)
  285. return;
  286. if (len < 24 + 6) {
  287. wpa_printf(MSG_INFO, "Too short Reassociation Response frame "
  288. "from " MACSTR, MAC2STR(mgmt->sa));
  289. return;
  290. }
  291. capab = le_to_host16(mgmt->u.reassoc_resp.capab_info);
  292. status = le_to_host16(mgmt->u.reassoc_resp.status_code);
  293. aid = le_to_host16(mgmt->u.reassoc_resp.aid);
  294. wpa_printf(MSG_DEBUG, "REASSOCRESP " MACSTR " -> " MACSTR
  295. " (capab=0x%x status=%u aid=%u)",
  296. MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status,
  297. aid & 0x3fff);
  298. if (status)
  299. return;
  300. if ((aid & 0xc000) != 0xc000) {
  301. wpa_printf(MSG_DEBUG, "Two MSBs of the AID were not set to 1 "
  302. "in Reassociation Response from " MACSTR,
  303. MAC2STR(mgmt->sa));
  304. }
  305. sta->aid = aid & 0xc000;
  306. if (sta->state < STATE2) {
  307. wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 when "
  308. "getting associated", MAC2STR(sta->addr));
  309. }
  310. if (sta->state < STATE3) {
  311. wpa_printf(MSG_DEBUG, "STA " MACSTR
  312. " moved to State 3 with " MACSTR,
  313. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  314. sta->state = STATE3;
  315. }
  316. }
  317. static void rx_mgmt_disassoc(struct wlantest *wt, const u8 *data, size_t len)
  318. {
  319. const struct ieee80211_mgmt *mgmt;
  320. struct wlantest_bss *bss;
  321. struct wlantest_sta *sta;
  322. mgmt = (const struct ieee80211_mgmt *) data;
  323. bss = bss_get(wt, mgmt->bssid);
  324. if (bss == NULL)
  325. return;
  326. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
  327. sta = sta_get(bss, mgmt->da);
  328. else
  329. sta = sta_get(bss, mgmt->sa);
  330. if (sta == NULL)
  331. return;
  332. if (len < 24 + 2) {
  333. wpa_printf(MSG_INFO, "Too short Disassociation frame from "
  334. MACSTR, MAC2STR(mgmt->sa));
  335. return;
  336. }
  337. wpa_printf(MSG_DEBUG, "DISASSOC " MACSTR " -> " MACSTR
  338. " (reason=%u)",
  339. MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
  340. le_to_host16(mgmt->u.disassoc.reason_code));
  341. if (sta->state < STATE2) {
  342. wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 or 3 "
  343. "when getting disassociated", MAC2STR(sta->addr));
  344. }
  345. if (sta->state > STATE2) {
  346. wpa_printf(MSG_DEBUG, "STA " MACSTR
  347. " moved to State 2 with " MACSTR,
  348. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  349. sta->state = STATE2;
  350. }
  351. }
  352. void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
  353. {
  354. const struct ieee80211_hdr *hdr;
  355. u16 fc, stype;
  356. if (len < 24)
  357. return;
  358. hdr = (const struct ieee80211_hdr *) data;
  359. fc = le_to_host16(hdr->frame_control);
  360. wt->rx_mgmt++;
  361. stype = WLAN_FC_GET_STYPE(fc);
  362. wpa_printf((stype == WLAN_FC_STYPE_BEACON ||
  363. stype == WLAN_FC_STYPE_PROBE_RESP ||
  364. stype == WLAN_FC_STYPE_PROBE_REQ) ?
  365. MSG_EXCESSIVE : MSG_MSGDUMP,
  366. "MGMT %s%s%s DA=" MACSTR " SA=" MACSTR " BSSID=" MACSTR,
  367. mgmt_stype(stype),
  368. fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
  369. fc & WLAN_FC_ISWEP ? " Prot" : "",
  370. MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
  371. MAC2STR(hdr->addr3));
  372. switch (stype) {
  373. case WLAN_FC_STYPE_BEACON:
  374. rx_mgmt_beacon(wt, data, len);
  375. break;
  376. case WLAN_FC_STYPE_PROBE_RESP:
  377. rx_mgmt_probe_resp(wt, data, len);
  378. break;
  379. case WLAN_FC_STYPE_AUTH:
  380. rx_mgmt_auth(wt, data, len);
  381. break;
  382. case WLAN_FC_STYPE_DEAUTH:
  383. rx_mgmt_deauth(wt, data, len);
  384. break;
  385. case WLAN_FC_STYPE_ASSOC_REQ:
  386. rx_mgmt_assoc_req(wt, data, len);
  387. break;
  388. case WLAN_FC_STYPE_ASSOC_RESP:
  389. rx_mgmt_assoc_resp(wt, data, len);
  390. break;
  391. case WLAN_FC_STYPE_REASSOC_REQ:
  392. rx_mgmt_reassoc_req(wt, data, len);
  393. break;
  394. case WLAN_FC_STYPE_REASSOC_RESP:
  395. rx_mgmt_reassoc_resp(wt, data, len);
  396. break;
  397. case WLAN_FC_STYPE_DISASSOC:
  398. rx_mgmt_disassoc(wt, data, len);
  399. break;
  400. }
  401. }