rx_data.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. /*
  2. * Received Data 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/eapol_common.h"
  18. #include "common/wpa_common.h"
  19. #include "wlantest.h"
  20. static const char * data_stype(u16 stype)
  21. {
  22. switch (stype) {
  23. case WLAN_FC_STYPE_DATA:
  24. return "DATA";
  25. case WLAN_FC_STYPE_DATA_CFACK:
  26. return "DATA-CFACK";
  27. case WLAN_FC_STYPE_DATA_CFPOLL:
  28. return "DATA-CFPOLL";
  29. case WLAN_FC_STYPE_DATA_CFACKPOLL:
  30. return "DATA-CFACKPOLL";
  31. case WLAN_FC_STYPE_NULLFUNC:
  32. return "NULLFUNC";
  33. case WLAN_FC_STYPE_CFACK:
  34. return "CFACK";
  35. case WLAN_FC_STYPE_CFPOLL:
  36. return "CFPOLL";
  37. case WLAN_FC_STYPE_CFACKPOLL:
  38. return "CFACKPOLL";
  39. case WLAN_FC_STYPE_QOS_DATA:
  40. return "QOSDATA";
  41. case WLAN_FC_STYPE_QOS_DATA_CFACK:
  42. return "QOSDATA-CFACK";
  43. case WLAN_FC_STYPE_QOS_DATA_CFPOLL:
  44. return "QOSDATA-CFPOLL";
  45. case WLAN_FC_STYPE_QOS_DATA_CFACKPOLL:
  46. return "QOSDATA-CFACKPOLL";
  47. case WLAN_FC_STYPE_QOS_NULL:
  48. return "QOS-NULL";
  49. case WLAN_FC_STYPE_QOS_CFPOLL:
  50. return "QOS-CFPOLL";
  51. case WLAN_FC_STYPE_QOS_CFACKPOLL:
  52. return "QOS-CFACKPOLL";
  53. }
  54. return "??";
  55. }
  56. static int check_mic(const u8 *kck, int ver, const u8 *data, size_t len)
  57. {
  58. u8 *buf;
  59. int ret = -1;
  60. struct ieee802_1x_hdr *hdr;
  61. struct wpa_eapol_key *key;
  62. u8 rx_mic[16];
  63. buf = os_malloc(len);
  64. if (buf == NULL)
  65. return -1;
  66. os_memcpy(buf, data, len);
  67. hdr = (struct ieee802_1x_hdr *) buf;
  68. key = (struct wpa_eapol_key *) (hdr + 1);
  69. os_memcpy(rx_mic, key->key_mic, 16);
  70. os_memset(key->key_mic, 0, 16);
  71. if (wpa_eapol_key_mic(kck, ver, buf, len, key->key_mic) == 0 &&
  72. os_memcmp(rx_mic, key->key_mic, 16) == 0)
  73. ret = 0;
  74. os_free(buf);
  75. return ret;
  76. }
  77. static void rx_data_eapol_key_1_of_4(struct wlantest *wt, const u8 *dst,
  78. const u8 *src, const u8 *data, size_t len)
  79. {
  80. struct wlantest_bss *bss;
  81. struct wlantest_sta *sta;
  82. const struct ieee802_1x_hdr *eapol;
  83. const struct wpa_eapol_key *hdr;
  84. wpa_printf(MSG_DEBUG, "EAPOL-Key 1/4 " MACSTR " -> " MACSTR,
  85. MAC2STR(src), MAC2STR(dst));
  86. bss = bss_get(wt, src);
  87. if (bss == NULL)
  88. return;
  89. sta = sta_get(bss, dst);
  90. if (sta == NULL)
  91. return;
  92. eapol = (const struct ieee802_1x_hdr *) data;
  93. hdr = (const struct wpa_eapol_key *) (eapol + 1);
  94. os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
  95. }
  96. static int try_pmk(struct wlantest_bss *bss, struct wlantest_sta *sta,
  97. u16 ver, const u8 *data, size_t len,
  98. struct wlantest_pmk *pmk)
  99. {
  100. struct wpa_ptk ptk;
  101. size_t ptk_len = 48; /* FIX: 64 for TKIP */
  102. wpa_pmk_to_ptk(pmk->pmk, sizeof(pmk->pmk),
  103. "Pairwise key expansion",
  104. bss->bssid, sta->addr, sta->anonce, sta->snonce,
  105. (u8 *) &ptk, ptk_len,
  106. 0 /* FIX: SHA256 based on AKM */);
  107. if (check_mic(ptk.kck, ver,
  108. data, len) < 0)
  109. return -1;
  110. wpa_printf(MSG_INFO, "Derived PTK for STA " MACSTR " BSSID " MACSTR
  111. ")", MAC2STR(sta->addr), MAC2STR(bss->bssid));
  112. os_memcpy(&sta->ptk, &ptk, sizeof(ptk));
  113. sta->ptk_set = 1;
  114. return 0;
  115. }
  116. static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss,
  117. struct wlantest_sta *sta, u16 ver,
  118. const u8 *data, size_t len)
  119. {
  120. struct wlantest_pmk *pmk;
  121. dl_list_for_each(pmk, &bss->pmk, struct wlantest_pmk, list) {
  122. if (try_pmk(bss, sta, ver, data, len, pmk) == 0)
  123. return;
  124. }
  125. dl_list_for_each(pmk, &wt->pmk, struct wlantest_pmk, list) {
  126. if (try_pmk(bss, sta, ver, data, len, pmk) == 0)
  127. return;
  128. }
  129. }
  130. static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
  131. const u8 *src, const u8 *data, size_t len)
  132. {
  133. struct wlantest_bss *bss;
  134. struct wlantest_sta *sta;
  135. const struct ieee802_1x_hdr *eapol;
  136. const struct wpa_eapol_key *hdr;
  137. u16 key_info;
  138. wpa_printf(MSG_DEBUG, "EAPOL-Key 2/4 " MACSTR " -> " MACSTR,
  139. MAC2STR(src), MAC2STR(dst));
  140. bss = bss_get(wt, dst);
  141. if (bss == NULL)
  142. return;
  143. sta = sta_get(bss, src);
  144. if (sta == NULL)
  145. return;
  146. eapol = (const struct ieee802_1x_hdr *) data;
  147. hdr = (const struct wpa_eapol_key *) (eapol + 1);
  148. os_memcpy(sta->snonce, hdr->key_nonce, WPA_NONCE_LEN);
  149. key_info = WPA_GET_BE16(hdr->key_info);
  150. derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, data, len);
  151. }
  152. static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
  153. const u8 *src, const u8 *data, size_t len)
  154. {
  155. struct wlantest_bss *bss;
  156. struct wlantest_sta *sta;
  157. const struct ieee802_1x_hdr *eapol;
  158. const struct wpa_eapol_key *hdr;
  159. int recalc = 0;
  160. u16 key_info;
  161. wpa_printf(MSG_DEBUG, "EAPOL-Key 3/4 " MACSTR " -> " MACSTR,
  162. MAC2STR(src), MAC2STR(dst));
  163. bss = bss_get(wt, src);
  164. if (bss == NULL)
  165. return;
  166. sta = sta_get(bss, dst);
  167. if (sta == NULL)
  168. return;
  169. eapol = (const struct ieee802_1x_hdr *) data;
  170. hdr = (const struct wpa_eapol_key *) (eapol + 1);
  171. key_info = WPA_GET_BE16(hdr->key_info);
  172. if (os_memcmp(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN) != 0) {
  173. wpa_printf(MSG_INFO, "EAPOL-Key ANonce mismatch between 1/4 "
  174. "and 3/4");
  175. recalc = 1;
  176. }
  177. os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
  178. if (recalc) {
  179. derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK,
  180. data, len);
  181. }
  182. if (!sta->ptk_set) {
  183. wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 3/4");
  184. return;
  185. }
  186. if (check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
  187. data, len) < 0) {
  188. wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC");
  189. return;
  190. }
  191. wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 3/4");
  192. /* TODO: decrypt Key Data and store GTK, IGTK */
  193. }
  194. static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst,
  195. const u8 *src, const u8 *data, size_t len)
  196. {
  197. struct wlantest_bss *bss;
  198. struct wlantest_sta *sta;
  199. const struct ieee802_1x_hdr *eapol;
  200. const struct wpa_eapol_key *hdr;
  201. u16 key_info;
  202. wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR,
  203. MAC2STR(src), MAC2STR(dst));
  204. bss = bss_get(wt, dst);
  205. if (bss == NULL)
  206. return;
  207. sta = sta_get(bss, src);
  208. if (sta == NULL)
  209. return;
  210. eapol = (const struct ieee802_1x_hdr *) data;
  211. hdr = (const struct wpa_eapol_key *) (eapol + 1);
  212. key_info = WPA_GET_BE16(hdr->key_info);
  213. if (!sta->ptk_set) {
  214. wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 4/4");
  215. return;
  216. }
  217. if (sta->ptk_set &&
  218. check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
  219. data, len) < 0) {
  220. wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC");
  221. return;
  222. }
  223. wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 4/4");
  224. }
  225. static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
  226. const u8 *src, const u8 *data, size_t len)
  227. {
  228. wpa_printf(MSG_DEBUG, "EAPOL-Key 1/2 " MACSTR " -> " MACSTR,
  229. MAC2STR(src), MAC2STR(dst));
  230. }
  231. static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst,
  232. const u8 *src, const u8 *data, size_t len)
  233. {
  234. wpa_printf(MSG_DEBUG, "EAPOL-Key 2/2 " MACSTR " -> " MACSTR,
  235. MAC2STR(src), MAC2STR(dst));
  236. }
  237. static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
  238. const u8 *src, const u8 *data, size_t len,
  239. int prot)
  240. {
  241. const struct ieee802_1x_hdr *eapol;
  242. const struct wpa_eapol_key *hdr;
  243. u16 key_info, key_length, ver, key_data_length;
  244. eapol = (const struct ieee802_1x_hdr *) data;
  245. hdr = (const struct wpa_eapol_key *) (eapol + 1);
  246. wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key",
  247. (const u8 *) hdr, len - sizeof(*eapol));
  248. if (len < sizeof(*hdr)) {
  249. wpa_printf(MSG_INFO, "Too short EAPOL-Key frame from " MACSTR,
  250. MAC2STR(src));
  251. return;
  252. }
  253. if (hdr->type == EAPOL_KEY_TYPE_RC4) {
  254. /* TODO: EAPOL-Key RC4 for WEP */
  255. return;
  256. }
  257. if (hdr->type != EAPOL_KEY_TYPE_RSN &&
  258. hdr->type != EAPOL_KEY_TYPE_WPA) {
  259. wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key type %u",
  260. hdr->type);
  261. return;
  262. }
  263. key_info = WPA_GET_BE16(hdr->key_info);
  264. key_length = WPA_GET_BE16(hdr->key_length);
  265. key_data_length = WPA_GET_BE16(hdr->key_data_length);
  266. ver = key_info & WPA_KEY_INFO_TYPE_MASK;
  267. wpa_printf(MSG_DEBUG, "EAPOL-Key ver=%u %c idx=%u%s%s%s%s%s%s%s%s "
  268. "datalen=%u",
  269. ver, key_info & WPA_KEY_INFO_KEY_TYPE ? 'P' : 'G',
  270. (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
  271. WPA_KEY_INFO_KEY_INDEX_SHIFT,
  272. (key_info & WPA_KEY_INFO_INSTALL) ? " Install" : "",
  273. (key_info & WPA_KEY_INFO_ACK) ? " ACK" : "",
  274. (key_info & WPA_KEY_INFO_MIC) ? " MIC" : "",
  275. (key_info & WPA_KEY_INFO_SECURE) ? " Secure" : "",
  276. (key_info & WPA_KEY_INFO_ERROR) ? " Error" : "",
  277. (key_info & WPA_KEY_INFO_REQUEST) ? " Request" : "",
  278. (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) ? " Encr" : "",
  279. (key_info & WPA_KEY_INFO_SMK_MESSAGE) ? " SMK" : "",
  280. key_data_length);
  281. if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
  282. ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
  283. ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
  284. wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key Key Descriptor "
  285. "Version %u", ver);
  286. return;
  287. }
  288. wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Replay Counter",
  289. hdr->replay_counter, WPA_REPLAY_COUNTER_LEN);
  290. wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Nonce",
  291. hdr->key_nonce, WPA_NONCE_LEN);
  292. wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key IV",
  293. hdr->key_iv, 16);
  294. wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key RSC",
  295. hdr->key_nonce, WPA_KEY_RSC_LEN);
  296. wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key MIC",
  297. hdr->key_mic, 16);
  298. if (key_info & (WPA_KEY_INFO_ERROR | WPA_KEY_INFO_REQUEST))
  299. return;
  300. if (key_info & WPA_KEY_INFO_SMK_MESSAGE)
  301. return;
  302. if (key_info & WPA_KEY_INFO_KEY_TYPE) {
  303. /* 4-Way Handshake */
  304. switch (key_info & (WPA_KEY_INFO_SECURE |
  305. WPA_KEY_INFO_MIC |
  306. WPA_KEY_INFO_ACK |
  307. WPA_KEY_INFO_INSTALL)) {
  308. case WPA_KEY_INFO_ACK:
  309. rx_data_eapol_key_1_of_4(wt, dst, src, data, len);
  310. break;
  311. case WPA_KEY_INFO_MIC:
  312. rx_data_eapol_key_2_of_4(wt, dst, src, data, len);
  313. break;
  314. case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
  315. WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL:
  316. rx_data_eapol_key_3_of_4(wt, dst, src, data, len);
  317. break;
  318. case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
  319. rx_data_eapol_key_4_of_4(wt, dst, src, data, len);
  320. break;
  321. default:
  322. wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
  323. break;
  324. }
  325. } else {
  326. /* Group Key Handshake */
  327. switch (key_info & (WPA_KEY_INFO_SECURE |
  328. WPA_KEY_INFO_MIC |
  329. WPA_KEY_INFO_ACK)) {
  330. case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
  331. WPA_KEY_INFO_ACK:
  332. rx_data_eapol_key_1_of_2(wt, dst, src, data, len);
  333. break;
  334. case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
  335. rx_data_eapol_key_2_of_2(wt, dst, src, data, len);
  336. break;
  337. default:
  338. wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
  339. break;
  340. }
  341. }
  342. }
  343. static void rx_data_eapol(struct wlantest *wt, const u8 *dst, const u8 *src,
  344. const u8 *data, size_t len, int prot)
  345. {
  346. const struct ieee802_1x_hdr *hdr;
  347. u16 length;
  348. const u8 *p;
  349. wpa_hexdump(MSG_EXCESSIVE, "EAPOL", data, len);
  350. if (len < sizeof(*hdr)) {
  351. wpa_printf(MSG_INFO, "Too short EAPOL frame from " MACSTR,
  352. MAC2STR(src));
  353. return;
  354. }
  355. hdr = (const struct ieee802_1x_hdr *) data;
  356. length = be_to_host16(hdr->length);
  357. wpa_printf(MSG_DEBUG, "RX EAPOL: " MACSTR " -> " MACSTR "%s ver=%u "
  358. "type=%u len=%u",
  359. MAC2STR(src), MAC2STR(dst), prot ? " Prot" : "",
  360. hdr->version, hdr->type, length);
  361. if (sizeof(*hdr) + length > len) {
  362. wpa_printf(MSG_INFO, "Truncated EAPOL frame from " MACSTR,
  363. MAC2STR(src));
  364. return;
  365. }
  366. if (sizeof(*hdr) + length < len) {
  367. wpa_printf(MSG_INFO, "EAPOL frame with %d extra bytes",
  368. (int) (len - sizeof(*hdr) - length));
  369. }
  370. p = (const u8 *) (hdr + 1);
  371. switch (hdr->type) {
  372. case IEEE802_1X_TYPE_EAP_PACKET:
  373. wpa_hexdump(MSG_MSGDUMP, "EAPOL - EAP packet", p, length);
  374. break;
  375. case IEEE802_1X_TYPE_EAPOL_START:
  376. wpa_hexdump(MSG_MSGDUMP, "EAPOL-Start", p, length);
  377. break;
  378. case IEEE802_1X_TYPE_EAPOL_LOGOFF:
  379. wpa_hexdump(MSG_MSGDUMP, "EAPOL-Logoff", p, length);
  380. break;
  381. case IEEE802_1X_TYPE_EAPOL_KEY:
  382. rx_data_eapol_key(wt, dst, src, data, sizeof(*hdr) + length,
  383. prot);
  384. break;
  385. case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT:
  386. wpa_hexdump(MSG_MSGDUMP, "EAPOL - Encapsulated ASF alert",
  387. p, length);
  388. break;
  389. default:
  390. wpa_hexdump(MSG_MSGDUMP, "Unknown EAPOL payload", p, length);
  391. break;
  392. }
  393. }
  394. static void rx_data_eth(struct wlantest *wt, const u8 *dst, const u8 *src,
  395. u16 ethertype, const u8 *data, size_t len, int prot)
  396. {
  397. if (ethertype == ETH_P_PAE)
  398. rx_data_eapol(wt, dst, src, data, len, prot);
  399. }
  400. static void rx_data_process(struct wlantest *wt, const u8 *dst, const u8 *src,
  401. const u8 *data, size_t len, int prot)
  402. {
  403. if (len == 0)
  404. return;
  405. if (len >= 8 && os_memcmp(data, "\xaa\xaa\x03\x00\x00\x00", 6) == 0) {
  406. rx_data_eth(wt, dst, src, WPA_GET_BE16(data + 6),
  407. data + 8, len - 8, prot);
  408. return;
  409. }
  410. wpa_hexdump(MSG_DEBUG, "Unrecognized LLC", data, len > 8 ? 8 : len);
  411. }
  412. static void rx_data_bss_prot(struct wlantest *wt,
  413. const struct ieee80211_hdr *hdr, const u8 *qos,
  414. const u8 *dst, const u8 *src, const u8 *data,
  415. size_t len)
  416. {
  417. /* TODO: Try to decrypt and if success, call rx_data_process() with
  418. * prot = 1 */
  419. }
  420. static void rx_data_bss(struct wlantest *wt, const struct ieee80211_hdr *hdr,
  421. const u8 *qos, const u8 *dst, const u8 *src,
  422. const u8 *data, size_t len)
  423. {
  424. u16 fc = le_to_host16(hdr->frame_control);
  425. int prot = !!(fc & WLAN_FC_ISWEP);
  426. if (qos) {
  427. u8 ack = (qos[0] & 0x60) >> 5;
  428. wpa_printf(MSG_MSGDUMP, "BSS DATA: " MACSTR " -> " MACSTR
  429. " len=%u%s tid=%u%s%s",
  430. MAC2STR(src), MAC2STR(dst), (unsigned int) len,
  431. prot ? " Prot" : "", qos[0] & 0x0f,
  432. (qos[0] & 0x10) ? " EOSP" : "",
  433. ack == 0 ? "" :
  434. (ack == 1 ? " NoAck" :
  435. (ack == 2 ? " NoExpAck" : " BA")));
  436. } else {
  437. wpa_printf(MSG_MSGDUMP, "BSS DATA: " MACSTR " -> " MACSTR
  438. " len=%u%s",
  439. MAC2STR(src), MAC2STR(dst), (unsigned int) len,
  440. prot ? " Prot" : "");
  441. }
  442. if (prot)
  443. rx_data_bss_prot(wt, hdr, qos, dst, src, data, len);
  444. else
  445. rx_data_process(wt, dst, src, data, len, 0);
  446. }
  447. void rx_data(struct wlantest *wt, const u8 *data, size_t len)
  448. {
  449. const struct ieee80211_hdr *hdr;
  450. u16 fc, stype;
  451. size_t hdrlen;
  452. const u8 *qos = NULL;
  453. if (len < 24)
  454. return;
  455. hdr = (const struct ieee80211_hdr *) data;
  456. fc = le_to_host16(hdr->frame_control);
  457. stype = WLAN_FC_GET_STYPE(fc);
  458. hdrlen = 24;
  459. if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
  460. (WLAN_FC_TODS | WLAN_FC_FROMDS))
  461. hdrlen += ETH_ALEN;
  462. if (stype & 0x08) {
  463. qos = data + hdrlen;
  464. hdrlen += 2;
  465. }
  466. if (len < hdrlen)
  467. return;
  468. wt->rx_data++;
  469. switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) {
  470. case 0:
  471. wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s IBSS DA=" MACSTR " SA="
  472. MACSTR " BSSID=" MACSTR,
  473. data_stype(WLAN_FC_GET_STYPE(fc)),
  474. fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
  475. fc & WLAN_FC_ISWEP ? " Prot" : "",
  476. MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
  477. MAC2STR(hdr->addr3));
  478. break;
  479. case WLAN_FC_FROMDS:
  480. wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s FromDS DA=" MACSTR
  481. " BSSID=" MACSTR " SA=" MACSTR,
  482. data_stype(WLAN_FC_GET_STYPE(fc)),
  483. fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
  484. fc & WLAN_FC_ISWEP ? " Prot" : "",
  485. MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
  486. MAC2STR(hdr->addr3));
  487. rx_data_bss(wt, hdr, qos, hdr->addr1, hdr->addr2,
  488. data + hdrlen, len - hdrlen);
  489. break;
  490. case WLAN_FC_TODS:
  491. wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s ToDS BSSID=" MACSTR
  492. " SA=" MACSTR " DA=" MACSTR,
  493. data_stype(WLAN_FC_GET_STYPE(fc)),
  494. fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
  495. fc & WLAN_FC_ISWEP ? " Prot" : "",
  496. MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
  497. MAC2STR(hdr->addr3));
  498. rx_data_bss(wt, hdr, qos, hdr->addr3, hdr->addr2,
  499. data + hdrlen, len - hdrlen);
  500. break;
  501. case WLAN_FC_TODS | WLAN_FC_FROMDS:
  502. wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s WDS RA=" MACSTR " TA="
  503. MACSTR " DA=" MACSTR " SA=" MACSTR,
  504. data_stype(WLAN_FC_GET_STYPE(fc)),
  505. fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
  506. fc & WLAN_FC_ISWEP ? " Prot" : "",
  507. MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
  508. MAC2STR(hdr->addr3),
  509. MAC2STR((const u8 *) (hdr + 1)));
  510. break;
  511. }
  512. }