1 /* 2 * IEEE 802.11 Common routines 3 * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 17 #include "common.h" 18 #include "ieee802_11_defs.h" 19 #include "ieee802_11_common.h" 20 21 22 static int ieee802_11_parse_vendor_specific(u8 *pos, size_t elen, 23 struct ieee802_11_elems *elems, 24 int show_errors) 25 { 26 unsigned int oui; 27 28 /* first 3 bytes in vendor specific information element are the IEEE 29 * OUI of the vendor. The following byte is used a vendor specific 30 * sub-type. */ 31 if (elen < 4) { 32 if (show_errors) { 33 wpa_printf(MSG_MSGDUMP, "short vendor specific " 34 "information element ignored (len=%lu)", 35 (unsigned long) elen); 36 } 37 return -1; 38 } 39 40 oui = WPA_GET_BE24(pos); 41 switch (oui) { 42 case OUI_MICROSOFT: 43 /* Microsoft/Wi-Fi information elements are further typed and 44 * subtyped */ 45 switch (pos[3]) { 46 case 1: 47 /* Microsoft OUI (00:50:F2) with OUI Type 1: 48 * real WPA information element */ 49 elems->wpa_ie = pos; 50 elems->wpa_ie_len = elen; 51 break; 52 case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */ 53 if (elen < 5) { 54 wpa_printf(MSG_MSGDUMP, "short WME " 55 "information element ignored " 56 "(len=%lu)", 57 (unsigned long) elen); 58 return -1; 59 } 60 switch (pos[4]) { 61 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT: 62 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT: 63 elems->wme = pos; 64 elems->wme_len = elen; 65 break; 66 case WME_OUI_SUBTYPE_TSPEC_ELEMENT: 67 elems->wme_tspec = pos; 68 elems->wme_tspec_len = elen; 69 break; 70 default: 71 wpa_printf(MSG_MSGDUMP, "unknown WME " 72 "information element ignored " 73 "(subtype=%d len=%lu)", 74 pos[4], (unsigned long) elen); 75 return -1; 76 } 77 break; 78 case 4: 79 /* Wi-Fi Protected Setup (WPS) IE */ 80 elems->wps_ie = pos; 81 elems->wps_ie_len = elen; 82 break; 83 default: 84 wpa_printf(MSG_MSGDUMP, "Unknown Microsoft " 85 "information element ignored " 86 "(type=%d len=%lu)\n", 87 pos[3], (unsigned long) elen); 88 return -1; 89 } 90 break; 91 92 case OUI_BROADCOM: 93 switch (pos[3]) { 94 case VENDOR_HT_CAPAB_OUI_TYPE: 95 elems->vendor_ht_cap = pos; 96 elems->vendor_ht_cap_len = elen; 97 break; 98 default: 99 wpa_printf(MSG_MSGDUMP, "Unknown Broadcom " 100 "information element ignored " 101 "(type=%d len=%lu)\n", 102 pos[3], (unsigned long) elen); 103 return -1; 104 } 105 break; 106 107 default: 108 wpa_printf(MSG_MSGDUMP, "unknown vendor specific information " 109 "element ignored (vendor OUI %02x:%02x:%02x " 110 "len=%lu)", 111 pos[0], pos[1], pos[2], (unsigned long) elen); 112 return -1; 113 } 114 115 return 0; 116 } 117 118 119 /** 120 * ieee802_11_parse_elems - Parse information elements in management frames 121 * @start: Pointer to the start of IEs 122 * @len: Length of IE buffer in octets 123 * @elems: Data structure for parsed elements 124 * @show_errors: Whether to show parsing errors in debug log 125 * Returns: Parsing result 126 */ 127 ParseRes ieee802_11_parse_elems(u8 *start, size_t len, 128 struct ieee802_11_elems *elems, 129 int show_errors) 130 { 131 size_t left = len; 132 u8 *pos = start; 133 int unknown = 0; 134 135 os_memset(elems, 0, sizeof(*elems)); 136 137 while (left >= 2) { 138 u8 id, elen; 139 140 id = *pos++; 141 elen = *pos++; 142 left -= 2; 143 144 if (elen > left) { 145 if (show_errors) { 146 wpa_printf(MSG_DEBUG, "IEEE 802.11 element " 147 "parse failed (id=%d elen=%d " 148 "left=%lu)", 149 id, elen, (unsigned long) left); 150 wpa_hexdump(MSG_MSGDUMP, "IEs", start, len); 151 } 152 return ParseFailed; 153 } 154 155 switch (id) { 156 case WLAN_EID_SSID: 157 elems->ssid = pos; 158 elems->ssid_len = elen; 159 break; 160 case WLAN_EID_SUPP_RATES: 161 elems->supp_rates = pos; 162 elems->supp_rates_len = elen; 163 break; 164 case WLAN_EID_FH_PARAMS: 165 elems->fh_params = pos; 166 elems->fh_params_len = elen; 167 break; 168 case WLAN_EID_DS_PARAMS: 169 elems->ds_params = pos; 170 elems->ds_params_len = elen; 171 break; 172 case WLAN_EID_CF_PARAMS: 173 elems->cf_params = pos; 174 elems->cf_params_len = elen; 175 break; 176 case WLAN_EID_TIM: 177 elems->tim = pos; 178 elems->tim_len = elen; 179 break; 180 case WLAN_EID_IBSS_PARAMS: 181 elems->ibss_params = pos; 182 elems->ibss_params_len = elen; 183 break; 184 case WLAN_EID_CHALLENGE: 185 elems->challenge = pos; 186 elems->challenge_len = elen; 187 break; 188 case WLAN_EID_ERP_INFO: 189 elems->erp_info = pos; 190 elems->erp_info_len = elen; 191 break; 192 case WLAN_EID_EXT_SUPP_RATES: 193 elems->ext_supp_rates = pos; 194 elems->ext_supp_rates_len = elen; 195 break; 196 case WLAN_EID_VENDOR_SPECIFIC: 197 if (ieee802_11_parse_vendor_specific(pos, elen, 198 elems, 199 show_errors)) 200 unknown++; 201 break; 202 case WLAN_EID_RSN: 203 elems->rsn_ie = pos; 204 elems->rsn_ie_len = elen; 205 break; 206 case WLAN_EID_PWR_CAPABILITY: 207 elems->power_cap = pos; 208 elems->power_cap_len = elen; 209 break; 210 case WLAN_EID_SUPPORTED_CHANNELS: 211 elems->supp_channels = pos; 212 elems->supp_channels_len = elen; 213 break; 214 case WLAN_EID_MOBILITY_DOMAIN: 215 elems->mdie = pos; 216 elems->mdie_len = elen; 217 break; 218 case WLAN_EID_FAST_BSS_TRANSITION: 219 elems->ftie = pos; 220 elems->ftie_len = elen; 221 break; 222 case WLAN_EID_TIMEOUT_INTERVAL: 223 elems->timeout_int = pos; 224 elems->timeout_int_len = elen; 225 break; 226 case WLAN_EID_HT_CAP: 227 elems->ht_capabilities = pos; 228 elems->ht_capabilities_len = elen; 229 break; 230 case WLAN_EID_HT_OPERATION: 231 elems->ht_operation = pos; 232 elems->ht_operation_len = elen; 233 break; 234 default: 235 unknown++; 236 if (!show_errors) 237 break; 238 wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse " 239 "ignored unknown element (id=%d elen=%d)", 240 id, elen); 241 break; 242 } 243 244 left -= elen; 245 pos += elen; 246 } 247 248 if (left) 249 return ParseFailed; 250 251 return unknown ? ParseUnknown : ParseOK; 252 } 253