]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/src/common/ieee802_11_common.c
Update to Zstandard 1.4.0
[FreeBSD/FreeBSD.git] / contrib / wpa / 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 "drivers/driver.h"
15 #include "qca-vendor.h"
16 #include "ieee802_11_defs.h"
17 #include "ieee802_11_common.h"
18
19
20 static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
21                                             struct ieee802_11_elems *elems,
22                                             int show_errors)
23 {
24         unsigned int oui;
25
26         /* first 3 bytes in vendor specific information element are the IEEE
27          * OUI of the vendor. The following byte is used a vendor specific
28          * sub-type. */
29         if (elen < 4) {
30                 if (show_errors) {
31                         wpa_printf(MSG_MSGDUMP, "short vendor specific "
32                                    "information element ignored (len=%lu)",
33                                    (unsigned long) elen);
34                 }
35                 return -1;
36         }
37
38         oui = WPA_GET_BE24(pos);
39         switch (oui) {
40         case OUI_MICROSOFT:
41                 /* Microsoft/Wi-Fi information elements are further typed and
42                  * subtyped */
43                 switch (pos[3]) {
44                 case 1:
45                         /* Microsoft OUI (00:50:F2) with OUI Type 1:
46                          * real WPA information element */
47                         elems->wpa_ie = pos;
48                         elems->wpa_ie_len = elen;
49                         break;
50                 case WMM_OUI_TYPE:
51                         /* WMM information element */
52                         if (elen < 5) {
53                                 wpa_printf(MSG_MSGDUMP, "short WMM "
54                                            "information element ignored "
55                                            "(len=%lu)",
56                                            (unsigned long) elen);
57                                 return -1;
58                         }
59                         switch (pos[4]) {
60                         case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
61                         case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
62                                 /*
63                                  * Share same pointer since only one of these
64                                  * is used and they start with same data.
65                                  * Length field can be used to distinguish the
66                                  * IEs.
67                                  */
68                                 elems->wmm = pos;
69                                 elems->wmm_len = elen;
70                                 break;
71                         case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
72                                 elems->wmm_tspec = pos;
73                                 elems->wmm_tspec_len = elen;
74                                 break;
75                         default:
76                                 wpa_printf(MSG_EXCESSIVE, "unknown WMM "
77                                            "information element ignored "
78                                            "(subtype=%d len=%lu)",
79                                            pos[4], (unsigned long) elen);
80                                 return -1;
81                         }
82                         break;
83                 case 4:
84                         /* Wi-Fi Protected Setup (WPS) IE */
85                         elems->wps_ie = pos;
86                         elems->wps_ie_len = elen;
87                         break;
88                 default:
89                         wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
90                                    "information element ignored "
91                                    "(type=%d len=%lu)",
92                                    pos[3], (unsigned long) elen);
93                         return -1;
94                 }
95                 break;
96
97         case OUI_WFA:
98                 switch (pos[3]) {
99                 case P2P_OUI_TYPE:
100                         /* Wi-Fi Alliance - P2P IE */
101                         elems->p2p = pos;
102                         elems->p2p_len = elen;
103                         break;
104                 case WFD_OUI_TYPE:
105                         /* Wi-Fi Alliance - WFD IE */
106                         elems->wfd = pos;
107                         elems->wfd_len = elen;
108                         break;
109                 case HS20_INDICATION_OUI_TYPE:
110                         /* Hotspot 2.0 */
111                         elems->hs20 = pos;
112                         elems->hs20_len = elen;
113                         break;
114                 case HS20_OSEN_OUI_TYPE:
115                         /* Hotspot 2.0 OSEN */
116                         elems->osen = pos;
117                         elems->osen_len = elen;
118                         break;
119                 case MBO_OUI_TYPE:
120                         /* MBO-OCE */
121                         elems->mbo = pos;
122                         elems->mbo_len = elen;
123                         break;
124                 case HS20_ROAMING_CONS_SEL_OUI_TYPE:
125                         /* Hotspot 2.0 Roaming Consortium Selection */
126                         elems->roaming_cons_sel = pos;
127                         elems->roaming_cons_sel_len = elen;
128                         break;
129                 default:
130                         wpa_printf(MSG_MSGDUMP, "Unknown WFA "
131                                    "information element ignored "
132                                    "(type=%d len=%lu)",
133                                    pos[3], (unsigned long) elen);
134                         return -1;
135                 }
136                 break;
137
138         case OUI_BROADCOM:
139                 switch (pos[3]) {
140                 case VENDOR_HT_CAPAB_OUI_TYPE:
141                         elems->vendor_ht_cap = pos;
142                         elems->vendor_ht_cap_len = elen;
143                         break;
144                 case VENDOR_VHT_TYPE:
145                         if (elen > 4 &&
146                             (pos[4] == VENDOR_VHT_SUBTYPE ||
147                              pos[4] == VENDOR_VHT_SUBTYPE2)) {
148                                 elems->vendor_vht = pos;
149                                 elems->vendor_vht_len = elen;
150                         } else
151                                 return -1;
152                         break;
153                 default:
154                         wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
155                                    "information element ignored "
156                                    "(type=%d len=%lu)",
157                                    pos[3], (unsigned long) elen);
158                         return -1;
159                 }
160                 break;
161
162         case OUI_QCA:
163                 switch (pos[3]) {
164                 case QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST:
165                         elems->pref_freq_list = pos;
166                         elems->pref_freq_list_len = elen;
167                         break;
168                 default:
169                         wpa_printf(MSG_EXCESSIVE,
170                                    "Unknown QCA information element ignored (type=%d len=%lu)",
171                                    pos[3], (unsigned long) elen);
172                         return -1;
173                 }
174                 break;
175
176         default:
177                 wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
178                            "information element ignored (vendor OUI "
179                            "%02x:%02x:%02x len=%lu)",
180                            pos[0], pos[1], pos[2], (unsigned long) elen);
181                 return -1;
182         }
183
184         return 0;
185 }
186
187
188 static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
189                                       struct ieee802_11_elems *elems,
190                                       int show_errors)
191 {
192         u8 ext_id;
193
194         if (elen < 1) {
195                 if (show_errors) {
196                         wpa_printf(MSG_MSGDUMP,
197                                    "short information element (Ext)");
198                 }
199                 return -1;
200         }
201
202         ext_id = *pos++;
203         elen--;
204
205         switch (ext_id) {
206         case WLAN_EID_EXT_ASSOC_DELAY_INFO:
207                 if (elen != 1)
208                         break;
209                 elems->assoc_delay_info = pos;
210                 break;
211         case WLAN_EID_EXT_FILS_REQ_PARAMS:
212                 if (elen < 3)
213                         break;
214                 elems->fils_req_params = pos;
215                 elems->fils_req_params_len = elen;
216                 break;
217         case WLAN_EID_EXT_FILS_KEY_CONFIRM:
218                 elems->fils_key_confirm = pos;
219                 elems->fils_key_confirm_len = elen;
220                 break;
221         case WLAN_EID_EXT_FILS_SESSION:
222                 if (elen != FILS_SESSION_LEN)
223                         break;
224                 elems->fils_session = pos;
225                 break;
226         case WLAN_EID_EXT_FILS_HLP_CONTAINER:
227                 if (elen < 2 * ETH_ALEN)
228                         break;
229                 elems->fils_hlp = pos;
230                 elems->fils_hlp_len = elen;
231                 break;
232         case WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN:
233                 if (elen < 1)
234                         break;
235                 elems->fils_ip_addr_assign = pos;
236                 elems->fils_ip_addr_assign_len = elen;
237                 break;
238         case WLAN_EID_EXT_KEY_DELIVERY:
239                 if (elen < WPA_KEY_RSC_LEN)
240                         break;
241                 elems->key_delivery = pos;
242                 elems->key_delivery_len = elen;
243                 break;
244         case WLAN_EID_EXT_FILS_WRAPPED_DATA:
245                 elems->fils_wrapped_data = pos;
246                 elems->fils_wrapped_data_len = elen;
247                 break;
248         case WLAN_EID_EXT_FILS_PUBLIC_KEY:
249                 if (elen < 1)
250                         break;
251                 elems->fils_pk = pos;
252                 elems->fils_pk_len = elen;
253                 break;
254         case WLAN_EID_EXT_FILS_NONCE:
255                 if (elen != FILS_NONCE_LEN)
256                         break;
257                 elems->fils_nonce = pos;
258                 break;
259         case WLAN_EID_EXT_OWE_DH_PARAM:
260                 if (elen < 2)
261                         break;
262                 elems->owe_dh = pos;
263                 elems->owe_dh_len = elen;
264                 break;
265         case WLAN_EID_EXT_PASSWORD_IDENTIFIER:
266                 elems->password_id = pos;
267                 elems->password_id_len = elen;
268                 break;
269         default:
270                 if (show_errors) {
271                         wpa_printf(MSG_MSGDUMP,
272                                    "IEEE 802.11 element parsing ignored unknown element extension (ext_id=%u elen=%u)",
273                                    ext_id, (unsigned int) elen);
274                 }
275                 return -1;
276         }
277
278         return 0;
279 }
280
281
282 /**
283  * ieee802_11_parse_elems - Parse information elements in management frames
284  * @start: Pointer to the start of IEs
285  * @len: Length of IE buffer in octets
286  * @elems: Data structure for parsed elements
287  * @show_errors: Whether to show parsing errors in debug log
288  * Returns: Parsing result
289  */
290 ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
291                                 struct ieee802_11_elems *elems,
292                                 int show_errors)
293 {
294         size_t left = len;
295         const u8 *pos = start;
296         int unknown = 0;
297
298         os_memset(elems, 0, sizeof(*elems));
299
300         while (left >= 2) {
301                 u8 id, elen;
302
303                 id = *pos++;
304                 elen = *pos++;
305                 left -= 2;
306
307                 if (elen > left) {
308                         if (show_errors) {
309                                 wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
310                                            "parse failed (id=%d elen=%d "
311                                            "left=%lu)",
312                                            id, elen, (unsigned long) left);
313                                 wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
314                         }
315                         return ParseFailed;
316                 }
317
318                 switch (id) {
319                 case WLAN_EID_SSID:
320                         if (elen > SSID_MAX_LEN) {
321                                 wpa_printf(MSG_DEBUG,
322                                            "Ignored too long SSID element (elen=%u)",
323                                            elen);
324                                 break;
325                         }
326                         elems->ssid = pos;
327                         elems->ssid_len = elen;
328                         break;
329                 case WLAN_EID_SUPP_RATES:
330                         elems->supp_rates = pos;
331                         elems->supp_rates_len = elen;
332                         break;
333                 case WLAN_EID_DS_PARAMS:
334                         if (elen < 1)
335                                 break;
336                         elems->ds_params = pos;
337                         break;
338                 case WLAN_EID_CF_PARAMS:
339                 case WLAN_EID_TIM:
340                         break;
341                 case WLAN_EID_CHALLENGE:
342                         elems->challenge = pos;
343                         elems->challenge_len = elen;
344                         break;
345                 case WLAN_EID_ERP_INFO:
346                         if (elen < 1)
347                                 break;
348                         elems->erp_info = pos;
349                         break;
350                 case WLAN_EID_EXT_SUPP_RATES:
351                         elems->ext_supp_rates = pos;
352                         elems->ext_supp_rates_len = elen;
353                         break;
354                 case WLAN_EID_VENDOR_SPECIFIC:
355                         if (ieee802_11_parse_vendor_specific(pos, elen,
356                                                              elems,
357                                                              show_errors))
358                                 unknown++;
359                         break;
360                 case WLAN_EID_RSN:
361                         elems->rsn_ie = pos;
362                         elems->rsn_ie_len = elen;
363                         break;
364                 case WLAN_EID_PWR_CAPABILITY:
365                         if (elen < 2)
366                                 break;
367                         elems->power_capab = pos;
368                         elems->power_capab_len = elen;
369                         break;
370                 case WLAN_EID_SUPPORTED_CHANNELS:
371                         elems->supp_channels = pos;
372                         elems->supp_channels_len = elen;
373                         break;
374                 case WLAN_EID_MOBILITY_DOMAIN:
375                         if (elen < sizeof(struct rsn_mdie))
376                                 break;
377                         elems->mdie = pos;
378                         elems->mdie_len = elen;
379                         break;
380                 case WLAN_EID_FAST_BSS_TRANSITION:
381                         if (elen < sizeof(struct rsn_ftie))
382                                 break;
383                         elems->ftie = pos;
384                         elems->ftie_len = elen;
385                         break;
386                 case WLAN_EID_TIMEOUT_INTERVAL:
387                         if (elen != 5)
388                                 break;
389                         elems->timeout_int = pos;
390                         break;
391                 case WLAN_EID_HT_CAP:
392                         if (elen < sizeof(struct ieee80211_ht_capabilities))
393                                 break;
394                         elems->ht_capabilities = pos;
395                         break;
396                 case WLAN_EID_HT_OPERATION:
397                         if (elen < sizeof(struct ieee80211_ht_operation))
398                                 break;
399                         elems->ht_operation = pos;
400                         break;
401                 case WLAN_EID_MESH_CONFIG:
402                         elems->mesh_config = pos;
403                         elems->mesh_config_len = elen;
404                         break;
405                 case WLAN_EID_MESH_ID:
406                         elems->mesh_id = pos;
407                         elems->mesh_id_len = elen;
408                         break;
409                 case WLAN_EID_PEER_MGMT:
410                         elems->peer_mgmt = pos;
411                         elems->peer_mgmt_len = elen;
412                         break;
413                 case WLAN_EID_VHT_CAP:
414                         if (elen < sizeof(struct ieee80211_vht_capabilities))
415                                 break;
416                         elems->vht_capabilities = pos;
417                         break;
418                 case WLAN_EID_VHT_OPERATION:
419                         if (elen < sizeof(struct ieee80211_vht_operation))
420                                 break;
421                         elems->vht_operation = pos;
422                         break;
423                 case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
424                         if (elen != 1)
425                                 break;
426                         elems->vht_opmode_notif = pos;
427                         break;
428                 case WLAN_EID_LINK_ID:
429                         if (elen < 18)
430                                 break;
431                         elems->link_id = pos;
432                         break;
433                 case WLAN_EID_INTERWORKING:
434                         elems->interworking = pos;
435                         elems->interworking_len = elen;
436                         break;
437                 case WLAN_EID_QOS_MAP_SET:
438                         if (elen < 16)
439                                 break;
440                         elems->qos_map_set = pos;
441                         elems->qos_map_set_len = elen;
442                         break;
443                 case WLAN_EID_EXT_CAPAB:
444                         elems->ext_capab = pos;
445                         elems->ext_capab_len = elen;
446                         break;
447                 case WLAN_EID_BSS_MAX_IDLE_PERIOD:
448                         if (elen < 3)
449                                 break;
450                         elems->bss_max_idle_period = pos;
451                         break;
452                 case WLAN_EID_SSID_LIST:
453                         elems->ssid_list = pos;
454                         elems->ssid_list_len = elen;
455                         break;
456                 case WLAN_EID_AMPE:
457                         elems->ampe = pos;
458                         elems->ampe_len = elen;
459                         break;
460                 case WLAN_EID_MIC:
461                         elems->mic = pos;
462                         elems->mic_len = elen;
463                         /* after mic everything is encrypted, so stop. */
464                         left = elen;
465                         break;
466                 case WLAN_EID_MULTI_BAND:
467                         if (elems->mb_ies.nof_ies >= MAX_NOF_MB_IES_SUPPORTED) {
468                                 wpa_printf(MSG_MSGDUMP,
469                                            "IEEE 802.11 element parse ignored MB IE (id=%d elen=%d)",
470                                            id, elen);
471                                 break;
472                         }
473
474                         elems->mb_ies.ies[elems->mb_ies.nof_ies].ie = pos;
475                         elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen;
476                         elems->mb_ies.nof_ies++;
477                         break;
478                 case WLAN_EID_SUPPORTED_OPERATING_CLASSES:
479                         elems->supp_op_classes = pos;
480                         elems->supp_op_classes_len = elen;
481                         break;
482                 case WLAN_EID_RRM_ENABLED_CAPABILITIES:
483                         elems->rrm_enabled = pos;
484                         elems->rrm_enabled_len = elen;
485                         break;
486                 case WLAN_EID_CAG_NUMBER:
487                         elems->cag_number = pos;
488                         elems->cag_number_len = elen;
489                         break;
490                 case WLAN_EID_AP_CSN:
491                         if (elen < 1)
492                                 break;
493                         elems->ap_csn = pos;
494                         break;
495                 case WLAN_EID_FILS_INDICATION:
496                         if (elen < 2)
497                                 break;
498                         elems->fils_indic = pos;
499                         elems->fils_indic_len = elen;
500                         break;
501                 case WLAN_EID_DILS:
502                         if (elen < 2)
503                                 break;
504                         elems->dils = pos;
505                         elems->dils_len = elen;
506                         break;
507                 case WLAN_EID_FRAGMENT:
508                         /* TODO */
509                         break;
510                 case WLAN_EID_EXTENSION:
511                         if (ieee802_11_parse_extension(pos, elen, elems,
512                                                        show_errors))
513                                 unknown++;
514                         break;
515                 default:
516                         unknown++;
517                         if (!show_errors)
518                                 break;
519                         wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
520                                    "ignored unknown element (id=%d elen=%d)",
521                                    id, elen);
522                         break;
523                 }
524
525                 left -= elen;
526                 pos += elen;
527         }
528
529         if (left)
530                 return ParseFailed;
531
532         return unknown ? ParseUnknown : ParseOK;
533 }
534
535
536 int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
537 {
538         int count = 0;
539         const u8 *pos, *end;
540
541         if (ies == NULL)
542                 return 0;
543
544         pos = ies;
545         end = ies + ies_len;
546
547         while (end - pos >= 2) {
548                 if (2 + pos[1] > end - pos)
549                         break;
550                 count++;
551                 pos += 2 + pos[1];
552         }
553
554         return count;
555 }
556
557
558 struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
559                                             u32 oui_type)
560 {
561         struct wpabuf *buf;
562         const u8 *end, *pos, *ie;
563
564         pos = ies;
565         end = ies + ies_len;
566         ie = NULL;
567
568         while (end - pos > 1) {
569                 if (2 + pos[1] > end - pos)
570                         return NULL;
571                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
572                     WPA_GET_BE32(&pos[2]) == oui_type) {
573                         ie = pos;
574                         break;
575                 }
576                 pos += 2 + pos[1];
577         }
578
579         if (ie == NULL)
580                 return NULL; /* No specified vendor IE found */
581
582         buf = wpabuf_alloc(ies_len);
583         if (buf == NULL)
584                 return NULL;
585
586         /*
587          * There may be multiple vendor IEs in the message, so need to
588          * concatenate their data fields.
589          */
590         while (end - pos > 1) {
591                 if (2 + pos[1] > end - pos)
592                         break;
593                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
594                     WPA_GET_BE32(&pos[2]) == oui_type)
595                         wpabuf_put_data(buf, pos + 6, pos[1] - 4);
596                 pos += 2 + pos[1];
597         }
598
599         return buf;
600 }
601
602
603 const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
604 {
605         u16 fc, type, stype;
606
607         /*
608          * PS-Poll frames are 16 bytes. All other frames are
609          * 24 bytes or longer.
610          */
611         if (len < 16)
612                 return NULL;
613
614         fc = le_to_host16(hdr->frame_control);
615         type = WLAN_FC_GET_TYPE(fc);
616         stype = WLAN_FC_GET_STYPE(fc);
617
618         switch (type) {
619         case WLAN_FC_TYPE_DATA:
620                 if (len < 24)
621                         return NULL;
622                 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
623                 case WLAN_FC_FROMDS | WLAN_FC_TODS:
624                 case WLAN_FC_TODS:
625                         return hdr->addr1;
626                 case WLAN_FC_FROMDS:
627                         return hdr->addr2;
628                 default:
629                         return NULL;
630                 }
631         case WLAN_FC_TYPE_CTRL:
632                 if (stype != WLAN_FC_STYPE_PSPOLL)
633                         return NULL;
634                 return hdr->addr1;
635         case WLAN_FC_TYPE_MGMT:
636                 return hdr->addr3;
637         default:
638                 return NULL;
639         }
640 }
641
642
643 int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
644                           const char *name, const char *val)
645 {
646         int num, v;
647         const char *pos;
648         struct hostapd_wmm_ac_params *ac;
649
650         /* skip 'wme_ac_' or 'wmm_ac_' prefix */
651         pos = name + 7;
652         if (os_strncmp(pos, "be_", 3) == 0) {
653                 num = 0;
654                 pos += 3;
655         } else if (os_strncmp(pos, "bk_", 3) == 0) {
656                 num = 1;
657                 pos += 3;
658         } else if (os_strncmp(pos, "vi_", 3) == 0) {
659                 num = 2;
660                 pos += 3;
661         } else if (os_strncmp(pos, "vo_", 3) == 0) {
662                 num = 3;
663                 pos += 3;
664         } else {
665                 wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
666                 return -1;
667         }
668
669         ac = &wmm_ac_params[num];
670
671         if (os_strcmp(pos, "aifs") == 0) {
672                 v = atoi(val);
673                 if (v < 1 || v > 255) {
674                         wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
675                         return -1;
676                 }
677                 ac->aifs = v;
678         } else if (os_strcmp(pos, "cwmin") == 0) {
679                 v = atoi(val);
680                 if (v < 0 || v > 15) {
681                         wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
682                         return -1;
683                 }
684                 ac->cwmin = v;
685         } else if (os_strcmp(pos, "cwmax") == 0) {
686                 v = atoi(val);
687                 if (v < 0 || v > 15) {
688                         wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
689                         return -1;
690                 }
691                 ac->cwmax = v;
692         } else if (os_strcmp(pos, "txop_limit") == 0) {
693                 v = atoi(val);
694                 if (v < 0 || v > 0xffff) {
695                         wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
696                         return -1;
697                 }
698                 ac->txop_limit = v;
699         } else if (os_strcmp(pos, "acm") == 0) {
700                 v = atoi(val);
701                 if (v < 0 || v > 1) {
702                         wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
703                         return -1;
704                 }
705                 ac->admission_control_mandatory = v;
706         } else {
707                 wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
708                 return -1;
709         }
710
711         return 0;
712 }
713
714
715 enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
716 {
717         u8 op_class;
718
719         return ieee80211_freq_to_channel_ext(freq, 0, VHT_CHANWIDTH_USE_HT,
720                                              &op_class, channel);
721 }
722
723
724 /**
725  * ieee80211_freq_to_channel_ext - Convert frequency into channel info
726  * for HT40 and VHT. DFS channels are not covered.
727  * @freq: Frequency (MHz) to convert
728  * @sec_channel: 0 = non-HT40, 1 = sec. channel above, -1 = sec. channel below
729  * @vht: VHT channel width (VHT_CHANWIDTH_*)
730  * @op_class: Buffer for returning operating class
731  * @channel: Buffer for returning channel number
732  * Returns: hw_mode on success, NUM_HOSTAPD_MODES on failure
733  */
734 enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
735                                                    int sec_channel, int vht,
736                                                    u8 *op_class, u8 *channel)
737 {
738         u8 vht_opclass;
739
740         /* TODO: more operating classes */
741
742         if (sec_channel > 1 || sec_channel < -1)
743                 return NUM_HOSTAPD_MODES;
744
745         if (freq >= 2412 && freq <= 2472) {
746                 if ((freq - 2407) % 5)
747                         return NUM_HOSTAPD_MODES;
748
749                 if (vht)
750                         return NUM_HOSTAPD_MODES;
751
752                 /* 2.407 GHz, channels 1..13 */
753                 if (sec_channel == 1)
754                         *op_class = 83;
755                 else if (sec_channel == -1)
756                         *op_class = 84;
757                 else
758                         *op_class = 81;
759
760                 *channel = (freq - 2407) / 5;
761
762                 return HOSTAPD_MODE_IEEE80211G;
763         }
764
765         if (freq == 2484) {
766                 if (sec_channel || vht)
767                         return NUM_HOSTAPD_MODES;
768
769                 *op_class = 82; /* channel 14 */
770                 *channel = 14;
771
772                 return HOSTAPD_MODE_IEEE80211B;
773         }
774
775         if (freq >= 4900 && freq < 5000) {
776                 if ((freq - 4000) % 5)
777                         return NUM_HOSTAPD_MODES;
778                 *channel = (freq - 4000) / 5;
779                 *op_class = 0; /* TODO */
780                 return HOSTAPD_MODE_IEEE80211A;
781         }
782
783         switch (vht) {
784         case VHT_CHANWIDTH_80MHZ:
785                 vht_opclass = 128;
786                 break;
787         case VHT_CHANWIDTH_160MHZ:
788                 vht_opclass = 129;
789                 break;
790         case VHT_CHANWIDTH_80P80MHZ:
791                 vht_opclass = 130;
792                 break;
793         default:
794                 vht_opclass = 0;
795                 break;
796         }
797
798         /* 5 GHz, channels 36..48 */
799         if (freq >= 5180 && freq <= 5240) {
800                 if ((freq - 5000) % 5)
801                         return NUM_HOSTAPD_MODES;
802
803                 if (vht_opclass)
804                         *op_class = vht_opclass;
805                 else if (sec_channel == 1)
806                         *op_class = 116;
807                 else if (sec_channel == -1)
808                         *op_class = 117;
809                 else
810                         *op_class = 115;
811
812                 *channel = (freq - 5000) / 5;
813
814                 return HOSTAPD_MODE_IEEE80211A;
815         }
816
817         /* 5 GHz, channels 52..64 */
818         if (freq >= 5260 && freq <= 5320) {
819                 if ((freq - 5000) % 5)
820                         return NUM_HOSTAPD_MODES;
821
822                 if (vht_opclass)
823                         *op_class = vht_opclass;
824                 else if (sec_channel == 1)
825                         *op_class = 119;
826                 else if (sec_channel == -1)
827                         *op_class = 120;
828                 else
829                         *op_class = 118;
830
831                 *channel = (freq - 5000) / 5;
832
833                 return HOSTAPD_MODE_IEEE80211A;
834         }
835
836         /* 5 GHz, channels 149..169 */
837         if (freq >= 5745 && freq <= 5845) {
838                 if ((freq - 5000) % 5)
839                         return NUM_HOSTAPD_MODES;
840
841                 if (vht_opclass)
842                         *op_class = vht_opclass;
843                 else if (sec_channel == 1)
844                         *op_class = 126;
845                 else if (sec_channel == -1)
846                         *op_class = 127;
847                 else if (freq <= 5805)
848                         *op_class = 124;
849                 else
850                         *op_class = 125;
851
852                 *channel = (freq - 5000) / 5;
853
854                 return HOSTAPD_MODE_IEEE80211A;
855         }
856
857         /* 5 GHz, channels 100..140 */
858         if (freq >= 5000 && freq <= 5700) {
859                 if ((freq - 5000) % 5)
860                         return NUM_HOSTAPD_MODES;
861
862                 if (vht_opclass)
863                         *op_class = vht_opclass;
864                 else if (sec_channel == 1)
865                         *op_class = 122;
866                 else if (sec_channel == -1)
867                         *op_class = 123;
868                 else
869                         *op_class = 121;
870
871                 *channel = (freq - 5000) / 5;
872
873                 return HOSTAPD_MODE_IEEE80211A;
874         }
875
876         if (freq >= 5000 && freq < 5900) {
877                 if ((freq - 5000) % 5)
878                         return NUM_HOSTAPD_MODES;
879                 *channel = (freq - 5000) / 5;
880                 *op_class = 0; /* TODO */
881                 return HOSTAPD_MODE_IEEE80211A;
882         }
883
884         /* 56.16 GHz, channel 1..4 */
885         if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
886                 if (sec_channel || vht)
887                         return NUM_HOSTAPD_MODES;
888
889                 *channel = (freq - 56160) / 2160;
890                 *op_class = 180;
891
892                 return HOSTAPD_MODE_IEEE80211AD;
893         }
894
895         return NUM_HOSTAPD_MODES;
896 }
897
898
899 static const char *const us_op_class_cc[] = {
900         "US", "CA", NULL
901 };
902
903 static const char *const eu_op_class_cc[] = {
904         "AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE",
905         "DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT",
906         "LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT",
907         "RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL
908 };
909
910 static const char *const jp_op_class_cc[] = {
911         "JP", NULL
912 };
913
914 static const char *const cn_op_class_cc[] = {
915         "CN", NULL
916 };
917
918
919 static int country_match(const char *const cc[], const char *const country)
920 {
921         int i;
922
923         if (country == NULL)
924                 return 0;
925         for (i = 0; cc[i]; i++) {
926                 if (cc[i][0] == country[0] && cc[i][1] == country[1])
927                         return 1;
928         }
929
930         return 0;
931 }
932
933
934 static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
935 {
936         switch (op_class) {
937         case 12: /* channels 1..11 */
938         case 32: /* channels 1..7; 40 MHz */
939         case 33: /* channels 5..11; 40 MHz */
940                 if (chan < 1 || chan > 11)
941                         return -1;
942                 return 2407 + 5 * chan;
943         case 1: /* channels 36,40,44,48 */
944         case 2: /* channels 52,56,60,64; dfs */
945         case 22: /* channels 36,44; 40 MHz */
946         case 23: /* channels 52,60; 40 MHz */
947         case 27: /* channels 40,48; 40 MHz */
948         case 28: /* channels 56,64; 40 MHz */
949                 if (chan < 36 || chan > 64)
950                         return -1;
951                 return 5000 + 5 * chan;
952         case 4: /* channels 100-144 */
953         case 24: /* channels 100-140; 40 MHz */
954                 if (chan < 100 || chan > 144)
955                         return -1;
956                 return 5000 + 5 * chan;
957         case 3: /* channels 149,153,157,161 */
958         case 25: /* channels 149,157; 40 MHz */
959         case 26: /* channels 149,157; 40 MHz */
960         case 30: /* channels 153,161; 40 MHz */
961         case 31: /* channels 153,161; 40 MHz */
962                 if (chan < 149 || chan > 161)
963                         return -1;
964                 return 5000 + 5 * chan;
965         case 5: /* channels 149,153,157,161,165 */
966                 if (chan < 149 || chan > 165)
967                         return -1;
968                 return 5000 + 5 * chan;
969         case 34: /* 60 GHz band, channels 1..3 */
970                 if (chan < 1 || chan > 3)
971                         return -1;
972                 return 56160 + 2160 * chan;
973         }
974         return -1;
975 }
976
977
978 static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
979 {
980         switch (op_class) {
981         case 4: /* channels 1..13 */
982         case 11: /* channels 1..9; 40 MHz */
983         case 12: /* channels 5..13; 40 MHz */
984                 if (chan < 1 || chan > 13)
985                         return -1;
986                 return 2407 + 5 * chan;
987         case 1: /* channels 36,40,44,48 */
988         case 2: /* channels 52,56,60,64; dfs */
989         case 5: /* channels 36,44; 40 MHz */
990         case 6: /* channels 52,60; 40 MHz */
991         case 8: /* channels 40,48; 40 MHz */
992         case 9: /* channels 56,64; 40 MHz */
993                 if (chan < 36 || chan > 64)
994                         return -1;
995                 return 5000 + 5 * chan;
996         case 3: /* channels 100-140 */
997         case 7: /* channels 100-132; 40 MHz */
998         case 10: /* channels 104-136; 40 MHz */
999         case 16: /* channels 100-140 */
1000                 if (chan < 100 || chan > 140)
1001                         return -1;
1002                 return 5000 + 5 * chan;
1003         case 17: /* channels 149,153,157,161,165,169 */
1004                 if (chan < 149 || chan > 169)
1005                         return -1;
1006                 return 5000 + 5 * chan;
1007         case 18: /* 60 GHz band, channels 1..4 */
1008                 if (chan < 1 || chan > 4)
1009                         return -1;
1010                 return 56160 + 2160 * chan;
1011         }
1012         return -1;
1013 }
1014
1015
1016 static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
1017 {
1018         switch (op_class) {
1019         case 30: /* channels 1..13 */
1020         case 56: /* channels 1..9; 40 MHz */
1021         case 57: /* channels 5..13; 40 MHz */
1022                 if (chan < 1 || chan > 13)
1023                         return -1;
1024                 return 2407 + 5 * chan;
1025         case 31: /* channel 14 */
1026                 if (chan != 14)
1027                         return -1;
1028                 return 2414 + 5 * chan;
1029         case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */
1030         case 32: /* channels 52,56,60,64 */
1031         case 33: /* channels 52,56,60,64 */
1032         case 36: /* channels 36,44; 40 MHz */
1033         case 37: /* channels 52,60; 40 MHz */
1034         case 38: /* channels 52,60; 40 MHz */
1035         case 41: /* channels 40,48; 40 MHz */
1036         case 42: /* channels 56,64; 40 MHz */
1037         case 43: /* channels 56,64; 40 MHz */
1038                 if (chan < 34 || chan > 64)
1039                         return -1;
1040                 return 5000 + 5 * chan;
1041         case 34: /* channels 100-140 */
1042         case 35: /* channels 100-140 */
1043         case 39: /* channels 100-132; 40 MHz */
1044         case 40: /* channels 100-132; 40 MHz */
1045         case 44: /* channels 104-136; 40 MHz */
1046         case 45: /* channels 104-136; 40 MHz */
1047         case 58: /* channels 100-140 */
1048                 if (chan < 100 || chan > 140)
1049                         return -1;
1050                 return 5000 + 5 * chan;
1051         case 59: /* 60 GHz band, channels 1..4 */
1052                 if (chan < 1 || chan > 3)
1053                         return -1;
1054                 return 56160 + 2160 * chan;
1055         }
1056         return -1;
1057 }
1058
1059
1060 static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
1061 {
1062         switch (op_class) {
1063         case 7: /* channels 1..13 */
1064         case 8: /* channels 1..9; 40 MHz */
1065         case 9: /* channels 5..13; 40 MHz */
1066                 if (chan < 1 || chan > 13)
1067                         return -1;
1068                 return 2407 + 5 * chan;
1069         case 1: /* channels 36,40,44,48 */
1070         case 2: /* channels 52,56,60,64; dfs */
1071         case 4: /* channels 36,44; 40 MHz */
1072         case 5: /* channels 52,60; 40 MHz */
1073                 if (chan < 36 || chan > 64)
1074                         return -1;
1075                 return 5000 + 5 * chan;
1076         case 3: /* channels 149,153,157,161,165 */
1077         case 6: /* channels 149,157; 40 MHz */
1078                 if (chan < 149 || chan > 165)
1079                         return -1;
1080                 return 5000 + 5 * chan;
1081         }
1082         return -1;
1083 }
1084
1085
1086 static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
1087 {
1088         /* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
1089         switch (op_class) {
1090         case 81:
1091                 /* channels 1..13 */
1092                 if (chan < 1 || chan > 13)
1093                         return -1;
1094                 return 2407 + 5 * chan;
1095         case 82:
1096                 /* channel 14 */
1097                 if (chan != 14)
1098                         return -1;
1099                 return 2414 + 5 * chan;
1100         case 83: /* channels 1..9; 40 MHz */
1101         case 84: /* channels 5..13; 40 MHz */
1102                 if (chan < 1 || chan > 13)
1103                         return -1;
1104                 return 2407 + 5 * chan;
1105         case 115: /* channels 36,40,44,48; indoor only */
1106         case 116: /* channels 36,44; 40 MHz; indoor only */
1107         case 117: /* channels 40,48; 40 MHz; indoor only */
1108         case 118: /* channels 52,56,60,64; dfs */
1109         case 119: /* channels 52,60; 40 MHz; dfs */
1110         case 120: /* channels 56,64; 40 MHz; dfs */
1111                 if (chan < 36 || chan > 64)
1112                         return -1;
1113                 return 5000 + 5 * chan;
1114         case 121: /* channels 100-140 */
1115         case 122: /* channels 100-142; 40 MHz */
1116         case 123: /* channels 104-136; 40 MHz */
1117                 if (chan < 100 || chan > 140)
1118                         return -1;
1119                 return 5000 + 5 * chan;
1120         case 124: /* channels 149,153,157,161 */
1121         case 126: /* channels 149,157; 40 MHz */
1122         case 127: /* channels 153,161; 40 MHz */
1123                 if (chan < 149 || chan > 161)
1124                         return -1;
1125                 return 5000 + 5 * chan;
1126         case 125: /* channels 149,153,157,161,165,169 */
1127                 if (chan < 149 || chan > 169)
1128                         return -1;
1129                 return 5000 + 5 * chan;
1130         case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
1131         case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
1132                 if (chan < 36 || chan > 161)
1133                         return -1;
1134                 return 5000 + 5 * chan;
1135         case 129: /* center freqs 50, 114; 160 MHz */
1136                 if (chan < 36 || chan > 128)
1137                         return -1;
1138                 return 5000 + 5 * chan;
1139         case 180: /* 60 GHz band, channels 1..4 */
1140                 if (chan < 1 || chan > 4)
1141                         return -1;
1142                 return 56160 + 2160 * chan;
1143         }
1144         return -1;
1145 }
1146
1147 /**
1148  * ieee80211_chan_to_freq - Convert channel info to frequency
1149  * @country: Country code, if known; otherwise, global operating class is used
1150  * @op_class: Operating class
1151  * @chan: Channel number
1152  * Returns: Frequency in MHz or -1 if the specified channel is unknown
1153  */
1154 int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
1155 {
1156         int freq;
1157
1158         if (country_match(us_op_class_cc, country)) {
1159                 freq = ieee80211_chan_to_freq_us(op_class, chan);
1160                 if (freq > 0)
1161                         return freq;
1162         }
1163
1164         if (country_match(eu_op_class_cc, country)) {
1165                 freq = ieee80211_chan_to_freq_eu(op_class, chan);
1166                 if (freq > 0)
1167                         return freq;
1168         }
1169
1170         if (country_match(jp_op_class_cc, country)) {
1171                 freq = ieee80211_chan_to_freq_jp(op_class, chan);
1172                 if (freq > 0)
1173                         return freq;
1174         }
1175
1176         if (country_match(cn_op_class_cc, country)) {
1177                 freq = ieee80211_chan_to_freq_cn(op_class, chan);
1178                 if (freq > 0)
1179                         return freq;
1180         }
1181
1182         return ieee80211_chan_to_freq_global(op_class, chan);
1183 }
1184
1185
1186 int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
1187                      u16 num_modes)
1188 {
1189         int i, j;
1190
1191         if (!modes || !num_modes)
1192                 return (freq >= 5260 && freq <= 5320) ||
1193                         (freq >= 5500 && freq <= 5700);
1194
1195         for (i = 0; i < num_modes; i++) {
1196                 for (j = 0; j < modes[i].num_channels; j++) {
1197                         if (modes[i].channels[j].freq == freq &&
1198                             (modes[i].channels[j].flag & HOSTAPD_CHAN_RADAR))
1199                                 return 1;
1200                 }
1201         }
1202
1203         return 0;
1204 }
1205
1206
1207 static int is_11b(u8 rate)
1208 {
1209         return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
1210 }
1211
1212
1213 int supp_rates_11b_only(struct ieee802_11_elems *elems)
1214 {
1215         int num_11b = 0, num_others = 0;
1216         int i;
1217
1218         if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
1219                 return 0;
1220
1221         for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
1222                 if (is_11b(elems->supp_rates[i]))
1223                         num_11b++;
1224                 else
1225                         num_others++;
1226         }
1227
1228         for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
1229              i++) {
1230                 if (is_11b(elems->ext_supp_rates[i]))
1231                         num_11b++;
1232                 else
1233                         num_others++;
1234         }
1235
1236         return num_11b > 0 && num_others == 0;
1237 }
1238
1239
1240 const char * fc2str(u16 fc)
1241 {
1242         u16 stype = WLAN_FC_GET_STYPE(fc);
1243 #define C2S(x) case x: return #x;
1244
1245         switch (WLAN_FC_GET_TYPE(fc)) {
1246         case WLAN_FC_TYPE_MGMT:
1247                 switch (stype) {
1248                 C2S(WLAN_FC_STYPE_ASSOC_REQ)
1249                 C2S(WLAN_FC_STYPE_ASSOC_RESP)
1250                 C2S(WLAN_FC_STYPE_REASSOC_REQ)
1251                 C2S(WLAN_FC_STYPE_REASSOC_RESP)
1252                 C2S(WLAN_FC_STYPE_PROBE_REQ)
1253                 C2S(WLAN_FC_STYPE_PROBE_RESP)
1254                 C2S(WLAN_FC_STYPE_BEACON)
1255                 C2S(WLAN_FC_STYPE_ATIM)
1256                 C2S(WLAN_FC_STYPE_DISASSOC)
1257                 C2S(WLAN_FC_STYPE_AUTH)
1258                 C2S(WLAN_FC_STYPE_DEAUTH)
1259                 C2S(WLAN_FC_STYPE_ACTION)
1260                 }
1261                 break;
1262         case WLAN_FC_TYPE_CTRL:
1263                 switch (stype) {
1264                 C2S(WLAN_FC_STYPE_PSPOLL)
1265                 C2S(WLAN_FC_STYPE_RTS)
1266                 C2S(WLAN_FC_STYPE_CTS)
1267                 C2S(WLAN_FC_STYPE_ACK)
1268                 C2S(WLAN_FC_STYPE_CFEND)
1269                 C2S(WLAN_FC_STYPE_CFENDACK)
1270                 }
1271                 break;
1272         case WLAN_FC_TYPE_DATA:
1273                 switch (stype) {
1274                 C2S(WLAN_FC_STYPE_DATA)
1275                 C2S(WLAN_FC_STYPE_DATA_CFACK)
1276                 C2S(WLAN_FC_STYPE_DATA_CFPOLL)
1277                 C2S(WLAN_FC_STYPE_DATA_CFACKPOLL)
1278                 C2S(WLAN_FC_STYPE_NULLFUNC)
1279                 C2S(WLAN_FC_STYPE_CFACK)
1280                 C2S(WLAN_FC_STYPE_CFPOLL)
1281                 C2S(WLAN_FC_STYPE_CFACKPOLL)
1282                 C2S(WLAN_FC_STYPE_QOS_DATA)
1283                 C2S(WLAN_FC_STYPE_QOS_DATA_CFACK)
1284                 C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL)
1285                 C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL)
1286                 C2S(WLAN_FC_STYPE_QOS_NULL)
1287                 C2S(WLAN_FC_STYPE_QOS_CFPOLL)
1288                 C2S(WLAN_FC_STYPE_QOS_CFACKPOLL)
1289                 }
1290                 break;
1291         }
1292         return "WLAN_FC_TYPE_UNKNOWN";
1293 #undef C2S
1294 }
1295
1296
1297 int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
1298                        size_t ies_len)
1299 {
1300         os_memset(info, 0, sizeof(*info));
1301
1302         while (ies_buf && ies_len >= 2 &&
1303                info->nof_ies < MAX_NOF_MB_IES_SUPPORTED) {
1304                 size_t len = 2 + ies_buf[1];
1305
1306                 if (len > ies_len) {
1307                         wpa_hexdump(MSG_DEBUG, "Truncated IEs",
1308                                     ies_buf, ies_len);
1309                         return -1;
1310                 }
1311
1312                 if (ies_buf[0] == WLAN_EID_MULTI_BAND) {
1313                         wpa_printf(MSG_DEBUG, "MB IE of %zu bytes found", len);
1314                         info->ies[info->nof_ies].ie = ies_buf + 2;
1315                         info->ies[info->nof_ies].ie_len = ies_buf[1];
1316                         info->nof_ies++;
1317                 }
1318
1319                 ies_len -= len;
1320                 ies_buf += len;
1321         }
1322
1323         return 0;
1324 }
1325
1326
1327 struct wpabuf * mb_ies_by_info(struct mb_ies_info *info)
1328 {
1329         struct wpabuf *mb_ies = NULL;
1330
1331         WPA_ASSERT(info != NULL);
1332
1333         if (info->nof_ies) {
1334                 u8 i;
1335                 size_t mb_ies_size = 0;
1336
1337                 for (i = 0; i < info->nof_ies; i++)
1338                         mb_ies_size += 2 + info->ies[i].ie_len;
1339
1340                 mb_ies = wpabuf_alloc(mb_ies_size);
1341                 if (mb_ies) {
1342                         for (i = 0; i < info->nof_ies; i++) {
1343                                 wpabuf_put_u8(mb_ies, WLAN_EID_MULTI_BAND);
1344                                 wpabuf_put_u8(mb_ies, info->ies[i].ie_len);
1345                                 wpabuf_put_data(mb_ies,
1346                                                 info->ies[i].ie,
1347                                                 info->ies[i].ie_len);
1348                         }
1349                 }
1350         }
1351
1352         return mb_ies;
1353 }
1354
1355
1356 const struct oper_class_map global_op_class[] = {
1357         { HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20, P2P_SUPP },
1358         { HOSTAPD_MODE_IEEE80211G, 82, 14, 14, 1, BW20, NO_P2P_SUPP },
1359
1360         /* Do not enable HT40 on 2.4 GHz for P2P use for now */
1361         { HOSTAPD_MODE_IEEE80211G, 83, 1, 9, 1, BW40PLUS, NO_P2P_SUPP },
1362         { HOSTAPD_MODE_IEEE80211G, 84, 5, 13, 1, BW40MINUS, NO_P2P_SUPP },
1363
1364         { HOSTAPD_MODE_IEEE80211A, 115, 36, 48, 4, BW20, P2P_SUPP },
1365         { HOSTAPD_MODE_IEEE80211A, 116, 36, 44, 8, BW40PLUS, P2P_SUPP },
1366         { HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS, P2P_SUPP },
1367         { HOSTAPD_MODE_IEEE80211A, 118, 52, 64, 4, BW20, NO_P2P_SUPP },
1368         { HOSTAPD_MODE_IEEE80211A, 119, 52, 60, 8, BW40PLUS, NO_P2P_SUPP },
1369         { HOSTAPD_MODE_IEEE80211A, 120, 56, 64, 8, BW40MINUS, NO_P2P_SUPP },
1370         { HOSTAPD_MODE_IEEE80211A, 121, 100, 140, 4, BW20, NO_P2P_SUPP },
1371         { HOSTAPD_MODE_IEEE80211A, 122, 100, 132, 8, BW40PLUS, NO_P2P_SUPP },
1372         { HOSTAPD_MODE_IEEE80211A, 123, 104, 136, 8, BW40MINUS, NO_P2P_SUPP },
1373         { HOSTAPD_MODE_IEEE80211A, 124, 149, 161, 4, BW20, P2P_SUPP },
1374         { HOSTAPD_MODE_IEEE80211A, 125, 149, 169, 4, BW20, P2P_SUPP },
1375         { HOSTAPD_MODE_IEEE80211A, 126, 149, 157, 8, BW40PLUS, P2P_SUPP },
1376         { HOSTAPD_MODE_IEEE80211A, 127, 153, 161, 8, BW40MINUS, P2P_SUPP },
1377
1378         /*
1379          * IEEE P802.11ac/D7.0 Table E-4 actually talks about channel center
1380          * frequency index 42, 58, 106, 122, 138, 155 with channel spacing of
1381          * 80 MHz, but currently use the following definition for simplicity
1382          * (these center frequencies are not actual channels, which makes
1383          * wpas_p2p_allow_channel() fail). wpas_p2p_verify_80mhz() should take
1384          * care of removing invalid channels.
1385          */
1386         { HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP },
1387         { HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP },
1388         { HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP },
1389         { HOSTAPD_MODE_IEEE80211AD, 180, 1, 4, 1, BW2160, P2P_SUPP },
1390         { -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
1391 };
1392
1393
1394 static enum phy_type ieee80211_phy_type_by_freq(int freq)
1395 {
1396         enum hostapd_hw_mode hw_mode;
1397         u8 channel;
1398
1399         hw_mode = ieee80211_freq_to_chan(freq, &channel);
1400
1401         switch (hw_mode) {
1402         case HOSTAPD_MODE_IEEE80211A:
1403                 return PHY_TYPE_OFDM;
1404         case HOSTAPD_MODE_IEEE80211B:
1405                 return PHY_TYPE_HRDSSS;
1406         case HOSTAPD_MODE_IEEE80211G:
1407                 return PHY_TYPE_ERP;
1408         case HOSTAPD_MODE_IEEE80211AD:
1409                 return PHY_TYPE_DMG;
1410         default:
1411                 return PHY_TYPE_UNSPECIFIED;
1412         };
1413 }
1414
1415
1416 /* ieee80211_get_phy_type - Derive the phy type by freq and bandwidth */
1417 enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht)
1418 {
1419         if (vht)
1420                 return PHY_TYPE_VHT;
1421         if (ht)
1422                 return PHY_TYPE_HT;
1423
1424         return ieee80211_phy_type_by_freq(freq);
1425 }
1426
1427
1428 size_t global_op_class_size = ARRAY_SIZE(global_op_class);
1429
1430
1431 /**
1432  * get_ie - Fetch a specified information element from IEs buffer
1433  * @ies: Information elements buffer
1434  * @len: Information elements buffer length
1435  * @eid: Information element identifier (WLAN_EID_*)
1436  * Returns: Pointer to the information element (id field) or %NULL if not found
1437  *
1438  * This function returns the first matching information element in the IEs
1439  * buffer or %NULL in case the element is not found.
1440  */
1441 const u8 * get_ie(const u8 *ies, size_t len, u8 eid)
1442 {
1443         const u8 *end;
1444
1445         if (!ies)
1446                 return NULL;
1447
1448         end = ies + len;
1449
1450         while (end - ies > 1) {
1451                 if (2 + ies[1] > end - ies)
1452                         break;
1453
1454                 if (ies[0] == eid)
1455                         return ies;
1456
1457                 ies += 2 + ies[1];
1458         }
1459
1460         return NULL;
1461 }
1462
1463
1464 /**
1465  * get_ie_ext - Fetch a specified extended information element from IEs buffer
1466  * @ies: Information elements buffer
1467  * @len: Information elements buffer length
1468  * @ext: Information element extension identifier (WLAN_EID_EXT_*)
1469  * Returns: Pointer to the information element (id field) or %NULL if not found
1470  *
1471  * This function returns the first matching information element in the IEs
1472  * buffer or %NULL in case the element is not found.
1473  */
1474 const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext)
1475 {
1476         const u8 *end;
1477
1478         if (!ies)
1479                 return NULL;
1480
1481         end = ies + len;
1482
1483         while (end - ies > 1) {
1484                 if (2 + ies[1] > end - ies)
1485                         break;
1486
1487                 if (ies[0] == WLAN_EID_EXTENSION && ies[1] >= 1 &&
1488                     ies[2] == ext)
1489                         return ies;
1490
1491                 ies += 2 + ies[1];
1492         }
1493
1494         return NULL;
1495 }
1496
1497
1498 size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len)
1499 {
1500         /*
1501          * MBO IE requires 6 bytes without the attributes: EID (1), length (1),
1502          * OUI (3), OUI type (1).
1503          */
1504         if (len < 6 + attr_len) {
1505                 wpa_printf(MSG_DEBUG,
1506                            "MBO: Not enough room in buffer for MBO IE: buf len = %zu, attr_len = %zu",
1507                            len, attr_len);
1508                 return 0;
1509         }
1510
1511         *buf++ = WLAN_EID_VENDOR_SPECIFIC;
1512         *buf++ = attr_len + 4;
1513         WPA_PUT_BE24(buf, OUI_WFA);
1514         buf += 3;
1515         *buf++ = MBO_OUI_TYPE;
1516         os_memcpy(buf, attr, attr_len);
1517
1518         return 6 + attr_len;
1519 }
1520
1521
1522 static const struct country_op_class us_op_class[] = {
1523         { 1, 115 },
1524         { 2, 118 },
1525         { 3, 124 },
1526         { 4, 121 },
1527         { 5, 125 },
1528         { 12, 81 },
1529         { 22, 116 },
1530         { 23, 119 },
1531         { 24, 122 },
1532         { 25, 126 },
1533         { 26, 126 },
1534         { 27, 117 },
1535         { 28, 120 },
1536         { 29, 123 },
1537         { 30, 127 },
1538         { 31, 127 },
1539         { 32, 83 },
1540         { 33, 84 },
1541         { 34, 180 },
1542 };
1543
1544 static const struct country_op_class eu_op_class[] = {
1545         { 1, 115 },
1546         { 2, 118 },
1547         { 3, 121 },
1548         { 4, 81 },
1549         { 5, 116 },
1550         { 6, 119 },
1551         { 7, 122 },
1552         { 8, 117 },
1553         { 9, 120 },
1554         { 10, 123 },
1555         { 11, 83 },
1556         { 12, 84 },
1557         { 17, 125 },
1558         { 18, 180 },
1559 };
1560
1561 static const struct country_op_class jp_op_class[] = {
1562         { 1, 115 },
1563         { 30, 81 },
1564         { 31, 82 },
1565         { 32, 118 },
1566         { 33, 118 },
1567         { 34, 121 },
1568         { 35, 121 },
1569         { 36, 116 },
1570         { 37, 119 },
1571         { 38, 119 },
1572         { 39, 122 },
1573         { 40, 122 },
1574         { 41, 117 },
1575         { 42, 120 },
1576         { 43, 120 },
1577         { 44, 123 },
1578         { 45, 123 },
1579         { 56, 83 },
1580         { 57, 84 },
1581         { 58, 121 },
1582         { 59, 180 },
1583 };
1584
1585 static const struct country_op_class cn_op_class[] = {
1586         { 1, 115 },
1587         { 2, 118 },
1588         { 3, 125 },
1589         { 4, 116 },
1590         { 5, 119 },
1591         { 6, 126 },
1592         { 7, 81 },
1593         { 8, 83 },
1594         { 9, 84 },
1595 };
1596
1597 static u8
1598 global_op_class_from_country_array(u8 op_class, size_t array_size,
1599                                    const struct country_op_class *country_array)
1600 {
1601         size_t i;
1602
1603         for (i = 0; i < array_size; i++) {
1604                 if (country_array[i].country_op_class == op_class)
1605                         return country_array[i].global_op_class;
1606         }
1607
1608         return 0;
1609 }
1610
1611
1612 u8 country_to_global_op_class(const char *country, u8 op_class)
1613 {
1614         const struct country_op_class *country_array;
1615         size_t size;
1616         u8 g_op_class;
1617
1618         if (country_match(us_op_class_cc, country)) {
1619                 country_array = us_op_class;
1620                 size = ARRAY_SIZE(us_op_class);
1621         } else if (country_match(eu_op_class_cc, country)) {
1622                 country_array = eu_op_class;
1623                 size = ARRAY_SIZE(eu_op_class);
1624         } else if (country_match(jp_op_class_cc, country)) {
1625                 country_array = jp_op_class;
1626                 size = ARRAY_SIZE(jp_op_class);
1627         } else if (country_match(cn_op_class_cc, country)) {
1628                 country_array = cn_op_class;
1629                 size = ARRAY_SIZE(cn_op_class);
1630         } else {
1631                 /*
1632                  * Countries that do not match any of the above countries use
1633                  * global operating classes
1634                  */
1635                 return op_class;
1636         }
1637
1638         g_op_class = global_op_class_from_country_array(op_class, size,
1639                                                         country_array);
1640
1641         /*
1642          * If the given operating class did not match any of the country's
1643          * operating classes, assume that global operating class is used.
1644          */
1645         return g_op_class ? g_op_class : op_class;
1646 }
1647
1648
1649 const struct oper_class_map * get_oper_class(const char *country, u8 op_class)
1650 {
1651         const struct oper_class_map *op;
1652
1653         if (country)
1654                 op_class = country_to_global_op_class(country, op_class);
1655
1656         op = &global_op_class[0];
1657         while (op->op_class && op->op_class != op_class)
1658                 op++;
1659
1660         if (!op->op_class)
1661                 return NULL;
1662
1663         return op;
1664 }
1665
1666
1667 int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
1668                                     size_t nei_rep_len)
1669 {
1670         u8 *nei_pos = nei_rep;
1671         const char *end;
1672
1673         /*
1674          * BSS Transition Candidate List Entries - Neighbor Report elements
1675          * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
1676          * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
1677          */
1678         while (pos) {
1679                 u8 *nei_start;
1680                 long int val;
1681                 char *endptr, *tmp;
1682
1683                 pos = os_strstr(pos, " neighbor=");
1684                 if (!pos)
1685                         break;
1686                 if (nei_pos + 15 > nei_rep + nei_rep_len) {
1687                         wpa_printf(MSG_DEBUG,
1688                                    "Not enough room for additional neighbor");
1689                         return -1;
1690                 }
1691                 pos += 10;
1692
1693                 nei_start = nei_pos;
1694                 *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
1695                 nei_pos++; /* length to be filled in */
1696
1697                 if (hwaddr_aton(pos, nei_pos)) {
1698                         wpa_printf(MSG_DEBUG, "Invalid BSSID");
1699                         return -1;
1700                 }
1701                 nei_pos += ETH_ALEN;
1702                 pos += 17;
1703                 if (*pos != ',') {
1704                         wpa_printf(MSG_DEBUG, "Missing BSSID Information");
1705                         return -1;
1706                 }
1707                 pos++;
1708
1709                 val = strtol(pos, &endptr, 0);
1710                 WPA_PUT_LE32(nei_pos, val);
1711                 nei_pos += 4;
1712                 if (*endptr != ',') {
1713                         wpa_printf(MSG_DEBUG, "Missing Operating Class");
1714                         return -1;
1715                 }
1716                 pos = endptr + 1;
1717
1718                 *nei_pos++ = atoi(pos); /* Operating Class */
1719                 pos = os_strchr(pos, ',');
1720                 if (pos == NULL) {
1721                         wpa_printf(MSG_DEBUG, "Missing Channel Number");
1722                         return -1;
1723                 }
1724                 pos++;
1725
1726                 *nei_pos++ = atoi(pos); /* Channel Number */
1727                 pos = os_strchr(pos, ',');
1728                 if (pos == NULL) {
1729                         wpa_printf(MSG_DEBUG, "Missing PHY Type");
1730                         return -1;
1731                 }
1732                 pos++;
1733
1734                 *nei_pos++ = atoi(pos); /* PHY Type */
1735                 end = os_strchr(pos, ' ');
1736                 tmp = os_strchr(pos, ',');
1737                 if (tmp && (!end || tmp < end)) {
1738                         /* Optional Subelements (hexdump) */
1739                         size_t len;
1740
1741                         pos = tmp + 1;
1742                         end = os_strchr(pos, ' ');
1743                         if (end)
1744                                 len = end - pos;
1745                         else
1746                                 len = os_strlen(pos);
1747                         if (nei_pos + len / 2 > nei_rep + nei_rep_len) {
1748                                 wpa_printf(MSG_DEBUG,
1749                                            "Not enough room for neighbor subelements");
1750                                 return -1;
1751                         }
1752                         if (len & 0x01 ||
1753                             hexstr2bin(pos, nei_pos, len / 2) < 0) {
1754                                 wpa_printf(MSG_DEBUG,
1755                                            "Invalid neighbor subelement info");
1756                                 return -1;
1757                         }
1758                         nei_pos += len / 2;
1759                         pos = end;
1760                 }
1761
1762                 nei_start[1] = nei_pos - nei_start - 2;
1763         }
1764
1765         return nei_pos - nei_rep;
1766 }