2 * IEEE 802.11 Common routines
3 * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "ieee802_11_defs.h"
13 #include "ieee802_11_common.h"
16 static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
17 struct ieee802_11_elems *elems,
22 /* first 3 bytes in vendor specific information element are the IEEE
23 * OUI of the vendor. The following byte is used a vendor specific
27 wpa_printf(MSG_MSGDUMP, "short vendor specific "
28 "information element ignored (len=%lu)",
29 (unsigned long) elen);
34 oui = WPA_GET_BE24(pos);
37 /* Microsoft/Wi-Fi information elements are further typed and
41 /* Microsoft OUI (00:50:F2) with OUI Type 1:
42 * real WPA information element */
44 elems->wpa_ie_len = elen;
47 /* WMM information element */
49 wpa_printf(MSG_MSGDUMP, "short WMM "
50 "information element ignored "
52 (unsigned long) elen);
56 case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
57 case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
59 * Share same pointer since only one of these
60 * is used and they start with same data.
61 * Length field can be used to distinguish the
65 elems->wmm_len = elen;
67 case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
68 elems->wmm_tspec = pos;
69 elems->wmm_tspec_len = elen;
72 wpa_printf(MSG_EXCESSIVE, "unknown WMM "
73 "information element ignored "
74 "(subtype=%d len=%lu)",
75 pos[4], (unsigned long) elen);
80 /* Wi-Fi Protected Setup (WPS) IE */
82 elems->wps_ie_len = elen;
85 wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
86 "information element ignored "
88 pos[3], (unsigned long) elen);
96 /* Wi-Fi Alliance - P2P IE */
98 elems->p2p_len = elen;
101 /* Wi-Fi Alliance - WFD IE */
103 elems->wfd_len = elen;
105 case HS20_INDICATION_OUI_TYPE:
108 elems->hs20_len = elen;
111 wpa_printf(MSG_MSGDUMP, "Unknown WFA "
112 "information element ignored "
113 "(type=%d len=%lu)\n",
114 pos[3], (unsigned long) elen);
121 case VENDOR_HT_CAPAB_OUI_TYPE:
122 elems->vendor_ht_cap = pos;
123 elems->vendor_ht_cap_len = elen;
126 wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
127 "information element ignored "
129 pos[3], (unsigned long) elen);
135 wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
136 "information element ignored (vendor OUI "
137 "%02x:%02x:%02x len=%lu)",
138 pos[0], pos[1], pos[2], (unsigned long) elen);
147 * ieee802_11_parse_elems - Parse information elements in management frames
148 * @start: Pointer to the start of IEs
149 * @len: Length of IE buffer in octets
150 * @elems: Data structure for parsed elements
151 * @show_errors: Whether to show parsing errors in debug log
152 * Returns: Parsing result
154 ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
155 struct ieee802_11_elems *elems,
159 const u8 *pos = start;
162 os_memset(elems, 0, sizeof(*elems));
173 wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
174 "parse failed (id=%d elen=%d "
176 id, elen, (unsigned long) left);
177 wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
185 elems->ssid_len = elen;
187 case WLAN_EID_SUPP_RATES:
188 elems->supp_rates = pos;
189 elems->supp_rates_len = elen;
191 case WLAN_EID_FH_PARAMS:
192 elems->fh_params = pos;
193 elems->fh_params_len = elen;
195 case WLAN_EID_DS_PARAMS:
196 elems->ds_params = pos;
197 elems->ds_params_len = elen;
199 case WLAN_EID_CF_PARAMS:
200 elems->cf_params = pos;
201 elems->cf_params_len = elen;
205 elems->tim_len = elen;
207 case WLAN_EID_IBSS_PARAMS:
208 elems->ibss_params = pos;
209 elems->ibss_params_len = elen;
211 case WLAN_EID_CHALLENGE:
212 elems->challenge = pos;
213 elems->challenge_len = elen;
215 case WLAN_EID_ERP_INFO:
216 elems->erp_info = pos;
217 elems->erp_info_len = elen;
219 case WLAN_EID_EXT_SUPP_RATES:
220 elems->ext_supp_rates = pos;
221 elems->ext_supp_rates_len = elen;
223 case WLAN_EID_VENDOR_SPECIFIC:
224 if (ieee802_11_parse_vendor_specific(pos, elen,
231 elems->rsn_ie_len = elen;
233 case WLAN_EID_PWR_CAPABILITY:
234 elems->power_cap = pos;
235 elems->power_cap_len = elen;
237 case WLAN_EID_SUPPORTED_CHANNELS:
238 elems->supp_channels = pos;
239 elems->supp_channels_len = elen;
241 case WLAN_EID_MOBILITY_DOMAIN:
243 elems->mdie_len = elen;
245 case WLAN_EID_FAST_BSS_TRANSITION:
247 elems->ftie_len = elen;
249 case WLAN_EID_TIMEOUT_INTERVAL:
250 elems->timeout_int = pos;
251 elems->timeout_int_len = elen;
253 case WLAN_EID_HT_CAP:
254 elems->ht_capabilities = pos;
255 elems->ht_capabilities_len = elen;
257 case WLAN_EID_HT_OPERATION:
258 elems->ht_operation = pos;
259 elems->ht_operation_len = elen;
261 case WLAN_EID_VHT_CAP:
262 elems->vht_capabilities = pos;
263 elems->vht_capabilities_len = elen;
265 case WLAN_EID_VHT_OPERATION:
266 elems->vht_operation = pos;
267 elems->vht_operation_len = elen;
269 case WLAN_EID_LINK_ID:
272 elems->link_id = pos;
274 case WLAN_EID_INTERWORKING:
275 elems->interworking = pos;
276 elems->interworking_len = elen;
278 case WLAN_EID_EXT_CAPAB:
279 elems->ext_capab = pos;
280 elems->ext_capab_len = elen;
282 case WLAN_EID_BSS_MAX_IDLE_PERIOD:
285 elems->bss_max_idle_period = pos;
287 case WLAN_EID_SSID_LIST:
288 elems->ssid_list = pos;
289 elems->ssid_list_len = elen;
295 wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
296 "ignored unknown element (id=%d elen=%d)",
308 return unknown ? ParseUnknown : ParseOK;
312 int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
323 while (pos + 2 <= end) {
324 if (pos + 2 + pos[1] > end)
334 struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
338 const u8 *end, *pos, *ie;
344 while (pos + 1 < end) {
345 if (pos + 2 + pos[1] > end)
347 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
348 WPA_GET_BE32(&pos[2]) == oui_type) {
356 return NULL; /* No specified vendor IE found */
358 buf = wpabuf_alloc(ies_len);
363 * There may be multiple vendor IEs in the message, so need to
364 * concatenate their data fields.
366 while (pos + 1 < end) {
367 if (pos + 2 + pos[1] > end)
369 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
370 WPA_GET_BE32(&pos[2]) == oui_type)
371 wpabuf_put_data(buf, pos + 6, pos[1] - 4);
379 const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
384 * PS-Poll frames are 16 bytes. All other frames are
385 * 24 bytes or longer.
390 fc = le_to_host16(hdr->frame_control);
391 type = WLAN_FC_GET_TYPE(fc);
392 stype = WLAN_FC_GET_STYPE(fc);
395 case WLAN_FC_TYPE_DATA:
398 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
399 case WLAN_FC_FROMDS | WLAN_FC_TODS:
407 case WLAN_FC_TYPE_CTRL:
408 if (stype != WLAN_FC_STYPE_PSPOLL)
411 case WLAN_FC_TYPE_MGMT:
419 int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
420 const char *name, const char *val)
424 struct hostapd_wmm_ac_params *ac;
426 /* skip 'wme_ac_' or 'wmm_ac_' prefix */
428 if (os_strncmp(pos, "be_", 3) == 0) {
431 } else if (os_strncmp(pos, "bk_", 3) == 0) {
434 } else if (os_strncmp(pos, "vi_", 3) == 0) {
437 } else if (os_strncmp(pos, "vo_", 3) == 0) {
441 wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
445 ac = &wmm_ac_params[num];
447 if (os_strcmp(pos, "aifs") == 0) {
449 if (v < 1 || v > 255) {
450 wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
454 } else if (os_strcmp(pos, "cwmin") == 0) {
456 if (v < 0 || v > 12) {
457 wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
461 } else if (os_strcmp(pos, "cwmax") == 0) {
463 if (v < 0 || v > 12) {
464 wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
468 } else if (os_strcmp(pos, "txop_limit") == 0) {
470 if (v < 0 || v > 0xffff) {
471 wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
475 } else if (os_strcmp(pos, "acm") == 0) {
477 if (v < 0 || v > 1) {
478 wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
481 ac->admission_control_mandatory = v;
483 wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);