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
);