2 * Received Management 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 "common/ieee802_11_defs.h"
19 #include "common/ieee802_11_common.h"
20 #include "crypto/aes_wrap.h"
24 static const char * mgmt_stype(u16 stype)
27 case WLAN_FC_STYPE_ASSOC_REQ:
29 case WLAN_FC_STYPE_ASSOC_RESP:
31 case WLAN_FC_STYPE_REASSOC_REQ:
33 case WLAN_FC_STYPE_REASSOC_RESP:
34 return "REASSOC-RESP";
35 case WLAN_FC_STYPE_PROBE_REQ:
37 case WLAN_FC_STYPE_PROBE_RESP:
39 case WLAN_FC_STYPE_BEACON:
41 case WLAN_FC_STYPE_ATIM:
43 case WLAN_FC_STYPE_DISASSOC:
45 case WLAN_FC_STYPE_AUTH:
47 case WLAN_FC_STYPE_DEAUTH:
49 case WLAN_FC_STYPE_ACTION:
56 static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len)
58 const struct ieee80211_mgmt *mgmt;
59 struct wlantest_bss *bss;
60 struct ieee802_11_elems elems;
62 mgmt = (const struct ieee80211_mgmt *) data;
63 bss = bss_get(wt, mgmt->bssid);
66 if (bss->proberesp_seen)
67 return; /* do not override with Beacon data */
68 bss->capab_info = le_to_host16(mgmt->u.beacon.capab_info);
69 if (ieee802_11_parse_elems(mgmt->u.beacon.variable,
70 len - (mgmt->u.beacon.variable - data),
71 &elems, 0) == ParseFailed) {
72 if (bss->parse_error_reported)
74 wpa_printf(MSG_INFO, "Invalid IEs in a Beacon frame from "
75 MACSTR, MAC2STR(mgmt->sa));
76 bss->parse_error_reported = 1;
80 bss_update(wt, bss, &elems);
84 static void rx_mgmt_probe_resp(struct wlantest *wt, const u8 *data, size_t len)
86 const struct ieee80211_mgmt *mgmt;
87 struct wlantest_bss *bss;
88 struct ieee802_11_elems elems;
90 mgmt = (const struct ieee80211_mgmt *) data;
91 bss = bss_get(wt, mgmt->bssid);
95 bss->capab_info = le_to_host16(mgmt->u.probe_resp.capab_info);
96 if (ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
97 len - (mgmt->u.probe_resp.variable - data),
98 &elems, 0) == ParseFailed) {
99 if (bss->parse_error_reported)
101 wpa_printf(MSG_INFO, "Invalid IEs in a Probe Response frame "
102 "from " MACSTR, MAC2STR(mgmt->sa));
103 bss->parse_error_reported = 1;
107 bss_update(wt, bss, &elems);
111 static void rx_mgmt_auth(struct wlantest *wt, const u8 *data, size_t len)
113 const struct ieee80211_mgmt *mgmt;
114 struct wlantest_bss *bss;
115 struct wlantest_sta *sta;
116 u16 alg, trans, status;
118 mgmt = (const struct ieee80211_mgmt *) data;
119 bss = bss_get(wt, mgmt->bssid);
122 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
123 sta = sta_get(bss, mgmt->da);
125 sta = sta_get(bss, mgmt->sa);
130 wpa_printf(MSG_INFO, "Too short Authentication frame from "
131 MACSTR, MAC2STR(mgmt->sa));
135 alg = le_to_host16(mgmt->u.auth.auth_alg);
136 trans = le_to_host16(mgmt->u.auth.auth_transaction);
137 status = le_to_host16(mgmt->u.auth.status_code);
139 wpa_printf(MSG_DEBUG, "AUTH " MACSTR " -> " MACSTR
140 " (alg=%u trans=%u status=%u)",
141 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), alg, trans, status);
143 if (alg == 0 && trans == 2 && status == 0) {
144 if (sta->state == STATE1) {
145 wpa_printf(MSG_DEBUG, "STA " MACSTR
146 " moved to State 2 with " MACSTR,
147 MAC2STR(sta->addr), MAC2STR(bss->bssid));
152 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
153 sta->counters[WLANTEST_STA_COUNTER_AUTH_RX]++;
155 sta->counters[WLANTEST_STA_COUNTER_AUTH_TX]++;
159 static void deauth_all_stas(struct wlantest_bss *bss)
161 struct wlantest_sta *sta;
162 dl_list_for_each(sta, &bss->sta, struct wlantest_sta, list) {
163 if (sta->state == STATE1)
165 wpa_printf(MSG_DEBUG, "STA " MACSTR
166 " moved to State 1 with " MACSTR,
167 MAC2STR(sta->addr), MAC2STR(bss->bssid));
173 static void tdls_link_down(struct wlantest_bss *bss, struct wlantest_sta *sta)
175 struct wlantest_tdls *tdls;
176 dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) {
177 if ((tdls->init == sta || tdls->resp == sta) && tdls->link_up)
179 wpa_printf(MSG_DEBUG, "TDLS: Set link down based on "
180 "STA deauth/disassoc");
187 static void rx_mgmt_deauth(struct wlantest *wt, const u8 *data, size_t len,
190 const struct ieee80211_mgmt *mgmt;
191 struct wlantest_bss *bss;
192 struct wlantest_sta *sta;
194 mgmt = (const struct ieee80211_mgmt *) data;
195 bss = bss_get(wt, mgmt->bssid);
198 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
199 sta = sta_get(bss, mgmt->da);
201 sta = sta_get(bss, mgmt->sa);
204 wpa_printf(MSG_INFO, "Too short Deauthentication frame from "
205 MACSTR, MAC2STR(mgmt->sa));
209 wpa_printf(MSG_DEBUG, "DEAUTH " MACSTR " -> " MACSTR
210 " (reason=%u) (valid=%d)",
211 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
212 le_to_host16(mgmt->u.deauth.reason_code), valid);
213 wpa_hexdump(MSG_MSGDUMP, "DEAUTH payload", data + 24, len - 24);
216 if (valid && mgmt->da[0] == 0xff)
217 deauth_all_stas(bss);
221 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
222 sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DEAUTH_RX :
223 WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX]++;
224 if (sta->pwrmgt && !sta->pspoll)
225 sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_ASLEEP]++;
227 sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_AWAKE]++;
229 sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DEAUTH_TX :
230 WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX]++;
233 wpa_printf(MSG_INFO, "Do not change STA " MACSTR " State "
234 "since Disassociation frame was not protected "
235 "correctly", MAC2STR(sta->addr));
239 if (sta->state != STATE1) {
240 wpa_printf(MSG_DEBUG, "STA " MACSTR
241 " moved to State 1 with " MACSTR,
242 MAC2STR(sta->addr), MAC2STR(bss->bssid));
245 tdls_link_down(bss, sta);
249 static void rx_mgmt_assoc_req(struct wlantest *wt, const u8 *data, size_t len)
251 const struct ieee80211_mgmt *mgmt;
252 struct wlantest_bss *bss;
253 struct wlantest_sta *sta;
254 struct ieee802_11_elems elems;
256 mgmt = (const struct ieee80211_mgmt *) data;
257 bss = bss_get(wt, mgmt->bssid);
260 sta = sta_get(bss, mgmt->sa);
265 wpa_printf(MSG_INFO, "Too short Association Request frame "
266 "from " MACSTR, MAC2STR(mgmt->sa));
270 wpa_printf(MSG_DEBUG, "ASSOCREQ " MACSTR " -> " MACSTR
271 " (capab=0x%x listen_int=%u)",
272 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
273 le_to_host16(mgmt->u.assoc_req.capab_info),
274 le_to_host16(mgmt->u.assoc_req.listen_interval));
276 sta->counters[WLANTEST_STA_COUNTER_ASSOCREQ_TX]++;
278 if (ieee802_11_parse_elems(mgmt->u.assoc_req.variable,
279 len - (mgmt->u.assoc_req.variable - data),
280 &elems, 0) == ParseFailed) {
281 wpa_printf(MSG_INFO, "Invalid IEs in Association Request "
282 "frame from " MACSTR, MAC2STR(mgmt->sa));
286 sta->assocreq_capab_info = le_to_host16(mgmt->u.assoc_req.capab_info);
287 sta->assocreq_listen_int =
288 le_to_host16(mgmt->u.assoc_req.listen_interval);
289 os_free(sta->assocreq_ies);
290 sta->assocreq_ies_len = len - (mgmt->u.assoc_req.variable - data);
291 sta->assocreq_ies = os_malloc(sta->assocreq_ies_len);
292 if (sta->assocreq_ies)
293 os_memcpy(sta->assocreq_ies, mgmt->u.assoc_req.variable,
294 sta->assocreq_ies_len);
296 sta_update_assoc(sta, &elems);
300 static void rx_mgmt_assoc_resp(struct wlantest *wt, const u8 *data, size_t len)
302 const struct ieee80211_mgmt *mgmt;
303 struct wlantest_bss *bss;
304 struct wlantest_sta *sta;
305 u16 capab, status, aid;
307 mgmt = (const struct ieee80211_mgmt *) data;
308 bss = bss_get(wt, mgmt->bssid);
311 sta = sta_get(bss, mgmt->da);
316 wpa_printf(MSG_INFO, "Too short Association Response frame "
317 "from " MACSTR, MAC2STR(mgmt->sa));
321 capab = le_to_host16(mgmt->u.assoc_resp.capab_info);
322 status = le_to_host16(mgmt->u.assoc_resp.status_code);
323 aid = le_to_host16(mgmt->u.assoc_resp.aid);
325 wpa_printf(MSG_DEBUG, "ASSOCRESP " MACSTR " -> " MACSTR
326 " (capab=0x%x status=%u aid=%u)",
327 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status,
330 if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
331 struct ieee802_11_elems elems;
332 const u8 *ies = mgmt->u.assoc_resp.variable;
333 size_t ies_len = len - (mgmt->u.assoc_resp.variable - data);
334 if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) ==
336 wpa_printf(MSG_INFO, "Failed to parse IEs in "
337 "AssocResp from " MACSTR,
339 } else if (elems.timeout_int == 0 ||
340 elems.timeout_int_len != 5) {
341 wpa_printf(MSG_INFO, "No valid Timeout Interval IE in "
342 "AssocResp (status=30) from " MACSTR,
346 WLANTEST_STA_COUNTER_ASSOCRESP_COMEBACK]++;
353 if ((aid & 0xc000) != 0xc000) {
354 wpa_printf(MSG_DEBUG, "Two MSBs of the AID were not set to 1 "
355 "in Association Response from " MACSTR,
358 sta->aid = aid & 0xc000;
360 if (sta->state < STATE2) {
361 wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 when "
362 "getting associated", MAC2STR(sta->addr));
365 if (sta->state < STATE3) {
366 wpa_printf(MSG_DEBUG, "STA " MACSTR
367 " moved to State 3 with " MACSTR,
368 MAC2STR(sta->addr), MAC2STR(bss->bssid));
374 static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data,
377 const struct ieee80211_mgmt *mgmt;
378 struct wlantest_bss *bss;
379 struct wlantest_sta *sta;
380 struct ieee802_11_elems elems;
382 mgmt = (const struct ieee80211_mgmt *) data;
383 bss = bss_get(wt, mgmt->bssid);
386 sta = sta_get(bss, mgmt->sa);
390 if (len < 24 + 4 + ETH_ALEN) {
391 wpa_printf(MSG_INFO, "Too short Reassociation Request frame "
392 "from " MACSTR, MAC2STR(mgmt->sa));
396 wpa_printf(MSG_DEBUG, "REASSOCREQ " MACSTR " -> " MACSTR
397 " (capab=0x%x listen_int=%u current_ap=" MACSTR ")",
398 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
399 le_to_host16(mgmt->u.reassoc_req.capab_info),
400 le_to_host16(mgmt->u.reassoc_req.listen_interval),
401 MAC2STR(mgmt->u.reassoc_req.current_ap));
403 sta->counters[WLANTEST_STA_COUNTER_REASSOCREQ_TX]++;
405 if (ieee802_11_parse_elems(mgmt->u.reassoc_req.variable,
406 len - (mgmt->u.reassoc_req.variable - data),
407 &elems, 0) == ParseFailed) {
408 wpa_printf(MSG_INFO, "Invalid IEs in Reassociation Request "
409 "frame from " MACSTR, MAC2STR(mgmt->sa));
413 sta->assocreq_capab_info =
414 le_to_host16(mgmt->u.reassoc_req.capab_info);
415 sta->assocreq_listen_int =
416 le_to_host16(mgmt->u.reassoc_req.listen_interval);
417 os_free(sta->assocreq_ies);
418 sta->assocreq_ies_len = len - (mgmt->u.reassoc_req.variable - data);
419 sta->assocreq_ies = os_malloc(sta->assocreq_ies_len);
420 if (sta->assocreq_ies)
421 os_memcpy(sta->assocreq_ies, mgmt->u.reassoc_req.variable,
422 sta->assocreq_ies_len);
424 sta_update_assoc(sta, &elems);
428 static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data,
431 const struct ieee80211_mgmt *mgmt;
432 struct wlantest_bss *bss;
433 struct wlantest_sta *sta;
434 u16 capab, status, aid;
436 mgmt = (const struct ieee80211_mgmt *) data;
437 bss = bss_get(wt, mgmt->bssid);
440 sta = sta_get(bss, mgmt->da);
445 wpa_printf(MSG_INFO, "Too short Reassociation Response frame "
446 "from " MACSTR, MAC2STR(mgmt->sa));
450 capab = le_to_host16(mgmt->u.reassoc_resp.capab_info);
451 status = le_to_host16(mgmt->u.reassoc_resp.status_code);
452 aid = le_to_host16(mgmt->u.reassoc_resp.aid);
454 wpa_printf(MSG_DEBUG, "REASSOCRESP " MACSTR " -> " MACSTR
455 " (capab=0x%x status=%u aid=%u)",
456 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status,
459 if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
460 struct ieee802_11_elems elems;
461 const u8 *ies = mgmt->u.reassoc_resp.variable;
462 size_t ies_len = len - (mgmt->u.reassoc_resp.variable - data);
463 if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) ==
465 wpa_printf(MSG_INFO, "Failed to parse IEs in "
466 "ReassocResp from " MACSTR,
468 } else if (elems.timeout_int == 0 ||
469 elems.timeout_int_len != 5) {
470 wpa_printf(MSG_INFO, "No valid Timeout Interval IE in "
471 "ReassocResp (status=30) from " MACSTR,
475 WLANTEST_STA_COUNTER_REASSOCRESP_COMEBACK]++;
482 if ((aid & 0xc000) != 0xc000) {
483 wpa_printf(MSG_DEBUG, "Two MSBs of the AID were not set to 1 "
484 "in Reassociation Response from " MACSTR,
487 sta->aid = aid & 0xc000;
489 if (sta->state < STATE2) {
490 wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 when "
491 "getting associated", MAC2STR(sta->addr));
494 if (sta->state < STATE3) {
495 wpa_printf(MSG_DEBUG, "STA " MACSTR
496 " moved to State 3 with " MACSTR,
497 MAC2STR(sta->addr), MAC2STR(bss->bssid));
503 static void disassoc_all_stas(struct wlantest_bss *bss)
505 struct wlantest_sta *sta;
506 dl_list_for_each(sta, &bss->sta, struct wlantest_sta, list) {
507 if (sta->state <= STATE2)
509 wpa_printf(MSG_DEBUG, "STA " MACSTR
510 " moved to State 2 with " MACSTR,
511 MAC2STR(sta->addr), MAC2STR(bss->bssid));
517 static void rx_mgmt_disassoc(struct wlantest *wt, const u8 *data, size_t len,
520 const struct ieee80211_mgmt *mgmt;
521 struct wlantest_bss *bss;
522 struct wlantest_sta *sta;
524 mgmt = (const struct ieee80211_mgmt *) data;
525 bss = bss_get(wt, mgmt->bssid);
528 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
529 sta = sta_get(bss, mgmt->da);
531 sta = sta_get(bss, mgmt->sa);
534 wpa_printf(MSG_INFO, "Too short Disassociation frame from "
535 MACSTR, MAC2STR(mgmt->sa));
539 wpa_printf(MSG_DEBUG, "DISASSOC " MACSTR " -> " MACSTR
540 " (reason=%u) (valid=%d)",
541 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
542 le_to_host16(mgmt->u.disassoc.reason_code), valid);
543 wpa_hexdump(MSG_MSGDUMP, "DISASSOC payload", data + 24, len - 24);
546 if (valid && mgmt->da[0] == 0xff)
547 disassoc_all_stas(bss);
551 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
552 sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DISASSOC_RX :
553 WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX]++;
554 if (sta->pwrmgt && !sta->pspoll)
556 WLANTEST_STA_COUNTER_DISASSOC_RX_ASLEEP]++;
559 WLANTEST_STA_COUNTER_DISASSOC_RX_AWAKE]++;
561 sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DISASSOC_TX :
562 WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX]++;
565 wpa_printf(MSG_INFO, "Do not change STA " MACSTR " State "
566 "since Disassociation frame was not protected "
567 "correctly", MAC2STR(sta->addr));
571 if (sta->state < STATE2) {
572 wpa_printf(MSG_DEBUG, "STA " MACSTR " was not in State 2 or 3 "
573 "when getting disassociated", MAC2STR(sta->addr));
576 if (sta->state > STATE2) {
577 wpa_printf(MSG_DEBUG, "STA " MACSTR
578 " moved to State 2 with " MACSTR,
579 MAC2STR(sta->addr), MAC2STR(bss->bssid));
582 tdls_link_down(bss, sta);
586 static void rx_mgmt_action_sa_query_req(struct wlantest *wt,
587 struct wlantest_sta *sta,
588 const struct ieee80211_mgmt *mgmt,
589 size_t len, int valid)
594 rx_id = (const u8 *) mgmt->u.action.u.sa_query_req.trans_id;
595 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
596 id = sta->ap_sa_query_tr;
598 id = sta->sta_sa_query_tr;
599 wpa_printf(MSG_INFO, "SA Query Request " MACSTR " -> " MACSTR
600 " (trans_id=%02x%02x)%s",
601 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), rx_id[0], rx_id[1],
602 valid ? "" : " (invalid protection)");
603 os_memcpy(id, mgmt->u.action.u.sa_query_req.trans_id, 2);
604 if (os_memcmp(mgmt->sa, sta->addr, ETH_ALEN) == 0)
605 sta->counters[valid ?
606 WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX :
607 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX]++;
609 sta->counters[valid ?
610 WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX :
611 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX]++;
615 static void rx_mgmt_action_sa_query_resp(struct wlantest *wt,
616 struct wlantest_sta *sta,
617 const struct ieee80211_mgmt *mgmt,
618 size_t len, int valid)
624 rx_id = (const u8 *) mgmt->u.action.u.sa_query_resp.trans_id;
625 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
626 id = sta->sta_sa_query_tr;
628 id = sta->ap_sa_query_tr;
629 match = os_memcmp(rx_id, id, 2) == 0;
630 wpa_printf(MSG_INFO, "SA Query Response " MACSTR " -> " MACSTR
631 " (trans_id=%02x%02x; %s)%s",
632 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), rx_id[0], rx_id[1],
633 match ? "match" : "mismatch",
634 valid ? "" : " (invalid protection)");
635 if (os_memcmp(mgmt->sa, sta->addr, ETH_ALEN) == 0)
636 sta->counters[(valid && match) ?
637 WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX :
638 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX]++;
640 sta->counters[(valid && match) ?
641 WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX :
642 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX]++;
646 static void rx_mgmt_action_sa_query(struct wlantest *wt,
647 struct wlantest_sta *sta,
648 const struct ieee80211_mgmt *mgmt,
649 size_t len, int valid)
651 if (len < 24 + 2 + WLAN_SA_QUERY_TR_ID_LEN) {
652 wpa_printf(MSG_INFO, "Too short SA Query frame from " MACSTR,
657 if (len > 24 + 2 + WLAN_SA_QUERY_TR_ID_LEN) {
658 size_t elen = len - (24 + 2 + WLAN_SA_QUERY_TR_ID_LEN);
659 wpa_printf(MSG_INFO, "Unexpected %u octets of extra data at "
660 "the end of SA Query frame from " MACSTR,
661 (unsigned) elen, MAC2STR(mgmt->sa));
662 wpa_hexdump(MSG_INFO, "SA Query extra data",
663 ((const u8 *) mgmt) + len - elen, elen);
666 switch (mgmt->u.action.u.sa_query_req.action) {
667 case WLAN_SA_QUERY_REQUEST:
668 rx_mgmt_action_sa_query_req(wt, sta, mgmt, len, valid);
670 case WLAN_SA_QUERY_RESPONSE:
671 rx_mgmt_action_sa_query_resp(wt, sta, mgmt, len, valid);
674 wpa_printf(MSG_INFO, "Unexpected SA Query action value %u "
676 mgmt->u.action.u.sa_query_req.action,
682 static void rx_mgmt_action(struct wlantest *wt, const u8 *data, size_t len,
685 const struct ieee80211_mgmt *mgmt;
686 struct wlantest_bss *bss;
687 struct wlantest_sta *sta;
689 mgmt = (const struct ieee80211_mgmt *) data;
690 if (mgmt->da[0] & 0x01) {
691 wpa_printf(MSG_DEBUG, "Group addressed Action frame: DA="
692 MACSTR " SA=" MACSTR " BSSID=" MACSTR
694 MAC2STR(mgmt->da), MAC2STR(mgmt->sa),
695 MAC2STR(mgmt->bssid), mgmt->u.action.category);
696 return; /* Ignore group addressed Action frames for now */
698 bss = bss_get(wt, mgmt->bssid);
701 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
702 sta = sta_get(bss, mgmt->da);
704 sta = sta_get(bss, mgmt->sa);
709 wpa_printf(MSG_INFO, "Too short Action frame from "
710 MACSTR, MAC2STR(mgmt->sa));
714 wpa_printf(MSG_DEBUG, "ACTION " MACSTR " -> " MACSTR
715 " (category=%u) (valid=%d)",
716 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
717 mgmt->u.action.category, valid);
718 wpa_hexdump(MSG_MSGDUMP, "ACTION payload", data + 24, len - 24);
720 if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
721 sta->state < STATE3) {
722 wpa_printf(MSG_INFO, "Action frame sent when STA is not in "
723 "State 3 (SA=" MACSTR " DATA=" MACSTR ")",
724 MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
727 switch (mgmt->u.action.category) {
728 case WLAN_ACTION_SA_QUERY:
729 rx_mgmt_action_sa_query(wt, sta, mgmt, len, valid);
735 static int check_mmie_mic(const u8 *igtk, const u8 *data, size_t len)
740 const struct ieee80211_hdr *hdr;
742 buf = os_malloc(len + 20 - 24);
746 /* BIP AAD: FC(masked) A1 A2 A3 */
747 hdr = (const struct ieee80211_hdr *) data;
748 fc = le_to_host16(hdr->frame_control);
749 fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA);
750 WPA_PUT_LE16(buf, fc);
751 os_memcpy(buf + 2, hdr->addr1, 3 * ETH_ALEN);
753 /* Frame body with MMIE MIC masked to zero */
754 os_memcpy(buf + 20, data + 24, len - 24 - 8);
755 os_memset(buf + 20 + len - 24 - 8, 0, 8);
757 wpa_hexdump(MSG_MSGDUMP, "BIP: AAD|Body(masked)", buf, len + 20 - 24);
758 /* MIC = L(AES-128-CMAC(AAD || Frame Body(masked)), 0, 64) */
759 if (omac1_aes_128(igtk, buf, len + 20 - 24, mic) < 0) {
766 if (os_memcmp(data + len - 8, mic, 8) != 0)
773 static int check_bip(struct wlantest *wt, const u8 *data, size_t len)
775 const struct ieee80211_mgmt *mgmt;
779 struct wlantest_bss *bss;
781 mgmt = (const struct ieee80211_mgmt *) data;
782 fc = le_to_host16(mgmt->frame_control);
783 stype = WLAN_FC_GET_STYPE(fc);
785 if (stype == WLAN_FC_STYPE_ACTION) {
788 if (mgmt->u.action.category == WLAN_ACTION_PUBLIC)
789 return 0; /* Not a robust management frame */
792 bss = bss_get(wt, mgmt->bssid);
794 return 0; /* No key known yet */
796 if (len < 24 + 18 || data[len - 18] != WLAN_EID_MMIE ||
797 data[len - 17] != 16) {
799 if (bss->rsn_capab & WPA_CAPABILITY_MFPC) {
800 wpa_printf(MSG_INFO, "Robust group-addressed "
801 "management frame sent without BIP by "
802 MACSTR, MAC2STR(mgmt->sa));
803 bss->counters[WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE]++;
809 mmie = data + len - 16;
810 keyid = WPA_GET_LE16(mmie);
811 if (keyid & 0xf000) {
812 wpa_printf(MSG_INFO, "MMIE KeyID reserved bits not zero "
813 "(%04x) from " MACSTR, keyid, MAC2STR(mgmt->sa));
816 if (keyid < 4 || keyid > 5) {
817 wpa_printf(MSG_INFO, "Unexpected MMIE KeyID %u from " MACSTR,
818 keyid, MAC2STR(mgmt->sa));
819 bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++;
822 wpa_printf(MSG_DEBUG, "MMIE KeyID %u", keyid);
823 wpa_hexdump(MSG_MSGDUMP, "MMIE IPN", mmie + 2, 6);
824 wpa_hexdump(MSG_MSGDUMP, "MMIE MIC", mmie + 8, 8);
826 if (!bss->igtk_set[keyid]) {
827 wpa_printf(MSG_DEBUG, "No IGTK known to validate BIP frame");
831 if (os_memcmp(mmie + 2, bss->ipn[keyid], 6) <= 0) {
832 wpa_printf(MSG_INFO, "BIP replay detected: SA=" MACSTR,
834 wpa_hexdump(MSG_INFO, "RX IPN", mmie + 2, 6);
835 wpa_hexdump(MSG_INFO, "Last RX IPN", bss->ipn[keyid], 6);
838 if (check_mmie_mic(bss->igtk[keyid], data, len) < 0) {
839 wpa_printf(MSG_INFO, "Invalid MMIE MIC in a frame from "
840 MACSTR, MAC2STR(mgmt->sa));
841 bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++;
845 wpa_printf(MSG_DEBUG, "Valid MMIE MIC");
846 os_memcpy(bss->ipn[keyid], mmie + 2, 6);
847 bss->counters[WLANTEST_BSS_COUNTER_VALID_BIP_MMIE]++;
849 if (stype == WLAN_FC_STYPE_DEAUTH)
850 bss->counters[WLANTEST_BSS_COUNTER_BIP_DEAUTH]++;
851 else if (stype == WLAN_FC_STYPE_DISASSOC)
852 bss->counters[WLANTEST_BSS_COUNTER_BIP_DISASSOC]++;
858 static u8 * mgmt_ccmp_decrypt(struct wlantest *wt, const u8 *data, size_t len,
861 struct wlantest_bss *bss;
862 struct wlantest_sta *sta;
863 const struct ieee80211_hdr *hdr;
865 u8 *decrypted, *frame = NULL;
868 hdr = (const struct ieee80211_hdr *) data;
869 bss = bss_get(wt, hdr->addr3);
872 if (os_memcmp(hdr->addr1, hdr->addr3, ETH_ALEN) == 0)
873 sta = sta_get(bss, hdr->addr2);
875 sta = sta_get(bss, hdr->addr1);
876 if (sta == NULL || !sta->ptk_set) {
877 wpa_printf(MSG_MSGDUMP, "No PTK known to decrypt the frame");
884 if (!(data[24 + 3] & 0x20)) {
885 wpa_printf(MSG_INFO, "Expected CCMP frame from " MACSTR
886 " did not have ExtIV bit set to 1",
887 MAC2STR(hdr->addr2));
891 if (data[24 + 2] != 0 || (data[24 + 3] & 0x1f) != 0) {
892 wpa_printf(MSG_INFO, "CCMP mgmt frame from " MACSTR " used "
893 "non-zero reserved bit", MAC2STR(hdr->addr2));
896 keyid = data[24 + 3] >> 6;
898 wpa_printf(MSG_INFO, "Unexpected non-zero KeyID %d in "
899 "individually addressed Management frame from "
900 MACSTR, keyid, MAC2STR(hdr->addr2));
903 if (os_memcmp(hdr->addr1, hdr->addr3, ETH_ALEN) == 0)
904 rsc = sta->rsc_tods[16];
906 rsc = sta->rsc_fromds[16];
908 ccmp_get_pn(pn, data + 24);
909 if (os_memcmp(pn, rsc, 6) <= 0) {
910 u16 seq_ctrl = le_to_host16(hdr->seq_ctrl);
911 wpa_printf(MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR
912 " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u",
913 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
915 WLAN_GET_SEQ_SEQ(seq_ctrl),
916 WLAN_GET_SEQ_FRAG(seq_ctrl));
917 wpa_hexdump(MSG_INFO, "RX PN", pn, 6);
918 wpa_hexdump(MSG_INFO, "RSC", rsc, 6);
921 decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data + 24, len - 24, dlen);
923 os_memcpy(rsc, pn, 6);
924 frame = os_malloc(24 + *dlen);
926 os_memcpy(frame, data, 24);
927 os_memcpy(frame + 24, decrypted, *dlen);
938 static int check_mgmt_ccmp(struct wlantest *wt, const u8 *data, size_t len)
940 const struct ieee80211_mgmt *mgmt;
942 struct wlantest_bss *bss;
943 struct wlantest_sta *sta;
945 mgmt = (const struct ieee80211_mgmt *) data;
946 fc = le_to_host16(mgmt->frame_control);
948 if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
950 mgmt->u.action.category == WLAN_ACTION_PUBLIC)
951 return 0; /* Not a robust management frame */
954 bss = bss_get(wt, mgmt->bssid);
957 if (os_memcmp(mgmt->da, mgmt->bssid, ETH_ALEN) == 0)
958 sta = sta_get(bss, mgmt->sa);
960 sta = sta_get(bss, mgmt->da);
964 if ((sta->rsn_capab & WPA_CAPABILITY_MFPC) &&
965 (sta->state == STATE3 ||
966 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION)) {
967 wpa_printf(MSG_INFO, "Robust individually-addressed "
968 "management frame sent without CCMP by "
969 MACSTR, MAC2STR(mgmt->sa));
977 void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
979 const struct ieee80211_hdr *hdr;
982 u8 *decrypted = NULL;
988 hdr = (const struct ieee80211_hdr *) data;
989 fc = le_to_host16(hdr->frame_control);
991 stype = WLAN_FC_GET_STYPE(fc);
993 if ((hdr->addr1[0] & 0x01) &&
994 (stype == WLAN_FC_STYPE_DEAUTH ||
995 stype == WLAN_FC_STYPE_DISASSOC ||
996 stype == WLAN_FC_STYPE_ACTION)) {
997 if (check_bip(wt, data, len) < 0)
1001 wpa_printf((stype == WLAN_FC_STYPE_BEACON ||
1002 stype == WLAN_FC_STYPE_PROBE_RESP ||
1003 stype == WLAN_FC_STYPE_PROBE_REQ) ?
1004 MSG_EXCESSIVE : MSG_MSGDUMP,
1005 "MGMT %s%s%s DA=" MACSTR " SA=" MACSTR " BSSID=" MACSTR,
1007 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
1008 fc & WLAN_FC_ISWEP ? " Prot" : "",
1009 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
1010 MAC2STR(hdr->addr3));
1012 if ((fc & WLAN_FC_ISWEP) &&
1013 !(hdr->addr1[0] & 0x01) &&
1014 (stype == WLAN_FC_STYPE_DEAUTH ||
1015 stype == WLAN_FC_STYPE_DISASSOC ||
1016 stype == WLAN_FC_STYPE_ACTION)) {
1017 decrypted = mgmt_ccmp_decrypt(wt, data, len, &dlen);
1019 write_pcap_decrypted(wt, decrypted, dlen, NULL, 0);
1026 if (!(fc & WLAN_FC_ISWEP) &&
1027 !(hdr->addr1[0] & 0x01) &&
1028 (stype == WLAN_FC_STYPE_DEAUTH ||
1029 stype == WLAN_FC_STYPE_DISASSOC ||
1030 stype == WLAN_FC_STYPE_ACTION)) {
1031 if (check_mgmt_ccmp(wt, data, len) < 0)
1036 case WLAN_FC_STYPE_BEACON:
1037 rx_mgmt_beacon(wt, data, len);
1039 case WLAN_FC_STYPE_PROBE_RESP:
1040 rx_mgmt_probe_resp(wt, data, len);
1042 case WLAN_FC_STYPE_AUTH:
1043 rx_mgmt_auth(wt, data, len);
1045 case WLAN_FC_STYPE_DEAUTH:
1046 rx_mgmt_deauth(wt, data, len, valid);
1048 case WLAN_FC_STYPE_ASSOC_REQ:
1049 rx_mgmt_assoc_req(wt, data, len);
1051 case WLAN_FC_STYPE_ASSOC_RESP:
1052 rx_mgmt_assoc_resp(wt, data, len);
1054 case WLAN_FC_STYPE_REASSOC_REQ:
1055 rx_mgmt_reassoc_req(wt, data, len);
1057 case WLAN_FC_STYPE_REASSOC_RESP:
1058 rx_mgmt_reassoc_resp(wt, data, len);
1060 case WLAN_FC_STYPE_DISASSOC:
1061 rx_mgmt_disassoc(wt, data, len, valid);
1063 case WLAN_FC_STYPE_ACTION:
1064 rx_mgmt_action(wt, data, len, valid);
1070 wt->last_mgmt_valid = valid;
1074 static void rx_mgmt_deauth_ack(struct wlantest *wt,
1075 const struct ieee80211_hdr *hdr)
1077 const struct ieee80211_mgmt *mgmt;
1078 struct wlantest_bss *bss;
1079 struct wlantest_sta *sta;
1081 mgmt = (const struct ieee80211_mgmt *) hdr;
1082 bss = bss_get(wt, mgmt->bssid);
1085 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
1086 sta = sta_get(bss, mgmt->da);
1088 sta = sta_get(bss, mgmt->sa);
1092 wpa_printf(MSG_DEBUG, "DEAUTH from " MACSTR " acknowledged by " MACSTR,
1093 MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
1094 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
1096 c = wt->last_mgmt_valid ?
1097 WLANTEST_STA_COUNTER_VALID_DEAUTH_RX_ACK :
1098 WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX_ACK;
1104 static void rx_mgmt_disassoc_ack(struct wlantest *wt,
1105 const struct ieee80211_hdr *hdr)
1107 const struct ieee80211_mgmt *mgmt;
1108 struct wlantest_bss *bss;
1109 struct wlantest_sta *sta;
1111 mgmt = (const struct ieee80211_mgmt *) hdr;
1112 bss = bss_get(wt, mgmt->bssid);
1115 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
1116 sta = sta_get(bss, mgmt->da);
1118 sta = sta_get(bss, mgmt->sa);
1122 wpa_printf(MSG_DEBUG, "DISASSOC from " MACSTR " acknowledged by "
1123 MACSTR, MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
1124 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
1126 c = wt->last_mgmt_valid ?
1127 WLANTEST_STA_COUNTER_VALID_DISASSOC_RX_ACK :
1128 WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX_ACK;
1134 void rx_mgmt_ack(struct wlantest *wt, const struct ieee80211_hdr *hdr)
1137 fc = le_to_host16(hdr->frame_control);
1138 stype = WLAN_FC_GET_STYPE(fc);
1140 wpa_printf(MSG_MSGDUMP, "MGMT ACK: stype=%u a1=" MACSTR " a2=" MACSTR
1142 stype, MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
1143 MAC2STR(hdr->addr3));
1146 case WLAN_FC_STYPE_DEAUTH:
1147 rx_mgmt_deauth_ack(wt, hdr);
1149 case WLAN_FC_STYPE_DISASSOC:
1150 rx_mgmt_disassoc_ack(wt, hdr);