ieee802_11_common.c

Go to the documentation of this file.
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         /* first 3 bytes in vendor specific information element are the IEEE
00030          * OUI of the vendor. The following byte is used a vendor specific
00031          * sub-type. */
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                 /* Microsoft/Wi-Fi information elements are further typed and
00045                  * subtyped */
00046                 switch (pos[3]) {
00047                 case 1:
00048                         /* Microsoft OUI (00:50:F2) with OUI Type 1:
00049                          * real WPA information element */
00050                         elems->wpa_ie = pos;
00051                         elems->wpa_ie_len = elen;
00052                         break;
00053                 case WMM_OUI_TYPE:
00054                         /* WMM information element */
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                                  * Share same pointer since only one of these
00067                                  * is used and they start with same data.
00068                                  * Length field can be used to distinguish the
00069                                  * IEs.
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                         /* Wi-Fi Protected Setup (WPS) IE */
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; /* No specified vendor IE found */
00309 
00310         buf = wpabuf_alloc(ies_len);
00311         if (buf == NULL)
00312                 return NULL;
00313 
00314         /*
00315          * There may be multiple vendor IEs in the message, so need to
00316          * concatenate their data fields.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:49 2009 for hostapd by  doxygen 1.6.1