00001
00016 #include "includes.h"
00017
00018 #include "common.h"
00019 #include "ieee802_11_defs.h"
00020 #include "ieee802_11_common.h"
00021
00022
00023 static int ieee802_11_parse_vendor_specific(u8 *pos, size_t elen,
00024 struct ieee802_11_elems *elems,
00025 int show_errors)
00026 {
00027 unsigned int oui;
00028
00029
00030
00031
00032 if (elen < 4) {
00033 if (show_errors) {
00034 wpa_printf(MSG_MSGDUMP, "short vendor specific "
00035 "information element ignored (len=%lu)",
00036 (unsigned long) elen);
00037 }
00038 return -1;
00039 }
00040
00041 oui = WPA_GET_BE24(pos);
00042 switch (oui) {
00043 case OUI_MICROSOFT:
00044
00045
00046 switch (pos[3]) {
00047 case 1:
00048
00049
00050 elems->wpa_ie = pos;
00051 elems->wpa_ie_len = elen;
00052 break;
00053 case WMM_OUI_TYPE:
00054
00055 if (elen < 5) {
00056 wpa_printf(MSG_MSGDUMP, "short WMM "
00057 "information element ignored "
00058 "(len=%lu)",
00059 (unsigned long) elen);
00060 return -1;
00061 }
00062 switch (pos[4]) {
00063 case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
00064 case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
00065
00066
00067
00068
00069
00070
00071 elems->wmm = pos;
00072 elems->wmm_len = elen;
00073 break;
00074 case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
00075 elems->wmm_tspec = pos;
00076 elems->wmm_tspec_len = elen;
00077 break;
00078 default:
00079 wpa_printf(MSG_MSGDUMP, "unknown WMM "
00080 "information element ignored "
00081 "(subtype=%d len=%lu)",
00082 pos[4], (unsigned long) elen);
00083 return -1;
00084 }
00085 break;
00086 case 4:
00087
00088 elems->wps_ie = pos;
00089 elems->wps_ie_len = elen;
00090 break;
00091 default:
00092 wpa_printf(MSG_MSGDUMP, "Unknown Microsoft "
00093 "information element ignored "
00094 "(type=%d len=%lu)\n",
00095 pos[3], (unsigned long) elen);
00096 return -1;
00097 }
00098 break;
00099
00100 case OUI_BROADCOM:
00101 switch (pos[3]) {
00102 case VENDOR_HT_CAPAB_OUI_TYPE:
00103 elems->vendor_ht_cap = pos;
00104 elems->vendor_ht_cap_len = elen;
00105 break;
00106 default:
00107 wpa_printf(MSG_MSGDUMP, "Unknown Broadcom "
00108 "information element ignored "
00109 "(type=%d len=%lu)\n",
00110 pos[3], (unsigned long) elen);
00111 return -1;
00112 }
00113 break;
00114
00115 default:
00116 wpa_printf(MSG_MSGDUMP, "unknown vendor specific information "
00117 "element ignored (vendor OUI %02x:%02x:%02x "
00118 "len=%lu)",
00119 pos[0], pos[1], pos[2], (unsigned long) elen);
00120 return -1;
00121 }
00122
00123 return 0;
00124 }
00125
00126
00136 ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
00137 struct ieee802_11_elems *elems,
00138 int show_errors)
00139 {
00140 size_t left = len;
00141 u8 *pos = start;
00142 int unknown = 0;
00143
00144 os_memset(elems, 0, sizeof(*elems));
00145
00146 while (left >= 2) {
00147 u8 id, elen;
00148
00149 id = *pos++;
00150 elen = *pos++;
00151 left -= 2;
00152
00153 if (elen > left) {
00154 if (show_errors) {
00155 wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
00156 "parse failed (id=%d elen=%d "
00157 "left=%lu)",
00158 id, elen, (unsigned long) left);
00159 wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
00160 }
00161 return ParseFailed;
00162 }
00163
00164 switch (id) {
00165 case WLAN_EID_SSID:
00166 elems->ssid = pos;
00167 elems->ssid_len = elen;
00168 break;
00169 case WLAN_EID_SUPP_RATES:
00170 elems->supp_rates = pos;
00171 elems->supp_rates_len = elen;
00172 break;
00173 case WLAN_EID_FH_PARAMS:
00174 elems->fh_params = pos;
00175 elems->fh_params_len = elen;
00176 break;
00177 case WLAN_EID_DS_PARAMS:
00178 elems->ds_params = pos;
00179 elems->ds_params_len = elen;
00180 break;
00181 case WLAN_EID_CF_PARAMS:
00182 elems->cf_params = pos;
00183 elems->cf_params_len = elen;
00184 break;
00185 case WLAN_EID_TIM:
00186 elems->tim = pos;
00187 elems->tim_len = elen;
00188 break;
00189 case WLAN_EID_IBSS_PARAMS:
00190 elems->ibss_params = pos;
00191 elems->ibss_params_len = elen;
00192 break;
00193 case WLAN_EID_CHALLENGE:
00194 elems->challenge = pos;
00195 elems->challenge_len = elen;
00196 break;
00197 case WLAN_EID_ERP_INFO:
00198 elems->erp_info = pos;
00199 elems->erp_info_len = elen;
00200 break;
00201 case WLAN_EID_EXT_SUPP_RATES:
00202 elems->ext_supp_rates = pos;
00203 elems->ext_supp_rates_len = elen;
00204 break;
00205 case WLAN_EID_VENDOR_SPECIFIC:
00206 if (ieee802_11_parse_vendor_specific(pos, elen,
00207 elems,
00208 show_errors))
00209 unknown++;
00210 break;
00211 case WLAN_EID_RSN:
00212 elems->rsn_ie = pos;
00213 elems->rsn_ie_len = elen;
00214 break;
00215 case WLAN_EID_PWR_CAPABILITY:
00216 elems->power_cap = pos;
00217 elems->power_cap_len = elen;
00218 break;
00219 case WLAN_EID_SUPPORTED_CHANNELS:
00220 elems->supp_channels = pos;
00221 elems->supp_channels_len = elen;
00222 break;
00223 case WLAN_EID_MOBILITY_DOMAIN:
00224 elems->mdie = pos;
00225 elems->mdie_len = elen;
00226 break;
00227 case WLAN_EID_FAST_BSS_TRANSITION:
00228 elems->ftie = pos;
00229 elems->ftie_len = elen;
00230 break;
00231 case WLAN_EID_TIMEOUT_INTERVAL:
00232 elems->timeout_int = pos;
00233 elems->timeout_int_len = elen;
00234 break;
00235 case WLAN_EID_HT_CAP:
00236 elems->ht_capabilities = pos;
00237 elems->ht_capabilities_len = elen;
00238 break;
00239 case WLAN_EID_HT_OPERATION:
00240 elems->ht_operation = pos;
00241 elems->ht_operation_len = elen;
00242 break;
00243 default:
00244 unknown++;
00245 if (!show_errors)
00246 break;
00247 wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
00248 "ignored unknown element (id=%d elen=%d)",
00249 id, elen);
00250 break;
00251 }
00252
00253 left -= elen;
00254 pos += elen;
00255 }
00256
00257 if (left)
00258 return ParseFailed;
00259
00260 return unknown ? ParseUnknown : ParseOK;
00261 }
00262
00263
00264 int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
00265 {
00266 int count = 0;
00267 const u8 *pos, *end;
00268
00269 if (ies == NULL)
00270 return 0;
00271
00272 pos = ies;
00273 end = ies + ies_len;
00274
00275 while (pos + 2 <= end) {
00276 if (pos + 2 + pos[1] > end)
00277 break;
00278 count++;
00279 pos += 2 + pos[1];
00280 }
00281
00282 return count;
00283 }
00284
00285
00286 struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
00287 u32 oui_type)
00288 {
00289 struct wpabuf *buf;
00290 const u8 *end, *pos, *ie;
00291
00292 pos = ies;
00293 end = ies + ies_len;
00294 ie = NULL;
00295
00296 while (pos + 1 < end) {
00297 if (pos + 2 + pos[1] > end)
00298 return NULL;
00299 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
00300 WPA_GET_BE32(&pos[2]) == oui_type) {
00301 ie = pos;
00302 break;
00303 }
00304 pos += 2 + pos[1];
00305 }
00306
00307 if (ie == NULL)
00308 return NULL;
00309
00310 buf = wpabuf_alloc(ies_len);
00311 if (buf == NULL)
00312 return NULL;
00313
00314
00315
00316
00317
00318 while (pos + 1 < end) {
00319 if (pos + 2 + pos[1] > end)
00320 break;
00321 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
00322 WPA_GET_BE32(&pos[2]) == oui_type)
00323 wpabuf_put_data(buf, pos + 6, pos[1] - 4);
00324 pos += 2 + pos[1];
00325 }
00326
00327 return buf;
00328 }
00329