process.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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_frame(struct wlantest *wt, const u8 *data, size_t len)
  90. {
  91. const struct ieee80211_hdr *hdr;
  92. u16 fc;
  93. wpa_hexdump(MSG_EXCESSIVE, "RX frame", data, len);
  94. if (len < 2)
  95. return;
  96. hdr = (const struct ieee80211_hdr *) data;
  97. fc = le_to_host16(hdr->frame_control);
  98. if (fc & WLAN_FC_PVER) {
  99. wpa_printf(MSG_DEBUG, "Drop RX frame with unexpected pver=%d",
  100. fc & WLAN_FC_PVER);
  101. return;
  102. }
  103. switch (WLAN_FC_GET_TYPE(fc)) {
  104. case WLAN_FC_TYPE_MGMT:
  105. if (len < 24)
  106. break;
  107. if (rx_duplicate(wt, hdr, len))
  108. break;
  109. rx_mgmt(wt, data, len);
  110. break;
  111. case WLAN_FC_TYPE_CTRL:
  112. if (len < 10)
  113. break;
  114. wt->rx_ctrl++;
  115. break;
  116. case WLAN_FC_TYPE_DATA:
  117. if (len < 24)
  118. break;
  119. if (rx_duplicate(wt, hdr, len))
  120. break;
  121. rx_data(wt, data, len);
  122. break;
  123. default:
  124. wpa_printf(MSG_DEBUG, "Drop RX frame with unexpected type %d",
  125. WLAN_FC_GET_TYPE(fc));
  126. break;
  127. }
  128. }
  129. static void tx_status(struct wlantest *wt, const u8 *data, size_t len, int ack)
  130. {
  131. wpa_printf(MSG_DEBUG, "TX status: ack=%d", ack);
  132. wpa_hexdump(MSG_EXCESSIVE, "TX status frame", data, len);
  133. }
  134. static int check_fcs(const u8 *frame, size_t frame_len, const u8 *fcs)
  135. {
  136. if (WPA_GET_LE32(fcs) != crc32(frame, frame_len))
  137. return -1;
  138. return 0;
  139. }
  140. void wlantest_process(struct wlantest *wt, const u8 *data, size_t len)
  141. {
  142. struct ieee80211_radiotap_iterator iter;
  143. int ret;
  144. int rxflags = 0, txflags = 0, failed = 0, fcs = 0;
  145. const u8 *frame, *fcspos;
  146. size_t frame_len;
  147. wpa_hexdump(MSG_EXCESSIVE, "Process data", data, len);
  148. if (ieee80211_radiotap_iterator_init(&iter, (void *) data, len)) {
  149. wpa_printf(MSG_INFO, "Invalid radiotap frame");
  150. return;
  151. }
  152. for (;;) {
  153. ret = ieee80211_radiotap_iterator_next(&iter);
  154. wpa_printf(MSG_EXCESSIVE, "radiotap iter: %d "
  155. "this_arg_index=%d", ret, iter.this_arg_index);
  156. if (ret == -ENOENT)
  157. break;
  158. if (ret) {
  159. wpa_printf(MSG_INFO, "Invalid radiotap header: %d",
  160. ret);
  161. return;
  162. }
  163. switch (iter.this_arg_index) {
  164. case IEEE80211_RADIOTAP_FLAGS:
  165. if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)
  166. fcs = 1;
  167. break;
  168. case IEEE80211_RADIOTAP_RX_FLAGS:
  169. rxflags = 1;
  170. break;
  171. case IEEE80211_RADIOTAP_TX_FLAGS:
  172. txflags = 1;
  173. failed = le_to_host16((*(u16 *) iter.this_arg)) &
  174. IEEE80211_RADIOTAP_F_TX_FAIL;
  175. break;
  176. }
  177. }
  178. frame = data + iter.max_length;
  179. frame_len = len - iter.max_length;
  180. if (fcs && frame_len >= 4) {
  181. frame_len -= 4;
  182. fcspos = frame + frame_len;
  183. if (check_fcs(frame, frame_len, fcspos) < 0) {
  184. wpa_printf(MSG_EXCESSIVE, "Drop RX frame with invalid "
  185. "FCS");
  186. wt->fcs_error++;
  187. return;
  188. }
  189. }
  190. if (rxflags && txflags)
  191. return;
  192. if (!txflags)
  193. rx_frame(wt, frame, frame_len);
  194. else
  195. tx_status(wt, frame, frame_len, !failed);
  196. }