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