2 * Received Data 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 "crypto/aes_wrap.h"
19 #include "crypto/crypto.h"
20 #include "common/ieee802_11_defs.h"
21 #include "common/eapol_common.h"
22 #include "common/wpa_common.h"
26 static const char * data_stype(u16 stype)
29 case WLAN_FC_STYPE_DATA:
31 case WLAN_FC_STYPE_DATA_CFACK:
33 case WLAN_FC_STYPE_DATA_CFPOLL:
35 case WLAN_FC_STYPE_DATA_CFACKPOLL:
36 return "DATA-CFACKPOLL";
37 case WLAN_FC_STYPE_NULLFUNC:
39 case WLAN_FC_STYPE_CFACK:
41 case WLAN_FC_STYPE_CFPOLL:
43 case WLAN_FC_STYPE_CFACKPOLL:
45 case WLAN_FC_STYPE_QOS_DATA:
47 case WLAN_FC_STYPE_QOS_DATA_CFACK:
48 return "QOSDATA-CFACK";
49 case WLAN_FC_STYPE_QOS_DATA_CFPOLL:
50 return "QOSDATA-CFPOLL";
51 case WLAN_FC_STYPE_QOS_DATA_CFACKPOLL:
52 return "QOSDATA-CFACKPOLL";
53 case WLAN_FC_STYPE_QOS_NULL:
55 case WLAN_FC_STYPE_QOS_CFPOLL:
57 case WLAN_FC_STYPE_QOS_CFACKPOLL:
58 return "QOS-CFACKPOLL";
64 static int check_mic(const u8 *kck, int ver, const u8 *data, size_t len)
68 struct ieee802_1x_hdr *hdr;
69 struct wpa_eapol_key *key;
75 os_memcpy(buf, data, len);
76 hdr = (struct ieee802_1x_hdr *) buf;
77 key = (struct wpa_eapol_key *) (hdr + 1);
79 os_memcpy(rx_mic, key->key_mic, 16);
80 os_memset(key->key_mic, 0, 16);
82 if (wpa_eapol_key_mic(kck, ver, buf, len, key->key_mic) == 0 &&
83 os_memcmp(rx_mic, key->key_mic, 16) == 0)
92 static void rx_data_eapol_key_1_of_4(struct wlantest *wt, const u8 *dst,
93 const u8 *src, const u8 *data, size_t len)
95 struct wlantest_bss *bss;
96 struct wlantest_sta *sta;
97 const struct ieee802_1x_hdr *eapol;
98 const struct wpa_eapol_key *hdr;
100 wpa_printf(MSG_DEBUG, "EAPOL-Key 1/4 " MACSTR " -> " MACSTR,
101 MAC2STR(src), MAC2STR(dst));
102 bss = bss_get(wt, src);
105 sta = sta_get(bss, dst);
109 eapol = (const struct ieee802_1x_hdr *) data;
110 hdr = (const struct wpa_eapol_key *) (eapol + 1);
111 os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
115 static int try_pmk(struct wlantest_bss *bss, struct wlantest_sta *sta,
116 u16 ver, const u8 *data, size_t len,
117 struct wlantest_pmk *pmk)
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,
130 wpa_printf(MSG_INFO, "Derived PTK for STA " MACSTR " BSSID " MACSTR
131 ")", MAC2STR(sta->addr), MAC2STR(bss->bssid));
132 os_memcpy(&sta->ptk, &ptk, sizeof(ptk));
138 static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss,
139 struct wlantest_sta *sta, u16 ver,
140 const u8 *data, size_t len)
142 struct wlantest_pmk *pmk;
144 dl_list_for_each(pmk, &bss->pmk, struct wlantest_pmk, list) {
145 if (try_pmk(bss, sta, ver, data, len, pmk) == 0)
149 dl_list_for_each(pmk, &wt->pmk, struct wlantest_pmk, list) {
150 if (try_pmk(bss, sta, ver, data, len, pmk) == 0)
156 static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
157 const u8 *src, const u8 *data, size_t len)
159 struct wlantest_bss *bss;
160 struct wlantest_sta *sta;
161 const struct ieee802_1x_hdr *eapol;
162 const struct wpa_eapol_key *hdr;
165 wpa_printf(MSG_DEBUG, "EAPOL-Key 2/4 " MACSTR " -> " MACSTR,
166 MAC2STR(src), MAC2STR(dst));
167 bss = bss_get(wt, dst);
170 sta = sta_get(bss, src);
174 eapol = (const struct ieee802_1x_hdr *) data;
175 hdr = (const struct wpa_eapol_key *) (eapol + 1);
176 os_memcpy(sta->snonce, hdr->key_nonce, WPA_NONCE_LEN);
177 key_info = WPA_GET_BE16(hdr->key_info);
178 derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, data, len);
182 static u8 * decrypt_eapol_key_data_rc4(const u8 *kek,
183 const struct wpa_eapol_key *hdr,
187 u16 keydatalen = WPA_GET_BE16(hdr->key_data_length);
189 buf = os_malloc(keydatalen);
193 os_memcpy(ek, hdr->key_iv, 16);
194 os_memcpy(ek + 16, kek, 16);
195 os_memcpy(buf, hdr + 1, keydatalen);
196 if (rc4_skip(ek, 32, 256, buf, keydatalen)) {
197 wpa_printf(MSG_INFO, "RC4 failed");
207 static u8 * decrypt_eapol_key_data_aes(const u8 *kek,
208 const struct wpa_eapol_key *hdr,
212 u16 keydatalen = WPA_GET_BE16(hdr->key_data_length);
214 if (keydatalen % 8) {
215 wpa_printf(MSG_INFO, "Unsupported AES-WRAP len %d",
219 keydatalen -= 8; /* AES-WRAP adds 8 bytes */
220 buf = os_malloc(keydatalen);
223 if (aes_unwrap(kek, keydatalen / 8, (u8 *) (hdr + 1), buf)) {
225 wpa_printf(MSG_INFO, "AES unwrap failed - "
226 "could not decrypt EAPOL-Key key data");
235 static u8 * decrypt_eapol_key_data(const u8 *kek, u16 ver,
236 const struct wpa_eapol_key *hdr,
240 case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
241 return decrypt_eapol_key_data_rc4(kek, hdr, len);
242 case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
243 case WPA_KEY_INFO_TYPE_AES_128_CMAC:
244 return decrypt_eapol_key_data_aes(kek, hdr, len);
246 wpa_printf(MSG_INFO, "Unsupported EAPOL-Key Key Descriptor "
253 static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
254 const u8 *src, const u8 *data, size_t len)
256 struct wlantest_bss *bss;
257 struct wlantest_sta *sta;
258 const struct ieee802_1x_hdr *eapol;
259 const struct wpa_eapol_key *hdr;
262 u16 key_info, ver, key_data_len;
264 size_t decrypted_len = 0;
266 wpa_printf(MSG_DEBUG, "EAPOL-Key 3/4 " MACSTR " -> " MACSTR,
267 MAC2STR(src), MAC2STR(dst));
268 bss = bss_get(wt, src);
271 sta = sta_get(bss, dst);
275 eapol = (const struct ieee802_1x_hdr *) data;
276 hdr = (const struct wpa_eapol_key *) (eapol + 1);
277 key_info = WPA_GET_BE16(hdr->key_info);
278 key_data_len = WPA_GET_BE16(hdr->key_data_length);
280 if (os_memcmp(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN) != 0) {
281 wpa_printf(MSG_INFO, "EAPOL-Key ANonce mismatch between 1/4 "
285 os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
287 derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK,
292 wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 3/4");
296 if (check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
298 wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC");
301 wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 3/4");
303 key_data = (const u8 *) (hdr + 1);
304 /* TODO: handle WPA without EncrKeyData bit */
305 if (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
306 wpa_printf(MSG_INFO, "EAPOL-Key 3/4 without EncrKeyData bit");
309 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
310 decrypted = decrypt_eapol_key_data(sta->ptk.kek, ver, hdr,
312 if (decrypted == NULL) {
313 wpa_printf(MSG_INFO, "Failed to decrypt EAPOL-Key Key Data");
316 wpa_hexdump(MSG_DEBUG, "Decrypted EAPOL-Key Key Data",
317 decrypted, decrypted_len);
318 /* TODO: parse KDEs and store GTK, IGTK */
323 static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst,
324 const u8 *src, const u8 *data, size_t len)
326 struct wlantest_bss *bss;
327 struct wlantest_sta *sta;
328 const struct ieee802_1x_hdr *eapol;
329 const struct wpa_eapol_key *hdr;
332 wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR,
333 MAC2STR(src), MAC2STR(dst));
334 bss = bss_get(wt, dst);
337 sta = sta_get(bss, src);
341 eapol = (const struct ieee802_1x_hdr *) data;
342 hdr = (const struct wpa_eapol_key *) (eapol + 1);
343 key_info = WPA_GET_BE16(hdr->key_info);
346 wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 4/4");
351 check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
353 wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC");
356 wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 4/4");
360 static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
361 const u8 *src, const u8 *data, size_t len)
363 wpa_printf(MSG_DEBUG, "EAPOL-Key 1/2 " MACSTR " -> " MACSTR,
364 MAC2STR(src), MAC2STR(dst));
368 static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst,
369 const u8 *src, const u8 *data, size_t len)
371 wpa_printf(MSG_DEBUG, "EAPOL-Key 2/2 " MACSTR " -> " MACSTR,
372 MAC2STR(src), MAC2STR(dst));
376 static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
377 const u8 *src, const u8 *data, size_t len,
380 const struct ieee802_1x_hdr *eapol;
381 const struct wpa_eapol_key *hdr;
383 u16 key_info, key_length, ver, key_data_length;
385 eapol = (const struct ieee802_1x_hdr *) data;
386 hdr = (const struct wpa_eapol_key *) (eapol + 1);
388 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key",
389 (const u8 *) hdr, len - sizeof(*eapol));
390 if (len < sizeof(*hdr)) {
391 wpa_printf(MSG_INFO, "Too short EAPOL-Key frame from " MACSTR,
396 if (hdr->type == EAPOL_KEY_TYPE_RC4) {
397 /* TODO: EAPOL-Key RC4 for WEP */
401 if (hdr->type != EAPOL_KEY_TYPE_RSN &&
402 hdr->type != EAPOL_KEY_TYPE_WPA) {
403 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key type %u",
408 key_info = WPA_GET_BE16(hdr->key_info);
409 key_length = WPA_GET_BE16(hdr->key_length);
410 key_data_length = WPA_GET_BE16(hdr->key_data_length);
411 key_data = (const u8 *) (hdr + 1);
412 if (key_data + key_data_length > data + len) {
413 wpa_printf(MSG_INFO, "Truncated EAPOL-Key from " MACSTR,
417 if (key_data + key_data_length < data + len) {
418 wpa_hexdump(MSG_DEBUG, "Extra data after EAPOL-Key Key Data "
419 "field", key_data + key_data_length,
420 data + len - key_data - key_data_length);
424 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
425 wpa_printf(MSG_DEBUG, "EAPOL-Key ver=%u %c idx=%u%s%s%s%s%s%s%s%s "
427 ver, key_info & WPA_KEY_INFO_KEY_TYPE ? 'P' : 'G',
428 (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
429 WPA_KEY_INFO_KEY_INDEX_SHIFT,
430 (key_info & WPA_KEY_INFO_INSTALL) ? " Install" : "",
431 (key_info & WPA_KEY_INFO_ACK) ? " ACK" : "",
432 (key_info & WPA_KEY_INFO_MIC) ? " MIC" : "",
433 (key_info & WPA_KEY_INFO_SECURE) ? " Secure" : "",
434 (key_info & WPA_KEY_INFO_ERROR) ? " Error" : "",
435 (key_info & WPA_KEY_INFO_REQUEST) ? " Request" : "",
436 (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) ? " Encr" : "",
437 (key_info & WPA_KEY_INFO_SMK_MESSAGE) ? " SMK" : "",
440 if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
441 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
442 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
443 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key Key Descriptor "
448 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Replay Counter",
449 hdr->replay_counter, WPA_REPLAY_COUNTER_LEN);
450 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Nonce",
451 hdr->key_nonce, WPA_NONCE_LEN);
452 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key IV",
454 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key RSC",
455 hdr->key_nonce, WPA_KEY_RSC_LEN);
456 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key MIC",
458 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data",
459 key_data, key_data_length);
461 if (key_info & (WPA_KEY_INFO_ERROR | WPA_KEY_INFO_REQUEST))
464 if (key_info & WPA_KEY_INFO_SMK_MESSAGE)
467 if (key_info & WPA_KEY_INFO_KEY_TYPE) {
468 /* 4-Way Handshake */
469 switch (key_info & (WPA_KEY_INFO_SECURE |
472 WPA_KEY_INFO_INSTALL)) {
473 case WPA_KEY_INFO_ACK:
474 rx_data_eapol_key_1_of_4(wt, dst, src, data, len);
476 case WPA_KEY_INFO_MIC:
477 rx_data_eapol_key_2_of_4(wt, dst, src, data, len);
479 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
480 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL:
481 rx_data_eapol_key_3_of_4(wt, dst, src, data, len);
483 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
484 rx_data_eapol_key_4_of_4(wt, dst, src, data, len);
487 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
491 /* Group Key Handshake */
492 switch (key_info & (WPA_KEY_INFO_SECURE |
495 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
497 rx_data_eapol_key_1_of_2(wt, dst, src, data, len);
499 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
500 rx_data_eapol_key_2_of_2(wt, dst, src, data, len);
503 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
510 static void rx_data_eapol(struct wlantest *wt, const u8 *dst, const u8 *src,
511 const u8 *data, size_t len, int prot)
513 const struct ieee802_1x_hdr *hdr;
517 wpa_hexdump(MSG_EXCESSIVE, "EAPOL", data, len);
518 if (len < sizeof(*hdr)) {
519 wpa_printf(MSG_INFO, "Too short EAPOL frame from " MACSTR,
524 hdr = (const struct ieee802_1x_hdr *) data;
525 length = be_to_host16(hdr->length);
526 wpa_printf(MSG_DEBUG, "RX EAPOL: " MACSTR " -> " MACSTR "%s ver=%u "
528 MAC2STR(src), MAC2STR(dst), prot ? " Prot" : "",
529 hdr->version, hdr->type, length);
530 if (sizeof(*hdr) + length > len) {
531 wpa_printf(MSG_INFO, "Truncated EAPOL frame from " MACSTR,
536 if (sizeof(*hdr) + length < len) {
537 wpa_printf(MSG_INFO, "EAPOL frame with %d extra bytes",
538 (int) (len - sizeof(*hdr) - length));
540 p = (const u8 *) (hdr + 1);
543 case IEEE802_1X_TYPE_EAP_PACKET:
544 wpa_hexdump(MSG_MSGDUMP, "EAPOL - EAP packet", p, length);
546 case IEEE802_1X_TYPE_EAPOL_START:
547 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Start", p, length);
549 case IEEE802_1X_TYPE_EAPOL_LOGOFF:
550 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Logoff", p, length);
552 case IEEE802_1X_TYPE_EAPOL_KEY:
553 rx_data_eapol_key(wt, dst, src, data, sizeof(*hdr) + length,
556 case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT:
557 wpa_hexdump(MSG_MSGDUMP, "EAPOL - Encapsulated ASF alert",
561 wpa_hexdump(MSG_MSGDUMP, "Unknown EAPOL payload", p, length);
567 static void rx_data_eth(struct wlantest *wt, const u8 *dst, const u8 *src,
568 u16 ethertype, const u8 *data, size_t len, int prot)
570 if (ethertype == ETH_P_PAE)
571 rx_data_eapol(wt, dst, src, data, len, prot);
575 static void rx_data_process(struct wlantest *wt, const u8 *dst, const u8 *src,
576 const u8 *data, size_t len, int prot)
581 if (len >= 8 && os_memcmp(data, "\xaa\xaa\x03\x00\x00\x00", 6) == 0) {
582 rx_data_eth(wt, dst, src, WPA_GET_BE16(data + 6),
583 data + 8, len - 8, prot);
587 wpa_hexdump(MSG_DEBUG, "Unrecognized LLC", data, len > 8 ? 8 : len);
591 static void rx_data_bss_prot(struct wlantest *wt,
592 const struct ieee80211_hdr *hdr, const u8 *qos,
593 const u8 *dst, const u8 *src, const u8 *data,
596 /* TODO: Try to decrypt and if success, call rx_data_process() with
601 static void rx_data_bss(struct wlantest *wt, const struct ieee80211_hdr *hdr,
602 const u8 *qos, const u8 *dst, const u8 *src,
603 const u8 *data, size_t len)
605 u16 fc = le_to_host16(hdr->frame_control);
606 int prot = !!(fc & WLAN_FC_ISWEP);
609 u8 ack = (qos[0] & 0x60) >> 5;
610 wpa_printf(MSG_MSGDUMP, "BSS DATA: " MACSTR " -> " MACSTR
611 " len=%u%s tid=%u%s%s",
612 MAC2STR(src), MAC2STR(dst), (unsigned int) len,
613 prot ? " Prot" : "", qos[0] & 0x0f,
614 (qos[0] & 0x10) ? " EOSP" : "",
616 (ack == 1 ? " NoAck" :
617 (ack == 2 ? " NoExpAck" : " BA")));
619 wpa_printf(MSG_MSGDUMP, "BSS DATA: " MACSTR " -> " MACSTR
621 MAC2STR(src), MAC2STR(dst), (unsigned int) len,
622 prot ? " Prot" : "");
626 rx_data_bss_prot(wt, hdr, qos, dst, src, data, len);
628 rx_data_process(wt, dst, src, data, len, 0);
632 void rx_data(struct wlantest *wt, const u8 *data, size_t len)
634 const struct ieee80211_hdr *hdr;
637 const u8 *qos = NULL;
642 hdr = (const struct ieee80211_hdr *) data;
643 fc = le_to_host16(hdr->frame_control);
644 stype = WLAN_FC_GET_STYPE(fc);
646 if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
647 (WLAN_FC_TODS | WLAN_FC_FROMDS))
657 switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) {
659 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s IBSS DA=" MACSTR " SA="
660 MACSTR " BSSID=" MACSTR,
661 data_stype(WLAN_FC_GET_STYPE(fc)),
662 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
663 fc & WLAN_FC_ISWEP ? " Prot" : "",
664 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
665 MAC2STR(hdr->addr3));
668 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s FromDS DA=" MACSTR
669 " BSSID=" MACSTR " SA=" MACSTR,
670 data_stype(WLAN_FC_GET_STYPE(fc)),
671 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
672 fc & WLAN_FC_ISWEP ? " Prot" : "",
673 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
674 MAC2STR(hdr->addr3));
675 rx_data_bss(wt, hdr, qos, hdr->addr1, hdr->addr2,
676 data + hdrlen, len - hdrlen);
679 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s ToDS BSSID=" MACSTR
680 " SA=" MACSTR " DA=" MACSTR,
681 data_stype(WLAN_FC_GET_STYPE(fc)),
682 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
683 fc & WLAN_FC_ISWEP ? " Prot" : "",
684 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
685 MAC2STR(hdr->addr3));
686 rx_data_bss(wt, hdr, qos, hdr->addr3, hdr->addr2,
687 data + hdrlen, len - hdrlen);
689 case WLAN_FC_TODS | WLAN_FC_FROMDS:
690 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s WDS RA=" MACSTR " TA="
691 MACSTR " DA=" MACSTR " SA=" MACSTR,
692 data_stype(WLAN_FC_GET_STYPE(fc)),
693 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
694 fc & WLAN_FC_ISWEP ? " Prot" : "",
695 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
697 MAC2STR((const u8 *) (hdr + 1)));