1 /* 2 * IEEE 802.11 Common routines 3 * Copyright (c) 2002-2008, Jouni Malinen <j (at) 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 WMM_OUI_TYPE: 53 /* WMM information element */ 54 if (elen < 5) { 55 wpa_printf(MSG_MSGDUMP, "short WMM " 56 "information element ignored " 57 "(len=%lu)", 58 (unsigned long) elen); 59 return -1; 60 } 61 switch (pos[4]) { 62 case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT: 63 case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT: 64 /* 65 * Share same pointer since only one of these 66 * is used and they start with same data. 67 * Length field can be used to distinguish the 68 * IEs. 69 */ 70 elems->wmm = pos; 71 elems->wmm_len = elen; 72 break; 73 case WMM_OUI_SUBTYPE_TSPEC_ELEMENT: 74 elems->wmm_tspec = pos; 75 elems->wmm_tspec_len = elen; 76 break; 77 default: 78 wpa_printf(MSG_MSGDUMP, "unknown WMM " 79 "information element ignored " 80 "(subtype=%d len=%lu)", 81 pos[4], (unsigned long) elen); 82 return -1; 83 } 84 break; 85 case 4: 86 /* Wi-Fi Protected Setup (WPS) IE */ 87 elems->wps_ie = pos; 88 elems->wps_ie_len = elen; 89 break; 90 default: 91 wpa_printf(MSG_MSGDUMP, "Unknown Microsoft " 92 "information element ignored " 93 "(type=%d len=%lu)\n", 94 pos[3], (unsigned long) elen); 95 return -1; 96 } 97 break; 98 99 case OUI_BROADCOM: 100 switch (pos[3]) { 101 case VENDOR_HT_CAPAB_OUI_TYPE: 102 elems->vendor_ht_cap = pos; 103 elems->vendor_ht_cap_len = elen; 104 break; 105 default: 106 wpa_printf(MSG_MSGDUMP, "Unknown Broadcom " 107 "information element ignored " 108 "(type=%d len=%lu)\n", 109 pos[3], (unsigned long) elen); 110 return -1; 111 } 112 break; 113 114 default: 115 wpa_printf(MSG_MSGDUMP, "unknown vendor specific information " 116 "element ignored (vendor OUI %02x:%02x:%02x " 117 "len=%lu)", 118 pos[0], pos[1], pos[2], (unsigned long) elen); 119 return -1; 120 } 121 122 return 0; 123 } 124 125 126 /** 127 * ieee802_11_parse_elems - Parse information elements in management frames 128 * @start: Pointer to the start of IEs 129 * @len: Length of IE buffer in octets 130 * @elems: Data structure for parsed elements 131 * @show_errors: Whether to show parsing errors in debug log 132 * Returns: Parsing result 133 */ 134 ParseRes ieee802_11_parse_elems(u8 *start, size_t len, 135 struct ieee802_11_elems *elems, 136 int show_errors) 137 { 138 size_t left = len; 139 u8 *pos = start; 140 int unknown = 0; 141 142 os_memset(elems, 0, sizeof(*elems)); 143 144 while (left >= 2) { 145 u8 id, elen; 146 147 id = *pos++; 148 elen = *pos++; 149 left -= 2; 150 151 if (elen > left) { 152 if (show_errors) { 153 wpa_printf(MSG_DEBUG, "IEEE 802.11 element " 154 "parse failed (id=%d elen=%d " 155 "left=%lu)", 156 id, elen, (unsigned long) left); 157 wpa_hexdump(MSG_MSGDUMP, "IEs", start, len); 158 } 159 return ParseFailed; 160 } 161 162 switch (id) { 163 case WLAN_EID_SSID: 164 elems->ssid = pos; 165 elems->ssid_len = elen; 166 break; 167 case WLAN_EID_SUPP_RATES: 168 elems->supp_rates = pos; 169 elems->supp_rates_len = elen; 170 break; 171 case WLAN_EID_FH_PARAMS: 172 elems->fh_params = pos; 173 elems->fh_params_len = elen; 174 break; 175 case WLAN_EID_DS_PARAMS: 176 elems->ds_params = pos; 177 elems->ds_params_len = elen; 178 break; 179 case WLAN_EID_CF_PARAMS: 180 elems->cf_params = pos; 181 elems->cf_params_len = elen; 182 break; 183 case WLAN_EID_TIM: 184 elems->tim = pos; 185 elems->tim_len = elen; 186 break; 187 case WLAN_EID_IBSS_PARAMS: 188 elems->ibss_params = pos; 189 elems->ibss_params_len = elen; 190 break; 191 case WLAN_EID_CHALLENGE: 192 elems->challenge = pos; 193 elems->challenge_len = elen; 194 break; 195 case WLAN_EID_ERP_INFO: 196 elems->erp_info = pos; 197 elems->erp_info_len = elen; 198 break; 199 case WLAN_EID_EXT_SUPP_RATES: 200 elems->ext_supp_rates = pos; 201 elems->ext_supp_rates_len = elen; 202 break; 203 case WLAN_EID_VENDOR_SPECIFIC: 204 if (ieee802_11_parse_vendor_specific(pos, elen, 205 elems, 206 show_errors)) 207 unknown++; 208 break; 209 case WLAN_EID_RSN: 210 elems->rsn_ie = pos; 211 elems->rsn_ie_len = elen; 212 break; 213 case WLAN_EID_PWR_CAPABILITY: 214 elems->power_cap = pos; 215 elems->power_cap_len = elen; 216 break; 217 case WLAN_EID_SUPPORTED_CHANNELS: 218 elems->supp_channels = pos; 219 elems->supp_channels_len = elen; 220 break; 221 case WLAN_EID_MOBILITY_DOMAIN: 222 elems->mdie = pos; 223 elems->mdie_len = elen; 224 break; 225 case WLAN_EID_FAST_BSS_TRANSITION: 226 elems->ftie = pos; 227 elems->ftie_len = elen; 228 break; 229 case WLAN_EID_TIMEOUT_INTERVAL: 230 elems->timeout_int = pos; 231 elems->timeout_int_len = elen; 232 break; 233 case WLAN_EID_HT_CAP: 234 elems->ht_capabilities = pos; 235 elems->ht_capabilities_len = elen; 236 break; 237 case WLAN_EID_HT_OPERATION: 238 elems->ht_operation = pos; 239 elems->ht_operation_len = elen; 240 break; 241 default: 242 unknown++; 243 if (!show_errors) 244 break; 245 wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse " 246 "ignored unknown element (id=%d elen=%d)", 247 id, elen); 248 break; 249 } 250 251 left -= elen; 252 pos += elen; 253 } 254 255 if (left) 256 return ParseFailed; 257 258 return unknown ? ParseUnknown : ParseOK; 259 } 260