]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/src/common/ieee802_11_common.c
Update llvm/clang to r241361.
[FreeBSD/FreeBSD.git] / contrib / wpa / src / common / ieee802_11_common.c
1 /*
2  * IEEE 802.11 Common routines
3  * Copyright (c) 2002-2013, 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 "ieee802_11_defs.h"
14 #include "ieee802_11_common.h"
15
16
17 static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
18                                             struct ieee802_11_elems *elems,
19                                             int show_errors)
20 {
21         unsigned int oui;
22
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
25          * sub-type. */
26         if (elen < 4) {
27                 if (show_errors) {
28                         wpa_printf(MSG_MSGDUMP, "short vendor specific "
29                                    "information element ignored (len=%lu)",
30                                    (unsigned long) elen);
31                 }
32                 return -1;
33         }
34
35         oui = WPA_GET_BE24(pos);
36         switch (oui) {
37         case OUI_MICROSOFT:
38                 /* Microsoft/Wi-Fi information elements are further typed and
39                  * subtyped */
40                 switch (pos[3]) {
41                 case 1:
42                         /* Microsoft OUI (00:50:F2) with OUI Type 1:
43                          * real WPA information element */
44                         elems->wpa_ie = pos;
45                         elems->wpa_ie_len = elen;
46                         break;
47                 case WMM_OUI_TYPE:
48                         /* WMM information element */
49                         if (elen < 5) {
50                                 wpa_printf(MSG_MSGDUMP, "short WMM "
51                                            "information element ignored "
52                                            "(len=%lu)",
53                                            (unsigned long) elen);
54                                 return -1;
55                         }
56                         switch (pos[4]) {
57                         case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
58                         case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
59                                 /*
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
63                                  * IEs.
64                                  */
65                                 elems->wmm = pos;
66                                 elems->wmm_len = elen;
67                                 break;
68                         case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
69                                 elems->wmm_tspec = pos;
70                                 elems->wmm_tspec_len = elen;
71                                 break;
72                         default:
73                                 wpa_printf(MSG_EXCESSIVE, "unknown WMM "
74                                            "information element ignored "
75                                            "(subtype=%d len=%lu)",
76                                            pos[4], (unsigned long) elen);
77                                 return -1;
78                         }
79                         break;
80                 case 4:
81                         /* Wi-Fi Protected Setup (WPS) IE */
82                         elems->wps_ie = pos;
83                         elems->wps_ie_len = elen;
84                         break;
85                 default:
86                         wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
87                                    "information element ignored "
88                                    "(type=%d len=%lu)",
89                                    pos[3], (unsigned long) elen);
90                         return -1;
91                 }
92                 break;
93
94         case OUI_WFA:
95                 switch (pos[3]) {
96                 case P2P_OUI_TYPE:
97                         /* Wi-Fi Alliance - P2P IE */
98                         elems->p2p = pos;
99                         elems->p2p_len = elen;
100                         break;
101                 case WFD_OUI_TYPE:
102                         /* Wi-Fi Alliance - WFD IE */
103                         elems->wfd = pos;
104                         elems->wfd_len = elen;
105                         break;
106                 case HS20_INDICATION_OUI_TYPE:
107                         /* Hotspot 2.0 */
108                         elems->hs20 = pos;
109                         elems->hs20_len = elen;
110                         break;
111                 case HS20_OSEN_OUI_TYPE:
112                         /* Hotspot 2.0 OSEN */
113                         elems->osen = pos;
114                         elems->osen_len = elen;
115                         break;
116                 default:
117                         wpa_printf(MSG_MSGDUMP, "Unknown WFA "
118                                    "information element ignored "
119                                    "(type=%d len=%lu)",
120                                    pos[3], (unsigned long) elen);
121                         return -1;
122                 }
123                 break;
124
125         case OUI_BROADCOM:
126                 switch (pos[3]) {
127                 case VENDOR_HT_CAPAB_OUI_TYPE:
128                         elems->vendor_ht_cap = pos;
129                         elems->vendor_ht_cap_len = elen;
130                         break;
131                 case VENDOR_VHT_TYPE:
132                         if (elen > 4 &&
133                             (pos[4] == VENDOR_VHT_SUBTYPE ||
134                              pos[4] == VENDOR_VHT_SUBTYPE2)) {
135                                 elems->vendor_vht = pos;
136                                 elems->vendor_vht_len = elen;
137                         } else
138                                 return -1;
139                         break;
140                 default:
141                         wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
142                                    "information element ignored "
143                                    "(type=%d len=%lu)",
144                                    pos[3], (unsigned long) elen);
145                         return -1;
146                 }
147                 break;
148
149         default:
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);
154                 return -1;
155         }
156
157         return 0;
158 }
159
160
161 /**
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
168  */
169 ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
170                                 struct ieee802_11_elems *elems,
171                                 int show_errors)
172 {
173         size_t left = len;
174         const u8 *pos = start;
175         int unknown = 0;
176
177         os_memset(elems, 0, sizeof(*elems));
178
179         while (left >= 2) {
180                 u8 id, elen;
181
182                 id = *pos++;
183                 elen = *pos++;
184                 left -= 2;
185
186                 if (elen > left) {
187                         if (show_errors) {
188                                 wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
189                                            "parse failed (id=%d elen=%d "
190                                            "left=%lu)",
191                                            id, elen, (unsigned long) left);
192                                 wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
193                         }
194                         return ParseFailed;
195                 }
196
197                 switch (id) {
198                 case WLAN_EID_SSID:
199                         elems->ssid = pos;
200                         elems->ssid_len = elen;
201                         break;
202                 case WLAN_EID_SUPP_RATES:
203                         elems->supp_rates = pos;
204                         elems->supp_rates_len = elen;
205                         break;
206                 case WLAN_EID_DS_PARAMS:
207                         elems->ds_params = pos;
208                         elems->ds_params_len = elen;
209                         break;
210                 case WLAN_EID_CF_PARAMS:
211                 case WLAN_EID_TIM:
212                         break;
213                 case WLAN_EID_CHALLENGE:
214                         elems->challenge = pos;
215                         elems->challenge_len = elen;
216                         break;
217                 case WLAN_EID_ERP_INFO:
218                         elems->erp_info = pos;
219                         elems->erp_info_len = elen;
220                         break;
221                 case WLAN_EID_EXT_SUPP_RATES:
222                         elems->ext_supp_rates = pos;
223                         elems->ext_supp_rates_len = elen;
224                         break;
225                 case WLAN_EID_VENDOR_SPECIFIC:
226                         if (ieee802_11_parse_vendor_specific(pos, elen,
227                                                              elems,
228                                                              show_errors))
229                                 unknown++;
230                         break;
231                 case WLAN_EID_RSN:
232                         elems->rsn_ie = pos;
233                         elems->rsn_ie_len = elen;
234                         break;
235                 case WLAN_EID_PWR_CAPABILITY:
236                         break;
237                 case WLAN_EID_SUPPORTED_CHANNELS:
238                         elems->supp_channels = pos;
239                         elems->supp_channels_len = elen;
240                         break;
241                 case WLAN_EID_MOBILITY_DOMAIN:
242                         elems->mdie = pos;
243                         elems->mdie_len = elen;
244                         break;
245                 case WLAN_EID_FAST_BSS_TRANSITION:
246                         elems->ftie = pos;
247                         elems->ftie_len = elen;
248                         break;
249                 case WLAN_EID_TIMEOUT_INTERVAL:
250                         elems->timeout_int = pos;
251                         elems->timeout_int_len = elen;
252                         break;
253                 case WLAN_EID_HT_CAP:
254                         elems->ht_capabilities = pos;
255                         elems->ht_capabilities_len = elen;
256                         break;
257                 case WLAN_EID_HT_OPERATION:
258                         elems->ht_operation = pos;
259                         elems->ht_operation_len = elen;
260                         break;
261                 case WLAN_EID_MESH_CONFIG:
262                         elems->mesh_config = pos;
263                         elems->mesh_config_len = elen;
264                         break;
265                 case WLAN_EID_MESH_ID:
266                         elems->mesh_id = pos;
267                         elems->mesh_id_len = elen;
268                         break;
269                 case WLAN_EID_PEER_MGMT:
270                         elems->peer_mgmt = pos;
271                         elems->peer_mgmt_len = elen;
272                         break;
273                 case WLAN_EID_VHT_CAP:
274                         elems->vht_capabilities = pos;
275                         elems->vht_capabilities_len = elen;
276                         break;
277                 case WLAN_EID_VHT_OPERATION:
278                         elems->vht_operation = pos;
279                         elems->vht_operation_len = elen;
280                         break;
281                 case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
282                         if (elen != 1)
283                                 break;
284                         elems->vht_opmode_notif = pos;
285                         break;
286                 case WLAN_EID_LINK_ID:
287                         if (elen < 18)
288                                 break;
289                         elems->link_id = pos;
290                         break;
291                 case WLAN_EID_INTERWORKING:
292                         elems->interworking = pos;
293                         elems->interworking_len = elen;
294                         break;
295                 case WLAN_EID_QOS_MAP_SET:
296                         if (elen < 16)
297                                 break;
298                         elems->qos_map_set = pos;
299                         elems->qos_map_set_len = elen;
300                         break;
301                 case WLAN_EID_EXT_CAPAB:
302                         elems->ext_capab = pos;
303                         elems->ext_capab_len = elen;
304                         break;
305                 case WLAN_EID_BSS_MAX_IDLE_PERIOD:
306                         if (elen < 3)
307                                 break;
308                         elems->bss_max_idle_period = pos;
309                         break;
310                 case WLAN_EID_SSID_LIST:
311                         elems->ssid_list = pos;
312                         elems->ssid_list_len = elen;
313                         break;
314                 case WLAN_EID_AMPE:
315                         elems->ampe = pos;
316                         elems->ampe_len = elen;
317                         break;
318                 case WLAN_EID_MIC:
319                         elems->mic = pos;
320                         elems->mic_len = elen;
321                         /* after mic everything is encrypted, so stop. */
322                         left = elen;
323                         break;
324                 default:
325                         unknown++;
326                         if (!show_errors)
327                                 break;
328                         wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
329                                    "ignored unknown element (id=%d elen=%d)",
330                                    id, elen);
331                         break;
332                 }
333
334                 left -= elen;
335                 pos += elen;
336         }
337
338         if (left)
339                 return ParseFailed;
340
341         return unknown ? ParseUnknown : ParseOK;
342 }
343
344
345 int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
346 {
347         int count = 0;
348         const u8 *pos, *end;
349
350         if (ies == NULL)
351                 return 0;
352
353         pos = ies;
354         end = ies + ies_len;
355
356         while (pos + 2 <= end) {
357                 if (pos + 2 + pos[1] > end)
358                         break;
359                 count++;
360                 pos += 2 + pos[1];
361         }
362
363         return count;
364 }
365
366
367 struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
368                                             u32 oui_type)
369 {
370         struct wpabuf *buf;
371         const u8 *end, *pos, *ie;
372
373         pos = ies;
374         end = ies + ies_len;
375         ie = NULL;
376
377         while (pos + 1 < end) {
378                 if (pos + 2 + pos[1] > end)
379                         return NULL;
380                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
381                     WPA_GET_BE32(&pos[2]) == oui_type) {
382                         ie = pos;
383                         break;
384                 }
385                 pos += 2 + pos[1];
386         }
387
388         if (ie == NULL)
389                 return NULL; /* No specified vendor IE found */
390
391         buf = wpabuf_alloc(ies_len);
392         if (buf == NULL)
393                 return NULL;
394
395         /*
396          * There may be multiple vendor IEs in the message, so need to
397          * concatenate their data fields.
398          */
399         while (pos + 1 < end) {
400                 if (pos + 2 + pos[1] > end)
401                         break;
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);
405                 pos += 2 + pos[1];
406         }
407
408         return buf;
409 }
410
411
412 const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
413 {
414         u16 fc, type, stype;
415
416         /*
417          * PS-Poll frames are 16 bytes. All other frames are
418          * 24 bytes or longer.
419          */
420         if (len < 16)
421                 return NULL;
422
423         fc = le_to_host16(hdr->frame_control);
424         type = WLAN_FC_GET_TYPE(fc);
425         stype = WLAN_FC_GET_STYPE(fc);
426
427         switch (type) {
428         case WLAN_FC_TYPE_DATA:
429                 if (len < 24)
430                         return NULL;
431                 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
432                 case WLAN_FC_FROMDS | WLAN_FC_TODS:
433                 case WLAN_FC_TODS:
434                         return hdr->addr1;
435                 case WLAN_FC_FROMDS:
436                         return hdr->addr2;
437                 default:
438                         return NULL;
439                 }
440         case WLAN_FC_TYPE_CTRL:
441                 if (stype != WLAN_FC_STYPE_PSPOLL)
442                         return NULL;
443                 return hdr->addr1;
444         case WLAN_FC_TYPE_MGMT:
445                 return hdr->addr3;
446         default:
447                 return NULL;
448         }
449 }
450
451
452 int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
453                           const char *name, const char *val)
454 {
455         int num, v;
456         const char *pos;
457         struct hostapd_wmm_ac_params *ac;
458
459         /* skip 'wme_ac_' or 'wmm_ac_' prefix */
460         pos = name + 7;
461         if (os_strncmp(pos, "be_", 3) == 0) {
462                 num = 0;
463                 pos += 3;
464         } else if (os_strncmp(pos, "bk_", 3) == 0) {
465                 num = 1;
466                 pos += 3;
467         } else if (os_strncmp(pos, "vi_", 3) == 0) {
468                 num = 2;
469                 pos += 3;
470         } else if (os_strncmp(pos, "vo_", 3) == 0) {
471                 num = 3;
472                 pos += 3;
473         } else {
474                 wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
475                 return -1;
476         }
477
478         ac = &wmm_ac_params[num];
479
480         if (os_strcmp(pos, "aifs") == 0) {
481                 v = atoi(val);
482                 if (v < 1 || v > 255) {
483                         wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
484                         return -1;
485                 }
486                 ac->aifs = v;
487         } else if (os_strcmp(pos, "cwmin") == 0) {
488                 v = atoi(val);
489                 if (v < 0 || v > 12) {
490                         wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
491                         return -1;
492                 }
493                 ac->cwmin = v;
494         } else if (os_strcmp(pos, "cwmax") == 0) {
495                 v = atoi(val);
496                 if (v < 0 || v > 12) {
497                         wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
498                         return -1;
499                 }
500                 ac->cwmax = v;
501         } else if (os_strcmp(pos, "txop_limit") == 0) {
502                 v = atoi(val);
503                 if (v < 0 || v > 0xffff) {
504                         wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
505                         return -1;
506                 }
507                 ac->txop_limit = v;
508         } else if (os_strcmp(pos, "acm") == 0) {
509                 v = atoi(val);
510                 if (v < 0 || v > 1) {
511                         wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
512                         return -1;
513                 }
514                 ac->admission_control_mandatory = v;
515         } else {
516                 wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
517                 return -1;
518         }
519
520         return 0;
521 }
522
523
524 enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
525 {
526         enum hostapd_hw_mode mode = NUM_HOSTAPD_MODES;
527
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;
533                 *channel = 14;
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;
543         }
544
545         return mode;
546 }
547
548
549 static const char *us_op_class_cc[] = {
550         "US", "CA", NULL
551 };
552
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
558 };
559
560 static const char *jp_op_class_cc[] = {
561         "JP", NULL
562 };
563
564 static const char *cn_op_class_cc[] = {
565         "CN", "CA", NULL
566 };
567
568
569 static int country_match(const char *cc[], const char *country)
570 {
571         int i;
572
573         if (country == NULL)
574                 return 0;
575         for (i = 0; cc[i]; i++) {
576                 if (cc[i][0] == country[0] && cc[i][1] == country[1])
577                         return 1;
578         }
579
580         return 0;
581 }
582
583
584 static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
585 {
586         switch (op_class) {
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)
591                         return -1;
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)
600                         return -1;
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)
605                         return -1;
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)
613                         return -1;
614                 return 5000 + 5 * chan;
615         case 34: /* 60 GHz band, channels 1..3 */
616                 if (chan < 1 || chan > 3)
617                         return -1;
618                 return 56160 + 2160 * chan;
619         }
620         return -1;
621 }
622
623
624 static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
625 {
626         switch (op_class) {
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)
631                         return -1;
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)
640                         return -1;
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)
647                         return -1;
648                 return 5000 + 5 * chan;
649         case 17: /* channels 149,153,157,161,165,169 */
650                 if (chan < 149 || chan > 169)
651                         return -1;
652                 return 5000 + 5 * chan;
653         case 18: /* 60 GHz band, channels 1..4 */
654                 if (chan < 1 || chan > 4)
655                         return -1;
656                 return 56160 + 2160 * chan;
657         }
658         return -1;
659 }
660
661
662 static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
663 {
664         switch (op_class) {
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)
669                         return -1;
670                 return 2407 + 5 * chan;
671         case 31: /* channel 14 */
672                 if (chan != 14)
673                         return -1;
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)
685                         return -1;
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)
695                         return -1;
696                 return 5000 + 5 * chan;
697         case 59: /* 60 GHz band, channels 1..4 */
698                 if (chan < 1 || chan > 3)
699                         return -1;
700                 return 56160 + 2160 * chan;
701         }
702         return -1;
703 }
704
705
706 static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
707 {
708         switch (op_class) {
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)
713                         return -1;
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)
720                         return -1;
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)
725                         return -1;
726                 return 5000 + 5 * chan;
727         }
728         return -1;
729 }
730
731
732 static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
733 {
734         /* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
735         switch (op_class) {
736         case 81:
737                 /* channels 1..13 */
738                 if (chan < 1 || chan > 13)
739                         return -1;
740                 return 2407 + 5 * chan;
741         case 82:
742                 /* channel 14 */
743                 if (chan != 14)
744                         return -1;
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)
749                         return -1;
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)
758                         return -1;
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)
764                         return -1;
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)
771                         return -1;
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)
776                         return -1;
777                 return 5000 + 5 * chan;
778         case 129: /* center freqs 50, 114; 160 MHz */
779                 if (chan < 50 || chan > 114)
780                         return -1;
781                 return 5000 + 5 * chan;
782         case 180: /* 60 GHz band, channels 1..4 */
783                 if (chan < 1 || chan > 4)
784                         return -1;
785                 return 56160 + 2160 * chan;
786         }
787         return -1;
788 }
789
790 /**
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
796  */
797 int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
798 {
799         int freq;
800
801         if (country_match(us_op_class_cc, country)) {
802                 freq = ieee80211_chan_to_freq_us(op_class, chan);
803                 if (freq > 0)
804                         return freq;
805         }
806
807         if (country_match(eu_op_class_cc, country)) {
808                 freq = ieee80211_chan_to_freq_eu(op_class, chan);
809                 if (freq > 0)
810                         return freq;
811         }
812
813         if (country_match(jp_op_class_cc, country)) {
814                 freq = ieee80211_chan_to_freq_jp(op_class, chan);
815                 if (freq > 0)
816                         return freq;
817         }
818
819         if (country_match(cn_op_class_cc, country)) {
820                 freq = ieee80211_chan_to_freq_cn(op_class, chan);
821                 if (freq > 0)
822                         return freq;
823         }
824
825         return ieee80211_chan_to_freq_global(op_class, chan);
826 }
827
828
829 int ieee80211_is_dfs(int freq)
830 {
831         /* TODO: this could be more accurate to better cover all domains */
832         return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700);
833 }
834
835
836 static int is_11b(u8 rate)
837 {
838         return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
839 }
840
841
842 int supp_rates_11b_only(struct ieee802_11_elems *elems)
843 {
844         int num_11b = 0, num_others = 0;
845         int i;
846
847         if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
848                 return 0;
849
850         for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
851                 if (is_11b(elems->supp_rates[i]))
852                         num_11b++;
853                 else
854                         num_others++;
855         }
856
857         for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
858              i++) {
859                 if (is_11b(elems->ext_supp_rates[i]))
860                         num_11b++;
861                 else
862                         num_others++;
863         }
864
865         return num_11b > 0 && num_others == 0;
866 }
867
868
869 const char * fc2str(u16 fc)
870 {
871         u16 stype = WLAN_FC_GET_STYPE(fc);
872 #define C2S(x) case x: return #x;
873
874         switch (WLAN_FC_GET_TYPE(fc)) {
875         case WLAN_FC_TYPE_MGMT:
876                 switch (stype) {
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)
889                 }
890                 break;
891         case WLAN_FC_TYPE_CTRL:
892                 switch (stype) {
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)
899                 }
900                 break;
901         case WLAN_FC_TYPE_DATA:
902                 switch (stype) {
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)
918                 }
919                 break;
920         }
921         return "WLAN_FC_TYPE_UNKNOWN";
922 #undef C2S
923 }