process.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * Received 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 "utils/radiotap.h"
  17. #include "utils/radiotap_iter.h"
  18. #include "common/ieee802_11_defs.h"
  19. #include "wlantest.h"
  20. static int rx_duplicate(struct wlantest *wt, const struct ieee80211_hdr *hdr,
  21. size_t len)
  22. {
  23. u16 fc;
  24. int tid = 16;
  25. const u8 *sta_addr, *bssid;
  26. struct wlantest_bss *bss;
  27. struct wlantest_sta *sta;
  28. int to_ap;
  29. le16 *seq_ctrl;
  30. if (hdr->addr1[0] & 0x01)
  31. return 0; /* Ignore group addressed frames */
  32. fc = le_to_host16(hdr->frame_control);
  33. if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) {
  34. bssid = hdr->addr3;
  35. if (os_memcmp(bssid, hdr->addr2, ETH_ALEN) == 0) {
  36. sta_addr = hdr->addr1;
  37. to_ap = 0;
  38. } else {
  39. if (os_memcmp(bssid, hdr->addr1, ETH_ALEN) != 0)
  40. return 0; /* Unsupported STA-to-STA frame */
  41. sta_addr = hdr->addr2;
  42. to_ap = 1;
  43. }
  44. } else {
  45. switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) {
  46. case 0:
  47. return 0; /* IBSS not supported */
  48. case WLAN_FC_FROMDS:
  49. sta_addr = hdr->addr1;
  50. bssid = hdr->addr2;
  51. to_ap = 0;
  52. break;
  53. case WLAN_FC_TODS:
  54. sta_addr = hdr->addr2;
  55. bssid = hdr->addr1;
  56. to_ap = 1;
  57. break;
  58. case WLAN_FC_TODS | WLAN_FC_FROMDS:
  59. return 0; /* WDS not supported */
  60. default:
  61. return 0;
  62. }
  63. if ((WLAN_FC_GET_STYPE(fc) & 0x08) && len >= 26) {
  64. const u8 *qos = ((const u8 *) hdr) + 24;
  65. tid = qos[0] & 0x0f;
  66. }
  67. }
  68. bss = bss_find(wt, bssid);
  69. if (bss == NULL)
  70. return 0;
  71. sta = sta_find(bss, sta_addr);
  72. if (sta == NULL)
  73. return 0;
  74. if (to_ap)
  75. seq_ctrl = &sta->seq_ctrl_to_ap[tid];
  76. else
  77. seq_ctrl = &sta->seq_ctrl_to_sta[tid];
  78. if ((fc & WLAN_FC_RETRY) && hdr->seq_ctrl == *seq_ctrl) {
  79. u16 s = le_to_host16(hdr->seq_ctrl);
  80. wpa_printf(MSG_MSGDUMP, "Ignore duplicated frame (seq=%u "
  81. "frag=%u A1=" MACSTR " A2=" MACSTR ")",
  82. WLAN_GET_SEQ_SEQ(s), WLAN_GET_SEQ_FRAG(s),
  83. MAC2STR(hdr->addr1), MAC2STR(hdr->addr2));
  84. return 1;
  85. }
  86. *seq_ctrl = hdr->seq_ctrl;
  87. return 0;
  88. }
  89. static void rx_ack(struct wlantest *wt, const struct ieee80211_hdr *hdr)
  90. {
  91. struct ieee80211_hdr *last = (struct ieee80211_hdr *) wt->last_hdr;
  92. u16 fc;
  93. if (wt->last_len < 24 || (last->addr1[0] & 0x01) ||
  94. os_memcmp(hdr->addr1, last->addr2, ETH_ALEN) != 0) {
  95. wpa_printf(MSG_MSGDUMP, "Unknown Ack frame (previous frame "
  96. "not seen)");
  97. return;
  98. }
  99. /* Ack to the previous frame */
  100. fc = le_to_host16(last->frame_control);
  101. if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT)
  102. rx_mgmt_ack(wt, last);
  103. }
  104. static void rx_frame(struct wlantest *wt, const u8 *data, size_t len)
  105. {
  106. const struct ieee80211_hdr *hdr;
  107. u16 fc;
  108. wpa_hexdump(MSG_EXCESSIVE, "RX frame", data, len);
  109. if (len < 2)
  110. return;
  111. hdr = (const struct ieee80211_hdr *) data;
  112. fc = le_to_host16(hdr->frame_control);
  113. if (fc & WLAN_FC_PVER) {
  114. wpa_printf(MSG_DEBUG, "Drop RX frame with unexpected pver=%d",
  115. fc & WLAN_FC_PVER);
  116. return;
  117. }
  118. switch (WLAN_FC_GET_TYPE(fc)) {
  119. case WLAN_FC_TYPE_MGMT:
  120. if (len < 24)
  121. break;
  122. if (rx_duplicate(wt, hdr, len))
  123. break;
  124. rx_mgmt(wt, data, len);
  125. break;
  126. case WLAN_FC_TYPE_CTRL:
  127. if (len < 10)
  128. break;
  129. wt->rx_ctrl++;
  130. if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACK)
  131. rx_ack(wt, hdr);
  132. break;
  133. case WLAN_FC_TYPE_DATA:
  134. if (len < 24)
  135. break;
  136. if (rx_duplicate(wt, hdr, len))
  137. break;
  138. rx_data(wt, data, len);
  139. break;
  140. default:
  141. wpa_printf(MSG_DEBUG, "Drop RX frame with unexpected type %d",
  142. WLAN_FC_GET_TYPE(fc));
  143. break;
  144. }
  145. os_memcpy(wt->last_hdr, data, len > sizeof(wt->last_hdr) ?
  146. sizeof(wt->last_hdr) : len);
  147. wt->last_len = len;
  148. }
  149. static void tx_status(struct wlantest *wt, const u8 *data, size_t len, int ack)
  150. {
  151. wpa_printf(MSG_DEBUG, "TX status: ack=%d", ack);
  152. wpa_hexdump(MSG_EXCESSIVE, "TX status frame", data, len);
  153. }
  154. static int check_fcs(const u8 *frame, size_t frame_len, const u8 *fcs)
  155. {
  156. if (WPA_GET_LE32(fcs) != crc32(frame, frame_len))
  157. return -1;
  158. return 0;
  159. }
  160. void wlantest_process(struct wlantest *wt, const u8 *data, size_t len)
  161. {
  162. struct ieee80211_radiotap_iterator iter;
  163. int ret;
  164. int rxflags = 0, txflags = 0, failed = 0, fcs = 0;
  165. const u8 *frame, *fcspos;
  166. size_t frame_len;
  167. wpa_hexdump(MSG_EXCESSIVE, "Process data", data, len);
  168. if (ieee80211_radiotap_iterator_init(&iter, (void *) data, len)) {
  169. wpa_printf(MSG_INFO, "Invalid radiotap frame");
  170. return;
  171. }
  172. for (;;) {
  173. ret = ieee80211_radiotap_iterator_next(&iter);
  174. wpa_printf(MSG_EXCESSIVE, "radiotap iter: %d "
  175. "this_arg_index=%d", ret, iter.this_arg_index);
  176. if (ret == -ENOENT)
  177. break;
  178. if (ret) {
  179. wpa_printf(MSG_INFO, "Invalid radiotap header: %d",
  180. ret);
  181. return;
  182. }
  183. switch (iter.this_arg_index) {
  184. case IEEE80211_RADIOTAP_FLAGS:
  185. if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)
  186. fcs = 1;
  187. break;
  188. case IEEE80211_RADIOTAP_RX_FLAGS:
  189. rxflags = 1;
  190. break;
  191. case IEEE80211_RADIOTAP_TX_FLAGS:
  192. txflags = 1;
  193. failed = le_to_host16((*(u16 *) iter.this_arg)) &
  194. IEEE80211_RADIOTAP_F_TX_FAIL;
  195. break;
  196. }
  197. }
  198. if (iter.max_length == 8) {
  199. wpa_printf(MSG_DEBUG, "Skip frame inserted by wlantest");
  200. return;
  201. }
  202. frame = data + iter.max_length;
  203. frame_len = len - iter.max_length;
  204. if (fcs && frame_len >= 4) {
  205. frame_len -= 4;
  206. fcspos = frame + frame_len;
  207. if (check_fcs(frame, frame_len, fcspos) < 0) {
  208. wpa_printf(MSG_EXCESSIVE, "Drop RX frame with invalid "
  209. "FCS");
  210. wt->fcs_error++;
  211. return;
  212. }
  213. }
  214. if (rxflags && txflags)
  215. return;
  216. if (!txflags)
  217. rx_frame(wt, frame, frame_len);
  218. else
  219. tx_status(wt, frame, frame_len, !failed);
  220. }
  221. void wlantest_process_prism(struct wlantest *wt, const u8 *data, size_t len)
  222. {
  223. int fcs = 0;
  224. const u8 *frame, *fcspos;
  225. size_t frame_len;
  226. u32 hdrlen;
  227. wpa_hexdump(MSG_EXCESSIVE, "Process data", data, len);
  228. if (len < 8)
  229. return;
  230. hdrlen = WPA_GET_LE32(data + 4);
  231. if (len < hdrlen) {
  232. wpa_printf(MSG_INFO, "Too short frame to include prism "
  233. "header");
  234. return;
  235. }
  236. frame = data + hdrlen;
  237. frame_len = len - hdrlen;
  238. fcs = 1;
  239. if (fcs && frame_len >= 4) {
  240. frame_len -= 4;
  241. fcspos = frame + frame_len;
  242. if (check_fcs(frame, frame_len, fcspos) < 0) {
  243. wpa_printf(MSG_EXCESSIVE, "Drop RX frame with invalid "
  244. "FCS");
  245. wt->fcs_error++;
  246. return;
  247. }
  248. }
  249. rx_frame(wt, frame, frame_len);
  250. }
  251. void wlantest_process_80211(struct wlantest *wt, const u8 *data, size_t len)
  252. {
  253. wpa_hexdump(MSG_EXCESSIVE, "Process data", data, len);
  254. rx_frame(wt, data, len);
  255. }