rx_data.c 16 KB

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