2 * Received frame processing
3 * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
15 #include "utils/includes.h"
17 #include "utils/common.h"
18 #include "utils/radiotap.h"
19 #include "utils/radiotap_iter.h"
20 #include "common/ieee802_11_defs.h"
21 #include "common/ieee802_11_common.h"
25 static const char * mgmt_stype(u16 stype)
28 case WLAN_FC_STYPE_ASSOC_REQ:
30 case WLAN_FC_STYPE_ASSOC_RESP:
32 case WLAN_FC_STYPE_REASSOC_REQ:
34 case WLAN_FC_STYPE_REASSOC_RESP:
35 return "REASSOC-RESP";
36 case WLAN_FC_STYPE_PROBE_REQ:
38 case WLAN_FC_STYPE_PROBE_RESP:
40 case WLAN_FC_STYPE_BEACON:
42 case WLAN_FC_STYPE_ATIM:
44 case WLAN_FC_STYPE_DISASSOC:
46 case WLAN_FC_STYPE_AUTH:
48 case WLAN_FC_STYPE_DEAUTH:
50 case WLAN_FC_STYPE_ACTION:
57 static void bss_update(struct wlantest_bss *bss,
58 struct ieee802_11_elems *elems)
60 if (elems->ssid == NULL || elems->ssid_len > 32) {
61 wpa_printf(MSG_INFO, "Invalid or missing SSID in a Beacon "
62 "frame for " MACSTR, MAC2STR(bss->bssid));
63 bss->parse_error_reported = 1;
67 os_memcpy(bss->ssid, elems->ssid, elems->ssid_len);
68 bss->ssid_len = elems->ssid_len;
70 if (elems->rsn_ie == NULL) {
72 wpa_printf(MSG_INFO, "BSS " MACSTR " - RSN IE removed",
77 if (bss->rsnie[0] == 0 ||
78 os_memcmp(bss->rsnie, elems->rsn_ie - 2,
79 elems->rsn_ie_len + 2) != 0) {
80 wpa_printf(MSG_INFO, "BSS " MACSTR " - RSN IE "
81 "stored", MAC2STR(bss->bssid));
82 wpa_hexdump(MSG_DEBUG, "RSN IE", elems->rsn_ie - 2,
83 elems->rsn_ie_len + 2);
85 os_memcpy(bss->rsnie, elems->rsn_ie - 2,
86 elems->rsn_ie_len + 2);
89 if (elems->wpa_ie == NULL) {
91 wpa_printf(MSG_INFO, "BSS " MACSTR " - WPA IE removed",
96 if (bss->wpaie[0] == 0 ||
97 os_memcmp(bss->wpaie, elems->wpa_ie - 2,
98 elems->wpa_ie_len + 2) != 0) {
99 wpa_printf(MSG_INFO, "BSS " MACSTR " - WPA IE "
100 "stored", MAC2STR(bss->bssid));
101 wpa_hexdump(MSG_DEBUG, "WPA IE", elems->wpa_ie - 2,
102 elems->wpa_ie_len + 2);
104 os_memcpy(bss->wpaie, elems->wpa_ie - 2,
105 elems->wpa_ie_len + 2);
110 static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len)
112 const struct ieee80211_mgmt *mgmt;
113 struct wlantest_bss *bss;
114 struct ieee802_11_elems elems;
116 mgmt = (const struct ieee80211_mgmt *) data;
117 bss = bss_get(wt, mgmt->bssid);
120 if (bss->proberesp_seen)
121 return; /* do not override with Beacon data */
122 bss->capab_info = le_to_host16(mgmt->u.beacon.capab_info);
123 if (ieee802_11_parse_elems(mgmt->u.beacon.variable,
124 len - (mgmt->u.beacon.variable - data),
125 &elems, 0) == ParseFailed) {
126 if (bss->parse_error_reported)
128 wpa_printf(MSG_INFO, "Invalid IEs in a Beacon frame from "
129 MACSTR, MAC2STR(mgmt->sa));
130 bss->parse_error_reported = 1;
134 bss_update(bss, &elems);
138 static void rx_mgmt_probe_resp(struct wlantest *wt, const u8 *data, size_t len)
140 const struct ieee80211_mgmt *mgmt;
141 struct wlantest_bss *bss;
142 struct ieee802_11_elems elems;
144 mgmt = (const struct ieee80211_mgmt *) data;
145 bss = bss_get(wt, mgmt->bssid);
149 bss->capab_info = le_to_host16(mgmt->u.probe_resp.capab_info);
150 if (ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
151 len - (mgmt->u.probe_resp.variable - data),
152 &elems, 0) == ParseFailed) {
153 if (bss->parse_error_reported)
155 wpa_printf(MSG_INFO, "Invalid IEs in a Probe Response frame "
156 "from " MACSTR, MAC2STR(mgmt->sa));
157 bss->parse_error_reported = 1;
161 bss_update(bss, &elems);
165 static void rx_mgmt_auth(struct wlantest *wt, const u8 *data, size_t len)
167 const struct ieee80211_mgmt *mgmt;
168 struct wlantest_bss *bss;
169 struct wlantest_sta *sta;
171 mgmt = (const struct ieee80211_mgmt *) data;
172 bss = bss_get(wt, mgmt->bssid);
175 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
176 sta = sta_get(bss, mgmt->da);
178 sta = sta_get(bss, mgmt->sa);
183 wpa_printf(MSG_INFO, "Too short Authentication frame from "
184 MACSTR, MAC2STR(mgmt->sa));
188 wpa_printf(MSG_DEBUG, "AUTH " MACSTR " -> " MACSTR
189 " (alg=%u trans=%u status=%u)",
190 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
191 le_to_host16(mgmt->u.auth.auth_alg),
192 le_to_host16(mgmt->u.auth.auth_transaction),
193 le_to_host16(mgmt->u.auth.status_code));
197 static void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
199 const struct ieee80211_hdr *hdr;
205 hdr = (const struct ieee80211_hdr *) data;
206 fc = le_to_host16(hdr->frame_control);
208 stype = WLAN_FC_GET_STYPE(fc);
210 wpa_printf((stype == WLAN_FC_STYPE_BEACON ||
211 stype == WLAN_FC_STYPE_PROBE_RESP ||
212 stype == WLAN_FC_STYPE_PROBE_REQ) ?
213 MSG_EXCESSIVE : MSG_MSGDUMP,
214 "MGMT %s%s%s DA=" MACSTR " SA=" MACSTR " BSSID=" MACSTR,
216 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
217 fc & WLAN_FC_ISWEP ? " Prot" : "",
218 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
219 MAC2STR(hdr->addr3));
222 case WLAN_FC_STYPE_BEACON:
223 rx_mgmt_beacon(wt, data, len);
225 case WLAN_FC_STYPE_PROBE_RESP:
226 rx_mgmt_probe_resp(wt, data, len);
228 case WLAN_FC_STYPE_AUTH:
229 rx_mgmt_auth(wt, data, len);
235 static const char * data_stype(u16 stype)
238 case WLAN_FC_STYPE_DATA:
240 case WLAN_FC_STYPE_DATA_CFACK:
242 case WLAN_FC_STYPE_DATA_CFPOLL:
243 return "DATA-CFPOLL";
244 case WLAN_FC_STYPE_DATA_CFACKPOLL:
245 return "DATA-CFACKPOLL";
246 case WLAN_FC_STYPE_NULLFUNC:
248 case WLAN_FC_STYPE_CFACK:
250 case WLAN_FC_STYPE_CFPOLL:
252 case WLAN_FC_STYPE_CFACKPOLL:
254 case WLAN_FC_STYPE_QOS_DATA:
256 case WLAN_FC_STYPE_QOS_DATA_CFACK:
257 return "QOSDATA-CFACK";
258 case WLAN_FC_STYPE_QOS_DATA_CFPOLL:
259 return "QOSDATA-CFPOLL";
260 case WLAN_FC_STYPE_QOS_DATA_CFACKPOLL:
261 return "QOSDATA-CFACKPOLL";
262 case WLAN_FC_STYPE_QOS_NULL:
264 case WLAN_FC_STYPE_QOS_CFPOLL:
266 case WLAN_FC_STYPE_QOS_CFACKPOLL:
267 return "QOS-CFACKPOLL";
273 static void rx_data(struct wlantest *wt, const u8 *data, size_t len)
275 const struct ieee80211_hdr *hdr;
281 hdr = (const struct ieee80211_hdr *) data;
282 fc = le_to_host16(hdr->frame_control);
285 switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) {
287 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s IBSS DA=" MACSTR " SA="
288 MACSTR " BSSID=" MACSTR,
289 data_stype(WLAN_FC_GET_STYPE(fc)),
290 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
291 fc & WLAN_FC_ISWEP ? " Prot" : "",
292 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
293 MAC2STR(hdr->addr3));
296 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s FromDS DA=" MACSTR
297 " BSSID=" MACSTR " SA=" MACSTR,
298 data_stype(WLAN_FC_GET_STYPE(fc)),
299 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
300 fc & WLAN_FC_ISWEP ? " Prot" : "",
301 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
302 MAC2STR(hdr->addr3));
305 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s ToDS BSSID=" MACSTR
306 " SA=" MACSTR " DA=" MACSTR,
307 data_stype(WLAN_FC_GET_STYPE(fc)),
308 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
309 fc & WLAN_FC_ISWEP ? " Prot" : "",
310 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
311 MAC2STR(hdr->addr3));
313 case WLAN_FC_TODS | WLAN_FC_FROMDS:
314 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s WDS RA=" MACSTR " TA="
315 MACSTR " DA=" MACSTR " SA=" MACSTR,
316 data_stype(WLAN_FC_GET_STYPE(fc)),
317 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
318 fc & WLAN_FC_ISWEP ? " Prot" : "",
319 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
321 MAC2STR((const u8 *) (hdr + 1)));
327 static void rx_frame(struct wlantest *wt, const u8 *data, size_t len)
329 const struct ieee80211_hdr *hdr;
332 wpa_hexdump(MSG_EXCESSIVE, "RX frame", data, len);
336 hdr = (const struct ieee80211_hdr *) data;
337 fc = le_to_host16(hdr->frame_control);
338 if (fc & WLAN_FC_PVER) {
339 wpa_printf(MSG_DEBUG, "Drop RX frame with unexpected pver=%d",
344 switch (WLAN_FC_GET_TYPE(fc)) {
345 case WLAN_FC_TYPE_MGMT:
346 rx_mgmt(wt, data, len);
348 case WLAN_FC_TYPE_CTRL:
353 case WLAN_FC_TYPE_DATA:
354 rx_data(wt, data, len);
357 wpa_printf(MSG_DEBUG, "Drop RX frame with unexpected type %d",
358 WLAN_FC_GET_TYPE(fc));
364 static void tx_status(struct wlantest *wt, const u8 *data, size_t len, int ack)
366 wpa_printf(MSG_DEBUG, "TX status: ack=%d", ack);
367 wpa_hexdump(MSG_EXCESSIVE, "TX status frame", data, len);
371 static int check_fcs(const u8 *frame, size_t frame_len, const u8 *fcs)
373 if (WPA_GET_LE32(fcs) != crc32(frame, frame_len))
379 void wlantest_process(struct wlantest *wt, const u8 *data, size_t len)
381 struct ieee80211_radiotap_iterator iter;
383 int rxflags = 0, txflags = 0, failed = 0, fcs = 0;
384 const u8 *frame, *fcspos;
387 wpa_hexdump(MSG_EXCESSIVE, "Process data", data, len);
389 if (ieee80211_radiotap_iterator_init(&iter, (void *) data, len)) {
390 wpa_printf(MSG_INFO, "Invalid radiotap frame");
395 ret = ieee80211_radiotap_iterator_next(&iter);
396 wpa_printf(MSG_EXCESSIVE, "radiotap iter: %d "
397 "this_arg_index=%d", ret, iter.this_arg_index);
401 wpa_printf(MSG_INFO, "Invalid radiotap header: %d",
405 switch (iter.this_arg_index) {
406 case IEEE80211_RADIOTAP_FLAGS:
407 if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)
410 case IEEE80211_RADIOTAP_RX_FLAGS:
413 case IEEE80211_RADIOTAP_TX_FLAGS:
415 failed = le_to_host16((*(u16 *) iter.this_arg)) &
416 IEEE80211_RADIOTAP_F_TX_FAIL;
422 frame = data + iter.max_length;
423 frame_len = len - iter.max_length;
425 if (fcs && frame_len >= 4) {
427 fcspos = frame + frame_len;
428 if (check_fcs(frame, frame_len, fcspos) < 0) {
429 wpa_printf(MSG_EXCESSIVE, "Drop RX frame with invalid "
436 if (rxflags && txflags)
439 rx_frame(wt, frame, frame_len);
441 tx_status(wt, frame, frame_len, !failed);