OLD | NEW |
(Empty) | |
| 1 //------------------------------------------------------------------------------ |
| 2 // <copyright file="wlan_recv_beacon.c" company="Atheros"> |
| 3 // Copyright (c) 2004-2008 Atheros Corporation. All rights reserved. |
| 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 // Software distributed under the License is distributed on an "AS |
| 10 // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or |
| 11 // implied. See the License for the specific language governing |
| 12 // rights and limitations under the License. |
| 13 // |
| 14 // |
| 15 //------------------------------------------------------------------------------ |
| 16 //============================================================================== |
| 17 // IEEE 802.11 input handling. |
| 18 // |
| 19 // Author(s): ="Atheros" |
| 20 //============================================================================== |
| 21 |
| 22 #include "a_config.h" |
| 23 #include "athdefs.h" |
| 24 #include "a_types.h" |
| 25 #include "a_osapi.h" |
| 26 #include <wmi.h> |
| 27 #include <ieee80211.h> |
| 28 #include <wlan_api.h> |
| 29 |
| 30 #define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \ |
| 31 if ((_len) < (_minlen)) { \ |
| 32 return A_EINVAL; \ |
| 33 } \ |
| 34 } while (0) |
| 35 |
| 36 #define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \ |
| 37 if ((__elem) == NULL) { \ |
| 38 return A_EINVAL; \ |
| 39 } \ |
| 40 if ((__elem)[1] > (__maxlen)) { \ |
| 41 return A_EINVAL; \ |
| 42 } \ |
| 43 } while (0) |
| 44 |
| 45 |
| 46 /* unaligned little endian access */ |
| 47 #define LE_READ_2(p) \ |
| 48 ((A_UINT16) \ |
| 49 ((((A_UINT8 *)(p))[0] ) | (((A_UINT8 *)(p))[1] << 8))) |
| 50 |
| 51 #define LE_READ_4(p) \ |
| 52 ((A_UINT32) \ |
| 53 ((((A_UINT8 *)(p))[0] ) | (((A_UINT8 *)(p))[1] << 8) | \ |
| 54 (((A_UINT8 *)(p))[2] << 16) | (((A_UINT8 *)(p))[3] << 24))) |
| 55 |
| 56 |
| 57 static int __inline |
| 58 iswpaoui(const A_UINT8 *frm) |
| 59 { |
| 60 return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI); |
| 61 } |
| 62 |
| 63 static int __inline |
| 64 iswmmoui(const A_UINT8 *frm) |
| 65 { |
| 66 return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI); |
| 67 } |
| 68 |
| 69 /* unused functions for now */ |
| 70 #if 0 |
| 71 static int __inline |
| 72 iswmmparam(const A_UINT8 *frm) |
| 73 { |
| 74 return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE; |
| 75 } |
| 76 |
| 77 static int __inline |
| 78 iswmminfo(const A_UINT8 *frm) |
| 79 { |
| 80 return frm[1] > 5 && frm[6] == WMM_INFO_OUI_SUBTYPE; |
| 81 } |
| 82 #endif |
| 83 |
| 84 static int __inline |
| 85 isatherosoui(const A_UINT8 *frm) |
| 86 { |
| 87 return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI); |
| 88 } |
| 89 |
| 90 static int __inline |
| 91 iswscoui(const A_UINT8 *frm) |
| 92 { |
| 93 return frm[1] > 3 && LE_READ_4(frm+2) == ((0x04<<24)|WPA_OUI); |
| 94 } |
| 95 |
| 96 A_STATUS |
| 97 wlan_parse_beacon(A_UINT8 *buf, int framelen, struct ieee80211_common_ie *cie) |
| 98 { |
| 99 A_UINT8 *frm, *efrm; |
| 100 A_UINT8 elemid_ssid = FALSE; |
| 101 |
| 102 frm = buf; |
| 103 efrm = (A_UINT8 *) (frm + framelen); |
| 104 |
| 105 /* |
| 106 * beacon/probe response frame format |
| 107 * [8] time stamp |
| 108 * [2] beacon interval |
| 109 * [2] capability information |
| 110 * [tlv] ssid |
| 111 * [tlv] supported rates |
| 112 * [tlv] country information |
| 113 * [tlv] parameter set (FH/DS) |
| 114 * [tlv] erp information |
| 115 * [tlv] extended supported rates |
| 116 * [tlv] WMM |
| 117 * [tlv] WPA or RSN |
| 118 * [tlv] Atheros Advanced Capabilities |
| 119 */ |
| 120 IEEE80211_VERIFY_LENGTH(efrm - frm, 12); |
| 121 A_MEMZERO(cie, sizeof(*cie)); |
| 122 |
| 123 cie->ie_tstamp = frm; frm += 8; |
| 124 cie->ie_beaconInt = A_LE2CPU16(*(A_UINT16 *)frm); frm += 2; |
| 125 cie->ie_capInfo = A_LE2CPU16(*(A_UINT16 *)frm); frm += 2; |
| 126 cie->ie_chan = 0; |
| 127 |
| 128 while (frm < efrm) { |
| 129 switch (*frm) { |
| 130 case IEEE80211_ELEMID_SSID: |
| 131 if (!elemid_ssid) { |
| 132 cie->ie_ssid = frm; |
| 133 elemid_ssid = TRUE; |
| 134 } |
| 135 break; |
| 136 case IEEE80211_ELEMID_RATES: |
| 137 cie->ie_rates = frm; |
| 138 break; |
| 139 case IEEE80211_ELEMID_COUNTRY: |
| 140 cie->ie_country = frm; |
| 141 break; |
| 142 case IEEE80211_ELEMID_FHPARMS: |
| 143 break; |
| 144 case IEEE80211_ELEMID_DSPARMS: |
| 145 cie->ie_chan = frm[2]; |
| 146 break; |
| 147 case IEEE80211_ELEMID_TIM: |
| 148 cie->ie_tim = frm; |
| 149 break; |
| 150 case IEEE80211_ELEMID_IBSSPARMS: |
| 151 break; |
| 152 case IEEE80211_ELEMID_XRATES: |
| 153 cie->ie_xrates = frm; |
| 154 break; |
| 155 case IEEE80211_ELEMID_ERP: |
| 156 if (frm[1] != 1) { |
| 157 //A_PRINTF("Discarding ERP Element - Bad Len\n"); |
| 158 return A_EINVAL; |
| 159 } |
| 160 cie->ie_erp = frm[2]; |
| 161 break; |
| 162 case IEEE80211_ELEMID_RSN: |
| 163 cie->ie_rsn = frm; |
| 164 break; |
| 165 case IEEE80211_ELEMID_HTCAP_ANA: |
| 166 cie->ie_htcap = frm; |
| 167 break; |
| 168 case IEEE80211_ELEMID_HTINFO_ANA: |
| 169 cie->ie_htop = frm; |
| 170 break; |
| 171 #ifdef WAPI_ENABLE |
| 172 case IEEE80211_ELEMID_WAPI: |
| 173 cie->ie_wapi = frm; |
| 174 break; |
| 175 #endif |
| 176 case IEEE80211_ELEMID_VENDOR: |
| 177 if (iswpaoui(frm)) { |
| 178 cie->ie_wpa = frm; |
| 179 } else if (iswmmoui(frm)) { |
| 180 cie->ie_wmm = frm; |
| 181 } else if (isatherosoui(frm)) { |
| 182 cie->ie_ath = frm; |
| 183 } else if(iswscoui(frm)) { |
| 184 cie->ie_wsc = frm; |
| 185 } |
| 186 break; |
| 187 default: |
| 188 break; |
| 189 } |
| 190 frm += frm[1] + 2; |
| 191 } |
| 192 IEEE80211_VERIFY_ELEMENT(cie->ie_rates, IEEE80211_RATE_MAXSIZE); |
| 193 IEEE80211_VERIFY_ELEMENT(cie->ie_ssid, IEEE80211_NWID_LEN); |
| 194 |
| 195 return A_OK; |
| 196 } |
OLD | NEW |