process.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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 void rx_frame(struct wlantest *wt, const u8 *data, size_t len)
  21. {
  22. const struct ieee80211_hdr *hdr;
  23. u16 fc;
  24. wpa_hexdump(MSG_EXCESSIVE, "RX frame", data, len);
  25. if (len < 2)
  26. return;
  27. hdr = (const struct ieee80211_hdr *) data;
  28. fc = le_to_host16(hdr->frame_control);
  29. if (fc & WLAN_FC_PVER) {
  30. wpa_printf(MSG_DEBUG, "Drop RX frame with unexpected pver=%d",
  31. fc & WLAN_FC_PVER);
  32. return;
  33. }
  34. switch (WLAN_FC_GET_TYPE(fc)) {
  35. case WLAN_FC_TYPE_MGMT:
  36. rx_mgmt(wt, data, len);
  37. break;
  38. case WLAN_FC_TYPE_CTRL:
  39. if (len < 10)
  40. return;
  41. wt->rx_ctrl++;
  42. break;
  43. case WLAN_FC_TYPE_DATA:
  44. rx_data(wt, data, len);
  45. break;
  46. default:
  47. wpa_printf(MSG_DEBUG, "Drop RX frame with unexpected type %d",
  48. WLAN_FC_GET_TYPE(fc));
  49. break;
  50. }
  51. }
  52. static void tx_status(struct wlantest *wt, const u8 *data, size_t len, int ack)
  53. {
  54. wpa_printf(MSG_DEBUG, "TX status: ack=%d", ack);
  55. wpa_hexdump(MSG_EXCESSIVE, "TX status frame", data, len);
  56. }
  57. static int check_fcs(const u8 *frame, size_t frame_len, const u8 *fcs)
  58. {
  59. if (WPA_GET_LE32(fcs) != crc32(frame, frame_len))
  60. return -1;
  61. return 0;
  62. }
  63. void wlantest_process(struct wlantest *wt, const u8 *data, size_t len)
  64. {
  65. struct ieee80211_radiotap_iterator iter;
  66. int ret;
  67. int rxflags = 0, txflags = 0, failed = 0, fcs = 0;
  68. const u8 *frame, *fcspos;
  69. size_t frame_len;
  70. wpa_hexdump(MSG_EXCESSIVE, "Process data", data, len);
  71. if (ieee80211_radiotap_iterator_init(&iter, (void *) data, len)) {
  72. wpa_printf(MSG_INFO, "Invalid radiotap frame");
  73. return;
  74. }
  75. for (;;) {
  76. ret = ieee80211_radiotap_iterator_next(&iter);
  77. wpa_printf(MSG_EXCESSIVE, "radiotap iter: %d "
  78. "this_arg_index=%d", ret, iter.this_arg_index);
  79. if (ret == -ENOENT)
  80. break;
  81. if (ret) {
  82. wpa_printf(MSG_INFO, "Invalid radiotap header: %d",
  83. ret);
  84. return;
  85. }
  86. switch (iter.this_arg_index) {
  87. case IEEE80211_RADIOTAP_FLAGS:
  88. if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)
  89. fcs = 1;
  90. break;
  91. case IEEE80211_RADIOTAP_RX_FLAGS:
  92. rxflags = 1;
  93. break;
  94. case IEEE80211_RADIOTAP_TX_FLAGS:
  95. txflags = 1;
  96. failed = le_to_host16((*(u16 *) iter.this_arg)) &
  97. IEEE80211_RADIOTAP_F_TX_FAIL;
  98. break;
  99. }
  100. }
  101. frame = data + iter.max_length;
  102. frame_len = len - iter.max_length;
  103. if (fcs && frame_len >= 4) {
  104. frame_len -= 4;
  105. fcspos = frame + frame_len;
  106. if (check_fcs(frame, frame_len, fcspos) < 0) {
  107. wpa_printf(MSG_EXCESSIVE, "Drop RX frame with invalid "
  108. "FCS");
  109. wt->fcs_error++;
  110. return;
  111. }
  112. }
  113. if (rxflags && txflags)
  114. return;
  115. if (!txflags)
  116. rx_frame(wt, frame, frame_len);
  117. else
  118. tx_status(wt, frame, frame_len, !failed);
  119. }