]> git.ipfire.org Git - thirdparty/hostap.git/blame - wlantest/rx_data.c
wlantest: Fix LLC debug print
[thirdparty/hostap.git] / wlantest / rx_data.c
CommitLineData
2d73f0a8
JM
1/*
2 * Received Data 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
15#include "utils/includes.h"
16
17#include "utils/common.h"
18#include "common/ieee802_11_defs.h"
32234bba
JM
19#include "common/eapol_common.h"
20#include "common/wpa_common.h"
2d73f0a8
JM
21#include "wlantest.h"
22
23
24static const char * data_stype(u16 stype)
25{
26 switch (stype) {
27 case WLAN_FC_STYPE_DATA:
28 return "DATA";
29 case WLAN_FC_STYPE_DATA_CFACK:
30 return "DATA-CFACK";
31 case WLAN_FC_STYPE_DATA_CFPOLL:
32 return "DATA-CFPOLL";
33 case WLAN_FC_STYPE_DATA_CFACKPOLL:
34 return "DATA-CFACKPOLL";
35 case WLAN_FC_STYPE_NULLFUNC:
36 return "NULLFUNC";
37 case WLAN_FC_STYPE_CFACK:
38 return "CFACK";
39 case WLAN_FC_STYPE_CFPOLL:
40 return "CFPOLL";
41 case WLAN_FC_STYPE_CFACKPOLL:
42 return "CFACKPOLL";
43 case WLAN_FC_STYPE_QOS_DATA:
44 return "QOSDATA";
45 case WLAN_FC_STYPE_QOS_DATA_CFACK:
46 return "QOSDATA-CFACK";
47 case WLAN_FC_STYPE_QOS_DATA_CFPOLL:
48 return "QOSDATA-CFPOLL";
49 case WLAN_FC_STYPE_QOS_DATA_CFACKPOLL:
50 return "QOSDATA-CFACKPOLL";
51 case WLAN_FC_STYPE_QOS_NULL:
52 return "QOS-NULL";
53 case WLAN_FC_STYPE_QOS_CFPOLL:
54 return "QOS-CFPOLL";
55 case WLAN_FC_STYPE_QOS_CFACKPOLL:
56 return "QOS-CFACKPOLL";
57 }
58 return "??";
59}
60
61
53650bca
JM
62static int check_mic(const u8 *kck, int ver, const u8 *data, size_t len)
63{
64 u8 *buf;
65 int ret = -1;
66 struct ieee802_1x_hdr *hdr;
67 struct wpa_eapol_key *key;
68 u8 rx_mic[16];
69
70 buf = os_malloc(len);
71 if (buf == NULL)
72 return -1;
73 os_memcpy(buf, data, len);
74 hdr = (struct ieee802_1x_hdr *) buf;
75 key = (struct wpa_eapol_key *) (hdr + 1);
76
77 os_memcpy(rx_mic, key->key_mic, 16);
78 os_memset(key->key_mic, 0, 16);
79
80 if (wpa_eapol_key_mic(kck, ver, buf, len, key->key_mic) == 0 &&
81 os_memcmp(rx_mic, key->key_mic, 16) == 0)
82 ret = 0;
83
84 os_free(buf);
85
86 return ret;
87}
88
89
32234bba
JM
90static void rx_data_eapol_key_1_of_4(struct wlantest *wt, const u8 *dst,
91 const u8 *src, const u8 *data, size_t len)
92{
53650bca
JM
93 struct wlantest_bss *bss;
94 struct wlantest_sta *sta;
95 const struct ieee802_1x_hdr *eapol;
96 const struct wpa_eapol_key *hdr;
97
32234bba
JM
98 wpa_printf(MSG_DEBUG, "EAPOL-Key 1/4 " MACSTR " -> " MACSTR,
99 MAC2STR(src), MAC2STR(dst));
53650bca
JM
100 bss = bss_get(wt, src);
101 if (bss == NULL)
102 return;
103 sta = sta_get(bss, dst);
104 if (sta == NULL)
105 return;
106
107 eapol = (const struct ieee802_1x_hdr *) data;
108 hdr = (const struct wpa_eapol_key *) (eapol + 1);
109 os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
110}
111
112
113static void derive_ptk(struct wlantest_bss *bss, struct wlantest_sta *sta,
114 u16 ver, const u8 *data, size_t len)
115{
116 struct wlantest_pmk *pmk;
117
118 dl_list_for_each(pmk, &bss->pmk, struct wlantest_pmk, list) {
119 struct wpa_ptk ptk;
120 size_t ptk_len = 48; /* FIX: 64 for TKIP */
121 wpa_pmk_to_ptk(pmk->pmk, sizeof(pmk->pmk),
122 "Pairwise key expansion",
123 bss->bssid, sta->addr, sta->anonce, sta->snonce,
124 (u8 *) &ptk, ptk_len,
125 0 /* FIX: SHA256 based on AKM */);
126 if (check_mic(ptk.kck, ver,
127 data, len) < 0)
128 continue;
129
130 wpa_printf(MSG_INFO, "Derived PTK for STA " MACSTR " BSSID "
131 MACSTR ")",
132 MAC2STR(sta->addr), MAC2STR(bss->bssid));
133 os_memcpy(&sta->ptk, &ptk, sizeof(ptk));
134 sta->ptk_set = 1;
135 break;
136 }
32234bba
JM
137}
138
139
140static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
141 const u8 *src, const u8 *data, size_t len)
142{
53650bca
JM
143 struct wlantest_bss *bss;
144 struct wlantest_sta *sta;
145 const struct ieee802_1x_hdr *eapol;
146 const struct wpa_eapol_key *hdr;
147 u16 key_info;
148
32234bba
JM
149 wpa_printf(MSG_DEBUG, "EAPOL-Key 2/4 " MACSTR " -> " MACSTR,
150 MAC2STR(src), MAC2STR(dst));
53650bca
JM
151 bss = bss_get(wt, dst);
152 if (bss == NULL)
153 return;
154 sta = sta_get(bss, src);
155 if (sta == NULL)
156 return;
157
158 eapol = (const struct ieee802_1x_hdr *) data;
159 hdr = (const struct wpa_eapol_key *) (eapol + 1);
160 os_memcpy(sta->snonce, hdr->key_nonce, WPA_NONCE_LEN);
161 key_info = WPA_GET_BE16(hdr->key_info);
162 derive_ptk(bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, data, len);
32234bba
JM
163}
164
165
166static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
167 const u8 *src, const u8 *data, size_t len)
168{
53650bca
JM
169 struct wlantest_bss *bss;
170 struct wlantest_sta *sta;
171 const struct ieee802_1x_hdr *eapol;
172 const struct wpa_eapol_key *hdr;
173 int recalc = 0;
174 u16 key_info;
175
32234bba
JM
176 wpa_printf(MSG_DEBUG, "EAPOL-Key 3/4 " MACSTR " -> " MACSTR,
177 MAC2STR(src), MAC2STR(dst));
53650bca
JM
178 bss = bss_get(wt, src);
179 if (bss == NULL)
180 return;
181 sta = sta_get(bss, dst);
182 if (sta == NULL)
183 return;
184
185 eapol = (const struct ieee802_1x_hdr *) data;
186 hdr = (const struct wpa_eapol_key *) (eapol + 1);
187 key_info = WPA_GET_BE16(hdr->key_info);
188 if (os_memcmp(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN) != 0) {
189 wpa_printf(MSG_INFO, "EAPOL-Key ANonce mismatch between 1/4 "
190 "and 3/4");
191 recalc = 1;
192 }
193 os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
194 if (recalc) {
195 derive_ptk(bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK,
196 data, len);
197 }
198
199 if (!sta->ptk_set) {
200 wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 3/4");
201 return;
202 }
203
204 if (check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
205 data, len) < 0) {
206 wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC");
207 return;
208 }
209 wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 3/4");
210
211 /* TODO: decrypt Key Data and store GTK, IGTK */
32234bba
JM
212}
213
214
215static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst,
216 const u8 *src, const u8 *data, size_t len)
217{
53650bca
JM
218 struct wlantest_bss *bss;
219 struct wlantest_sta *sta;
220 const struct ieee802_1x_hdr *eapol;
221 const struct wpa_eapol_key *hdr;
222 u16 key_info;
223
32234bba
JM
224 wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR,
225 MAC2STR(src), MAC2STR(dst));
53650bca
JM
226 bss = bss_get(wt, dst);
227 if (bss == NULL)
228 return;
229 sta = sta_get(bss, src);
230 if (sta == NULL)
231 return;
232
233 eapol = (const struct ieee802_1x_hdr *) data;
234 hdr = (const struct wpa_eapol_key *) (eapol + 1);
235 key_info = WPA_GET_BE16(hdr->key_info);
236
237 if (!sta->ptk_set) {
238 wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 4/4");
239 return;
240 }
241
242 if (sta->ptk_set &&
243 check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
244 data, len) < 0) {
245 wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC");
246 return;
247 }
248 wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 4/4");
32234bba
JM
249}
250
251
252static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
253 const u8 *src, const u8 *data, size_t len)
254{
255 wpa_printf(MSG_DEBUG, "EAPOL-Key 1/2 " MACSTR " -> " MACSTR,
256 MAC2STR(src), MAC2STR(dst));
257}
258
259
260static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst,
261 const u8 *src, const u8 *data, size_t len)
262{
263 wpa_printf(MSG_DEBUG, "EAPOL-Key 2/2 " MACSTR " -> " MACSTR,
264 MAC2STR(src), MAC2STR(dst));
265}
266
267
268static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
269 const u8 *src, const u8 *data, size_t len,
270 int prot)
271{
53650bca 272 const struct ieee802_1x_hdr *eapol;
32234bba
JM
273 const struct wpa_eapol_key *hdr;
274 u16 key_info, key_length, ver, key_data_length;
275
53650bca
JM
276 eapol = (const struct ieee802_1x_hdr *) data;
277 hdr = (const struct wpa_eapol_key *) (eapol + 1);
278
279 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key",
280 (const u8 *) hdr, len - sizeof(*eapol));
32234bba
JM
281 if (len < sizeof(*hdr)) {
282 wpa_printf(MSG_INFO, "Too short EAPOL-Key frame from " MACSTR,
283 MAC2STR(src));
284 return;
285 }
32234bba
JM
286
287 if (hdr->type == EAPOL_KEY_TYPE_RC4) {
288 /* TODO: EAPOL-Key RC4 for WEP */
289 return;
290 }
291
292 if (hdr->type != EAPOL_KEY_TYPE_RSN &&
293 hdr->type != EAPOL_KEY_TYPE_WPA) {
294 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key type %u",
295 hdr->type);
296 return;
297 }
298
299 key_info = WPA_GET_BE16(hdr->key_info);
300 key_length = WPA_GET_BE16(hdr->key_length);
301 key_data_length = WPA_GET_BE16(hdr->key_data_length);
302 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
303 wpa_printf(MSG_DEBUG, "EAPOL-Key ver=%u %c idx=%u%s%s%s%s%s%s%s%s "
304 "datalen=%u",
305 ver, key_info & WPA_KEY_INFO_KEY_TYPE ? 'P' : 'G',
306 (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
307 WPA_KEY_INFO_KEY_INDEX_SHIFT,
308 (key_info & WPA_KEY_INFO_INSTALL) ? " Install" : "",
309 (key_info & WPA_KEY_INFO_ACK) ? " ACK" : "",
310 (key_info & WPA_KEY_INFO_MIC) ? " MIC" : "",
311 (key_info & WPA_KEY_INFO_SECURE) ? " Secure" : "",
312 (key_info & WPA_KEY_INFO_ERROR) ? " Error" : "",
313 (key_info & WPA_KEY_INFO_REQUEST) ? " Request" : "",
314 (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) ? " Encr" : "",
315 (key_info & WPA_KEY_INFO_SMK_MESSAGE) ? " SMK" : "",
316 key_data_length);
317
318 if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
319 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
320 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
321 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key Key Descriptor "
322 "Version %u", ver);
323 return;
324 }
325
326 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Replay Counter",
327 hdr->replay_counter, WPA_REPLAY_COUNTER_LEN);
328 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Nonce",
329 hdr->key_nonce, WPA_NONCE_LEN);
330 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key IV",
331 hdr->key_iv, 16);
332 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key RSC",
333 hdr->key_nonce, WPA_KEY_RSC_LEN);
334 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key MIC",
335 hdr->key_mic, 16);
336
337 if (key_info & (WPA_KEY_INFO_ERROR | WPA_KEY_INFO_REQUEST))
338 return;
339
340 if (key_info & WPA_KEY_INFO_SMK_MESSAGE)
341 return;
342
343 if (key_info & WPA_KEY_INFO_KEY_TYPE) {
344 /* 4-Way Handshake */
345 switch (key_info & (WPA_KEY_INFO_SECURE |
346 WPA_KEY_INFO_MIC |
347 WPA_KEY_INFO_ACK |
348 WPA_KEY_INFO_INSTALL)) {
349 case WPA_KEY_INFO_ACK:
350 rx_data_eapol_key_1_of_4(wt, dst, src, data, len);
351 break;
352 case WPA_KEY_INFO_MIC:
353 rx_data_eapol_key_2_of_4(wt, dst, src, data, len);
354 break;
355 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
356 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL:
357 rx_data_eapol_key_3_of_4(wt, dst, src, data, len);
358 break;
359 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
360 rx_data_eapol_key_4_of_4(wt, dst, src, data, len);
361 break;
362 default:
363 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
364 break;
365 }
366 } else {
367 /* Group Key Handshake */
368 switch (key_info & (WPA_KEY_INFO_SECURE |
369 WPA_KEY_INFO_MIC |
370 WPA_KEY_INFO_ACK)) {
371 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
372 WPA_KEY_INFO_ACK:
373 rx_data_eapol_key_1_of_2(wt, dst, src, data, len);
374 break;
375 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
376 rx_data_eapol_key_2_of_2(wt, dst, src, data, len);
377 break;
378 default:
379 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
380 break;
381 }
382 }
383}
384
385
386static void rx_data_eapol(struct wlantest *wt, const u8 *dst, const u8 *src,
387 const u8 *data, size_t len, int prot)
388{
389 const struct ieee802_1x_hdr *hdr;
390 u16 length;
391 const u8 *p;
392
393 wpa_hexdump(MSG_EXCESSIVE, "EAPOL", data, len);
394 if (len < sizeof(*hdr)) {
395 wpa_printf(MSG_INFO, "Too short EAPOL frame from " MACSTR,
396 MAC2STR(src));
397 return;
398 }
399
400 hdr = (const struct ieee802_1x_hdr *) data;
401 length = be_to_host16(hdr->length);
402 wpa_printf(MSG_DEBUG, "RX EAPOL: " MACSTR " -> " MACSTR "%s ver=%u "
403 "type=%u len=%u",
404 MAC2STR(src), MAC2STR(dst), prot ? " Prot" : "",
405 hdr->version, hdr->type, length);
406 if (sizeof(*hdr) + length > len) {
407 wpa_printf(MSG_INFO, "Truncated EAPOL frame from " MACSTR,
408 MAC2STR(src));
409 return;
410 }
411
412 if (sizeof(*hdr) + length < len) {
413 wpa_printf(MSG_INFO, "EAPOL frame with %d extra bytes",
414 (int) (len - sizeof(*hdr) - length));
415 }
416 p = (const u8 *) (hdr + 1);
417
418 switch (hdr->type) {
419 case IEEE802_1X_TYPE_EAP_PACKET:
420 wpa_hexdump(MSG_MSGDUMP, "EAPOL - EAP packet", p, length);
421 break;
422 case IEEE802_1X_TYPE_EAPOL_START:
423 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Start", p, length);
424 break;
425 case IEEE802_1X_TYPE_EAPOL_LOGOFF:
426 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Logoff", p, length);
427 break;
428 case IEEE802_1X_TYPE_EAPOL_KEY:
53650bca
JM
429 rx_data_eapol_key(wt, dst, src, data, sizeof(*hdr) + length,
430 prot);
32234bba
JM
431 break;
432 case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT:
433 wpa_hexdump(MSG_MSGDUMP, "EAPOL - Encapsulated ASF alert",
434 p, length);
435 break;
436 default:
437 wpa_hexdump(MSG_MSGDUMP, "Unknown EAPOL payload", p, length);
438 break;
439 }
440}
441
442
443static void rx_data_eth(struct wlantest *wt, const u8 *dst, const u8 *src,
444 u16 ethertype, const u8 *data, size_t len, int prot)
445{
446 if (ethertype == ETH_P_PAE)
447 rx_data_eapol(wt, dst, src, data, len, prot);
448}
449
450
451static void rx_data_process(struct wlantest *wt, const u8 *dst, const u8 *src,
452 const u8 *data, size_t len, int prot)
453{
4bc82fc7
JM
454 if (len == 0)
455 return;
456
32234bba
JM
457 if (len >= 8 && os_memcmp(data, "\xaa\xaa\x03\x00\x00\x00", 6) == 0) {
458 rx_data_eth(wt, dst, src, WPA_GET_BE16(data + 6),
459 data + 8, len - 8, prot);
460 return;
461 }
462
4bc82fc7 463 wpa_hexdump(MSG_DEBUG, "Unrecognized LLC", data, len > 8 ? 8 : len);
32234bba
JM
464}
465
466
467static void rx_data_bss_prot(struct wlantest *wt,
468 const struct ieee80211_hdr *hdr, const u8 *qos,
469 const u8 *dst, const u8 *src, const u8 *data,
470 size_t len)
471{
472 /* TODO: Try to decrypt and if success, call rx_data_process() with
473 * prot = 1 */
474}
475
476
477static void rx_data_bss(struct wlantest *wt, const struct ieee80211_hdr *hdr,
478 const u8 *qos, const u8 *dst, const u8 *src,
479 const u8 *data, size_t len)
480{
481 u16 fc = le_to_host16(hdr->frame_control);
482 int prot = !!(fc & WLAN_FC_ISWEP);
483
484 if (qos) {
485 u8 ack = (qos[0] & 0x60) >> 5;
486 wpa_printf(MSG_MSGDUMP, "BSS DATA: " MACSTR " -> " MACSTR
487 " len=%u%s tid=%u%s%s",
488 MAC2STR(src), MAC2STR(dst), (unsigned int) len,
489 prot ? " Prot" : "", qos[0] & 0x0f,
490 (qos[0] & 0x10) ? " EOSP" : "",
491 ack == 0 ? "" :
492 (ack == 1 ? " NoAck" :
493 (ack == 2 ? " NoExpAck" : " BA")));
494 } else {
495 wpa_printf(MSG_MSGDUMP, "BSS DATA: " MACSTR " -> " MACSTR
496 " len=%u%s",
497 MAC2STR(src), MAC2STR(dst), (unsigned int) len,
498 prot ? " Prot" : "");
499 }
500
501 if (prot)
502 rx_data_bss_prot(wt, hdr, qos, dst, src, data, len);
503 else
504 rx_data_process(wt, dst, src, data, len, 0);
505}
506
507
2d73f0a8
JM
508void rx_data(struct wlantest *wt, const u8 *data, size_t len)
509{
510 const struct ieee80211_hdr *hdr;
32234bba
JM
511 u16 fc, stype;
512 size_t hdrlen;
513 const u8 *qos = NULL;
2d73f0a8
JM
514
515 if (len < 24)
516 return;
517
518 hdr = (const struct ieee80211_hdr *) data;
519 fc = le_to_host16(hdr->frame_control);
32234bba
JM
520 stype = WLAN_FC_GET_STYPE(fc);
521 hdrlen = 24;
522 if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
523 (WLAN_FC_TODS | WLAN_FC_FROMDS))
524 hdrlen += ETH_ALEN;
525 if (stype & 0x08) {
526 qos = data + hdrlen;
527 hdrlen += 2;
528 }
529 if (len < hdrlen)
530 return;
2d73f0a8
JM
531 wt->rx_data++;
532
533 switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) {
534 case 0:
535 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s IBSS DA=" MACSTR " SA="
536 MACSTR " BSSID=" MACSTR,
537 data_stype(WLAN_FC_GET_STYPE(fc)),
538 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
539 fc & WLAN_FC_ISWEP ? " Prot" : "",
540 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
541 MAC2STR(hdr->addr3));
542 break;
543 case WLAN_FC_FROMDS:
544 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s FromDS DA=" MACSTR
545 " BSSID=" MACSTR " SA=" MACSTR,
546 data_stype(WLAN_FC_GET_STYPE(fc)),
547 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
548 fc & WLAN_FC_ISWEP ? " Prot" : "",
549 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
550 MAC2STR(hdr->addr3));
32234bba
JM
551 rx_data_bss(wt, hdr, qos, hdr->addr1, hdr->addr2,
552 data + hdrlen, len - hdrlen);
2d73f0a8
JM
553 break;
554 case WLAN_FC_TODS:
555 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s ToDS BSSID=" MACSTR
556 " SA=" MACSTR " DA=" MACSTR,
557 data_stype(WLAN_FC_GET_STYPE(fc)),
558 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
559 fc & WLAN_FC_ISWEP ? " Prot" : "",
560 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
561 MAC2STR(hdr->addr3));
32234bba
JM
562 rx_data_bss(wt, hdr, qos, hdr->addr3, hdr->addr2,
563 data + hdrlen, len - hdrlen);
2d73f0a8
JM
564 break;
565 case WLAN_FC_TODS | WLAN_FC_FROMDS:
566 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s WDS RA=" MACSTR " TA="
567 MACSTR " DA=" MACSTR " SA=" MACSTR,
568 data_stype(WLAN_FC_GET_STYPE(fc)),
569 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
570 fc & WLAN_FC_ISWEP ? " Prot" : "",
571 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
572 MAC2STR(hdr->addr3),
573 MAC2STR((const u8 *) (hdr + 1)));
574 break;
575 }
576}