ieee802_11_common.c
Go to the documentation of this file.
00001 /*
00002  * IEEE 802.11 Common routines
00003  * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  *
00009  * Alternatively, this software may be distributed under the terms of BSD
00010  * license.
00011  *
00012  * See README and COPYING for more details.
00013  */
00014 
00015 #include "includes.h"
00016 
00017 #include "common.h"
00018 #include "ieee802_11_defs.h"
00019 #include "ieee802_11_common.h"
00020 
00021 
00022 static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
00023                                             struct ieee802_11_elems *elems,
00024                                             int show_errors)
00025 {
00026         unsigned int oui;
00027 
00028         /* first 3 bytes in vendor specific information element are the IEEE
00029          * OUI of the vendor. The following byte is used a vendor specific
00030          * sub-type. */
00031         if (elen < 4) {
00032                 if (show_errors) {
00033                         wpa_printf(MSG_MSGDUMP, "short vendor specific "
00034                                    "information element ignored (len=%lu)",
00035                                    (unsigned long) elen);
00036                 }
00037                 return -1;
00038         }
00039 
00040         oui = WPA_GET_BE24(pos);
00041         switch (oui) {
00042         case OUI_MICROSOFT:
00043                 /* Microsoft/Wi-Fi information elements are further typed and
00044                  * subtyped */
00045                 switch (pos[3]) {
00046                 case 1:
00047                         /* Microsoft OUI (00:50:F2) with OUI Type 1:
00048                          * real WPA information element */
00049                         elems->wpa_ie = pos;
00050                         elems->wpa_ie_len = elen;
00051                         break;
00052                 case WMM_OUI_TYPE:
00053                         /* WMM information element */
00054                         if (elen < 5) {
00055                                 wpa_printf(MSG_MSGDUMP, "short WMM "
00056                                            "information element ignored "
00057                                            "(len=%lu)",
00058                                            (unsigned long) elen);
00059                                 return -1;
00060                         }
00061                         switch (pos[4]) {
00062                         case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
00063                         case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
00064                                 /*
00065                                  * Share same pointer since only one of these
00066                                  * is used and they start with same data.
00067                                  * Length field can be used to distinguish the
00068                                  * IEs.
00069                                  */
00070                                 elems->wmm = pos;
00071                                 elems->wmm_len = elen;
00072                                 break;
00073                         case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
00074                                 elems->wmm_tspec = pos;
00075                                 elems->wmm_tspec_len = elen;
00076                                 break;
00077                         default:
00078                                 wpa_printf(MSG_MSGDUMP, "unknown WMM "
00079                                            "information element ignored "
00080                                            "(subtype=%d len=%lu)",
00081                                            pos[4], (unsigned long) elen);
00082                                 return -1;
00083                         }
00084                         break;
00085                 case 4:
00086                         /* Wi-Fi Protected Setup (WPS) IE */
00087                         elems->wps_ie = pos;
00088                         elems->wps_ie_len = elen;
00089                         break;
00090                 default:
00091                         wpa_printf(MSG_MSGDUMP, "Unknown Microsoft "
00092                                    "information element ignored "
00093                                    "(type=%d len=%lu)\n",
00094                                    pos[3], (unsigned long) elen);
00095                         return -1;
00096                 }
00097                 break;
00098 
00099         case OUI_BROADCOM:
00100                 switch (pos[3]) {
00101                 case VENDOR_HT_CAPAB_OUI_TYPE:
00102                         elems->vendor_ht_cap = pos;
00103                         elems->vendor_ht_cap_len = elen;
00104                         break;
00105                 default:
00106                         wpa_printf(MSG_MSGDUMP, "Unknown Broadcom "
00107                                    "information element ignored "
00108                                    "(type=%d len=%lu)\n",
00109                                    pos[3], (unsigned long) elen);
00110                         return -1;
00111                 }
00112                 break;
00113 
00114         default:
00115                 wpa_printf(MSG_MSGDUMP, "unknown vendor specific information "
00116                            "element ignored (vendor OUI %02x:%02x:%02x "
00117                            "len=%lu)",
00118                            pos[0], pos[1], pos[2], (unsigned long) elen);
00119                 return -1;
00120         }
00121 
00122         return 0;
00123 }
00124 
00125 
00134 ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
00135                                 struct ieee802_11_elems *elems,
00136                                 int show_errors)
00137 {
00138         size_t left = len;
00139         const u8 *pos = start;
00140         int unknown = 0;
00141 
00142         os_memset(elems, 0, sizeof(*elems));
00143 
00144         while (left >= 2) {
00145                 u8 id, elen;
00146 
00147                 id = *pos++;
00148                 elen = *pos++;
00149                 left -= 2;
00150 
00151                 if (elen > left) {
00152                         if (show_errors) {
00153                                 wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
00154                                            "parse failed (id=%d elen=%d "
00155                                            "left=%lu)",
00156                                            id, elen, (unsigned long) left);
00157                                 wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
00158                         }
00159                         return ParseFailed;
00160                 }
00161 
00162                 switch (id) {
00163                 case WLAN_EID_SSID:
00164                         elems->ssid = pos;
00165                         elems->ssid_len = elen;
00166                         break;
00167                 case WLAN_EID_SUPP_RATES:
00168                         elems->supp_rates = pos;
00169                         elems->supp_rates_len = elen;
00170                         break;
00171                 case WLAN_EID_FH_PARAMS:
00172                         elems->fh_params = pos;
00173                         elems->fh_params_len = elen;
00174                         break;
00175                 case WLAN_EID_DS_PARAMS:
00176                         elems->ds_params = pos;
00177                         elems->ds_params_len = elen;
00178                         break;
00179                 case WLAN_EID_CF_PARAMS:
00180                         elems->cf_params = pos;
00181                         elems->cf_params_len = elen;
00182                         break;
00183                 case WLAN_EID_TIM:
00184                         elems->tim = pos;
00185                         elems->tim_len = elen;
00186                         break;
00187                 case WLAN_EID_IBSS_PARAMS:
00188                         elems->ibss_params = pos;
00189                         elems->ibss_params_len = elen;
00190                         break;
00191                 case WLAN_EID_CHALLENGE:
00192                         elems->challenge = pos;
00193                         elems->challenge_len = elen;
00194                         break;
00195                 case WLAN_EID_ERP_INFO:
00196                         elems->erp_info = pos;
00197                         elems->erp_info_len = elen;
00198                         break;
00199                 case WLAN_EID_EXT_SUPP_RATES:
00200                         elems->ext_supp_rates = pos;
00201                         elems->ext_supp_rates_len = elen;
00202                         break;
00203                 case WLAN_EID_VENDOR_SPECIFIC:
00204                         if (ieee802_11_parse_vendor_specific(pos, elen,
00205                                                              elems,
00206                                                              show_errors))
00207                                 unknown++;
00208                         break;
00209                 case WLAN_EID_RSN:
00210                         elems->rsn_ie = pos;
00211                         elems->rsn_ie_len = elen;
00212                         break;
00213                 case WLAN_EID_PWR_CAPABILITY:
00214                         elems->power_cap = pos;
00215                         elems->power_cap_len = elen;
00216                         break;
00217                 case WLAN_EID_SUPPORTED_CHANNELS:
00218                         elems->supp_channels = pos;
00219                         elems->supp_channels_len = elen;
00220                         break;
00221                 case WLAN_EID_MOBILITY_DOMAIN:
00222                         elems->mdie = pos;
00223                         elems->mdie_len = elen;
00224                         break;
00225                 case WLAN_EID_FAST_BSS_TRANSITION:
00226                         elems->ftie = pos;
00227                         elems->ftie_len = elen;
00228                         break;
00229                 case WLAN_EID_TIMEOUT_INTERVAL:
00230                         elems->timeout_int = pos;
00231                         elems->timeout_int_len = elen;
00232                         break;
00233                 case WLAN_EID_HT_CAP:
00234                         elems->ht_capabilities = pos;
00235                         elems->ht_capabilities_len = elen;
00236                         break;
00237                 case WLAN_EID_HT_OPERATION:
00238                         elems->ht_operation = pos;
00239                         elems->ht_operation_len = elen;
00240                         break;
00241                 default:
00242                         unknown++;
00243                         if (!show_errors)
00244                                 break;
00245                         wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
00246                                    "ignored unknown element (id=%d elen=%d)",
00247                                    id, elen);
00248                         break;
00249                 }
00250 
00251                 left -= elen;
00252                 pos += elen;
00253         }
00254 
00255         if (left)
00256                 return ParseFailed;
00257 
00258         return unknown ? ParseUnknown : ParseOK;
00259 }
00260 
00261 
00262 int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
00263 {
00264         int count = 0;
00265         const u8 *pos, *end;
00266 
00267         if (ies == NULL)
00268                 return 0;
00269 
00270         pos = ies;
00271         end = ies + ies_len;
00272 
00273         while (pos + 2 <= end) {
00274                 if (pos + 2 + pos[1] > end)
00275                         break;
00276                 count++;
00277                 pos += 2 + pos[1];
00278         }
00279 
00280         return count;
00281 }
00282 
00283 
00284 struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
00285                                             u32 oui_type)
00286 {
00287         struct wpabuf *buf;
00288         const u8 *end, *pos, *ie;
00289 
00290         pos = ies;
00291         end = ies + ies_len;
00292         ie = NULL;
00293 
00294         while (pos + 1 < end) {
00295                 if (pos + 2 + pos[1] > end)
00296                         return NULL;
00297                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
00298                     WPA_GET_BE32(&pos[2]) == oui_type) {
00299                         ie = pos;
00300                         break;
00301                 }
00302                 pos += 2 + pos[1];
00303         }
00304 
00305         if (ie == NULL)
00306                 return NULL; /* No specified vendor IE found */
00307 
00308         buf = wpabuf_alloc(ies_len);
00309         if (buf == NULL)
00310                 return NULL;
00311 
00312         /*
00313          * There may be multiple vendor IEs in the message, so need to
00314          * concatenate their data fields.
00315          */
00316         while (pos + 1 < end) {
00317                 if (pos + 2 + pos[1] > end)
00318                         break;
00319                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
00320                     WPA_GET_BE32(&pos[2]) == oui_type)
00321                         wpabuf_put_data(buf, pos + 6, pos[1] - 4);
00322                 pos += 2 + pos[1];
00323         }
00324 
00325         return buf;
00326 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:35