18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE 802.11 Common routines
39d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
124b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt#include "defs.h"
139d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt#include "wpa_common.h"
14d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "qca-vendor.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11_defs.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11_common.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    struct ieee802_11_elems *elems,
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    int show_errors)
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int oui;
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* first 3 bytes in vendor specific information element are the IEEE
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * OUI of the vendor. The following byte is used a vendor specific
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * sub-type. */
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elen < 4) {
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (show_errors) {
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_MSGDUMP, "short vendor specific "
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "information element ignored (len=%lu)",
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long) elen);
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	oui = WPA_GET_BE24(pos);
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (oui) {
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case OUI_MICROSOFT:
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Microsoft/Wi-Fi information elements are further typed and
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * subtyped */
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (pos[3]) {
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 1:
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Microsoft OUI (00:50:F2) with OUI Type 1:
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * real WPA information element */
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->wpa_ie = pos;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->wpa_ie_len = elen;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WMM_OUI_TYPE:
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* WMM information element */
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (elen < 5) {
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_MSGDUMP, "short WMM "
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "information element ignored "
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "(len=%lu)",
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (unsigned long) elen);
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			switch (pos[4]) {
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				/*
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 * Share same pointer since only one of these
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 * is used and they start with same data.
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 * Length field can be used to distinguish the
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 * IEs.
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 */
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				elems->wmm = pos;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				elems->wmm_len = elen;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				elems->wmm_tspec = pos;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				elems->wmm_tspec_len = elen;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			default:
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_EXCESSIVE, "unknown WMM "
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "information element ignored "
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "(subtype=%d len=%lu)",
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   pos[4], (unsigned long) elen);
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 4:
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Wi-Fi Protected Setup (WPS) IE */
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->wps_ie = pos;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->wps_ie_len = elen;
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "information element ignored "
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "(type=%d len=%lu)",
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   pos[3], (unsigned long) elen);
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case OUI_WFA:
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (pos[3]) {
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case P2P_OUI_TYPE:
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Wi-Fi Alliance - P2P IE */
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->p2p = pos;
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->p2p_len = elen;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
10361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		case WFD_OUI_TYPE:
10461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			/* Wi-Fi Alliance - WFD IE */
10561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			elems->wfd = pos;
10661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			elems->wfd_len = elen;
10761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
10804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		case HS20_INDICATION_OUI_TYPE:
10904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			/* Hotspot 2.0 */
11004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			elems->hs20 = pos;
11104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			elems->hs20_len = elen;
11204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			break;
113f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		case HS20_OSEN_OUI_TYPE:
114f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			/* Hotspot 2.0 OSEN */
115f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			elems->osen = pos;
116f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			elems->osen_len = elen;
117f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			break;
11857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		case MBO_OUI_TYPE:
11957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt			/* MBO-OCE */
12057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt			elems->mbo = pos;
12157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt			elems->mbo_len = elen;
12257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt			break;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_MSGDUMP, "Unknown WFA "
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "information element ignored "
126717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt				   "(type=%d len=%lu)",
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   pos[3], (unsigned long) elen);
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case OUI_BROADCOM:
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (pos[3]) {
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case VENDOR_HT_CAPAB_OUI_TYPE:
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->vendor_ht_cap = pos;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->vendor_ht_cap_len = elen;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1382f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		case VENDOR_VHT_TYPE:
1392f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			if (elen > 4 &&
1402f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			    (pos[4] == VENDOR_VHT_SUBTYPE ||
1412f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			     pos[4] == VENDOR_VHT_SUBTYPE2)) {
1422f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				elems->vendor_vht = pos;
1432f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				elems->vendor_vht_len = elen;
1442f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			} else
1452f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				return -1;
1462f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			break;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "information element ignored "
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "(type=%d len=%lu)",
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   pos[3], (unsigned long) elen);
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
156d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case OUI_QCA:
157d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		switch (pos[3]) {
158d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		case QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST:
159d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			elems->pref_freq_list = pos;
160d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			elems->pref_freq_list_len = elen;
161d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
162d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		default:
163d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			wpa_printf(MSG_EXCESSIVE,
164d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   "Unknown QCA information element ignored (type=%d len=%lu)",
165d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   pos[3], (unsigned long) elen);
166d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return -1;
167d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
168d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		break;
169d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "information element ignored (vendor OUI "
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%02x:%02x:%02x len=%lu)",
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   pos[0], pos[1], pos[2], (unsigned long) elen);
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1829839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidtstatic int ieee802_11_parse_extension(const u8 *pos, size_t elen,
1839839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt				      struct ieee802_11_elems *elems,
1849839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt				      int show_errors)
1859839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt{
1869839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	u8 ext_id;
1879839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt
1889839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	if (elen < 1) {
1899839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		if (show_errors) {
1909839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			wpa_printf(MSG_MSGDUMP,
1919839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt				   "short information element (Ext)");
1929839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		}
1939839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		return -1;
1949839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	}
1959839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt
1969839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	ext_id = *pos++;
1979839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	elen--;
1989839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt
1999839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	switch (ext_id) {
2009839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	case WLAN_EID_EXT_ASSOC_DELAY_INFO:
2019839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		if (elen != 1)
2029839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
2039839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->assoc_delay_info = pos;
2049839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		break;
2059839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	case WLAN_EID_EXT_FILS_REQ_PARAMS:
2069839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		if (elen < 3)
2079839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
2089839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_req_params = pos;
2099839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_req_params_len = elen;
2109839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		break;
2119839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	case WLAN_EID_EXT_FILS_KEY_CONFIRM:
2129839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_key_confirm = pos;
2139839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_key_confirm_len = elen;
2149839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		break;
2159839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	case WLAN_EID_EXT_FILS_SESSION:
2169839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		if (elen != FILS_SESSION_LEN)
2179839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
2189839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_session = pos;
2199839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		break;
2209839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	case WLAN_EID_EXT_FILS_HLP_CONTAINER:
2219839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		if (elen < 2 * ETH_ALEN)
2229839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
2239839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_hlp = pos;
2249839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_hlp_len = elen;
2259839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		break;
2269839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	case WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN:
2279839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		if (elen < 1)
2289839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
2299839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_ip_addr_assign = pos;
2309839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_ip_addr_assign_len = elen;
2319839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		break;
2329839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	case WLAN_EID_EXT_KEY_DELIVERY:
2339839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		if (elen < WPA_KEY_RSC_LEN)
2349839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
2359839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->key_delivery = pos;
2369839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->key_delivery_len = elen;
2379839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		break;
2389839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	case WLAN_EID_EXT_FILS_WRAPPED_DATA:
2399839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_wrapped_data = pos;
2409839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_wrapped_data_len = elen;
2419839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		break;
2429839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	case WLAN_EID_EXT_FILS_PUBLIC_KEY:
2439839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		if (elen < 1)
2449839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
2459839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_pk = pos;
2469839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_pk_len = elen;
2479839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		break;
2489839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	case WLAN_EID_EXT_FILS_NONCE:
2499839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		if (elen != FILS_NONCE_LEN)
2509839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
2519839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		elems->fils_nonce = pos;
2529839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		break;
253d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	case WLAN_EID_EXT_OWE_DH_PARAM:
254d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (elen < 2)
255d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			break;
256d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		elems->owe_dh = pos;
257d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		elems->owe_dh_len = elen;
258d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		break;
2599839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	default:
2609839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		if (show_errors) {
2619839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			wpa_printf(MSG_MSGDUMP,
2629839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt				   "IEEE 802.11 element parsing ignored unknown element extension (ext_id=%u elen=%u)",
2639839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt				   ext_id, (unsigned int) elen);
2649839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		}
2659839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		return -1;
2669839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	}
2679839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt
2689839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	return 0;
2699839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt}
2709839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt
2719839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ieee802_11_parse_elems - Parse information elements in management frames
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @start: Pointer to the start of IEs
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of IE buffer in octets
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @elems: Data structure for parsed elements
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @show_errors: Whether to show parsing errors in debug log
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Parsing result
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct ieee802_11_elems *elems,
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				int show_errors)
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left = len;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos = start;
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int unknown = 0;
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(elems, 0, sizeof(*elems));
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (left >= 2) {
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 id, elen;
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		id = *pos++;
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		elen = *pos++;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		left -= 2;
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (elen > left) {
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (show_errors) {
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "parse failed (id=%d elen=%d "
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "left=%lu)",
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   id, elen, (unsigned long) left);
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return ParseFailed;
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (id) {
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_SSID:
3109d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt			if (elen > SSID_MAX_LEN) {
3119d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt				wpa_printf(MSG_DEBUG,
3129d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt					   "Ignored too long SSID element (elen=%u)",
3139d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt					   elen);
3149d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt				break;
3159d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt			}
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->ssid = pos;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->ssid_len = elen;
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_SUPP_RATES:
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->supp_rates = pos;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->supp_rates_len = elen;
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_DS_PARAMS:
3249d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt			if (elen < 1)
3259d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt				break;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->ds_params = pos;
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_CF_PARAMS:
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_TIM:
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_CHALLENGE:
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->challenge = pos;
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->challenge_len = elen;
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_ERP_INFO:
3369d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt			if (elen < 1)
3379d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt				break;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->erp_info = pos;
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_EXT_SUPP_RATES:
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->ext_supp_rates = pos;
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->ext_supp_rates_len = elen;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_VENDOR_SPECIFIC:
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ieee802_11_parse_vendor_specific(pos, elen,
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							     elems,
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							     show_errors))
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				unknown++;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_RSN:
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->rsn_ie = pos;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->rsn_ie_len = elen;
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_PWR_CAPABILITY:
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_SUPPORTED_CHANNELS:
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->supp_channels = pos;
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->supp_channels_len = elen;
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_MOBILITY_DOMAIN:
3619d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt			if (elen < sizeof(struct rsn_mdie))
3629d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt				break;
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->mdie = pos;
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->mdie_len = elen;
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_FAST_BSS_TRANSITION:
3679d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt			if (elen < sizeof(struct rsn_ftie))
3689d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt				break;
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->ftie = pos;
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->ftie_len = elen;
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_TIMEOUT_INTERVAL:
3739d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt			if (elen != 5)
3749d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt				break;
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->timeout_int = pos;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_HT_CAP:
3789d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt			if (elen < sizeof(struct ieee80211_ht_capabilities))
3799d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt				break;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->ht_capabilities = pos;
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_HT_OPERATION:
3839d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt			if (elen < sizeof(struct ieee80211_ht_operation))
3849d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt				break;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->ht_operation = pos;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		case WLAN_EID_MESH_CONFIG:
3886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			elems->mesh_config = pos;
3896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			elems->mesh_config_len = elen;
3906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			break;
3916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		case WLAN_EID_MESH_ID:
3926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			elems->mesh_id = pos;
3936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			elems->mesh_id_len = elen;
3946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			break;
3956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		case WLAN_EID_PEER_MGMT:
3966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			elems->peer_mgmt = pos;
3976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			elems->peer_mgmt_len = elen;
3986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			break;
39961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		case WLAN_EID_VHT_CAP:
4009d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt			if (elen < sizeof(struct ieee80211_vht_capabilities))
4019d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt				break;
40261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			elems->vht_capabilities = pos;
40361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
40461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		case WLAN_EID_VHT_OPERATION:
4059d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt			if (elen < sizeof(struct ieee80211_vht_operation))
4069d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt				break;
40761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			elems->vht_operation = pos;
40861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
409bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
410bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt			if (elen != 1)
411bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt				break;
412bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt			elems->vht_opmode_notif = pos;
413bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt			break;
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_EID_LINK_ID:
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (elen < 18)
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			elems->link_id = pos;
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		case WLAN_EID_INTERWORKING:
4201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			elems->interworking = pos;
4211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			elems->interworking_len = elen;
4221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			break;
423051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		case WLAN_EID_QOS_MAP_SET:
424051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			if (elen < 16)
425051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				break;
426051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			elems->qos_map_set = pos;
427051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			elems->qos_map_set_len = elen;
428051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			break;
42904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		case WLAN_EID_EXT_CAPAB:
43004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			elems->ext_capab = pos;
43104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			elems->ext_capab_len = elen;
43204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			break;
43304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		case WLAN_EID_BSS_MAX_IDLE_PERIOD:
43404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			if (elen < 3)
43504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				break;
43604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			elems->bss_max_idle_period = pos;
43704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			break;
438a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		case WLAN_EID_SSID_LIST:
439a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			elems->ssid_list = pos;
440a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			elems->ssid_list_len = elen;
441a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			break;
4426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		case WLAN_EID_AMPE:
4436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			elems->ampe = pos;
4446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			elems->ampe_len = elen;
4456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			break;
4466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		case WLAN_EID_MIC:
4476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			elems->mic = pos;
4486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			elems->mic_len = elen;
4496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			/* after mic everything is encrypted, so stop. */
4506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			left = elen;
4516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			break;
452d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		case WLAN_EID_MULTI_BAND:
453d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			if (elems->mb_ies.nof_ies >= MAX_NOF_MB_IES_SUPPORTED) {
454d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				wpa_printf(MSG_MSGDUMP,
455d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					   "IEEE 802.11 element parse ignored MB IE (id=%d elen=%d)",
456d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					   id, elen);
457d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				break;
458d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			}
459d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
460d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			elems->mb_ies.ies[elems->mb_ies.nof_ies].ie = pos;
461d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen;
462d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			elems->mb_ies.nof_ies++;
463d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
4649c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt		case WLAN_EID_SUPPORTED_OPERATING_CLASSES:
4659c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt			elems->supp_op_classes = pos;
4669c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt			elems->supp_op_classes_len = elen;
4679c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt			break;
468849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt		case WLAN_EID_RRM_ENABLED_CAPABILITIES:
469849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt			elems->rrm_enabled = pos;
470849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt			elems->rrm_enabled_len = elen;
471849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt			break;
4729839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		case WLAN_EID_CAG_NUMBER:
4739839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			elems->cag_number = pos;
4749839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			elems->cag_number_len = elen;
4759839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
4769839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		case WLAN_EID_AP_CSN:
4779839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			if (elen < 1)
4789839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt				break;
4799839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			elems->ap_csn = pos;
4809839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
4819839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		case WLAN_EID_FILS_INDICATION:
4829839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			if (elen < 2)
4839839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt				break;
4849839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			elems->fils_indic = pos;
4859839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			elems->fils_indic_len = elen;
4869839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
4879839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		case WLAN_EID_DILS:
4889839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			if (elen < 2)
4899839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt				break;
4909839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			elems->dils = pos;
4919839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			elems->dils_len = elen;
4929839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
4939839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		case WLAN_EID_FRAGMENT:
4949839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			/* TODO */
4959839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
4969839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		case WLAN_EID_EXTENSION:
4979839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			if (ieee802_11_parse_extension(pos, elen, elems,
4989839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt						       show_errors))
4999839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt				unknown++;
5009839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			break;
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			unknown++;
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!show_errors)
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "ignored unknown element (id=%d elen=%d)",
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   id, elen);
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		left -= elen;
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += elen;
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left)
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return ParseFailed;
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return unknown ? ParseUnknown : ParseOK;
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ieee802_11_ie_count(const u8 *ies, size_t ies_len)
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int count = 0;
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ies == NULL)
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = ies;
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = ies + ies_len;
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
533d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	while (end - pos >= 2) {
534d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (2 + pos[1] > end - pos)
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2 + pos[1];
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return count;
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    u32 oui_type)
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *end, *pos, *ie;
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = ies;
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = ies + ies_len;
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ie = NULL;
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
554d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	while (end - pos > 1) {
555d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (2 + pos[1] > end - pos)
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    WPA_GET_BE32(&pos[2]) == oui_type) {
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ie = pos;
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2 + pos[1];
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie == NULL)
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL; /* No specified vendor IE found */
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = wpabuf_alloc(ies_len);
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * There may be multiple vendor IEs in the message, so need to
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * concatenate their data fields.
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
576d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	while (end - pos > 1) {
577d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (2 + pos[1] > end - pos)
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    WPA_GET_BE32(&pos[2]) == oui_type)
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_put_data(buf, pos + 6, pos[1] - 4);
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2 + pos[1];
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
5901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
5911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u16 fc, type, stype;
5921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/*
5941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 * PS-Poll frames are 16 bytes. All other frames are
5951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 * 24 bytes or longer.
5961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 */
5971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (len < 16)
5981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
5991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	fc = le_to_host16(hdr->frame_control);
6011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	type = WLAN_FC_GET_TYPE(fc);
6021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	stype = WLAN_FC_GET_STYPE(fc);
6031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (type) {
6051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WLAN_FC_TYPE_DATA:
6061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (len < 24)
6071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return NULL;
6081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
6091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		case WLAN_FC_FROMDS | WLAN_FC_TODS:
6101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		case WLAN_FC_TODS:
6111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return hdr->addr1;
6121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		case WLAN_FC_FROMDS:
6131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return hdr->addr2;
6141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		default:
6151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return NULL;
6161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
6171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WLAN_FC_TYPE_CTRL:
6181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (stype != WLAN_FC_STYPE_PSPOLL)
6191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return NULL;
6201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return hdr->addr1;
6211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WLAN_FC_TYPE_MGMT:
6221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return hdr->addr3;
6231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	default:
6241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
6251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
6261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
62761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
62861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
62961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
63061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			  const char *name, const char *val)
63161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
63261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int num, v;
63361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const char *pos;
63461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct hostapd_wmm_ac_params *ac;
63561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
63661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	/* skip 'wme_ac_' or 'wmm_ac_' prefix */
63761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = name + 7;
63861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (os_strncmp(pos, "be_", 3) == 0) {
63961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		num = 0;
64061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += 3;
64161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (os_strncmp(pos, "bk_", 3) == 0) {
64261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		num = 1;
64361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += 3;
64461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (os_strncmp(pos, "vi_", 3) == 0) {
64561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		num = 2;
64661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += 3;
64761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (os_strncmp(pos, "vo_", 3) == 0) {
64861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		num = 3;
64961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += 3;
65061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else {
65161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
65261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
65361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
65461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
65561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ac = &wmm_ac_params[num];
65661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
65761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (os_strcmp(pos, "aifs") == 0) {
65861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		v = atoi(val);
65961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (v < 1 || v > 255) {
66061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
66161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
66261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
66361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		ac->aifs = v;
66461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (os_strcmp(pos, "cwmin") == 0) {
66561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		v = atoi(val);
6664171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt		if (v < 0 || v > 15) {
66761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
66861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
66961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
67061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		ac->cwmin = v;
67161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (os_strcmp(pos, "cwmax") == 0) {
67261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		v = atoi(val);
6734171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt		if (v < 0 || v > 15) {
67461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
67561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
67661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
67761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		ac->cwmax = v;
67861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (os_strcmp(pos, "txop_limit") == 0) {
67961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		v = atoi(val);
68061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (v < 0 || v > 0xffff) {
68161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
68261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
68361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
68461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		ac->txop_limit = v;
68561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (os_strcmp(pos, "acm") == 0) {
68661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		v = atoi(val);
68761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (v < 0 || v > 1) {
68861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
68961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
69061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
69161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		ac->admission_control_mandatory = v;
69261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else {
69361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
69461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
69561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
69661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
69761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
69861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
6994b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt
7004b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt
7014b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidtenum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
7024b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt{
703d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u8 op_class;
704d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
705d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return ieee80211_freq_to_channel_ext(freq, 0, VHT_CHANWIDTH_USE_HT,
706d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					     &op_class, channel);
707d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
708d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
709d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
710d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/**
711d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * ieee80211_freq_to_channel_ext - Convert frequency into channel info
712d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * for HT40 and VHT. DFS channels are not covered.
713d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * @freq: Frequency (MHz) to convert
714d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * @sec_channel: 0 = non-HT40, 1 = sec. channel above, -1 = sec. channel below
715d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * @vht: VHT channel width (VHT_CHANWIDTH_*)
716d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * @op_class: Buffer for returning operating class
717d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * @channel: Buffer for returning channel number
718d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * Returns: hw_mode on success, NUM_HOSTAPD_MODES on failure
719d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt */
720d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtenum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
721d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt						   int sec_channel, int vht,
722d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt						   u8 *op_class, u8 *channel)
723d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
724d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u8 vht_opclass;
725d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
726d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	/* TODO: more operating classes */
727d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
728d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (sec_channel > 1 || sec_channel < -1)
729d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return NUM_HOSTAPD_MODES;
7304b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt
7314b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	if (freq >= 2412 && freq <= 2472) {
732d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if ((freq - 2407) % 5)
733d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return NUM_HOSTAPD_MODES;
734d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
735d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (vht)
736d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return NUM_HOSTAPD_MODES;
737d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
738d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		/* 2.407 GHz, channels 1..13 */
739d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (sec_channel == 1)
740d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = 83;
741d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		else if (sec_channel == -1)
742d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = 84;
743d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		else
744d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = 81;
745d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
7464b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		*channel = (freq - 2407) / 5;
747d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
748d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return HOSTAPD_MODE_IEEE80211G;
749d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
750d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
751d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (freq == 2484) {
752d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (sec_channel || vht)
753d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return NUM_HOSTAPD_MODES;
754d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
755d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		*op_class = 82; /* channel 14 */
7564b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		*channel = 14;
757d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
758d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return HOSTAPD_MODE_IEEE80211B;
759d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
760d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
761d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (freq >= 4900 && freq < 5000) {
762d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if ((freq - 4000) % 5)
763d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return NUM_HOSTAPD_MODES;
7644b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		*channel = (freq - 4000) / 5;
765d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		*op_class = 0; /* TODO */
766d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return HOSTAPD_MODE_IEEE80211A;
767d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
768d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
769d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	switch (vht) {
770d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case VHT_CHANWIDTH_80MHZ:
771d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		vht_opclass = 128;
772d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		break;
773d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case VHT_CHANWIDTH_160MHZ:
774d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		vht_opclass = 129;
775d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		break;
776d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case VHT_CHANWIDTH_80P80MHZ:
777d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		vht_opclass = 130;
778d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		break;
779d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	default:
780d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		vht_opclass = 0;
781d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		break;
782d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
783d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
784d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	/* 5 GHz, channels 36..48 */
785d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (freq >= 5180 && freq <= 5240) {
786d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if ((freq - 5000) % 5)
787d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return NUM_HOSTAPD_MODES;
788d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
789d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (vht_opclass)
790d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = vht_opclass;
791d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		else if (sec_channel == 1)
792d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = 116;
793d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		else if (sec_channel == -1)
794d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = 117;
795d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		else
796d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = 115;
797d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
7984b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		*channel = (freq - 5000) / 5;
799d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
800d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return HOSTAPD_MODE_IEEE80211A;
801d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
802d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
8039839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	/* 5 GHz, channels 52..64 */
8049839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	if (freq >= 5260 && freq <= 5320) {
8059839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		if ((freq - 5000) % 5)
8069839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			return NUM_HOSTAPD_MODES;
8079839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt
8089839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		if (vht_opclass)
8099839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			*op_class = vht_opclass;
8109839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		else if (sec_channel == 1)
8119839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			*op_class = 119;
8129839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		else if (sec_channel == -1)
8139839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			*op_class = 120;
8149839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		else
8159839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt			*op_class = 118;
8169839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt
8179839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		*channel = (freq - 5000) / 5;
8189839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt
8199839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt		return HOSTAPD_MODE_IEEE80211A;
8209839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt	}
8219839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt
822d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	/* 5 GHz, channels 149..169 */
823d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (freq >= 5745 && freq <= 5845) {
824d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if ((freq - 5000) % 5)
825d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return NUM_HOSTAPD_MODES;
826d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
827d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (vht_opclass)
828d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = vht_opclass;
829d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		else if (sec_channel == 1)
830d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = 126;
831d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		else if (sec_channel == -1)
832d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = 127;
833d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		else if (freq <= 5805)
834d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = 124;
835d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		else
836d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = 125;
837d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
838d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		*channel = (freq - 5000) / 5;
839d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
840d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return HOSTAPD_MODE_IEEE80211A;
841d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
842d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
843d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	/* 5 GHz, channels 100..140 */
844d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (freq >= 5000 && freq <= 5700) {
845d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if ((freq - 5000) % 5)
846d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return NUM_HOSTAPD_MODES;
847d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
848d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (vht_opclass)
849d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = vht_opclass;
850d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		else if (sec_channel == 1)
851d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = 122;
852d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		else if (sec_channel == -1)
853d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = 123;
854d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		else
855d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*op_class = 121;
856d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
857d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		*channel = (freq - 5000) / 5;
858d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
859d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return HOSTAPD_MODE_IEEE80211A;
860d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
861d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
862d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (freq >= 5000 && freq < 5900) {
863d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if ((freq - 5000) % 5)
864d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return NUM_HOSTAPD_MODES;
865d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		*channel = (freq - 5000) / 5;
866d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		*op_class = 0; /* TODO */
867d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return HOSTAPD_MODE_IEEE80211A;
868d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
869d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
870d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	/* 56.16 GHz, channel 1..4 */
871d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
872d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (sec_channel || vht)
873d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return NUM_HOSTAPD_MODES;
874d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
8754b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		*channel = (freq - 56160) / 2160;
876d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		*op_class = 180;
877d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
878d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return HOSTAPD_MODE_IEEE80211AD;
8794b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	}
8804b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt
881d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return NUM_HOSTAPD_MODES;
8824b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt}
88334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
88434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
8851d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic const char *const us_op_class_cc[] = {
8866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	"US", "CA", NULL
8876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt};
8886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
8891d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic const char *const eu_op_class_cc[] = {
8906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	"AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE",
8916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	"DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT",
8926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	"LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT",
8936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	"RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL
8946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt};
8956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
8961d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic const char *const jp_op_class_cc[] = {
8976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	"JP", NULL
8986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt};
8996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9001d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic const char *const cn_op_class_cc[] = {
901a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	"CN", NULL
9026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt};
9036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9051d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic int country_match(const char *const cc[], const char *const country)
9066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
9076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	int i;
9086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (country == NULL)
9106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 0;
9116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	for (i = 0; cc[i]; i++) {
9126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (cc[i][0] == country[0] && cc[i][1] == country[1])
9136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return 1;
9146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
9156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return 0;
9176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
9186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
9216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
9226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	switch (op_class) {
9236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 12: /* channels 1..11 */
9246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 32: /* channels 1..7; 40 MHz */
9256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 33: /* channels 5..11; 40 MHz */
9266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 1 || chan > 11)
9276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
9286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 2407 + 5 * chan;
9296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 1: /* channels 36,40,44,48 */
9306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 2: /* channels 52,56,60,64; dfs */
9316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 22: /* channels 36,44; 40 MHz */
9326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 23: /* channels 52,60; 40 MHz */
9336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 27: /* channels 40,48; 40 MHz */
9346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 28: /* channels 56,64; 40 MHz */
9356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 36 || chan > 64)
9366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
9376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
9386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 4: /* channels 100-144 */
9396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 24: /* channels 100-140; 40 MHz */
9406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 100 || chan > 144)
9416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
9426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
9436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 3: /* channels 149,153,157,161 */
9446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 25: /* channels 149,157; 40 MHz */
9456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 26: /* channels 149,157; 40 MHz */
9466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 30: /* channels 153,161; 40 MHz */
9476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 31: /* channels 153,161; 40 MHz */
9486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 149 || chan > 161)
9496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
9506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
951a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	case 5: /* channels 149,153,157,161,165 */
952a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		if (chan < 149 || chan > 165)
953a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			return -1;
954a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		return 5000 + 5 * chan;
9556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 34: /* 60 GHz band, channels 1..3 */
9566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 1 || chan > 3)
9576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
9586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 56160 + 2160 * chan;
9596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
9606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return -1;
9616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
9626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
9656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
9666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	switch (op_class) {
9676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 4: /* channels 1..13 */
9686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 11: /* channels 1..9; 40 MHz */
9696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 12: /* channels 5..13; 40 MHz */
9706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 1 || chan > 13)
9716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
9726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 2407 + 5 * chan;
9736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 1: /* channels 36,40,44,48 */
9746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 2: /* channels 52,56,60,64; dfs */
9756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 5: /* channels 36,44; 40 MHz */
9766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 6: /* channels 52,60; 40 MHz */
9776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 8: /* channels 40,48; 40 MHz */
9786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 9: /* channels 56,64; 40 MHz */
9796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 36 || chan > 64)
9806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
9816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
9826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 3: /* channels 100-140 */
9836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 7: /* channels 100-132; 40 MHz */
9846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 10: /* channels 104-136; 40 MHz */
9856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 16: /* channels 100-140 */
9866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 100 || chan > 140)
9876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
9886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
9896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 17: /* channels 149,153,157,161,165,169 */
9906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 149 || chan > 169)
9916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
9926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
9936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 18: /* 60 GHz band, channels 1..4 */
9946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 1 || chan > 4)
9956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
9966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 56160 + 2160 * chan;
9976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
9986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return -1;
9996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
10006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
10036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
10046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	switch (op_class) {
10056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 30: /* channels 1..13 */
10066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 56: /* channels 1..9; 40 MHz */
10076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 57: /* channels 5..13; 40 MHz */
10086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 1 || chan > 13)
10096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
10106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 2407 + 5 * chan;
10116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 31: /* channel 14 */
10126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan != 14)
10136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
10146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 2414 + 5 * chan;
10156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */
10166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 32: /* channels 52,56,60,64 */
10176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 33: /* channels 52,56,60,64 */
10186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 36: /* channels 36,44; 40 MHz */
10196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 37: /* channels 52,60; 40 MHz */
10206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 38: /* channels 52,60; 40 MHz */
10216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 41: /* channels 40,48; 40 MHz */
10226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 42: /* channels 56,64; 40 MHz */
10236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 43: /* channels 56,64; 40 MHz */
10246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 34 || chan > 64)
10256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
10266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
10276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 34: /* channels 100-140 */
10286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 35: /* channels 100-140 */
10296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 39: /* channels 100-132; 40 MHz */
10306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 40: /* channels 100-132; 40 MHz */
10316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 44: /* channels 104-136; 40 MHz */
10326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 45: /* channels 104-136; 40 MHz */
10336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 58: /* channels 100-140 */
10346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 100 || chan > 140)
10356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
10366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
10376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 59: /* 60 GHz band, channels 1..4 */
10386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 1 || chan > 3)
10396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
10406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 56160 + 2160 * chan;
10416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
10426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return -1;
10436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
10446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
10476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
10486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	switch (op_class) {
10496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 7: /* channels 1..13 */
10506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 8: /* channels 1..9; 40 MHz */
10516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 9: /* channels 5..13; 40 MHz */
10526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 1 || chan > 13)
10536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
10546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 2407 + 5 * chan;
10556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 1: /* channels 36,40,44,48 */
10566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 2: /* channels 52,56,60,64; dfs */
10576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 4: /* channels 36,44; 40 MHz */
10586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 5: /* channels 52,60; 40 MHz */
10596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 36 || chan > 64)
10606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
10616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
10626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 3: /* channels 149,153,157,161,165 */
10636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 6: /* channels 149,157; 40 MHz */
10646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 149 || chan > 165)
10656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
10666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
10676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
10686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return -1;
10696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
10706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
10736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
10746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
10756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	switch (op_class) {
10766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 81:
10776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/* channels 1..13 */
10786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 1 || chan > 13)
10796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
10806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 2407 + 5 * chan;
10816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 82:
10826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/* channel 14 */
10836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan != 14)
10846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
10856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 2414 + 5 * chan;
10866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 83: /* channels 1..9; 40 MHz */
10876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 84: /* channels 5..13; 40 MHz */
10886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 1 || chan > 13)
10896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
10906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 2407 + 5 * chan;
10916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 115: /* channels 36,40,44,48; indoor only */
10926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 116: /* channels 36,44; 40 MHz; indoor only */
10936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 117: /* channels 40,48; 40 MHz; indoor only */
10946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 118: /* channels 52,56,60,64; dfs */
10956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 119: /* channels 52,60; 40 MHz; dfs */
10966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 120: /* channels 56,64; 40 MHz; dfs */
10976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 36 || chan > 64)
10986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
10996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
11006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 121: /* channels 100-140 */
11016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 122: /* channels 100-142; 40 MHz */
11026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 123: /* channels 104-136; 40 MHz */
11036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 100 || chan > 140)
11046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
11056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
11066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 124: /* channels 149,153,157,161 */
11076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 126: /* channels 149,157; 40 MHz */
11086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 127: /* channels 153,161; 40 MHz */
11096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 149 || chan > 161)
11106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
11116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
1112a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt	case 125: /* channels 149,153,157,161,165,169 */
1113a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		if (chan < 149 || chan > 169)
1114a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt			return -1;
1115a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt		return 5000 + 5 * chan;
11166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
11176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
11186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 36 || chan > 161)
11196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
11206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
11216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 129: /* center freqs 50, 114; 160 MHz */
1122d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (chan < 36 || chan > 128)
11236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
11246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 5000 + 5 * chan;
11256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case 180: /* 60 GHz band, channels 1..4 */
11266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (chan < 1 || chan > 4)
11276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
11286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 56160 + 2160 * chan;
11296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
11306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return -1;
11316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
11326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
11336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/**
11346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * ieee80211_chan_to_freq - Convert channel info to frequency
11356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @country: Country code, if known; otherwise, global operating class is used
11366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @op_class: Operating class
11376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @chan: Channel number
11386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Returns: Frequency in MHz or -1 if the specified channel is unknown
11396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */
11406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
11416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
11426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	int freq;
11436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
11446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (country_match(us_op_class_cc, country)) {
11456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		freq = ieee80211_chan_to_freq_us(op_class, chan);
11466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (freq > 0)
11476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return freq;
11486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
11496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
11506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (country_match(eu_op_class_cc, country)) {
11516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		freq = ieee80211_chan_to_freq_eu(op_class, chan);
11526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (freq > 0)
11536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return freq;
11546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
11556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
11566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (country_match(jp_op_class_cc, country)) {
11576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		freq = ieee80211_chan_to_freq_jp(op_class, chan);
11586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (freq > 0)
11596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return freq;
11606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
11616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
11626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (country_match(cn_op_class_cc, country)) {
11636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		freq = ieee80211_chan_to_freq_cn(op_class, chan);
11646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (freq > 0)
11656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return freq;
11666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
11676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
11686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return ieee80211_chan_to_freq_global(op_class, chan);
11696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
11706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
11716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1172203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidtint ieee80211_is_dfs(int freq)
1173203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt{
1174203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	/* TODO: this could be more accurate to better cover all domains */
1175203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700);
1176203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt}
1177203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt
1178203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt
117934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int is_11b(u8 rate)
118034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
118134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
118234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
118334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
118434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
118534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtint supp_rates_11b_only(struct ieee802_11_elems *elems)
118634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
118734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	int num_11b = 0, num_others = 0;
118834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	int i;
118934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
119034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
119134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 0;
119234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
119334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
119434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		if (is_11b(elems->supp_rates[i]))
119534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			num_11b++;
119634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		else
119734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			num_others++;
119834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
119934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
120034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
120134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	     i++) {
120234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		if (is_11b(elems->ext_supp_rates[i]))
120334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			num_11b++;
120434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		else
120534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			num_others++;
120634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
120734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
120834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return num_11b > 0 && num_others == 0;
120934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
12102271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt
12112271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt
12122271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidtconst char * fc2str(u16 fc)
12132271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt{
12142271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	u16 stype = WLAN_FC_GET_STYPE(fc);
12152271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt#define C2S(x) case x: return #x;
12162271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt
12172271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	switch (WLAN_FC_GET_TYPE(fc)) {
12182271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	case WLAN_FC_TYPE_MGMT:
12192271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		switch (stype) {
12202271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_ASSOC_REQ)
12212271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_ASSOC_RESP)
12222271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_REASSOC_REQ)
12232271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_REASSOC_RESP)
12242271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_PROBE_REQ)
12252271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_PROBE_RESP)
12262271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_BEACON)
12272271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_ATIM)
12282271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_DISASSOC)
12292271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_AUTH)
12302271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_DEAUTH)
12312271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_ACTION)
12322271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		}
12332271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		break;
12342271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	case WLAN_FC_TYPE_CTRL:
12352271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		switch (stype) {
12362271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_PSPOLL)
12372271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_RTS)
12382271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_CTS)
12392271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_ACK)
12402271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_CFEND)
12412271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_CFENDACK)
12422271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		}
12432271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		break;
12442271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	case WLAN_FC_TYPE_DATA:
12452271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		switch (stype) {
12462271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_DATA)
12472271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_DATA_CFACK)
12482271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_DATA_CFPOLL)
12492271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_DATA_CFACKPOLL)
12502271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_NULLFUNC)
12512271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_CFACK)
12522271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_CFPOLL)
12532271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_CFACKPOLL)
12542271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_QOS_DATA)
12552271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_QOS_DATA_CFACK)
12562271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL)
12572271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL)
12582271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_QOS_NULL)
12592271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_QOS_CFPOLL)
12602271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		C2S(WLAN_FC_STYPE_QOS_CFACKPOLL)
12612271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		}
12622271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		break;
12632271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	}
12642271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	return "WLAN_FC_TYPE_UNKNOWN";
12652271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt#undef C2S
12662271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt}
1267d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1268d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1269d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
1270d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		       size_t ies_len)
1271d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
1272d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_memset(info, 0, sizeof(*info));
1273d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1274d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	while (ies_buf && ies_len >= 2 &&
1275d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	       info->nof_ies < MAX_NOF_MB_IES_SUPPORTED) {
1276d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		size_t len = 2 + ies_buf[1];
1277d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1278d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (len > ies_len) {
1279d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "Truncated IEs",
1280d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    ies_buf, ies_len);
1281d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return -1;
1282d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
1283d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1284d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (ies_buf[0] == WLAN_EID_MULTI_BAND) {
1285d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			wpa_printf(MSG_DEBUG, "MB IE of %zu bytes found", len);
1286d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			info->ies[info->nof_ies].ie = ies_buf + 2;
1287d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			info->ies[info->nof_ies].ie_len = ies_buf[1];
1288d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			info->nof_ies++;
1289d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
1290d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1291d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ies_len -= len;
1292d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ies_buf += len;
1293d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
1294d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1295d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return 0;
1296d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
1297d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1298d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1299d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstruct wpabuf * mb_ies_by_info(struct mb_ies_info *info)
1300d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
1301d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct wpabuf *mb_ies = NULL;
1302d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1303d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	WPA_ASSERT(info != NULL);
1304d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1305d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (info->nof_ies) {
1306d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		u8 i;
1307d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		size_t mb_ies_size = 0;
1308d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1309d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		for (i = 0; i < info->nof_ies; i++)
1310d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			mb_ies_size += 2 + info->ies[i].ie_len;
1311d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1312d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		mb_ies = wpabuf_alloc(mb_ies_size);
1313d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (mb_ies) {
1314d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			for (i = 0; i < info->nof_ies; i++) {
1315d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				wpabuf_put_u8(mb_ies, WLAN_EID_MULTI_BAND);
1316d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				wpabuf_put_u8(mb_ies, info->ies[i].ie_len);
1317d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				wpabuf_put_data(mb_ies,
1318d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt						info->ies[i].ie,
1319d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt						info->ies[i].ie_len);
1320d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			}
1321d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
1322d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
1323d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
1324d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return mb_ies;
1325d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
132657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
132757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
132857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtconst struct oper_class_map global_op_class[] = {
132957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20, P2P_SUPP },
133057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211G, 82, 14, 14, 1, BW20, NO_P2P_SUPP },
133157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
133257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	/* Do not enable HT40 on 2.4 GHz for P2P use for now */
133357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211G, 83, 1, 9, 1, BW40PLUS, NO_P2P_SUPP },
133457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211G, 84, 5, 13, 1, BW40MINUS, NO_P2P_SUPP },
133557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
133657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 115, 36, 48, 4, BW20, P2P_SUPP },
133757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 116, 36, 44, 8, BW40PLUS, P2P_SUPP },
133857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS, P2P_SUPP },
133957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 118, 52, 64, 4, BW20, NO_P2P_SUPP },
134057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 119, 52, 60, 8, BW40PLUS, NO_P2P_SUPP },
134157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 120, 56, 64, 8, BW40MINUS, NO_P2P_SUPP },
134257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 121, 100, 140, 4, BW20, NO_P2P_SUPP },
134357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 122, 100, 132, 8, BW40PLUS, NO_P2P_SUPP },
134457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 123, 104, 136, 8, BW40MINUS, NO_P2P_SUPP },
134557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 124, 149, 161, 4, BW20, P2P_SUPP },
134657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 125, 149, 169, 4, BW20, P2P_SUPP },
134757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 126, 149, 157, 8, BW40PLUS, P2P_SUPP },
134857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 127, 153, 161, 8, BW40MINUS, P2P_SUPP },
134957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
135057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	/*
135157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	 * IEEE P802.11ac/D7.0 Table E-4 actually talks about channel center
135257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	 * frequency index 42, 58, 106, 122, 138, 155 with channel spacing of
135357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	 * 80 MHz, but currently use the following definition for simplicity
135457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	 * (these center frequencies are not actual channels, which makes
135557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	 * wpas_p2p_allow_channel() fail). wpas_p2p_verify_80mhz() should take
135657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	 * care of removing invalid channels.
135757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	 */
135857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP },
135957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP },
136057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP },
136157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ HOSTAPD_MODE_IEEE80211AD, 180, 1, 4, 1, BW2160, P2P_SUPP },
136257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	{ -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
136357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt};
136457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
136557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
136657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtstatic enum phy_type ieee80211_phy_type_by_freq(int freq)
136757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{
136857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	enum hostapd_hw_mode hw_mode;
136957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	u8 channel;
137057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
137157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	hw_mode = ieee80211_freq_to_chan(freq, &channel);
137257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
137357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	switch (hw_mode) {
137457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	case HOSTAPD_MODE_IEEE80211A:
137557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		return PHY_TYPE_OFDM;
137657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	case HOSTAPD_MODE_IEEE80211B:
137757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		return PHY_TYPE_HRDSSS;
137857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	case HOSTAPD_MODE_IEEE80211G:
137957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		return PHY_TYPE_ERP;
138057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	case HOSTAPD_MODE_IEEE80211AD:
138157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		return PHY_TYPE_DMG;
138257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	default:
138357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		return PHY_TYPE_UNSPECIFIED;
138457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	};
138557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt}
138657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
138757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
138857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt/* ieee80211_get_phy_type - Derive the phy type by freq and bandwidth */
138957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtenum phy_type ieee80211_get_phy_type(int freq, int ht, int vht)
139057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{
139157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	if (vht)
139257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		return PHY_TYPE_VHT;
139357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	if (ht)
139457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		return PHY_TYPE_HT;
139557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
139657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	return ieee80211_phy_type_by_freq(freq);
139757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt}
139857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
139957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
140057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtsize_t global_op_class_size = ARRAY_SIZE(global_op_class);
140157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
140257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
140357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt/**
140457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * get_ie - Fetch a specified information element from IEs buffer
140557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * @ies: Information elements buffer
140657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * @len: Information elements buffer length
140757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * @eid: Information element identifier (WLAN_EID_*)
140857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * Returns: Pointer to the information element (id field) or %NULL if not found
140957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt *
141057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * This function returns the first matching information element in the IEs
141157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * buffer or %NULL in case the element is not found.
141257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt */
141357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtconst u8 * get_ie(const u8 *ies, size_t len, u8 eid)
141457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{
141557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	const u8 *end;
141657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
141757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	if (!ies)
141857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		return NULL;
141957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
142057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	end = ies + len;
142157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
142257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	while (end - ies > 1) {
142357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		if (2 + ies[1] > end - ies)
142457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt			break;
142557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
142657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		if (ies[0] == eid)
142757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt			return ies;
142857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
142957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		ies += 2 + ies[1];
143057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	}
143157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
143257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	return NULL;
143357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt}
143457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
143557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
1436d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt/**
1437d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * get_ie_ext - Fetch a specified extended information element from IEs buffer
1438d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * @ies: Information elements buffer
1439d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * @len: Information elements buffer length
1440d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * @ext: Information element extension identifier (WLAN_EID_EXT_*)
1441d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * Returns: Pointer to the information element (id field) or %NULL if not found
1442d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt *
1443d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * This function returns the first matching information element in the IEs
1444d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * buffer or %NULL in case the element is not found.
1445d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt */
1446d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidtconst u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext)
1447d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt{
1448d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	const u8 *end;
1449d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1450d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (!ies)
1451d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return NULL;
1452d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1453d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	end = ies + len;
1454d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1455d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	while (end - ies > 1) {
1456d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (2 + ies[1] > end - ies)
1457d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			break;
1458d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1459d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (ies[0] == WLAN_EID_EXTENSION && ies[1] >= 1 &&
1460d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		    ies[2] == ext)
1461d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			return ies;
1462d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1463d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		ies += 2 + ies[1];
1464d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	}
1465d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1466d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	return NULL;
1467d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt}
1468d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1469d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
147057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtsize_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len)
147157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{
147257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	/*
147357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	 * MBO IE requires 6 bytes without the attributes: EID (1), length (1),
147457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	 * OUI (3), OUI type (1).
147557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	 */
147657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	if (len < 6 + attr_len) {
147757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		wpa_printf(MSG_DEBUG,
147857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt			   "MBO: Not enough room in buffer for MBO IE: buf len = %zu, attr_len = %zu",
147957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt			   len, attr_len);
148057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		return 0;
148157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	}
148257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
148357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	*buf++ = WLAN_EID_VENDOR_SPECIFIC;
148457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	*buf++ = attr_len + 4;
148557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	WPA_PUT_BE24(buf, OUI_WFA);
148657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	buf += 3;
148757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	*buf++ = MBO_OUI_TYPE;
148857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	os_memcpy(buf, attr, attr_len);
148957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
149057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	return 6 + attr_len;
149157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt}
1492293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1493293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1494293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidtstatic const struct country_op_class us_op_class[] = {
1495293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 1, 115 },
1496293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 2, 118 },
1497293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 3, 124 },
1498293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 4, 121 },
1499293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 5, 125 },
1500293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 12, 81 },
1501293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 22, 116 },
1502293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 23, 119 },
1503293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 24, 122 },
1504293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 25, 126 },
1505293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 26, 126 },
1506293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 27, 117 },
1507293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 28, 120 },
1508293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 29, 123 },
1509293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 30, 127 },
1510293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 31, 127 },
1511293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 32, 83 },
1512293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 33, 84 },
1513293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 34, 180 },
1514293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt};
1515293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1516293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidtstatic const struct country_op_class eu_op_class[] = {
1517293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 1, 115 },
1518293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 2, 118 },
1519293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 3, 121 },
1520293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 4, 81 },
1521293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 5, 116 },
1522293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 6, 119 },
1523293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 7, 122 },
1524293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 8, 117 },
1525293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 9, 120 },
1526293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 10, 123 },
1527293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 11, 83 },
1528293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 12, 84 },
1529293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 17, 125 },
1530293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 18, 180 },
1531293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt};
1532293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1533293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidtstatic const struct country_op_class jp_op_class[] = {
1534293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 1, 115 },
1535293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 30, 81 },
1536293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 31, 82 },
1537293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 32, 118 },
1538293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 33, 118 },
1539293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 34, 121 },
1540293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 35, 121 },
1541293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 36, 116 },
1542293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 37, 119 },
1543293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 38, 119 },
1544293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 39, 122 },
1545293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 40, 122 },
1546293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 41, 117 },
1547293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 42, 120 },
1548293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 43, 120 },
1549293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 44, 123 },
1550293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 45, 123 },
1551293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 56, 83 },
1552293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 57, 84 },
1553293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 58, 121 },
1554293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 59, 180 },
1555293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt};
1556293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1557293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidtstatic const struct country_op_class cn_op_class[] = {
1558293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 1, 115 },
1559293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 2, 118 },
1560293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 3, 125 },
1561293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 4, 116 },
1562293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 5, 119 },
1563293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 6, 126 },
1564293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 7, 81 },
1565293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 8, 83 },
1566293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	{ 9, 84 },
1567293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt};
1568293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1569293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidtstatic u8
1570293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidtglobal_op_class_from_country_array(u8 op_class, size_t array_size,
1571293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt				   const struct country_op_class *country_array)
1572293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt{
1573293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	size_t i;
1574293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1575293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	for (i = 0; i < array_size; i++) {
1576293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		if (country_array[i].country_op_class == op_class)
1577293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt			return country_array[i].global_op_class;
1578293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	}
1579293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1580293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	return 0;
1581293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt}
1582293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1583293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1584293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidtu8 country_to_global_op_class(const char *country, u8 op_class)
1585293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt{
1586293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	const struct country_op_class *country_array;
1587293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	size_t size;
1588293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	u8 g_op_class;
1589293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1590293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	if (country_match(us_op_class_cc, country)) {
1591293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		country_array = us_op_class;
1592293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		size = ARRAY_SIZE(us_op_class);
1593293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	} else if (country_match(eu_op_class_cc, country)) {
1594293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		country_array = eu_op_class;
1595293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		size = ARRAY_SIZE(eu_op_class);
1596293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	} else if (country_match(jp_op_class_cc, country)) {
1597293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		country_array = jp_op_class;
1598293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		size = ARRAY_SIZE(jp_op_class);
1599293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	} else if (country_match(cn_op_class_cc, country)) {
1600293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		country_array = cn_op_class;
1601293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		size = ARRAY_SIZE(cn_op_class);
1602293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	} else {
1603293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		/*
1604293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		 * Countries that do not match any of the above countries use
1605293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		 * global operating classes
1606293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		 */
1607293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		return op_class;
1608293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	}
1609293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1610293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	g_op_class = global_op_class_from_country_array(op_class, size,
1611293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt							country_array);
1612293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1613293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	/*
1614293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	 * If the given operating class did not match any of the country's
1615293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	 * operating classes, assume that global operating class is used.
1616293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	 */
1617293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	return g_op_class ? g_op_class : op_class;
1618293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt}
1619293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1620293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1621293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidtconst struct oper_class_map * get_oper_class(const char *country, u8 op_class)
1622293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt{
1623293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	const struct oper_class_map *op;
1624293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1625293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	if (country)
1626293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		op_class = country_to_global_op_class(country, op_class);
1627293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1628293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	op = &global_op_class[0];
1629293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	while (op->op_class && op->op_class != op_class)
1630293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		op++;
1631293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1632293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	if (!op->op_class)
1633293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt		return NULL;
1634293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt
1635293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt	return op;
1636293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt}
1637d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1638d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1639d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidtint ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
1640d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				    size_t nei_rep_len)
1641d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt{
1642d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	u8 *nei_pos = nei_rep;
1643d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	const char *end;
1644d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1645d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	/*
1646d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * BSS Transition Candidate List Entries - Neighbor Report elements
1647d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
1648d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
1649d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	 */
1650d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	while (pos) {
1651d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		u8 *nei_start;
1652d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		long int val;
1653d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		char *endptr, *tmp;
1654d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1655d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		pos = os_strstr(pos, " neighbor=");
1656d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (!pos)
1657d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			break;
1658d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (nei_pos + 15 > nei_rep + nei_rep_len) {
1659d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			wpa_printf(MSG_DEBUG,
1660d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				   "Not enough room for additional neighbor");
1661d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			return -1;
1662d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
1663d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		pos += 10;
1664d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1665d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		nei_start = nei_pos;
1666d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		*nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
1667d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		nei_pos++; /* length to be filled in */
1668d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1669d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (hwaddr_aton(pos, nei_pos)) {
1670d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Invalid BSSID");
1671d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			return -1;
1672d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
1673d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		nei_pos += ETH_ALEN;
1674d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		pos += 17;
1675d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (*pos != ',') {
1676d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Missing BSSID Information");
1677d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			return -1;
1678d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
1679d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		pos++;
1680d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1681d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		val = strtol(pos, &endptr, 0);
1682d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		WPA_PUT_LE32(nei_pos, val);
1683d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		nei_pos += 4;
1684d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (*endptr != ',') {
1685d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Missing Operating Class");
1686d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			return -1;
1687d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
1688d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		pos = endptr + 1;
1689d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1690d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		*nei_pos++ = atoi(pos); /* Operating Class */
1691d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		pos = os_strchr(pos, ',');
1692d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (pos == NULL) {
1693d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Missing Channel Number");
1694d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			return -1;
1695d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
1696d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		pos++;
1697d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1698d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		*nei_pos++ = atoi(pos); /* Channel Number */
1699d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		pos = os_strchr(pos, ',');
1700d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (pos == NULL) {
1701d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Missing PHY Type");
1702d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			return -1;
1703d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
1704d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		pos++;
1705d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1706d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		*nei_pos++ = atoi(pos); /* PHY Type */
1707d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		end = os_strchr(pos, ' ');
1708d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		tmp = os_strchr(pos, ',');
1709d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		if (tmp && (!end || tmp < end)) {
1710d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			/* Optional Subelements (hexdump) */
1711d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			size_t len;
1712d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1713d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			pos = tmp + 1;
1714d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			end = os_strchr(pos, ' ');
1715d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			if (end)
1716d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				len = end - pos;
1717d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			else
1718d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				len = os_strlen(pos);
1719d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			if (nei_pos + len / 2 > nei_rep + nei_rep_len) {
1720d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				wpa_printf(MSG_DEBUG,
1721d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt					   "Not enough room for neighbor subelements");
1722d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				return -1;
1723d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			}
1724d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			if (len & 0x01 ||
1725d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			    hexstr2bin(pos, nei_pos, len / 2) < 0) {
1726d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				wpa_printf(MSG_DEBUG,
1727d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt					   "Invalid neighbor subelement info");
1728d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt				return -1;
1729d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			}
1730d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			nei_pos += len / 2;
1731d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt			pos = end;
1732d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		}
1733d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1734d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		nei_start[1] = nei_pos - nei_start - 2;
1735d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	}
1736d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
1737d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	return nei_pos - nei_rep;
1738d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt}
1739