2 * IEEE 802.11 Common routines
3 * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
13 #include "ieee802_11_defs.h"
14 #include "ieee802_11_common.h"
17 static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
18 struct ieee802_11_elems *elems,
23 /* first 3 bytes in vendor specific information element are the IEEE
24 * OUI of the vendor. The following byte is used a vendor specific
28 wpa_printf(MSG_MSGDUMP, "short vendor specific "
29 "information element ignored (len=%lu)",
30 (unsigned long) elen);
35 oui = WPA_GET_BE24(pos);
38 /* Microsoft/Wi-Fi information elements are further typed and
42 /* Microsoft OUI (00:50:F2) with OUI Type 1:
43 * real WPA information element */
45 elems->wpa_ie_len = elen;
48 /* WMM information element */
50 wpa_printf(MSG_MSGDUMP, "short WMM "
51 "information element ignored "
53 (unsigned long) elen);
57 case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
58 case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
60 * Share same pointer since only one of these
61 * is used and they start with same data.
62 * Length field can be used to distinguish the
66 elems->wmm_len = elen;
68 case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
69 elems->wmm_tspec = pos;
70 elems->wmm_tspec_len = elen;
73 wpa_printf(MSG_EXCESSIVE, "unknown WMM "
74 "information element ignored "
75 "(subtype=%d len=%lu)",
76 pos[4], (unsigned long) elen);
81 /* Wi-Fi Protected Setup (WPS) IE */
83 elems->wps_ie_len = elen;
86 wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
87 "information element ignored "
89 pos[3], (unsigned long) elen);
97 /* Wi-Fi Alliance - P2P IE */
99 elems->p2p_len = elen;
102 /* Wi-Fi Alliance - WFD IE */
104 elems->wfd_len = elen;
106 case HS20_INDICATION_OUI_TYPE:
109 elems->hs20_len = elen;
111 case HS20_OSEN_OUI_TYPE:
112 /* Hotspot 2.0 OSEN */
114 elems->osen_len = elen;
117 wpa_printf(MSG_MSGDUMP, "Unknown WFA "
118 "information element ignored "
120 pos[3], (unsigned long) elen);
127 case VENDOR_HT_CAPAB_OUI_TYPE:
128 elems->vendor_ht_cap = pos;
129 elems->vendor_ht_cap_len = elen;
131 case VENDOR_VHT_TYPE:
133 (pos[4] == VENDOR_VHT_SUBTYPE ||
134 pos[4] == VENDOR_VHT_SUBTYPE2)) {
135 elems->vendor_vht = pos;
136 elems->vendor_vht_len = elen;
141 wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
142 "information element ignored "
144 pos[3], (unsigned long) elen);
150 wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
151 "information element ignored (vendor OUI "
152 "%02x:%02x:%02x len=%lu)",
153 pos[0], pos[1], pos[2], (unsigned long) elen);
162 * ieee802_11_parse_elems - Parse information elements in management frames
163 * @start: Pointer to the start of IEs
164 * @len: Length of IE buffer in octets
165 * @elems: Data structure for parsed elements
166 * @show_errors: Whether to show parsing errors in debug log
167 * Returns: Parsing result
169 ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
170 struct ieee802_11_elems *elems,
174 const u8 *pos = start;
177 os_memset(elems, 0, sizeof(*elems));
188 wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
189 "parse failed (id=%d elen=%d "
191 id, elen, (unsigned long) left);
192 wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
200 elems->ssid_len = elen;
202 case WLAN_EID_SUPP_RATES:
203 elems->supp_rates = pos;
204 elems->supp_rates_len = elen;
206 case WLAN_EID_DS_PARAMS:
207 elems->ds_params = pos;
208 elems->ds_params_len = elen;
210 case WLAN_EID_CF_PARAMS:
213 case WLAN_EID_CHALLENGE:
214 elems->challenge = pos;
215 elems->challenge_len = elen;
217 case WLAN_EID_ERP_INFO:
218 elems->erp_info = pos;
219 elems->erp_info_len = elen;
221 case WLAN_EID_EXT_SUPP_RATES:
222 elems->ext_supp_rates = pos;
223 elems->ext_supp_rates_len = elen;
225 case WLAN_EID_VENDOR_SPECIFIC:
226 if (ieee802_11_parse_vendor_specific(pos, elen,
233 elems->rsn_ie_len = elen;
235 case WLAN_EID_PWR_CAPABILITY:
237 case WLAN_EID_SUPPORTED_CHANNELS:
238 elems->supp_channels = pos;
239 elems->supp_channels_len = elen;
241 case WLAN_EID_MOBILITY_DOMAIN:
243 elems->mdie_len = elen;
245 case WLAN_EID_FAST_BSS_TRANSITION:
247 elems->ftie_len = elen;
249 case WLAN_EID_TIMEOUT_INTERVAL:
250 elems->timeout_int = pos;
251 elems->timeout_int_len = elen;
253 case WLAN_EID_HT_CAP:
254 elems->ht_capabilities = pos;
255 elems->ht_capabilities_len = elen;
257 case WLAN_EID_HT_OPERATION:
258 elems->ht_operation = pos;
259 elems->ht_operation_len = elen;
261 case WLAN_EID_MESH_CONFIG:
262 elems->mesh_config = pos;
263 elems->mesh_config_len = elen;
265 case WLAN_EID_MESH_ID:
266 elems->mesh_id = pos;
267 elems->mesh_id_len = elen;
269 case WLAN_EID_PEER_MGMT:
270 elems->peer_mgmt = pos;
271 elems->peer_mgmt_len = elen;
273 case WLAN_EID_VHT_CAP:
274 elems->vht_capabilities = pos;
275 elems->vht_capabilities_len = elen;
277 case WLAN_EID_VHT_OPERATION:
278 elems->vht_operation = pos;
279 elems->vht_operation_len = elen;
281 case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
284 elems->vht_opmode_notif = pos;
286 case WLAN_EID_LINK_ID:
289 elems->link_id = pos;
291 case WLAN_EID_INTERWORKING:
292 elems->interworking = pos;
293 elems->interworking_len = elen;
295 case WLAN_EID_QOS_MAP_SET:
298 elems->qos_map_set = pos;
299 elems->qos_map_set_len = elen;
301 case WLAN_EID_EXT_CAPAB:
302 elems->ext_capab = pos;
303 elems->ext_capab_len = elen;
305 case WLAN_EID_BSS_MAX_IDLE_PERIOD:
308 elems->bss_max_idle_period = pos;
310 case WLAN_EID_SSID_LIST:
311 elems->ssid_list = pos;
312 elems->ssid_list_len = elen;
316 elems->ampe_len = elen;
320 elems->mic_len = elen;
321 /* after mic everything is encrypted, so stop. */
328 wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
329 "ignored unknown element (id=%d elen=%d)",
341 return unknown ? ParseUnknown : ParseOK;
345 int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
356 while (pos + 2 <= end) {
357 if (pos + 2 + pos[1] > end)
367 struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
371 const u8 *end, *pos, *ie;
377 while (pos + 1 < end) {
378 if (pos + 2 + pos[1] > end)
380 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
381 WPA_GET_BE32(&pos[2]) == oui_type) {
389 return NULL; /* No specified vendor IE found */
391 buf = wpabuf_alloc(ies_len);
396 * There may be multiple vendor IEs in the message, so need to
397 * concatenate their data fields.
399 while (pos + 1 < end) {
400 if (pos + 2 + pos[1] > end)
402 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
403 WPA_GET_BE32(&pos[2]) == oui_type)
404 wpabuf_put_data(buf, pos + 6, pos[1] - 4);
412 const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
417 * PS-Poll frames are 16 bytes. All other frames are
418 * 24 bytes or longer.
423 fc = le_to_host16(hdr->frame_control);
424 type = WLAN_FC_GET_TYPE(fc);
425 stype = WLAN_FC_GET_STYPE(fc);
428 case WLAN_FC_TYPE_DATA:
431 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
432 case WLAN_FC_FROMDS | WLAN_FC_TODS:
440 case WLAN_FC_TYPE_CTRL:
441 if (stype != WLAN_FC_STYPE_PSPOLL)
444 case WLAN_FC_TYPE_MGMT:
452 int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
453 const char *name, const char *val)
457 struct hostapd_wmm_ac_params *ac;
459 /* skip 'wme_ac_' or 'wmm_ac_' prefix */
461 if (os_strncmp(pos, "be_", 3) == 0) {
464 } else if (os_strncmp(pos, "bk_", 3) == 0) {
467 } else if (os_strncmp(pos, "vi_", 3) == 0) {
470 } else if (os_strncmp(pos, "vo_", 3) == 0) {
474 wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
478 ac = &wmm_ac_params[num];
480 if (os_strcmp(pos, "aifs") == 0) {
482 if (v < 1 || v > 255) {
483 wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
487 } else if (os_strcmp(pos, "cwmin") == 0) {
489 if (v < 0 || v > 12) {
490 wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
494 } else if (os_strcmp(pos, "cwmax") == 0) {
496 if (v < 0 || v > 12) {
497 wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
501 } else if (os_strcmp(pos, "txop_limit") == 0) {
503 if (v < 0 || v > 0xffff) {
504 wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
508 } else if (os_strcmp(pos, "acm") == 0) {
510 if (v < 0 || v > 1) {
511 wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
514 ac->admission_control_mandatory = v;
516 wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
524 enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
526 enum hostapd_hw_mode mode = NUM_HOSTAPD_MODES;
528 if (freq >= 2412 && freq <= 2472) {
529 mode = HOSTAPD_MODE_IEEE80211G;
530 *channel = (freq - 2407) / 5;
531 } else if (freq == 2484) {
532 mode = HOSTAPD_MODE_IEEE80211B;
534 } else if (freq >= 4900 && freq < 5000) {
535 mode = HOSTAPD_MODE_IEEE80211A;
536 *channel = (freq - 4000) / 5;
537 } else if (freq >= 5000 && freq < 5900) {
538 mode = HOSTAPD_MODE_IEEE80211A;
539 *channel = (freq - 5000) / 5;
540 } else if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
541 mode = HOSTAPD_MODE_IEEE80211AD;
542 *channel = (freq - 56160) / 2160;
549 static const char *us_op_class_cc[] = {
553 static const char *eu_op_class_cc[] = {
554 "AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE",
555 "DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT",
556 "LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT",
557 "RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL
560 static const char *jp_op_class_cc[] = {
564 static const char *cn_op_class_cc[] = {
569 static int country_match(const char *cc[], const char *country)
575 for (i = 0; cc[i]; i++) {
576 if (cc[i][0] == country[0] && cc[i][1] == country[1])
584 static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
587 case 12: /* channels 1..11 */
588 case 32: /* channels 1..7; 40 MHz */
589 case 33: /* channels 5..11; 40 MHz */
590 if (chan < 1 || chan > 11)
592 return 2407 + 5 * chan;
593 case 1: /* channels 36,40,44,48 */
594 case 2: /* channels 52,56,60,64; dfs */
595 case 22: /* channels 36,44; 40 MHz */
596 case 23: /* channels 52,60; 40 MHz */
597 case 27: /* channels 40,48; 40 MHz */
598 case 28: /* channels 56,64; 40 MHz */
599 if (chan < 36 || chan > 64)
601 return 5000 + 5 * chan;
602 case 4: /* channels 100-144 */
603 case 24: /* channels 100-140; 40 MHz */
604 if (chan < 100 || chan > 144)
606 return 5000 + 5 * chan;
607 case 3: /* channels 149,153,157,161 */
608 case 25: /* channels 149,157; 40 MHz */
609 case 26: /* channels 149,157; 40 MHz */
610 case 30: /* channels 153,161; 40 MHz */
611 case 31: /* channels 153,161; 40 MHz */
612 if (chan < 149 || chan > 161)
614 return 5000 + 5 * chan;
615 case 34: /* 60 GHz band, channels 1..3 */
616 if (chan < 1 || chan > 3)
618 return 56160 + 2160 * chan;
624 static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
627 case 4: /* channels 1..13 */
628 case 11: /* channels 1..9; 40 MHz */
629 case 12: /* channels 5..13; 40 MHz */
630 if (chan < 1 || chan > 13)
632 return 2407 + 5 * chan;
633 case 1: /* channels 36,40,44,48 */
634 case 2: /* channels 52,56,60,64; dfs */
635 case 5: /* channels 36,44; 40 MHz */
636 case 6: /* channels 52,60; 40 MHz */
637 case 8: /* channels 40,48; 40 MHz */
638 case 9: /* channels 56,64; 40 MHz */
639 if (chan < 36 || chan > 64)
641 return 5000 + 5 * chan;
642 case 3: /* channels 100-140 */
643 case 7: /* channels 100-132; 40 MHz */
644 case 10: /* channels 104-136; 40 MHz */
645 case 16: /* channels 100-140 */
646 if (chan < 100 || chan > 140)
648 return 5000 + 5 * chan;
649 case 17: /* channels 149,153,157,161,165,169 */
650 if (chan < 149 || chan > 169)
652 return 5000 + 5 * chan;
653 case 18: /* 60 GHz band, channels 1..4 */
654 if (chan < 1 || chan > 4)
656 return 56160 + 2160 * chan;
662 static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
665 case 30: /* channels 1..13 */
666 case 56: /* channels 1..9; 40 MHz */
667 case 57: /* channels 5..13; 40 MHz */
668 if (chan < 1 || chan > 13)
670 return 2407 + 5 * chan;
671 case 31: /* channel 14 */
674 return 2414 + 5 * chan;
675 case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */
676 case 32: /* channels 52,56,60,64 */
677 case 33: /* channels 52,56,60,64 */
678 case 36: /* channels 36,44; 40 MHz */
679 case 37: /* channels 52,60; 40 MHz */
680 case 38: /* channels 52,60; 40 MHz */
681 case 41: /* channels 40,48; 40 MHz */
682 case 42: /* channels 56,64; 40 MHz */
683 case 43: /* channels 56,64; 40 MHz */
684 if (chan < 34 || chan > 64)
686 return 5000 + 5 * chan;
687 case 34: /* channels 100-140 */
688 case 35: /* channels 100-140 */
689 case 39: /* channels 100-132; 40 MHz */
690 case 40: /* channels 100-132; 40 MHz */
691 case 44: /* channels 104-136; 40 MHz */
692 case 45: /* channels 104-136; 40 MHz */
693 case 58: /* channels 100-140 */
694 if (chan < 100 || chan > 140)
696 return 5000 + 5 * chan;
697 case 59: /* 60 GHz band, channels 1..4 */
698 if (chan < 1 || chan > 3)
700 return 56160 + 2160 * chan;
706 static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
709 case 7: /* channels 1..13 */
710 case 8: /* channels 1..9; 40 MHz */
711 case 9: /* channels 5..13; 40 MHz */
712 if (chan < 1 || chan > 13)
714 return 2407 + 5 * chan;
715 case 1: /* channels 36,40,44,48 */
716 case 2: /* channels 52,56,60,64; dfs */
717 case 4: /* channels 36,44; 40 MHz */
718 case 5: /* channels 52,60; 40 MHz */
719 if (chan < 36 || chan > 64)
721 return 5000 + 5 * chan;
722 case 3: /* channels 149,153,157,161,165 */
723 case 6: /* channels 149,157; 40 MHz */
724 if (chan < 149 || chan > 165)
726 return 5000 + 5 * chan;
732 static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
734 /* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
738 if (chan < 1 || chan > 13)
740 return 2407 + 5 * chan;
745 return 2414 + 5 * chan;
746 case 83: /* channels 1..9; 40 MHz */
747 case 84: /* channels 5..13; 40 MHz */
748 if (chan < 1 || chan > 13)
750 return 2407 + 5 * chan;
751 case 115: /* channels 36,40,44,48; indoor only */
752 case 116: /* channels 36,44; 40 MHz; indoor only */
753 case 117: /* channels 40,48; 40 MHz; indoor only */
754 case 118: /* channels 52,56,60,64; dfs */
755 case 119: /* channels 52,60; 40 MHz; dfs */
756 case 120: /* channels 56,64; 40 MHz; dfs */
757 if (chan < 36 || chan > 64)
759 return 5000 + 5 * chan;
760 case 121: /* channels 100-140 */
761 case 122: /* channels 100-142; 40 MHz */
762 case 123: /* channels 104-136; 40 MHz */
763 if (chan < 100 || chan > 140)
765 return 5000 + 5 * chan;
766 case 124: /* channels 149,153,157,161 */
767 case 125: /* channels 149,153,157,161,165,169 */
768 case 126: /* channels 149,157; 40 MHz */
769 case 127: /* channels 153,161; 40 MHz */
770 if (chan < 149 || chan > 161)
772 return 5000 + 5 * chan;
773 case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
774 case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
775 if (chan < 36 || chan > 161)
777 return 5000 + 5 * chan;
778 case 129: /* center freqs 50, 114; 160 MHz */
779 if (chan < 50 || chan > 114)
781 return 5000 + 5 * chan;
782 case 180: /* 60 GHz band, channels 1..4 */
783 if (chan < 1 || chan > 4)
785 return 56160 + 2160 * chan;
791 * ieee80211_chan_to_freq - Convert channel info to frequency
792 * @country: Country code, if known; otherwise, global operating class is used
793 * @op_class: Operating class
794 * @chan: Channel number
795 * Returns: Frequency in MHz or -1 if the specified channel is unknown
797 int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
801 if (country_match(us_op_class_cc, country)) {
802 freq = ieee80211_chan_to_freq_us(op_class, chan);
807 if (country_match(eu_op_class_cc, country)) {
808 freq = ieee80211_chan_to_freq_eu(op_class, chan);
813 if (country_match(jp_op_class_cc, country)) {
814 freq = ieee80211_chan_to_freq_jp(op_class, chan);
819 if (country_match(cn_op_class_cc, country)) {
820 freq = ieee80211_chan_to_freq_cn(op_class, chan);
825 return ieee80211_chan_to_freq_global(op_class, chan);
829 int ieee80211_is_dfs(int freq)
831 /* TODO: this could be more accurate to better cover all domains */
832 return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700);
836 static int is_11b(u8 rate)
838 return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
842 int supp_rates_11b_only(struct ieee802_11_elems *elems)
844 int num_11b = 0, num_others = 0;
847 if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
850 for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
851 if (is_11b(elems->supp_rates[i]))
857 for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
859 if (is_11b(elems->ext_supp_rates[i]))
865 return num_11b > 0 && num_others == 0;
869 const char * fc2str(u16 fc)
871 u16 stype = WLAN_FC_GET_STYPE(fc);
872 #define C2S(x) case x: return #x;
874 switch (WLAN_FC_GET_TYPE(fc)) {
875 case WLAN_FC_TYPE_MGMT:
877 C2S(WLAN_FC_STYPE_ASSOC_REQ)
878 C2S(WLAN_FC_STYPE_ASSOC_RESP)
879 C2S(WLAN_FC_STYPE_REASSOC_REQ)
880 C2S(WLAN_FC_STYPE_REASSOC_RESP)
881 C2S(WLAN_FC_STYPE_PROBE_REQ)
882 C2S(WLAN_FC_STYPE_PROBE_RESP)
883 C2S(WLAN_FC_STYPE_BEACON)
884 C2S(WLAN_FC_STYPE_ATIM)
885 C2S(WLAN_FC_STYPE_DISASSOC)
886 C2S(WLAN_FC_STYPE_AUTH)
887 C2S(WLAN_FC_STYPE_DEAUTH)
888 C2S(WLAN_FC_STYPE_ACTION)
891 case WLAN_FC_TYPE_CTRL:
893 C2S(WLAN_FC_STYPE_PSPOLL)
894 C2S(WLAN_FC_STYPE_RTS)
895 C2S(WLAN_FC_STYPE_CTS)
896 C2S(WLAN_FC_STYPE_ACK)
897 C2S(WLAN_FC_STYPE_CFEND)
898 C2S(WLAN_FC_STYPE_CFENDACK)
901 case WLAN_FC_TYPE_DATA:
903 C2S(WLAN_FC_STYPE_DATA)
904 C2S(WLAN_FC_STYPE_DATA_CFACK)
905 C2S(WLAN_FC_STYPE_DATA_CFPOLL)
906 C2S(WLAN_FC_STYPE_DATA_CFACKPOLL)
907 C2S(WLAN_FC_STYPE_NULLFUNC)
908 C2S(WLAN_FC_STYPE_CFACK)
909 C2S(WLAN_FC_STYPE_CFPOLL)
910 C2S(WLAN_FC_STYPE_CFACKPOLL)
911 C2S(WLAN_FC_STYPE_QOS_DATA)
912 C2S(WLAN_FC_STYPE_QOS_DATA_CFACK)
913 C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL)
914 C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL)
915 C2S(WLAN_FC_STYPE_QOS_NULL)
916 C2S(WLAN_FC_STYPE_QOS_CFPOLL)
917 C2S(WLAN_FC_STYPE_QOS_CFACKPOLL)
921 return "WLAN_FC_TYPE_UNKNOWN";