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