rx_mgmt.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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(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(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. mgmt = (const struct ieee80211_mgmt *) data;
  168. bss = bss_get(wt, mgmt->bssid);
  169. if (bss == NULL)
  170. return;
  171. sta = sta_get(bss, mgmt->sa);
  172. if (sta == NULL)
  173. return;
  174. if (len < 24 + 4) {
  175. wpa_printf(MSG_INFO, "Too short Association Request frame "
  176. "from " MACSTR, MAC2STR(mgmt->sa));
  177. return;
  178. }
  179. wpa_printf(MSG_DEBUG, "ASSOCREQ " MACSTR " -> " MACSTR
  180. " (capab=0x%x listen_int=%u)",
  181. MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
  182. le_to_host16(mgmt->u.assoc_req.capab_info),
  183. le_to_host16(mgmt->u.assoc_req.listen_interval));
  184. }
  185. static void rx_mgmt_assoc_resp(struct wlantest *wt, const u8 *data, size_t len)
  186. {
  187. const struct ieee80211_mgmt *mgmt;
  188. struct wlantest_bss *bss;
  189. struct wlantest_sta *sta;
  190. u16 capab, status, aid;
  191. mgmt = (const struct ieee80211_mgmt *) data;
  192. bss = bss_get(wt, mgmt->bssid);
  193. if (bss == NULL)
  194. return;
  195. sta = sta_get(bss, mgmt->da);
  196. if (sta == NULL)
  197. return;
  198. if (len < 24 + 6) {
  199. wpa_printf(MSG_INFO, "Too short Association Response frame "
  200. "from " MACSTR, MAC2STR(mgmt->sa));
  201. return;
  202. }
  203. capab = le_to_host16(mgmt->u.assoc_resp.capab_info);
  204. status = le_to_host16(mgmt->u.assoc_resp.status_code);
  205. aid = le_to_host16(mgmt->u.assoc_resp.aid);
  206. wpa_printf(MSG_DEBUG, "ASSOCRESP " MACSTR " -> " MACSTR
  207. " (capab=0x%x status=%u aid=%u)",
  208. MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status,
  209. aid & 0x3fff);
  210. if (status)
  211. return;
  212. if ((aid & 0xc000) != 0xc000) {
  213. wpa_printf(MSG_DEBUG, "Two MSBs of the AID were not set to 1 "
  214. "in Association Response from " MACSTR,
  215. MAC2STR(mgmt->sa));
  216. }
  217. sta->aid = aid & 0xc000;
  218. if (sta->state < STATE2) {
  219. wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 when "
  220. "getting associated", MAC2STR(sta->addr));
  221. }
  222. if (sta->state < STATE3) {
  223. wpa_printf(MSG_DEBUG, "STA " MACSTR
  224. " moved to State 3 with " MACSTR,
  225. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  226. sta->state = STATE3;
  227. }
  228. }
  229. static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data,
  230. size_t len)
  231. {
  232. const struct ieee80211_mgmt *mgmt;
  233. struct wlantest_bss *bss;
  234. struct wlantest_sta *sta;
  235. mgmt = (const struct ieee80211_mgmt *) data;
  236. bss = bss_get(wt, mgmt->bssid);
  237. if (bss == NULL)
  238. return;
  239. sta = sta_get(bss, mgmt->sa);
  240. if (sta == NULL)
  241. return;
  242. if (len < 24 + 4 + ETH_ALEN) {
  243. wpa_printf(MSG_INFO, "Too short Reassociation Request frame "
  244. "from " MACSTR, MAC2STR(mgmt->sa));
  245. return;
  246. }
  247. wpa_printf(MSG_DEBUG, "REASSOCREQ " MACSTR " -> " MACSTR
  248. " (capab=0x%x listen_int=%u current_ap=" MACSTR ")",
  249. MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
  250. le_to_host16(mgmt->u.reassoc_req.capab_info),
  251. le_to_host16(mgmt->u.reassoc_req.listen_interval),
  252. MAC2STR(mgmt->u.reassoc_req.current_ap));
  253. }
  254. static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data,
  255. size_t len)
  256. {
  257. const struct ieee80211_mgmt *mgmt;
  258. struct wlantest_bss *bss;
  259. struct wlantest_sta *sta;
  260. u16 capab, status, aid;
  261. mgmt = (const struct ieee80211_mgmt *) data;
  262. bss = bss_get(wt, mgmt->bssid);
  263. if (bss == NULL)
  264. return;
  265. sta = sta_get(bss, mgmt->da);
  266. if (sta == NULL)
  267. return;
  268. if (len < 24 + 6) {
  269. wpa_printf(MSG_INFO, "Too short Reassociation Response frame "
  270. "from " MACSTR, MAC2STR(mgmt->sa));
  271. return;
  272. }
  273. capab = le_to_host16(mgmt->u.reassoc_resp.capab_info);
  274. status = le_to_host16(mgmt->u.reassoc_resp.status_code);
  275. aid = le_to_host16(mgmt->u.reassoc_resp.aid);
  276. wpa_printf(MSG_DEBUG, "REASSOCRESP " MACSTR " -> " MACSTR
  277. " (capab=0x%x status=%u aid=%u)",
  278. MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status,
  279. aid & 0x3fff);
  280. if (status)
  281. return;
  282. if ((aid & 0xc000) != 0xc000) {
  283. wpa_printf(MSG_DEBUG, "Two MSBs of the AID were not set to 1 "
  284. "in Reassociation Response from " MACSTR,
  285. MAC2STR(mgmt->sa));
  286. }
  287. sta->aid = aid & 0xc000;
  288. if (sta->state < STATE2) {
  289. wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 when "
  290. "getting associated", MAC2STR(sta->addr));
  291. }
  292. if (sta->state < STATE3) {
  293. wpa_printf(MSG_DEBUG, "STA " MACSTR
  294. " moved to State 3 with " MACSTR,
  295. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  296. sta->state = STATE3;
  297. }
  298. }
  299. static void rx_mgmt_disassoc(struct wlantest *wt, const u8 *data, size_t len)
  300. {
  301. const struct ieee80211_mgmt *mgmt;
  302. struct wlantest_bss *bss;
  303. struct wlantest_sta *sta;
  304. mgmt = (const struct ieee80211_mgmt *) data;
  305. bss = bss_get(wt, mgmt->bssid);
  306. if (bss == NULL)
  307. return;
  308. if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
  309. sta = sta_get(bss, mgmt->da);
  310. else
  311. sta = sta_get(bss, mgmt->sa);
  312. if (sta == NULL)
  313. return;
  314. if (len < 24 + 2) {
  315. wpa_printf(MSG_INFO, "Too short Disassociation frame from "
  316. MACSTR, MAC2STR(mgmt->sa));
  317. return;
  318. }
  319. wpa_printf(MSG_DEBUG, "DISASSOC " MACSTR " -> " MACSTR
  320. " (reason=%u)",
  321. MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
  322. le_to_host16(mgmt->u.disassoc.reason_code));
  323. if (sta->state < STATE2) {
  324. wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 or 3 "
  325. "when getting disassociated", MAC2STR(sta->addr));
  326. }
  327. if (sta->state > STATE2) {
  328. wpa_printf(MSG_DEBUG, "STA " MACSTR
  329. " moved to State 2 with " MACSTR,
  330. MAC2STR(sta->addr), MAC2STR(bss->bssid));
  331. sta->state = STATE2;
  332. }
  333. }
  334. void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
  335. {
  336. const struct ieee80211_hdr *hdr;
  337. u16 fc, stype;
  338. if (len < 24)
  339. return;
  340. hdr = (const struct ieee80211_hdr *) data;
  341. fc = le_to_host16(hdr->frame_control);
  342. wt->rx_mgmt++;
  343. stype = WLAN_FC_GET_STYPE(fc);
  344. wpa_printf((stype == WLAN_FC_STYPE_BEACON ||
  345. stype == WLAN_FC_STYPE_PROBE_RESP ||
  346. stype == WLAN_FC_STYPE_PROBE_REQ) ?
  347. MSG_EXCESSIVE : MSG_MSGDUMP,
  348. "MGMT %s%s%s DA=" MACSTR " SA=" MACSTR " BSSID=" MACSTR,
  349. mgmt_stype(stype),
  350. fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
  351. fc & WLAN_FC_ISWEP ? " Prot" : "",
  352. MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
  353. MAC2STR(hdr->addr3));
  354. switch (stype) {
  355. case WLAN_FC_STYPE_BEACON:
  356. rx_mgmt_beacon(wt, data, len);
  357. break;
  358. case WLAN_FC_STYPE_PROBE_RESP:
  359. rx_mgmt_probe_resp(wt, data, len);
  360. break;
  361. case WLAN_FC_STYPE_AUTH:
  362. rx_mgmt_auth(wt, data, len);
  363. break;
  364. case WLAN_FC_STYPE_DEAUTH:
  365. rx_mgmt_deauth(wt, data, len);
  366. break;
  367. case WLAN_FC_STYPE_ASSOC_REQ:
  368. rx_mgmt_assoc_req(wt, data, len);
  369. break;
  370. case WLAN_FC_STYPE_ASSOC_RESP:
  371. rx_mgmt_assoc_resp(wt, data, len);
  372. break;
  373. case WLAN_FC_STYPE_REASSOC_REQ:
  374. rx_mgmt_reassoc_req(wt, data, len);
  375. break;
  376. case WLAN_FC_STYPE_REASSOC_RESP:
  377. rx_mgmt_reassoc_resp(wt, data, len);
  378. break;
  379. case WLAN_FC_STYPE_DISASSOC:
  380. rx_mgmt_disassoc(wt, data, len);
  381. break;
  382. }
  383. }