2 * IEEE 802.11 Common routines
3 * Copyright (c) 2002-2015, 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 "wpa_common.h"
14 #include "qca-vendor.h"
15 #include "ieee802_11_defs.h"
16 #include "ieee802_11_common.h"
19 static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
20 struct ieee802_11_elems *elems,
25 /* first 3 bytes in vendor specific information element are the IEEE
26 * OUI of the vendor. The following byte is used a vendor specific
30 wpa_printf(MSG_MSGDUMP, "short vendor specific "
31 "information element ignored (len=%lu)",
32 (unsigned long) elen);
37 oui = WPA_GET_BE24(pos);
40 /* Microsoft/Wi-Fi information elements are further typed and
44 /* Microsoft OUI (00:50:F2) with OUI Type 1:
45 * real WPA information element */
47 elems->wpa_ie_len = elen;
50 /* WMM information element */
52 wpa_printf(MSG_MSGDUMP, "short WMM "
53 "information element ignored "
55 (unsigned long) elen);
59 case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
60 case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
62 * Share same pointer since only one of these
63 * is used and they start with same data.
64 * Length field can be used to distinguish the
68 elems->wmm_len = elen;
70 case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
71 elems->wmm_tspec = pos;
72 elems->wmm_tspec_len = elen;
75 wpa_printf(MSG_EXCESSIVE, "unknown WMM "
76 "information element ignored "
77 "(subtype=%d len=%lu)",
78 pos[4], (unsigned long) elen);
83 /* Wi-Fi Protected Setup (WPS) IE */
85 elems->wps_ie_len = elen;
88 wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
89 "information element ignored "
91 pos[3], (unsigned long) elen);
99 /* Wi-Fi Alliance - P2P IE */
101 elems->p2p_len = elen;
104 /* Wi-Fi Alliance - WFD IE */
106 elems->wfd_len = elen;
108 case HS20_INDICATION_OUI_TYPE:
111 elems->hs20_len = elen;
113 case HS20_OSEN_OUI_TYPE:
114 /* Hotspot 2.0 OSEN */
116 elems->osen_len = elen;
119 wpa_printf(MSG_MSGDUMP, "Unknown WFA "
120 "information element ignored "
122 pos[3], (unsigned long) elen);
129 case VENDOR_HT_CAPAB_OUI_TYPE:
130 elems->vendor_ht_cap = pos;
131 elems->vendor_ht_cap_len = elen;
133 case VENDOR_VHT_TYPE:
135 (pos[4] == VENDOR_VHT_SUBTYPE ||
136 pos[4] == VENDOR_VHT_SUBTYPE2)) {
137 elems->vendor_vht = pos;
138 elems->vendor_vht_len = elen;
143 wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
144 "information element ignored "
146 pos[3], (unsigned long) elen);
153 case QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST:
154 elems->pref_freq_list = pos;
155 elems->pref_freq_list_len = elen;
158 wpa_printf(MSG_EXCESSIVE,
159 "Unknown QCA information element ignored (type=%d len=%lu)",
160 pos[3], (unsigned long) elen);
166 wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
167 "information element ignored (vendor OUI "
168 "%02x:%02x:%02x len=%lu)",
169 pos[0], pos[1], pos[2], (unsigned long) elen);
178 * ieee802_11_parse_elems - Parse information elements in management frames
179 * @start: Pointer to the start of IEs
180 * @len: Length of IE buffer in octets
181 * @elems: Data structure for parsed elements
182 * @show_errors: Whether to show parsing errors in debug log
183 * Returns: Parsing result
185 ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
186 struct ieee802_11_elems *elems,
190 const u8 *pos = start;
193 os_memset(elems, 0, sizeof(*elems));
204 wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
205 "parse failed (id=%d elen=%d "
207 id, elen, (unsigned long) left);
208 wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
215 if (elen > SSID_MAX_LEN) {
216 wpa_printf(MSG_DEBUG,
217 "Ignored too long SSID element (elen=%u)",
222 elems->ssid_len = elen;
224 case WLAN_EID_SUPP_RATES:
225 elems->supp_rates = pos;
226 elems->supp_rates_len = elen;
228 case WLAN_EID_DS_PARAMS:
231 elems->ds_params = pos;
233 case WLAN_EID_CF_PARAMS:
236 case WLAN_EID_CHALLENGE:
237 elems->challenge = pos;
238 elems->challenge_len = elen;
240 case WLAN_EID_ERP_INFO:
243 elems->erp_info = pos;
245 case WLAN_EID_EXT_SUPP_RATES:
246 elems->ext_supp_rates = pos;
247 elems->ext_supp_rates_len = elen;
249 case WLAN_EID_VENDOR_SPECIFIC:
250 if (ieee802_11_parse_vendor_specific(pos, elen,
257 elems->rsn_ie_len = elen;
259 case WLAN_EID_PWR_CAPABILITY:
261 case WLAN_EID_SUPPORTED_CHANNELS:
262 elems->supp_channels = pos;
263 elems->supp_channels_len = elen;
265 case WLAN_EID_MOBILITY_DOMAIN:
266 if (elen < sizeof(struct rsn_mdie))
269 elems->mdie_len = elen;
271 case WLAN_EID_FAST_BSS_TRANSITION:
272 if (elen < sizeof(struct rsn_ftie))
275 elems->ftie_len = elen;
277 case WLAN_EID_TIMEOUT_INTERVAL:
280 elems->timeout_int = pos;
282 case WLAN_EID_HT_CAP:
283 if (elen < sizeof(struct ieee80211_ht_capabilities))
285 elems->ht_capabilities = pos;
287 case WLAN_EID_HT_OPERATION:
288 if (elen < sizeof(struct ieee80211_ht_operation))
290 elems->ht_operation = pos;
292 case WLAN_EID_MESH_CONFIG:
293 elems->mesh_config = pos;
294 elems->mesh_config_len = elen;
296 case WLAN_EID_MESH_ID:
297 elems->mesh_id = pos;
298 elems->mesh_id_len = elen;
300 case WLAN_EID_PEER_MGMT:
301 elems->peer_mgmt = pos;
302 elems->peer_mgmt_len = elen;
304 case WLAN_EID_VHT_CAP:
305 if (elen < sizeof(struct ieee80211_vht_capabilities))
307 elems->vht_capabilities = pos;
309 case WLAN_EID_VHT_OPERATION:
310 if (elen < sizeof(struct ieee80211_vht_operation))
312 elems->vht_operation = pos;
314 case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
317 elems->vht_opmode_notif = pos;
319 case WLAN_EID_LINK_ID:
322 elems->link_id = pos;
324 case WLAN_EID_INTERWORKING:
325 elems->interworking = pos;
326 elems->interworking_len = elen;
328 case WLAN_EID_QOS_MAP_SET:
331 elems->qos_map_set = pos;
332 elems->qos_map_set_len = elen;
334 case WLAN_EID_EXT_CAPAB:
335 elems->ext_capab = pos;
336 elems->ext_capab_len = elen;
338 case WLAN_EID_BSS_MAX_IDLE_PERIOD:
341 elems->bss_max_idle_period = pos;
343 case WLAN_EID_SSID_LIST:
344 elems->ssid_list = pos;
345 elems->ssid_list_len = elen;
349 elems->ampe_len = elen;
353 elems->mic_len = elen;
354 /* after mic everything is encrypted, so stop. */
357 case WLAN_EID_MULTI_BAND:
358 if (elems->mb_ies.nof_ies >= MAX_NOF_MB_IES_SUPPORTED) {
359 wpa_printf(MSG_MSGDUMP,
360 "IEEE 802.11 element parse ignored MB IE (id=%d elen=%d)",
365 elems->mb_ies.ies[elems->mb_ies.nof_ies].ie = pos;
366 elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen;
367 elems->mb_ies.nof_ies++;
373 wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
374 "ignored unknown element (id=%d elen=%d)",
386 return unknown ? ParseUnknown : ParseOK;
390 int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
401 while (end - pos >= 2) {
402 if (2 + pos[1] > end - pos)
412 struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
416 const u8 *end, *pos, *ie;
422 while (end - pos > 1) {
423 if (2 + pos[1] > end - pos)
425 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
426 WPA_GET_BE32(&pos[2]) == oui_type) {
434 return NULL; /* No specified vendor IE found */
436 buf = wpabuf_alloc(ies_len);
441 * There may be multiple vendor IEs in the message, so need to
442 * concatenate their data fields.
444 while (end - pos > 1) {
445 if (2 + pos[1] > end - pos)
447 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
448 WPA_GET_BE32(&pos[2]) == oui_type)
449 wpabuf_put_data(buf, pos + 6, pos[1] - 4);
457 const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
462 * PS-Poll frames are 16 bytes. All other frames are
463 * 24 bytes or longer.
468 fc = le_to_host16(hdr->frame_control);
469 type = WLAN_FC_GET_TYPE(fc);
470 stype = WLAN_FC_GET_STYPE(fc);
473 case WLAN_FC_TYPE_DATA:
476 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
477 case WLAN_FC_FROMDS | WLAN_FC_TODS:
485 case WLAN_FC_TYPE_CTRL:
486 if (stype != WLAN_FC_STYPE_PSPOLL)
489 case WLAN_FC_TYPE_MGMT:
497 int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
498 const char *name, const char *val)
502 struct hostapd_wmm_ac_params *ac;
504 /* skip 'wme_ac_' or 'wmm_ac_' prefix */
506 if (os_strncmp(pos, "be_", 3) == 0) {
509 } else if (os_strncmp(pos, "bk_", 3) == 0) {
512 } else if (os_strncmp(pos, "vi_", 3) == 0) {
515 } else if (os_strncmp(pos, "vo_", 3) == 0) {
519 wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
523 ac = &wmm_ac_params[num];
525 if (os_strcmp(pos, "aifs") == 0) {
527 if (v < 1 || v > 255) {
528 wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
532 } else if (os_strcmp(pos, "cwmin") == 0) {
534 if (v < 0 || v > 15) {
535 wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
539 } else if (os_strcmp(pos, "cwmax") == 0) {
541 if (v < 0 || v > 15) {
542 wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
546 } else if (os_strcmp(pos, "txop_limit") == 0) {
548 if (v < 0 || v > 0xffff) {
549 wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
553 } else if (os_strcmp(pos, "acm") == 0) {
555 if (v < 0 || v > 1) {
556 wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
559 ac->admission_control_mandatory = v;
561 wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
569 enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
573 return ieee80211_freq_to_channel_ext(freq, 0, VHT_CHANWIDTH_USE_HT,
579 * ieee80211_freq_to_channel_ext - Convert frequency into channel info
580 * for HT40 and VHT. DFS channels are not covered.
581 * @freq: Frequency (MHz) to convert
582 * @sec_channel: 0 = non-HT40, 1 = sec. channel above, -1 = sec. channel below
583 * @vht: VHT channel width (VHT_CHANWIDTH_*)
584 * @op_class: Buffer for returning operating class
585 * @channel: Buffer for returning channel number
586 * Returns: hw_mode on success, NUM_HOSTAPD_MODES on failure
588 enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
589 int sec_channel, int vht,
590 u8 *op_class, u8 *channel)
594 /* TODO: more operating classes */
596 if (sec_channel > 1 || sec_channel < -1)
597 return NUM_HOSTAPD_MODES;
599 if (freq >= 2412 && freq <= 2472) {
600 if ((freq - 2407) % 5)
601 return NUM_HOSTAPD_MODES;
604 return NUM_HOSTAPD_MODES;
606 /* 2.407 GHz, channels 1..13 */
607 if (sec_channel == 1)
609 else if (sec_channel == -1)
614 *channel = (freq - 2407) / 5;
616 return HOSTAPD_MODE_IEEE80211G;
620 if (sec_channel || vht)
621 return NUM_HOSTAPD_MODES;
623 *op_class = 82; /* channel 14 */
626 return HOSTAPD_MODE_IEEE80211B;
629 if (freq >= 4900 && freq < 5000) {
630 if ((freq - 4000) % 5)
631 return NUM_HOSTAPD_MODES;
632 *channel = (freq - 4000) / 5;
633 *op_class = 0; /* TODO */
634 return HOSTAPD_MODE_IEEE80211A;
638 case VHT_CHANWIDTH_80MHZ:
641 case VHT_CHANWIDTH_160MHZ:
644 case VHT_CHANWIDTH_80P80MHZ:
652 /* 5 GHz, channels 36..48 */
653 if (freq >= 5180 && freq <= 5240) {
654 if ((freq - 5000) % 5)
655 return NUM_HOSTAPD_MODES;
658 *op_class = vht_opclass;
659 else if (sec_channel == 1)
661 else if (sec_channel == -1)
666 *channel = (freq - 5000) / 5;
668 return HOSTAPD_MODE_IEEE80211A;
671 /* 5 GHz, channels 149..169 */
672 if (freq >= 5745 && freq <= 5845) {
673 if ((freq - 5000) % 5)
674 return NUM_HOSTAPD_MODES;
677 *op_class = vht_opclass;
678 else if (sec_channel == 1)
680 else if (sec_channel == -1)
682 else if (freq <= 5805)
687 *channel = (freq - 5000) / 5;
689 return HOSTAPD_MODE_IEEE80211A;
692 /* 5 GHz, channels 100..140 */
693 if (freq >= 5000 && freq <= 5700) {
694 if ((freq - 5000) % 5)
695 return NUM_HOSTAPD_MODES;
698 *op_class = vht_opclass;
699 else if (sec_channel == 1)
701 else if (sec_channel == -1)
706 *channel = (freq - 5000) / 5;
708 return HOSTAPD_MODE_IEEE80211A;
711 if (freq >= 5000 && freq < 5900) {
712 if ((freq - 5000) % 5)
713 return NUM_HOSTAPD_MODES;
714 *channel = (freq - 5000) / 5;
715 *op_class = 0; /* TODO */
716 return HOSTAPD_MODE_IEEE80211A;
719 /* 56.16 GHz, channel 1..4 */
720 if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
721 if (sec_channel || vht)
722 return NUM_HOSTAPD_MODES;
724 *channel = (freq - 56160) / 2160;
727 return HOSTAPD_MODE_IEEE80211AD;
730 return NUM_HOSTAPD_MODES;
734 static const char *const us_op_class_cc[] = {
738 static const char *const eu_op_class_cc[] = {
739 "AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE",
740 "DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT",
741 "LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT",
742 "RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL
745 static const char *const jp_op_class_cc[] = {
749 static const char *const cn_op_class_cc[] = {
754 static int country_match(const char *const cc[], const char *const country)
760 for (i = 0; cc[i]; i++) {
761 if (cc[i][0] == country[0] && cc[i][1] == country[1])
769 static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
772 case 12: /* channels 1..11 */
773 case 32: /* channels 1..7; 40 MHz */
774 case 33: /* channels 5..11; 40 MHz */
775 if (chan < 1 || chan > 11)
777 return 2407 + 5 * chan;
778 case 1: /* channels 36,40,44,48 */
779 case 2: /* channels 52,56,60,64; dfs */
780 case 22: /* channels 36,44; 40 MHz */
781 case 23: /* channels 52,60; 40 MHz */
782 case 27: /* channels 40,48; 40 MHz */
783 case 28: /* channels 56,64; 40 MHz */
784 if (chan < 36 || chan > 64)
786 return 5000 + 5 * chan;
787 case 4: /* channels 100-144 */
788 case 24: /* channels 100-140; 40 MHz */
789 if (chan < 100 || chan > 144)
791 return 5000 + 5 * chan;
792 case 3: /* channels 149,153,157,161 */
793 case 25: /* channels 149,157; 40 MHz */
794 case 26: /* channels 149,157; 40 MHz */
795 case 30: /* channels 153,161; 40 MHz */
796 case 31: /* channels 153,161; 40 MHz */
797 if (chan < 149 || chan > 161)
799 return 5000 + 5 * chan;
800 case 5: /* channels 149,153,157,161,165 */
801 if (chan < 149 || chan > 165)
803 return 5000 + 5 * chan;
804 case 34: /* 60 GHz band, channels 1..3 */
805 if (chan < 1 || chan > 3)
807 return 56160 + 2160 * chan;
813 static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
816 case 4: /* channels 1..13 */
817 case 11: /* channels 1..9; 40 MHz */
818 case 12: /* channels 5..13; 40 MHz */
819 if (chan < 1 || chan > 13)
821 return 2407 + 5 * chan;
822 case 1: /* channels 36,40,44,48 */
823 case 2: /* channels 52,56,60,64; dfs */
824 case 5: /* channels 36,44; 40 MHz */
825 case 6: /* channels 52,60; 40 MHz */
826 case 8: /* channels 40,48; 40 MHz */
827 case 9: /* channels 56,64; 40 MHz */
828 if (chan < 36 || chan > 64)
830 return 5000 + 5 * chan;
831 case 3: /* channels 100-140 */
832 case 7: /* channels 100-132; 40 MHz */
833 case 10: /* channels 104-136; 40 MHz */
834 case 16: /* channels 100-140 */
835 if (chan < 100 || chan > 140)
837 return 5000 + 5 * chan;
838 case 17: /* channels 149,153,157,161,165,169 */
839 if (chan < 149 || chan > 169)
841 return 5000 + 5 * chan;
842 case 18: /* 60 GHz band, channels 1..4 */
843 if (chan < 1 || chan > 4)
845 return 56160 + 2160 * chan;
851 static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
854 case 30: /* channels 1..13 */
855 case 56: /* channels 1..9; 40 MHz */
856 case 57: /* channels 5..13; 40 MHz */
857 if (chan < 1 || chan > 13)
859 return 2407 + 5 * chan;
860 case 31: /* channel 14 */
863 return 2414 + 5 * chan;
864 case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */
865 case 32: /* channels 52,56,60,64 */
866 case 33: /* channels 52,56,60,64 */
867 case 36: /* channels 36,44; 40 MHz */
868 case 37: /* channels 52,60; 40 MHz */
869 case 38: /* channels 52,60; 40 MHz */
870 case 41: /* channels 40,48; 40 MHz */
871 case 42: /* channels 56,64; 40 MHz */
872 case 43: /* channels 56,64; 40 MHz */
873 if (chan < 34 || chan > 64)
875 return 5000 + 5 * chan;
876 case 34: /* channels 100-140 */
877 case 35: /* channels 100-140 */
878 case 39: /* channels 100-132; 40 MHz */
879 case 40: /* channels 100-132; 40 MHz */
880 case 44: /* channels 104-136; 40 MHz */
881 case 45: /* channels 104-136; 40 MHz */
882 case 58: /* channels 100-140 */
883 if (chan < 100 || chan > 140)
885 return 5000 + 5 * chan;
886 case 59: /* 60 GHz band, channels 1..4 */
887 if (chan < 1 || chan > 3)
889 return 56160 + 2160 * chan;
895 static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
898 case 7: /* channels 1..13 */
899 case 8: /* channels 1..9; 40 MHz */
900 case 9: /* channels 5..13; 40 MHz */
901 if (chan < 1 || chan > 13)
903 return 2407 + 5 * chan;
904 case 1: /* channels 36,40,44,48 */
905 case 2: /* channels 52,56,60,64; dfs */
906 case 4: /* channels 36,44; 40 MHz */
907 case 5: /* channels 52,60; 40 MHz */
908 if (chan < 36 || chan > 64)
910 return 5000 + 5 * chan;
911 case 3: /* channels 149,153,157,161,165 */
912 case 6: /* channels 149,157; 40 MHz */
913 if (chan < 149 || chan > 165)
915 return 5000 + 5 * chan;
921 static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
923 /* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
927 if (chan < 1 || chan > 13)
929 return 2407 + 5 * chan;
934 return 2414 + 5 * chan;
935 case 83: /* channels 1..9; 40 MHz */
936 case 84: /* channels 5..13; 40 MHz */
937 if (chan < 1 || chan > 13)
939 return 2407 + 5 * chan;
940 case 115: /* channels 36,40,44,48; indoor only */
941 case 116: /* channels 36,44; 40 MHz; indoor only */
942 case 117: /* channels 40,48; 40 MHz; indoor only */
943 case 118: /* channels 52,56,60,64; dfs */
944 case 119: /* channels 52,60; 40 MHz; dfs */
945 case 120: /* channels 56,64; 40 MHz; dfs */
946 if (chan < 36 || chan > 64)
948 return 5000 + 5 * chan;
949 case 121: /* channels 100-140 */
950 case 122: /* channels 100-142; 40 MHz */
951 case 123: /* channels 104-136; 40 MHz */
952 if (chan < 100 || chan > 140)
954 return 5000 + 5 * chan;
955 case 124: /* channels 149,153,157,161 */
956 case 126: /* channels 149,157; 40 MHz */
957 case 127: /* channels 153,161; 40 MHz */
958 if (chan < 149 || chan > 161)
960 return 5000 + 5 * chan;
961 case 125: /* channels 149,153,157,161,165,169 */
962 if (chan < 149 || chan > 169)
964 return 5000 + 5 * chan;
965 case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
966 case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
967 if (chan < 36 || chan > 161)
969 return 5000 + 5 * chan;
970 case 129: /* center freqs 50, 114; 160 MHz */
971 if (chan < 50 || chan > 114)
973 return 5000 + 5 * chan;
974 case 180: /* 60 GHz band, channels 1..4 */
975 if (chan < 1 || chan > 4)
977 return 56160 + 2160 * chan;
983 * ieee80211_chan_to_freq - Convert channel info to frequency
984 * @country: Country code, if known; otherwise, global operating class is used
985 * @op_class: Operating class
986 * @chan: Channel number
987 * Returns: Frequency in MHz or -1 if the specified channel is unknown
989 int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
993 if (country_match(us_op_class_cc, country)) {
994 freq = ieee80211_chan_to_freq_us(op_class, chan);
999 if (country_match(eu_op_class_cc, country)) {
1000 freq = ieee80211_chan_to_freq_eu(op_class, chan);
1005 if (country_match(jp_op_class_cc, country)) {
1006 freq = ieee80211_chan_to_freq_jp(op_class, chan);
1011 if (country_match(cn_op_class_cc, country)) {
1012 freq = ieee80211_chan_to_freq_cn(op_class, chan);
1017 return ieee80211_chan_to_freq_global(op_class, chan);
1021 int ieee80211_is_dfs(int freq)
1023 /* TODO: this could be more accurate to better cover all domains */
1024 return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700);
1028 static int is_11b(u8 rate)
1030 return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
1034 int supp_rates_11b_only(struct ieee802_11_elems *elems)
1036 int num_11b = 0, num_others = 0;
1039 if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
1042 for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
1043 if (is_11b(elems->supp_rates[i]))
1049 for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
1051 if (is_11b(elems->ext_supp_rates[i]))
1057 return num_11b > 0 && num_others == 0;
1061 const char * fc2str(u16 fc)
1063 u16 stype = WLAN_FC_GET_STYPE(fc);
1064 #define C2S(x) case x: return #x;
1066 switch (WLAN_FC_GET_TYPE(fc)) {
1067 case WLAN_FC_TYPE_MGMT:
1069 C2S(WLAN_FC_STYPE_ASSOC_REQ)
1070 C2S(WLAN_FC_STYPE_ASSOC_RESP)
1071 C2S(WLAN_FC_STYPE_REASSOC_REQ)
1072 C2S(WLAN_FC_STYPE_REASSOC_RESP)
1073 C2S(WLAN_FC_STYPE_PROBE_REQ)
1074 C2S(WLAN_FC_STYPE_PROBE_RESP)
1075 C2S(WLAN_FC_STYPE_BEACON)
1076 C2S(WLAN_FC_STYPE_ATIM)
1077 C2S(WLAN_FC_STYPE_DISASSOC)
1078 C2S(WLAN_FC_STYPE_AUTH)
1079 C2S(WLAN_FC_STYPE_DEAUTH)
1080 C2S(WLAN_FC_STYPE_ACTION)
1083 case WLAN_FC_TYPE_CTRL:
1085 C2S(WLAN_FC_STYPE_PSPOLL)
1086 C2S(WLAN_FC_STYPE_RTS)
1087 C2S(WLAN_FC_STYPE_CTS)
1088 C2S(WLAN_FC_STYPE_ACK)
1089 C2S(WLAN_FC_STYPE_CFEND)
1090 C2S(WLAN_FC_STYPE_CFENDACK)
1093 case WLAN_FC_TYPE_DATA:
1095 C2S(WLAN_FC_STYPE_DATA)
1096 C2S(WLAN_FC_STYPE_DATA_CFACK)
1097 C2S(WLAN_FC_STYPE_DATA_CFPOLL)
1098 C2S(WLAN_FC_STYPE_DATA_CFACKPOLL)
1099 C2S(WLAN_FC_STYPE_NULLFUNC)
1100 C2S(WLAN_FC_STYPE_CFACK)
1101 C2S(WLAN_FC_STYPE_CFPOLL)
1102 C2S(WLAN_FC_STYPE_CFACKPOLL)
1103 C2S(WLAN_FC_STYPE_QOS_DATA)
1104 C2S(WLAN_FC_STYPE_QOS_DATA_CFACK)
1105 C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL)
1106 C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL)
1107 C2S(WLAN_FC_STYPE_QOS_NULL)
1108 C2S(WLAN_FC_STYPE_QOS_CFPOLL)
1109 C2S(WLAN_FC_STYPE_QOS_CFACKPOLL)
1113 return "WLAN_FC_TYPE_UNKNOWN";
1118 int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
1121 os_memset(info, 0, sizeof(*info));
1123 while (ies_buf && ies_len >= 2 &&
1124 info->nof_ies < MAX_NOF_MB_IES_SUPPORTED) {
1125 size_t len = 2 + ies_buf[1];
1127 if (len > ies_len) {
1128 wpa_hexdump(MSG_DEBUG, "Truncated IEs",
1133 if (ies_buf[0] == WLAN_EID_MULTI_BAND) {
1134 wpa_printf(MSG_DEBUG, "MB IE of %zu bytes found", len);
1135 info->ies[info->nof_ies].ie = ies_buf + 2;
1136 info->ies[info->nof_ies].ie_len = ies_buf[1];
1148 struct wpabuf * mb_ies_by_info(struct mb_ies_info *info)
1150 struct wpabuf *mb_ies = NULL;
1152 WPA_ASSERT(info != NULL);
1154 if (info->nof_ies) {
1156 size_t mb_ies_size = 0;
1158 for (i = 0; i < info->nof_ies; i++)
1159 mb_ies_size += 2 + info->ies[i].ie_len;
1161 mb_ies = wpabuf_alloc(mb_ies_size);
1163 for (i = 0; i < info->nof_ies; i++) {
1164 wpabuf_put_u8(mb_ies, WLAN_EID_MULTI_BAND);
1165 wpabuf_put_u8(mb_ies, info->ies[i].ie_len);
1166 wpabuf_put_data(mb_ies,
1168 info->ies[i].ie_len);
1178 * get_ie - Fetch a specified information element from IEs buffer
1179 * @ies: Information elements buffer
1180 * @len: Information elements buffer length
1181 * @eid: Information element identifier (WLAN_EID_*)
1182 * Returns: Pointer to the information element (id field) or %NULL if not found
1184 * This function returns the first matching information element in the IEs
1185 * buffer or %NULL in case the element is not found.
1187 const u8 * get_ie(const u8 *ies, size_t len, u8 eid)
1196 while (end - ies > 1) {
1197 if (2 + ies[1] > end - ies)
1210 size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len)
1213 * MBO IE requires 6 bytes without the attributes: EID (1), length (1),
1214 * OUI (3), OUI type (1).
1216 if (len < 6 + attr_len) {
1217 wpa_printf(MSG_DEBUG,
1218 "MBO: Not enough room in buffer for MBO IE: buf len = %zu, attr_len = %zu",
1223 *buf++ = WLAN_EID_VENDOR_SPECIFIC;
1224 *buf++ = attr_len + 4;
1225 WPA_PUT_BE24(buf, OUI_WFA);
1227 *buf++ = MBO_OUI_TYPE;
1228 os_memcpy(buf, attr, attr_len);
1230 return 6 + attr_len;