7843e6fea3fb253a5606bb834f137e879c1529c0
[mech_eap.git] / src / common / ieee802_11_common.c
1 /*
2  * IEEE 802.11 Common routines
3  * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "defs.h"
13 #include "wpa_common.h"
14 #include "ieee802_11_defs.h"
15 #include "ieee802_11_common.h"
16
17
18 static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
19                                             struct ieee802_11_elems *elems,
20                                             int show_errors)
21 {
22         unsigned int oui;
23
24         /* first 3 bytes in vendor specific information element are the IEEE
25          * OUI of the vendor. The following byte is used a vendor specific
26          * sub-type. */
27         if (elen < 4) {
28                 if (show_errors) {
29                         wpa_printf(MSG_MSGDUMP, "short vendor specific "
30                                    "information element ignored (len=%lu)",
31                                    (unsigned long) elen);
32                 }
33                 return -1;
34         }
35
36         oui = WPA_GET_BE24(pos);
37         switch (oui) {
38         case OUI_MICROSOFT:
39                 /* Microsoft/Wi-Fi information elements are further typed and
40                  * subtyped */
41                 switch (pos[3]) {
42                 case 1:
43                         /* Microsoft OUI (00:50:F2) with OUI Type 1:
44                          * real WPA information element */
45                         elems->wpa_ie = pos;
46                         elems->wpa_ie_len = elen;
47                         break;
48                 case WMM_OUI_TYPE:
49                         /* WMM information element */
50                         if (elen < 5) {
51                                 wpa_printf(MSG_MSGDUMP, "short WMM "
52                                            "information element ignored "
53                                            "(len=%lu)",
54                                            (unsigned long) elen);
55                                 return -1;
56                         }
57                         switch (pos[4]) {
58                         case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
59                         case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
60                                 /*
61                                  * Share same pointer since only one of these
62                                  * is used and they start with same data.
63                                  * Length field can be used to distinguish the
64                                  * IEs.
65                                  */
66                                 elems->wmm = pos;
67                                 elems->wmm_len = elen;
68                                 break;
69                         case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
70                                 elems->wmm_tspec = pos;
71                                 elems->wmm_tspec_len = elen;
72                                 break;
73                         default:
74                                 wpa_printf(MSG_EXCESSIVE, "unknown WMM "
75                                            "information element ignored "
76                                            "(subtype=%d len=%lu)",
77                                            pos[4], (unsigned long) elen);
78                                 return -1;
79                         }
80                         break;
81                 case 4:
82                         /* Wi-Fi Protected Setup (WPS) IE */
83                         elems->wps_ie = pos;
84                         elems->wps_ie_len = elen;
85                         break;
86                 default:
87                         wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
88                                    "information element ignored "
89                                    "(type=%d len=%lu)",
90                                    pos[3], (unsigned long) elen);
91                         return -1;
92                 }
93                 break;
94
95         case OUI_WFA:
96                 switch (pos[3]) {
97                 case P2P_OUI_TYPE:
98                         /* Wi-Fi Alliance - P2P IE */
99                         elems->p2p = pos;
100                         elems->p2p_len = elen;
101                         break;
102                 case WFD_OUI_TYPE:
103                         /* Wi-Fi Alliance - WFD IE */
104                         elems->wfd = pos;
105                         elems->wfd_len = elen;
106                         break;
107                 case HS20_INDICATION_OUI_TYPE:
108                         /* Hotspot 2.0 */
109                         elems->hs20 = pos;
110                         elems->hs20_len = elen;
111                         break;
112                 case HS20_OSEN_OUI_TYPE:
113                         /* Hotspot 2.0 OSEN */
114                         elems->osen = pos;
115                         elems->osen_len = elen;
116                         break;
117                 default:
118                         wpa_printf(MSG_MSGDUMP, "Unknown WFA "
119                                    "information element ignored "
120                                    "(type=%d len=%lu)",
121                                    pos[3], (unsigned long) elen);
122                         return -1;
123                 }
124                 break;
125
126         case OUI_BROADCOM:
127                 switch (pos[3]) {
128                 case VENDOR_HT_CAPAB_OUI_TYPE:
129                         elems->vendor_ht_cap = pos;
130                         elems->vendor_ht_cap_len = elen;
131                         break;
132                 case VENDOR_VHT_TYPE:
133                         if (elen > 4 &&
134                             (pos[4] == VENDOR_VHT_SUBTYPE ||
135                              pos[4] == VENDOR_VHT_SUBTYPE2)) {
136                                 elems->vendor_vht = pos;
137                                 elems->vendor_vht_len = elen;
138                         } else
139                                 return -1;
140                         break;
141                 default:
142                         wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
143                                    "information element ignored "
144                                    "(type=%d len=%lu)",
145                                    pos[3], (unsigned long) elen);
146                         return -1;
147                 }
148                 break;
149
150         default:
151                 wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
152                            "information element ignored (vendor OUI "
153                            "%02x:%02x:%02x len=%lu)",
154                            pos[0], pos[1], pos[2], (unsigned long) elen);
155                 return -1;
156         }
157
158         return 0;
159 }
160
161
162 /**
163  * ieee802_11_parse_elems - Parse information elements in management frames
164  * @start: Pointer to the start of IEs
165  * @len: Length of IE buffer in octets
166  * @elems: Data structure for parsed elements
167  * @show_errors: Whether to show parsing errors in debug log
168  * Returns: Parsing result
169  */
170 ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
171                                 struct ieee802_11_elems *elems,
172                                 int show_errors)
173 {
174         size_t left = len;
175         const u8 *pos = start;
176         int unknown = 0;
177
178         os_memset(elems, 0, sizeof(*elems));
179
180         while (left >= 2) {
181                 u8 id, elen;
182
183                 id = *pos++;
184                 elen = *pos++;
185                 left -= 2;
186
187                 if (elen > left) {
188                         if (show_errors) {
189                                 wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
190                                            "parse failed (id=%d elen=%d "
191                                            "left=%lu)",
192                                            id, elen, (unsigned long) left);
193                                 wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
194                         }
195                         return ParseFailed;
196                 }
197
198                 switch (id) {
199                 case WLAN_EID_SSID:
200                         if (elen > SSID_MAX_LEN) {
201                                 wpa_printf(MSG_DEBUG,
202                                            "Ignored too long SSID element (elen=%u)",
203                                            elen);
204                                 break;
205                         }
206                         elems->ssid = pos;
207                         elems->ssid_len = elen;
208                         break;
209                 case WLAN_EID_SUPP_RATES:
210                         elems->supp_rates = pos;
211                         elems->supp_rates_len = elen;
212                         break;
213                 case WLAN_EID_DS_PARAMS:
214                         if (elen < 1)
215                                 break;
216                         elems->ds_params = pos;
217                         break;
218                 case WLAN_EID_CF_PARAMS:
219                 case WLAN_EID_TIM:
220                         break;
221                 case WLAN_EID_CHALLENGE:
222                         elems->challenge = pos;
223                         elems->challenge_len = elen;
224                         break;
225                 case WLAN_EID_ERP_INFO:
226                         if (elen < 1)
227                                 break;
228                         elems->erp_info = pos;
229                         break;
230                 case WLAN_EID_EXT_SUPP_RATES:
231                         elems->ext_supp_rates = pos;
232                         elems->ext_supp_rates_len = elen;
233                         break;
234                 case WLAN_EID_VENDOR_SPECIFIC:
235                         if (ieee802_11_parse_vendor_specific(pos, elen,
236                                                              elems,
237                                                              show_errors))
238                                 unknown++;
239                         break;
240                 case WLAN_EID_RSN:
241                         elems->rsn_ie = pos;
242                         elems->rsn_ie_len = elen;
243                         break;
244                 case WLAN_EID_PWR_CAPABILITY:
245                         break;
246                 case WLAN_EID_SUPPORTED_CHANNELS:
247                         elems->supp_channels = pos;
248                         elems->supp_channels_len = elen;
249                         break;
250                 case WLAN_EID_MOBILITY_DOMAIN:
251                         if (elen < sizeof(struct rsn_mdie))
252                                 break;
253                         elems->mdie = pos;
254                         elems->mdie_len = elen;
255                         break;
256                 case WLAN_EID_FAST_BSS_TRANSITION:
257                         if (elen < sizeof(struct rsn_ftie))
258                                 break;
259                         elems->ftie = pos;
260                         elems->ftie_len = elen;
261                         break;
262                 case WLAN_EID_TIMEOUT_INTERVAL:
263                         if (elen != 5)
264                                 break;
265                         elems->timeout_int = pos;
266                         break;
267                 case WLAN_EID_HT_CAP:
268                         if (elen < sizeof(struct ieee80211_ht_capabilities))
269                                 break;
270                         elems->ht_capabilities = pos;
271                         break;
272                 case WLAN_EID_HT_OPERATION:
273                         if (elen < sizeof(struct ieee80211_ht_operation))
274                                 break;
275                         elems->ht_operation = pos;
276                         break;
277                 case WLAN_EID_MESH_CONFIG:
278                         elems->mesh_config = pos;
279                         elems->mesh_config_len = elen;
280                         break;
281                 case WLAN_EID_MESH_ID:
282                         elems->mesh_id = pos;
283                         elems->mesh_id_len = elen;
284                         break;
285                 case WLAN_EID_PEER_MGMT:
286                         elems->peer_mgmt = pos;
287                         elems->peer_mgmt_len = elen;
288                         break;
289                 case WLAN_EID_VHT_CAP:
290                         if (elen < sizeof(struct ieee80211_vht_capabilities))
291                                 break;
292                         elems->vht_capabilities = pos;
293                         break;
294                 case WLAN_EID_VHT_OPERATION:
295                         if (elen < sizeof(struct ieee80211_vht_operation))
296                                 break;
297                         elems->vht_operation = pos;
298                         break;
299                 case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
300                         if (elen != 1)
301                                 break;
302                         elems->vht_opmode_notif = pos;
303                         break;
304                 case WLAN_EID_LINK_ID:
305                         if (elen < 18)
306                                 break;
307                         elems->link_id = pos;
308                         break;
309                 case WLAN_EID_INTERWORKING:
310                         elems->interworking = pos;
311                         elems->interworking_len = elen;
312                         break;
313                 case WLAN_EID_QOS_MAP_SET:
314                         if (elen < 16)
315                                 break;
316                         elems->qos_map_set = pos;
317                         elems->qos_map_set_len = elen;
318                         break;
319                 case WLAN_EID_EXT_CAPAB:
320                         elems->ext_capab = pos;
321                         elems->ext_capab_len = elen;
322                         break;
323                 case WLAN_EID_BSS_MAX_IDLE_PERIOD:
324                         if (elen < 3)
325                                 break;
326                         elems->bss_max_idle_period = pos;
327                         break;
328                 case WLAN_EID_SSID_LIST:
329                         elems->ssid_list = pos;
330                         elems->ssid_list_len = elen;
331                         break;
332                 case WLAN_EID_AMPE:
333                         elems->ampe = pos;
334                         elems->ampe_len = elen;
335                         break;
336                 case WLAN_EID_MIC:
337                         elems->mic = pos;
338                         elems->mic_len = elen;
339                         /* after mic everything is encrypted, so stop. */
340                         left = elen;
341                         break;
342                 default:
343                         unknown++;
344                         if (!show_errors)
345                                 break;
346                         wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
347                                    "ignored unknown element (id=%d elen=%d)",
348                                    id, elen);
349                         break;
350                 }
351
352                 left -= elen;
353                 pos += elen;
354         }
355
356         if (left)
357                 return ParseFailed;
358
359         return unknown ? ParseUnknown : ParseOK;
360 }
361
362
363 int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
364 {
365         int count = 0;
366         const u8 *pos, *end;
367
368         if (ies == NULL)
369                 return 0;
370
371         pos = ies;
372         end = ies + ies_len;
373
374         while (pos + 2 <= end) {
375                 if (pos + 2 + pos[1] > end)
376                         break;
377                 count++;
378                 pos += 2 + pos[1];
379         }
380
381         return count;
382 }
383
384
385 struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
386                                             u32 oui_type)
387 {
388         struct wpabuf *buf;
389         const u8 *end, *pos, *ie;
390
391         pos = ies;
392         end = ies + ies_len;
393         ie = NULL;
394
395         while (pos + 1 < end) {
396                 if (pos + 2 + pos[1] > end)
397                         return NULL;
398                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
399                     WPA_GET_BE32(&pos[2]) == oui_type) {
400                         ie = pos;
401                         break;
402                 }
403                 pos += 2 + pos[1];
404         }
405
406         if (ie == NULL)
407                 return NULL; /* No specified vendor IE found */
408
409         buf = wpabuf_alloc(ies_len);
410         if (buf == NULL)
411                 return NULL;
412
413         /*
414          * There may be multiple vendor IEs in the message, so need to
415          * concatenate their data fields.
416          */
417         while (pos + 1 < end) {
418                 if (pos + 2 + pos[1] > end)
419                         break;
420                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
421                     WPA_GET_BE32(&pos[2]) == oui_type)
422                         wpabuf_put_data(buf, pos + 6, pos[1] - 4);
423                 pos += 2 + pos[1];
424         }
425
426         return buf;
427 }
428
429
430 const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
431 {
432         u16 fc, type, stype;
433
434         /*
435          * PS-Poll frames are 16 bytes. All other frames are
436          * 24 bytes or longer.
437          */
438         if (len < 16)
439                 return NULL;
440
441         fc = le_to_host16(hdr->frame_control);
442         type = WLAN_FC_GET_TYPE(fc);
443         stype = WLAN_FC_GET_STYPE(fc);
444
445         switch (type) {
446         case WLAN_FC_TYPE_DATA:
447                 if (len < 24)
448                         return NULL;
449                 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
450                 case WLAN_FC_FROMDS | WLAN_FC_TODS:
451                 case WLAN_FC_TODS:
452                         return hdr->addr1;
453                 case WLAN_FC_FROMDS:
454                         return hdr->addr2;
455                 default:
456                         return NULL;
457                 }
458         case WLAN_FC_TYPE_CTRL:
459                 if (stype != WLAN_FC_STYPE_PSPOLL)
460                         return NULL;
461                 return hdr->addr1;
462         case WLAN_FC_TYPE_MGMT:
463                 return hdr->addr3;
464         default:
465                 return NULL;
466         }
467 }
468
469
470 int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
471                           const char *name, const char *val)
472 {
473         int num, v;
474         const char *pos;
475         struct hostapd_wmm_ac_params *ac;
476
477         /* skip 'wme_ac_' or 'wmm_ac_' prefix */
478         pos = name + 7;
479         if (os_strncmp(pos, "be_", 3) == 0) {
480                 num = 0;
481                 pos += 3;
482         } else if (os_strncmp(pos, "bk_", 3) == 0) {
483                 num = 1;
484                 pos += 3;
485         } else if (os_strncmp(pos, "vi_", 3) == 0) {
486                 num = 2;
487                 pos += 3;
488         } else if (os_strncmp(pos, "vo_", 3) == 0) {
489                 num = 3;
490                 pos += 3;
491         } else {
492                 wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
493                 return -1;
494         }
495
496         ac = &wmm_ac_params[num];
497
498         if (os_strcmp(pos, "aifs") == 0) {
499                 v = atoi(val);
500                 if (v < 1 || v > 255) {
501                         wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
502                         return -1;
503                 }
504                 ac->aifs = v;
505         } else if (os_strcmp(pos, "cwmin") == 0) {
506                 v = atoi(val);
507                 if (v < 0 || v > 12) {
508                         wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
509                         return -1;
510                 }
511                 ac->cwmin = v;
512         } else if (os_strcmp(pos, "cwmax") == 0) {
513                 v = atoi(val);
514                 if (v < 0 || v > 12) {
515                         wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
516                         return -1;
517                 }
518                 ac->cwmax = v;
519         } else if (os_strcmp(pos, "txop_limit") == 0) {
520                 v = atoi(val);
521                 if (v < 0 || v > 0xffff) {
522                         wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
523                         return -1;
524                 }
525                 ac->txop_limit = v;
526         } else if (os_strcmp(pos, "acm") == 0) {
527                 v = atoi(val);
528                 if (v < 0 || v > 1) {
529                         wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
530                         return -1;
531                 }
532                 ac->admission_control_mandatory = v;
533         } else {
534                 wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
535                 return -1;
536         }
537
538         return 0;
539 }
540
541
542 enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
543 {
544         enum hostapd_hw_mode mode = NUM_HOSTAPD_MODES;
545
546         if (freq >= 2412 && freq <= 2472) {
547                 mode = HOSTAPD_MODE_IEEE80211G;
548                 *channel = (freq - 2407) / 5;
549         } else if (freq == 2484) {
550                 mode = HOSTAPD_MODE_IEEE80211B;
551                 *channel = 14;
552         } else if (freq >= 4900 && freq < 5000) {
553                 mode = HOSTAPD_MODE_IEEE80211A;
554                 *channel = (freq - 4000) / 5;
555         } else if (freq >= 5000 && freq < 5900) {
556                 mode = HOSTAPD_MODE_IEEE80211A;
557                 *channel = (freq - 5000) / 5;
558         } else if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
559                 mode = HOSTAPD_MODE_IEEE80211AD;
560                 *channel = (freq - 56160) / 2160;
561         }
562
563         return mode;
564 }
565
566
567 static const char *us_op_class_cc[] = {
568         "US", "CA", NULL
569 };
570
571 static const char *eu_op_class_cc[] = {
572         "AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE",
573         "DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT",
574         "LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT",
575         "RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL
576 };
577
578 static const char *jp_op_class_cc[] = {
579         "JP", NULL
580 };
581
582 static const char *cn_op_class_cc[] = {
583         "CN", "CA", NULL
584 };
585
586
587 static int country_match(const char *cc[], const char *country)
588 {
589         int i;
590
591         if (country == NULL)
592                 return 0;
593         for (i = 0; cc[i]; i++) {
594                 if (cc[i][0] == country[0] && cc[i][1] == country[1])
595                         return 1;
596         }
597
598         return 0;
599 }
600
601
602 static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
603 {
604         switch (op_class) {
605         case 12: /* channels 1..11 */
606         case 32: /* channels 1..7; 40 MHz */
607         case 33: /* channels 5..11; 40 MHz */
608                 if (chan < 1 || chan > 11)
609                         return -1;
610                 return 2407 + 5 * chan;
611         case 1: /* channels 36,40,44,48 */
612         case 2: /* channels 52,56,60,64; dfs */
613         case 22: /* channels 36,44; 40 MHz */
614         case 23: /* channels 52,60; 40 MHz */
615         case 27: /* channels 40,48; 40 MHz */
616         case 28: /* channels 56,64; 40 MHz */
617                 if (chan < 36 || chan > 64)
618                         return -1;
619                 return 5000 + 5 * chan;
620         case 4: /* channels 100-144 */
621         case 24: /* channels 100-140; 40 MHz */
622                 if (chan < 100 || chan > 144)
623                         return -1;
624                 return 5000 + 5 * chan;
625         case 3: /* channels 149,153,157,161 */
626         case 25: /* channels 149,157; 40 MHz */
627         case 26: /* channels 149,157; 40 MHz */
628         case 30: /* channels 153,161; 40 MHz */
629         case 31: /* channels 153,161; 40 MHz */
630                 if (chan < 149 || chan > 161)
631                         return -1;
632                 return 5000 + 5 * chan;
633         case 34: /* 60 GHz band, channels 1..3 */
634                 if (chan < 1 || chan > 3)
635                         return -1;
636                 return 56160 + 2160 * chan;
637         }
638         return -1;
639 }
640
641
642 static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
643 {
644         switch (op_class) {
645         case 4: /* channels 1..13 */
646         case 11: /* channels 1..9; 40 MHz */
647         case 12: /* channels 5..13; 40 MHz */
648                 if (chan < 1 || chan > 13)
649                         return -1;
650                 return 2407 + 5 * chan;
651         case 1: /* channels 36,40,44,48 */
652         case 2: /* channels 52,56,60,64; dfs */
653         case 5: /* channels 36,44; 40 MHz */
654         case 6: /* channels 52,60; 40 MHz */
655         case 8: /* channels 40,48; 40 MHz */
656         case 9: /* channels 56,64; 40 MHz */
657                 if (chan < 36 || chan > 64)
658                         return -1;
659                 return 5000 + 5 * chan;
660         case 3: /* channels 100-140 */
661         case 7: /* channels 100-132; 40 MHz */
662         case 10: /* channels 104-136; 40 MHz */
663         case 16: /* channels 100-140 */
664                 if (chan < 100 || chan > 140)
665                         return -1;
666                 return 5000 + 5 * chan;
667         case 17: /* channels 149,153,157,161,165,169 */
668                 if (chan < 149 || chan > 169)
669                         return -1;
670                 return 5000 + 5 * chan;
671         case 18: /* 60 GHz band, channels 1..4 */
672                 if (chan < 1 || chan > 4)
673                         return -1;
674                 return 56160 + 2160 * chan;
675         }
676         return -1;
677 }
678
679
680 static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
681 {
682         switch (op_class) {
683         case 30: /* channels 1..13 */
684         case 56: /* channels 1..9; 40 MHz */
685         case 57: /* channels 5..13; 40 MHz */
686                 if (chan < 1 || chan > 13)
687                         return -1;
688                 return 2407 + 5 * chan;
689         case 31: /* channel 14 */
690                 if (chan != 14)
691                         return -1;
692                 return 2414 + 5 * chan;
693         case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */
694         case 32: /* channels 52,56,60,64 */
695         case 33: /* channels 52,56,60,64 */
696         case 36: /* channels 36,44; 40 MHz */
697         case 37: /* channels 52,60; 40 MHz */
698         case 38: /* channels 52,60; 40 MHz */
699         case 41: /* channels 40,48; 40 MHz */
700         case 42: /* channels 56,64; 40 MHz */
701         case 43: /* channels 56,64; 40 MHz */
702                 if (chan < 34 || chan > 64)
703                         return -1;
704                 return 5000 + 5 * chan;
705         case 34: /* channels 100-140 */
706         case 35: /* channels 100-140 */
707         case 39: /* channels 100-132; 40 MHz */
708         case 40: /* channels 100-132; 40 MHz */
709         case 44: /* channels 104-136; 40 MHz */
710         case 45: /* channels 104-136; 40 MHz */
711         case 58: /* channels 100-140 */
712                 if (chan < 100 || chan > 140)
713                         return -1;
714                 return 5000 + 5 * chan;
715         case 59: /* 60 GHz band, channels 1..4 */
716                 if (chan < 1 || chan > 3)
717                         return -1;
718                 return 56160 + 2160 * chan;
719         }
720         return -1;
721 }
722
723
724 static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
725 {
726         switch (op_class) {
727         case 7: /* channels 1..13 */
728         case 8: /* channels 1..9; 40 MHz */
729         case 9: /* channels 5..13; 40 MHz */
730                 if (chan < 1 || chan > 13)
731                         return -1;
732                 return 2407 + 5 * chan;
733         case 1: /* channels 36,40,44,48 */
734         case 2: /* channels 52,56,60,64; dfs */
735         case 4: /* channels 36,44; 40 MHz */
736         case 5: /* channels 52,60; 40 MHz */
737                 if (chan < 36 || chan > 64)
738                         return -1;
739                 return 5000 + 5 * chan;
740         case 3: /* channels 149,153,157,161,165 */
741         case 6: /* channels 149,157; 40 MHz */
742                 if (chan < 149 || chan > 165)
743                         return -1;
744                 return 5000 + 5 * chan;
745         }
746         return -1;
747 }
748
749
750 static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
751 {
752         /* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
753         switch (op_class) {
754         case 81:
755                 /* channels 1..13 */
756                 if (chan < 1 || chan > 13)
757                         return -1;
758                 return 2407 + 5 * chan;
759         case 82:
760                 /* channel 14 */
761                 if (chan != 14)
762                         return -1;
763                 return 2414 + 5 * chan;
764         case 83: /* channels 1..9; 40 MHz */
765         case 84: /* channels 5..13; 40 MHz */
766                 if (chan < 1 || chan > 13)
767                         return -1;
768                 return 2407 + 5 * chan;
769         case 115: /* channels 36,40,44,48; indoor only */
770         case 116: /* channels 36,44; 40 MHz; indoor only */
771         case 117: /* channels 40,48; 40 MHz; indoor only */
772         case 118: /* channels 52,56,60,64; dfs */
773         case 119: /* channels 52,60; 40 MHz; dfs */
774         case 120: /* channels 56,64; 40 MHz; dfs */
775                 if (chan < 36 || chan > 64)
776                         return -1;
777                 return 5000 + 5 * chan;
778         case 121: /* channels 100-140 */
779         case 122: /* channels 100-142; 40 MHz */
780         case 123: /* channels 104-136; 40 MHz */
781                 if (chan < 100 || chan > 140)
782                         return -1;
783                 return 5000 + 5 * chan;
784         case 124: /* channels 149,153,157,161 */
785         case 125: /* channels 149,153,157,161,165,169 */
786         case 126: /* channels 149,157; 40 MHz */
787         case 127: /* channels 153,161; 40 MHz */
788                 if (chan < 149 || chan > 161)
789                         return -1;
790                 return 5000 + 5 * chan;
791         case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
792         case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
793                 if (chan < 36 || chan > 161)
794                         return -1;
795                 return 5000 + 5 * chan;
796         case 129: /* center freqs 50, 114; 160 MHz */
797                 if (chan < 50 || chan > 114)
798                         return -1;
799                 return 5000 + 5 * chan;
800         case 180: /* 60 GHz band, channels 1..4 */
801                 if (chan < 1 || chan > 4)
802                         return -1;
803                 return 56160 + 2160 * chan;
804         }
805         return -1;
806 }
807
808 /**
809  * ieee80211_chan_to_freq - Convert channel info to frequency
810  * @country: Country code, if known; otherwise, global operating class is used
811  * @op_class: Operating class
812  * @chan: Channel number
813  * Returns: Frequency in MHz or -1 if the specified channel is unknown
814  */
815 int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
816 {
817         int freq;
818
819         if (country_match(us_op_class_cc, country)) {
820                 freq = ieee80211_chan_to_freq_us(op_class, chan);
821                 if (freq > 0)
822                         return freq;
823         }
824
825         if (country_match(eu_op_class_cc, country)) {
826                 freq = ieee80211_chan_to_freq_eu(op_class, chan);
827                 if (freq > 0)
828                         return freq;
829         }
830
831         if (country_match(jp_op_class_cc, country)) {
832                 freq = ieee80211_chan_to_freq_jp(op_class, chan);
833                 if (freq > 0)
834                         return freq;
835         }
836
837         if (country_match(cn_op_class_cc, country)) {
838                 freq = ieee80211_chan_to_freq_cn(op_class, chan);
839                 if (freq > 0)
840                         return freq;
841         }
842
843         return ieee80211_chan_to_freq_global(op_class, chan);
844 }
845
846
847 int ieee80211_is_dfs(int freq)
848 {
849         /* TODO: this could be more accurate to better cover all domains */
850         return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700);
851 }
852
853
854 static int is_11b(u8 rate)
855 {
856         return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
857 }
858
859
860 int supp_rates_11b_only(struct ieee802_11_elems *elems)
861 {
862         int num_11b = 0, num_others = 0;
863         int i;
864
865         if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
866                 return 0;
867
868         for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
869                 if (is_11b(elems->supp_rates[i]))
870                         num_11b++;
871                 else
872                         num_others++;
873         }
874
875         for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
876              i++) {
877                 if (is_11b(elems->ext_supp_rates[i]))
878                         num_11b++;
879                 else
880                         num_others++;
881         }
882
883         return num_11b > 0 && num_others == 0;
884 }
885
886
887 const char * fc2str(u16 fc)
888 {
889         u16 stype = WLAN_FC_GET_STYPE(fc);
890 #define C2S(x) case x: return #x;
891
892         switch (WLAN_FC_GET_TYPE(fc)) {
893         case WLAN_FC_TYPE_MGMT:
894                 switch (stype) {
895                 C2S(WLAN_FC_STYPE_ASSOC_REQ)
896                 C2S(WLAN_FC_STYPE_ASSOC_RESP)
897                 C2S(WLAN_FC_STYPE_REASSOC_REQ)
898                 C2S(WLAN_FC_STYPE_REASSOC_RESP)
899                 C2S(WLAN_FC_STYPE_PROBE_REQ)
900                 C2S(WLAN_FC_STYPE_PROBE_RESP)
901                 C2S(WLAN_FC_STYPE_BEACON)
902                 C2S(WLAN_FC_STYPE_ATIM)
903                 C2S(WLAN_FC_STYPE_DISASSOC)
904                 C2S(WLAN_FC_STYPE_AUTH)
905                 C2S(WLAN_FC_STYPE_DEAUTH)
906                 C2S(WLAN_FC_STYPE_ACTION)
907                 }
908                 break;
909         case WLAN_FC_TYPE_CTRL:
910                 switch (stype) {
911                 C2S(WLAN_FC_STYPE_PSPOLL)
912                 C2S(WLAN_FC_STYPE_RTS)
913                 C2S(WLAN_FC_STYPE_CTS)
914                 C2S(WLAN_FC_STYPE_ACK)
915                 C2S(WLAN_FC_STYPE_CFEND)
916                 C2S(WLAN_FC_STYPE_CFENDACK)
917                 }
918                 break;
919         case WLAN_FC_TYPE_DATA:
920                 switch (stype) {
921                 C2S(WLAN_FC_STYPE_DATA)
922                 C2S(WLAN_FC_STYPE_DATA_CFACK)
923                 C2S(WLAN_FC_STYPE_DATA_CFPOLL)
924                 C2S(WLAN_FC_STYPE_DATA_CFACKPOLL)
925                 C2S(WLAN_FC_STYPE_NULLFUNC)
926                 C2S(WLAN_FC_STYPE_CFACK)
927                 C2S(WLAN_FC_STYPE_CFPOLL)
928                 C2S(WLAN_FC_STYPE_CFACKPOLL)
929                 C2S(WLAN_FC_STYPE_QOS_DATA)
930                 C2S(WLAN_FC_STYPE_QOS_DATA_CFACK)
931                 C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL)
932                 C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL)
933                 C2S(WLAN_FC_STYPE_QOS_NULL)
934                 C2S(WLAN_FC_STYPE_QOS_CFPOLL)
935                 C2S(WLAN_FC_STYPE_QOS_CFACKPOLL)
936                 }
937                 break;
938         }
939         return "WLAN_FC_TYPE_UNKNOWN";
940 #undef C2S
941 }