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