rtw_ieee80211.c 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17. *
  18. *
  19. ******************************************************************************/
  20. #define _IEEE80211_C
  21. #include <drv_types.h>
  22. u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
  23. u16 RTW_WPA_VERSION = 1;
  24. u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 };
  25. u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 };
  26. u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 };
  27. u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 };
  28. u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 };
  29. u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 };
  30. u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 };
  31. u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 };
  32. u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 };
  33. u16 RSN_VERSION_BSD = 1;
  34. u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 };
  35. u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 };
  36. u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 };
  37. u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 };
  38. u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 };
  39. u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 };
  40. u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 };
  41. u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };
  42. //-----------------------------------------------------------
  43. // for adhoc-master to generate ie and provide supported-rate to fw
  44. //-----------------------------------------------------------
  45. static u8 WIFI_CCKRATES[] =
  46. {(IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK),
  47. (IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK),
  48. (IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK),
  49. (IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK)};
  50. static u8 WIFI_OFDMRATES[] =
  51. {(IEEE80211_OFDM_RATE_6MB),
  52. (IEEE80211_OFDM_RATE_9MB),
  53. (IEEE80211_OFDM_RATE_12MB),
  54. (IEEE80211_OFDM_RATE_18MB),
  55. (IEEE80211_OFDM_RATE_24MB),
  56. IEEE80211_OFDM_RATE_36MB,
  57. IEEE80211_OFDM_RATE_48MB,
  58. IEEE80211_OFDM_RATE_54MB};
  59. int rtw_get_bit_value_from_ieee_value(u8 val)
  60. {
  61. unsigned char dot11_rate_table[]={2,4,11,22,12,18,24,36,48,72,96,108,0}; // last element must be zero!!
  62. int i=0;
  63. while(dot11_rate_table[i] != 0) {
  64. if (dot11_rate_table[i] == val)
  65. return BIT(i);
  66. i++;
  67. }
  68. return 0;
  69. }
  70. uint rtw_is_cckrates_included(u8 *rate)
  71. {
  72. u32 i = 0;
  73. while(rate[i]!=0)
  74. {
  75. if ( (((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
  76. (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22) )
  77. return _TRUE;
  78. i++;
  79. }
  80. return _FALSE;
  81. }
  82. uint rtw_is_cckratesonly_included(u8 *rate)
  83. {
  84. u32 i = 0;
  85. while(rate[i]!=0)
  86. {
  87. if ( (((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
  88. (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22) )
  89. return _FALSE;
  90. i++;
  91. }
  92. return _TRUE;
  93. }
  94. int rtw_check_network_type(unsigned char *rate, int ratelen, int channel)
  95. {
  96. if (channel > 14)
  97. {
  98. if ((rtw_is_cckrates_included(rate)) == _TRUE)
  99. return WIRELESS_INVALID;
  100. else
  101. return WIRELESS_11A;
  102. }
  103. else // could be pure B, pure G, or B/G
  104. {
  105. if ((rtw_is_cckratesonly_included(rate)) == _TRUE)
  106. return WIRELESS_11B;
  107. else if((rtw_is_cckrates_included(rate)) == _TRUE)
  108. return WIRELESS_11BG;
  109. else
  110. return WIRELESS_11G;
  111. }
  112. }
  113. u8 *rtw_set_fixed_ie(unsigned char *pbuf, unsigned int len, unsigned char *source,
  114. unsigned int *frlen)
  115. {
  116. _rtw_memcpy((void *)pbuf, (void *)source, len);
  117. *frlen = *frlen + len;
  118. return (pbuf + len);
  119. }
  120. // rtw_set_ie will update frame length
  121. u8 *rtw_set_ie
  122. (
  123. u8 *pbuf,
  124. sint index,
  125. uint len,
  126. u8 *source,
  127. uint *frlen //frame length
  128. )
  129. {
  130. _func_enter_;
  131. *pbuf = (u8)index;
  132. *(pbuf + 1) = (u8)len;
  133. if (len > 0)
  134. _rtw_memcpy((void *)(pbuf + 2), (void *)source, len);
  135. *frlen = *frlen + (len + 2);
  136. return (pbuf + len + 2);
  137. _func_exit_;
  138. }
  139. inline u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode,
  140. u8 new_ch, u8 ch_switch_cnt)
  141. {
  142. u8 ie_data[3];
  143. ie_data[0] = ch_switch_mode;
  144. ie_data[1] = new_ch;
  145. ie_data[2] = ch_switch_cnt;
  146. return rtw_set_ie(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len);
  147. }
  148. inline u8 secondary_ch_offset_to_hal_ch_offset(u8 ch_offset)
  149. {
  150. if (ch_offset == SCN)
  151. return HAL_PRIME_CHNL_OFFSET_DONT_CARE;
  152. else if(ch_offset == SCA)
  153. return HAL_PRIME_CHNL_OFFSET_UPPER;
  154. else if(ch_offset == SCB)
  155. return HAL_PRIME_CHNL_OFFSET_LOWER;
  156. return HAL_PRIME_CHNL_OFFSET_DONT_CARE;
  157. }
  158. inline u8 hal_ch_offset_to_secondary_ch_offset(u8 ch_offset)
  159. {
  160. if (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
  161. return SCN;
  162. else if(ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
  163. return SCB;
  164. else if(ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
  165. return SCA;
  166. return SCN;
  167. }
  168. inline u8 *rtw_set_ie_secondary_ch_offset(u8 *buf, u32 *buf_len, u8 secondary_ch_offset)
  169. {
  170. return rtw_set_ie(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET, 1, &secondary_ch_offset, buf_len);
  171. }
  172. inline u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl,
  173. u8 flags, u16 reason, u16 precedence)
  174. {
  175. u8 ie_data[6];
  176. ie_data[0] = ttl;
  177. ie_data[1] = flags;
  178. RTW_PUT_LE16((u8*)&ie_data[2], reason);
  179. RTW_PUT_LE16((u8*)&ie_data[4], precedence);
  180. return rtw_set_ie(buf, 0x118, 6, ie_data, buf_len);
  181. }
  182. /*----------------------------------------------------------------------------
  183. index: the information element id index, limit is the limit for search
  184. -----------------------------------------------------------------------------*/
  185. u8 *rtw_get_ie(u8 *pbuf, sint index, sint *len, sint limit)
  186. {
  187. sint tmp,i;
  188. u8 *p;
  189. _func_enter_;
  190. if (limit < 1){
  191. _func_exit_;
  192. return NULL;
  193. }
  194. p = pbuf;
  195. i = 0;
  196. *len = 0;
  197. while(1)
  198. {
  199. if (*p == index)
  200. {
  201. *len = *(p + 1);
  202. return (p);
  203. }
  204. else
  205. {
  206. tmp = *(p + 1);
  207. p += (tmp + 2);
  208. i += (tmp + 2);
  209. }
  210. if (i >= limit)
  211. break;
  212. }
  213. _func_exit_;
  214. return NULL;
  215. }
  216. /**
  217. * rtw_get_ie_ex - Search specific IE from a series of IEs
  218. * @in_ie: Address of IEs to search
  219. * @in_len: Length limit from in_ie
  220. * @eid: Element ID to match
  221. * @oui: OUI to match
  222. * @oui_len: OUI length
  223. * @ie: If not NULL and the specific IE is found, the IE will be copied to the buf starting from the specific IE
  224. * @ielen: If not NULL and the specific IE is found, will set to the length of the entire IE
  225. *
  226. * Returns: The address of the specific IE found, or NULL
  227. */
  228. u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, uint *ielen)
  229. {
  230. uint cnt;
  231. u8 *target_ie = NULL;
  232. if(ielen)
  233. *ielen = 0;
  234. if(!in_ie || in_len<=0)
  235. return target_ie;
  236. cnt = 0;
  237. while(cnt<in_len)
  238. {
  239. if(eid == in_ie[cnt]
  240. && ( !oui || _rtw_memcmp(&in_ie[cnt+2], oui, oui_len) == _TRUE))
  241. {
  242. target_ie = &in_ie[cnt];
  243. if(ie)
  244. _rtw_memcpy(ie, &in_ie[cnt], in_ie[cnt+1]+2);
  245. if(ielen)
  246. *ielen = in_ie[cnt+1]+2;
  247. break;
  248. }
  249. else
  250. {
  251. cnt+=in_ie[cnt+1]+2; //goto next
  252. }
  253. }
  254. return target_ie;
  255. }
  256. /**
  257. * rtw_ies_remove_ie - Find matching IEs and remove
  258. * @ies: Address of IEs to search
  259. * @ies_len: Pointer of length of ies, will update to new length
  260. * @offset: The offset to start scarch
  261. * @eid: Element ID to match
  262. * @oui: OUI to match
  263. * @oui_len: OUI length
  264. *
  265. * Returns: _SUCCESS: ies is updated, _FAIL: not updated
  266. */
  267. int rtw_ies_remove_ie(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u8 oui_len)
  268. {
  269. int ret = _FAIL;
  270. u8 *target_ie;
  271. u32 target_ielen;
  272. u8 *start;
  273. uint search_len;
  274. if(!ies || !ies_len || *ies_len <= offset)
  275. goto exit;
  276. start = ies + offset;
  277. search_len = *ies_len - offset;
  278. while (1) {
  279. target_ie = rtw_get_ie_ex(start, search_len, eid, oui, oui_len, NULL, &target_ielen);
  280. if (target_ie && target_ielen) {
  281. u8 buf[MAX_IE_SZ] = {0};
  282. u8 *remain_ies = target_ie + target_ielen;
  283. uint remain_len = search_len - (remain_ies - start);
  284. _rtw_memcpy(buf, remain_ies, remain_len);
  285. _rtw_memcpy(target_ie, buf, remain_len);
  286. *ies_len = *ies_len - target_ielen;
  287. ret = _SUCCESS;
  288. start = target_ie;
  289. search_len = remain_len;
  290. } else {
  291. break;
  292. }
  293. }
  294. exit:
  295. return ret;
  296. }
  297. void rtw_set_supported_rate(u8* SupportedRates, uint mode)
  298. {
  299. _func_enter_;
  300. _rtw_memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
  301. switch (mode)
  302. {
  303. case WIRELESS_11B:
  304. _rtw_memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
  305. break;
  306. case WIRELESS_11G:
  307. case WIRELESS_11A:
  308. case WIRELESS_11_5N:
  309. case WIRELESS_11A_5N://Todo: no basic rate for ofdm ?
  310. case WIRELESS_11_5AC:
  311. _rtw_memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
  312. break;
  313. case WIRELESS_11BG:
  314. case WIRELESS_11G_24N:
  315. case WIRELESS_11_24N:
  316. case WIRELESS_11BG_24N:
  317. _rtw_memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
  318. _rtw_memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
  319. break;
  320. }
  321. _func_exit_;
  322. }
  323. uint rtw_get_rateset_len(u8 *rateset)
  324. {
  325. uint i = 0;
  326. _func_enter_;
  327. while(1)
  328. {
  329. if ((rateset[i]) == 0)
  330. break;
  331. if (i > 12)
  332. break;
  333. i++;
  334. }
  335. _func_exit_;
  336. return i;
  337. }
  338. int rtw_generate_ie(struct registry_priv *pregistrypriv)
  339. {
  340. u8 wireless_mode;
  341. int sz = 0, rateLen;
  342. WLAN_BSSID_EX* pdev_network = &pregistrypriv->dev_network;
  343. u8* ie = pdev_network->IEs;
  344. _func_enter_;
  345. //timestamp will be inserted by hardware
  346. sz += 8;
  347. ie += sz;
  348. //beacon interval : 2bytes
  349. *(u16*)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);//BCN_INTERVAL;
  350. sz += 2;
  351. ie += 2;
  352. //capability info
  353. *(u16*)ie = 0;
  354. *(u16*)ie |= cpu_to_le16(cap_IBSS);
  355. if(pregistrypriv->preamble == PREAMBLE_SHORT)
  356. *(u16*)ie |= cpu_to_le16(cap_ShortPremble);
  357. if (pdev_network->Privacy)
  358. *(u16*)ie |= cpu_to_le16(cap_Privacy);
  359. sz += 2;
  360. ie += 2;
  361. //SSID
  362. ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz);
  363. //supported rates
  364. if(pregistrypriv->wireless_mode == WIRELESS_11ABGN)
  365. {
  366. if(pdev_network->Configuration.DSConfig > 14)
  367. wireless_mode = WIRELESS_11A_5N;
  368. else
  369. wireless_mode = WIRELESS_11BG_24N;
  370. }
  371. else
  372. {
  373. wireless_mode = pregistrypriv->wireless_mode;
  374. }
  375. rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode) ;
  376. rateLen = rtw_get_rateset_len(pdev_network->SupportedRates);
  377. if (rateLen > 8)
  378. {
  379. ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz);
  380. //ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
  381. }
  382. else
  383. {
  384. ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz);
  385. }
  386. //DS parameter set
  387. ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz);
  388. //IBSS Parameter Set
  389. ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz);
  390. if (rateLen > 8)
  391. {
  392. ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
  393. }
  394. #ifdef CONFIG_80211N_HT
  395. //HT Cap.
  396. if(((pregistrypriv->wireless_mode&WIRELESS_11_5N)||(pregistrypriv->wireless_mode&WIRELESS_11_24N))
  397. && (pregistrypriv->ht_enable==_TRUE))
  398. {
  399. //todo:
  400. }
  401. #endif //CONFIG_80211N_HT
  402. //pdev_network->IELength = sz; //update IELength
  403. _func_exit_;
  404. //return _SUCCESS;
  405. return sz;
  406. }
  407. unsigned char *rtw_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit)
  408. {
  409. int len;
  410. u16 val16;
  411. unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
  412. u8 *pbuf = pie;
  413. int limit_new = limit;
  414. while(1)
  415. {
  416. pbuf = rtw_get_ie(pbuf, _WPA_IE_ID_, &len, limit_new);
  417. if (pbuf) {
  418. //check if oui matches...
  419. if (_rtw_memcmp((pbuf + 2), wpa_oui_type, sizeof (wpa_oui_type)) == _FALSE) {
  420. goto check_next_ie;
  421. }
  422. //check version...
  423. _rtw_memcpy((u8 *)&val16, (pbuf + 6), sizeof(val16));
  424. val16 = le16_to_cpu(val16);
  425. if (val16 != 0x0001)
  426. goto check_next_ie;
  427. *wpa_ie_len = *(pbuf + 1);
  428. return pbuf;
  429. }
  430. else {
  431. *wpa_ie_len = 0;
  432. return NULL;
  433. }
  434. check_next_ie:
  435. limit_new = limit - (pbuf - pie) - 2 - len;
  436. if (limit_new <= 0)
  437. break;
  438. pbuf += (2 + len);
  439. }
  440. *wpa_ie_len = 0;
  441. return NULL;
  442. }
  443. unsigned char *rtw_get_wpa2_ie(unsigned char *pie, int *rsn_ie_len, int limit)
  444. {
  445. return rtw_get_ie(pie, _WPA2_IE_ID_,rsn_ie_len, limit);
  446. }
  447. int rtw_get_wpa_cipher_suite(u8 *s)
  448. {
  449. if (_rtw_memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == _TRUE)
  450. return WPA_CIPHER_NONE;
  451. if (_rtw_memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == _TRUE)
  452. return WPA_CIPHER_WEP40;
  453. if (_rtw_memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == _TRUE)
  454. return WPA_CIPHER_TKIP;
  455. if (_rtw_memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == _TRUE)
  456. return WPA_CIPHER_CCMP;
  457. if (_rtw_memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == _TRUE)
  458. return WPA_CIPHER_WEP104;
  459. return 0;
  460. }
  461. int rtw_get_wpa2_cipher_suite(u8 *s)
  462. {
  463. if (_rtw_memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == _TRUE)
  464. return WPA_CIPHER_NONE;
  465. if (_rtw_memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == _TRUE)
  466. return WPA_CIPHER_WEP40;
  467. if (_rtw_memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == _TRUE)
  468. return WPA_CIPHER_TKIP;
  469. if (_rtw_memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == _TRUE)
  470. return WPA_CIPHER_CCMP;
  471. if (_rtw_memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == _TRUE)
  472. return WPA_CIPHER_WEP104;
  473. return 0;
  474. }
  475. int rtw_parse_wpa_ie(u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
  476. {
  477. int i, ret=_SUCCESS;
  478. int left, count;
  479. u8 *pos;
  480. u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1};
  481. if (wpa_ie_len <= 0) {
  482. /* No WPA IE - fail silently */
  483. return _FAIL;
  484. }
  485. if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie+1) != (u8)(wpa_ie_len - 2)) ||
  486. (_rtw_memcmp(wpa_ie+2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN) != _TRUE) )
  487. {
  488. return _FAIL;
  489. }
  490. pos = wpa_ie;
  491. pos += 8;
  492. left = wpa_ie_len - 8;
  493. //group_cipher
  494. if (left >= WPA_SELECTOR_LEN) {
  495. *group_cipher = rtw_get_wpa_cipher_suite(pos);
  496. pos += WPA_SELECTOR_LEN;
  497. left -= WPA_SELECTOR_LEN;
  498. }
  499. else if (left > 0)
  500. {
  501. RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie length mismatch, %u too much", __FUNCTION__, left));
  502. return _FAIL;
  503. }
  504. //pairwise_cipher
  505. if (left >= 2)
  506. {
  507. //count = le16_to_cpu(*(u16*)pos);
  508. count = RTW_GET_LE16(pos);
  509. pos += 2;
  510. left -= 2;
  511. if (count == 0 || left < count * WPA_SELECTOR_LEN) {
  512. RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie count botch (pairwise), "
  513. "count %u left %u", __FUNCTION__, count, left));
  514. return _FAIL;
  515. }
  516. for (i = 0; i < count; i++)
  517. {
  518. *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos);
  519. pos += WPA_SELECTOR_LEN;
  520. left -= WPA_SELECTOR_LEN;
  521. }
  522. }
  523. else if (left == 1)
  524. {
  525. RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie too short (for key mgmt)", __FUNCTION__));
  526. return _FAIL;
  527. }
  528. if (is_8021x) {
  529. if (left >= 6) {
  530. pos += 2;
  531. if (_rtw_memcmp(pos, SUITE_1X, 4) == 1) {
  532. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("%s : there has 802.1x auth\n", __FUNCTION__));
  533. *is_8021x = 1;
  534. }
  535. }
  536. }
  537. return ret;
  538. }
  539. int rtw_parse_wpa2_ie(u8* rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
  540. {
  541. int i, ret=_SUCCESS;
  542. int left, count;
  543. u8 *pos;
  544. u8 SUITE_1X[4] = {0x00,0x0f, 0xac, 0x01};
  545. if (rsn_ie_len <= 0) {
  546. /* No RSN IE - fail silently */
  547. return _FAIL;
  548. }
  549. if ((*rsn_ie!= _WPA2_IE_ID_) || (*(rsn_ie+1) != (u8)(rsn_ie_len - 2)))
  550. {
  551. return _FAIL;
  552. }
  553. pos = rsn_ie;
  554. pos += 4;
  555. left = rsn_ie_len - 4;
  556. //group_cipher
  557. if (left >= RSN_SELECTOR_LEN) {
  558. *group_cipher = rtw_get_wpa2_cipher_suite(pos);
  559. pos += RSN_SELECTOR_LEN;
  560. left -= RSN_SELECTOR_LEN;
  561. } else if (left > 0) {
  562. RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie length mismatch, %u too much", __FUNCTION__, left));
  563. return _FAIL;
  564. }
  565. //pairwise_cipher
  566. if (left >= 2)
  567. {
  568. //count = le16_to_cpu(*(u16*)pos);
  569. count = RTW_GET_LE16(pos);
  570. pos += 2;
  571. left -= 2;
  572. if (count == 0 || left < count * RSN_SELECTOR_LEN) {
  573. RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie count botch (pairwise), "
  574. "count %u left %u", __FUNCTION__, count, left));
  575. return _FAIL;
  576. }
  577. for (i = 0; i < count; i++)
  578. {
  579. *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos);
  580. pos += RSN_SELECTOR_LEN;
  581. left -= RSN_SELECTOR_LEN;
  582. }
  583. }
  584. else if (left == 1)
  585. {
  586. RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie too short (for key mgmt)", __FUNCTION__));
  587. return _FAIL;
  588. }
  589. if (is_8021x) {
  590. if (left >= 6) {
  591. pos += 2;
  592. if (_rtw_memcmp(pos, SUITE_1X, 4) == 1) {
  593. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("%s (): there has 802.1x auth\n", __FUNCTION__));
  594. *is_8021x = 1;
  595. }
  596. }
  597. }
  598. return ret;
  599. }
  600. #ifdef CONFIG_WAPI_SUPPORT
  601. int rtw_get_wapi_ie(u8 *in_ie,uint in_len,u8 *wapi_ie,u16 *wapi_len)
  602. {
  603. u8 authmode, i;
  604. uint cnt;
  605. u8 wapi_oui1[4]={0x0,0x14,0x72,0x01};
  606. u8 wapi_oui2[4]={0x0,0x14,0x72,0x02};
  607. _func_enter_;
  608. cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
  609. while(cnt<in_len)
  610. {
  611. authmode=in_ie[cnt];
  612. //if(authmode==_WAPI_IE_)
  613. if(authmode==_WAPI_IE_ && (_rtw_memcmp(&in_ie[cnt+6], wapi_oui1,4)==_TRUE ||
  614. _rtw_memcmp(&in_ie[cnt+6], wapi_oui2,4)==_TRUE))
  615. {
  616. if (wapi_ie) {
  617. _rtw_memcpy(wapi_ie, &in_ie[cnt],in_ie[cnt+1]+2);
  618. for(i=0;i<(in_ie[cnt+1]+2);i=i+8){
  619. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
  620. wapi_ie[i],wapi_ie[i+1],wapi_ie[i+2],wapi_ie[i+3],wapi_ie[i+4],
  621. wapi_ie[i+5],wapi_ie[i+6],wapi_ie[i+7]));
  622. }
  623. }
  624. *wapi_len=in_ie[cnt+1]+2;
  625. cnt+=in_ie[cnt+1]+2; //get next
  626. }
  627. else
  628. {
  629. cnt+=in_ie[cnt+1]+2; //get next
  630. }
  631. }
  632. return *wapi_len;
  633. _func_exit_;
  634. }
  635. #endif
  636. int rtw_get_sec_ie(u8 *in_ie,uint in_len,u8 *rsn_ie,u16 *rsn_len,u8 *wpa_ie,u16 *wpa_len)
  637. {
  638. u8 authmode, sec_idx, i;
  639. u8 wpa_oui[4]={0x0,0x50,0xf2,0x01};
  640. uint cnt;
  641. _func_enter_;
  642. //Search required WPA or WPA2 IE and copy to sec_ie[ ]
  643. cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
  644. sec_idx=0;
  645. while(cnt<in_len)
  646. {
  647. authmode=in_ie[cnt];
  648. if((authmode==_WPA_IE_ID_)&&(_rtw_memcmp(&in_ie[cnt+2], &wpa_oui[0],4)==_TRUE))
  649. {
  650. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n rtw_get_wpa_ie: sec_idx=%d in_ie[cnt+1]+2=%d\n",sec_idx,in_ie[cnt+1]+2));
  651. if (wpa_ie) {
  652. _rtw_memcpy(wpa_ie, &in_ie[cnt],in_ie[cnt+1]+2);
  653. for(i=0;i<(in_ie[cnt+1]+2);i=i+8){
  654. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
  655. wpa_ie[i],wpa_ie[i+1],wpa_ie[i+2],wpa_ie[i+3],wpa_ie[i+4],
  656. wpa_ie[i+5],wpa_ie[i+6],wpa_ie[i+7]));
  657. }
  658. }
  659. *wpa_len=in_ie[cnt+1]+2;
  660. cnt+=in_ie[cnt+1]+2; //get next
  661. }
  662. else
  663. {
  664. if(authmode==_WPA2_IE_ID_)
  665. {
  666. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n get_rsn_ie: sec_idx=%d in_ie[cnt+1]+2=%d\n",sec_idx,in_ie[cnt+1]+2));
  667. if (rsn_ie) {
  668. _rtw_memcpy(rsn_ie, &in_ie[cnt],in_ie[cnt+1]+2);
  669. for(i=0;i<(in_ie[cnt+1]+2);i=i+8){
  670. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
  671. rsn_ie[i],rsn_ie[i+1],rsn_ie[i+2],rsn_ie[i+3],rsn_ie[i+4],
  672. rsn_ie[i+5],rsn_ie[i+6],rsn_ie[i+7]));
  673. }
  674. }
  675. *rsn_len=in_ie[cnt+1]+2;
  676. cnt+=in_ie[cnt+1]+2; //get next
  677. }
  678. else
  679. {
  680. cnt+=in_ie[cnt+1]+2; //get next
  681. }
  682. }
  683. }
  684. _func_exit_;
  685. return (*rsn_len+*wpa_len);
  686. }
  687. u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen)
  688. {
  689. u8 match = _FALSE;
  690. u8 eid, wps_oui[4]={0x0,0x50,0xf2,0x04};
  691. if(ie_ptr == NULL) return match;
  692. eid = ie_ptr[0];
  693. if((eid==_WPA_IE_ID_)&&(_rtw_memcmp(&ie_ptr[2], wps_oui, 4)==_TRUE))
  694. {
  695. //DBG_8192C("==> found WPS_IE.....\n");
  696. *wps_ielen = ie_ptr[1]+2;
  697. match=_TRUE;
  698. }
  699. return match;
  700. }
  701. /**
  702. * rtw_get_wps_ie - Search WPS IE from a series of IEs
  703. * @in_ie: Address of IEs to search
  704. * @in_len: Length limit from in_ie
  705. * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie
  706. * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE
  707. *
  708. * Returns: The address of the WPS IE found, or NULL
  709. */
  710. u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
  711. {
  712. uint cnt;
  713. u8 *wpsie_ptr=NULL;
  714. u8 eid, wps_oui[4]={0x0,0x50,0xf2,0x04};
  715. if(wps_ielen)
  716. *wps_ielen = 0;
  717. if(!in_ie || in_len<=0)
  718. return wpsie_ptr;
  719. cnt = 0;
  720. while(cnt<in_len)
  721. {
  722. eid = in_ie[cnt];
  723. if((eid==_WPA_IE_ID_)&&(_rtw_memcmp(&in_ie[cnt+2], wps_oui, 4)==_TRUE))
  724. {
  725. wpsie_ptr = &in_ie[cnt];
  726. if(wps_ie)
  727. _rtw_memcpy(wps_ie, &in_ie[cnt], in_ie[cnt+1]+2);
  728. if(wps_ielen)
  729. *wps_ielen = in_ie[cnt+1]+2;
  730. cnt+=in_ie[cnt+1]+2;
  731. break;
  732. }
  733. else
  734. {
  735. cnt+=in_ie[cnt+1]+2; //goto next
  736. }
  737. }
  738. return wpsie_ptr;
  739. }
  740. /**
  741. * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE
  742. * @wps_ie: Address of WPS IE to search
  743. * @wps_ielen: Length limit from wps_ie
  744. * @target_attr_id: The attribute ID of WPS attribute to search
  745. * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr
  746. * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute
  747. *
  748. * Returns: the address of the specific WPS attribute found, or NULL
  749. */
  750. u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_attr, u32 *len_attr)
  751. {
  752. u8 *attr_ptr = NULL;
  753. u8 * target_attr_ptr = NULL;
  754. u8 wps_oui[4]={0x00,0x50,0xF2,0x04};
  755. if(len_attr)
  756. *len_attr = 0;
  757. if ( ( wps_ie[0] != _VENDOR_SPECIFIC_IE_ ) ||
  758. ( _rtw_memcmp( wps_ie + 2, wps_oui , 4 ) != _TRUE ) )
  759. {
  760. return attr_ptr;
  761. }
  762. // 6 = 1(Element ID) + 1(Length) + 4(WPS OUI)
  763. attr_ptr = wps_ie + 6; //goto first attr
  764. while(attr_ptr - wps_ie < wps_ielen)
  765. {
  766. // 4 = 2(Attribute ID) + 2(Length)
  767. u16 attr_id = RTW_GET_BE16(attr_ptr);
  768. u16 attr_data_len = RTW_GET_BE16(attr_ptr + 2);
  769. u16 attr_len = attr_data_len + 4;
  770. //DBG_871X("%s attr_ptr:%p, id:%u, length:%u\n", __FUNCTION__, attr_ptr, attr_id, attr_data_len);
  771. if( attr_id == target_attr_id )
  772. {
  773. target_attr_ptr = attr_ptr;
  774. if(buf_attr)
  775. _rtw_memcpy(buf_attr, attr_ptr, attr_len);
  776. if(len_attr)
  777. *len_attr = attr_len;
  778. break;
  779. }
  780. else
  781. {
  782. attr_ptr += attr_len; //goto next
  783. }
  784. }
  785. return target_attr_ptr;
  786. }
  787. /**
  788. * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE
  789. * @wps_ie: Address of WPS IE to search
  790. * @wps_ielen: Length limit from wps_ie
  791. * @target_attr_id: The attribute ID of WPS attribute to search
  792. * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content
  793. * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content
  794. *
  795. * Returns: the address of the specific WPS attribute content found, or NULL
  796. */
  797. u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_content, uint *len_content)
  798. {
  799. u8 *attr_ptr;
  800. u32 attr_len;
  801. if(len_content)
  802. *len_content = 0;
  803. attr_ptr = rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &attr_len);
  804. if(attr_ptr && attr_len)
  805. {
  806. if(buf_content)
  807. _rtw_memcpy(buf_content, attr_ptr+4, attr_len-4);
  808. if(len_content)
  809. *len_content = attr_len-4;
  810. return attr_ptr+4;
  811. }
  812. return NULL;
  813. }
  814. static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
  815. struct rtw_ieee802_11_elems *elems,
  816. int show_errors)
  817. {
  818. unsigned int oui;
  819. /* first 3 bytes in vendor specific information element are the IEEE
  820. * OUI of the vendor. The following byte is used a vendor specific
  821. * sub-type. */
  822. if (elen < 4) {
  823. if (show_errors) {
  824. DBG_871X("short vendor specific "
  825. "information element ignored (len=%lu)\n",
  826. (unsigned long) elen);
  827. }
  828. return -1;
  829. }
  830. oui = RTW_GET_BE24(pos);
  831. switch (oui) {
  832. case OUI_MICROSOFT:
  833. /* Microsoft/Wi-Fi information elements are further typed and
  834. * subtyped */
  835. switch (pos[3]) {
  836. case 1:
  837. /* Microsoft OUI (00:50:F2) with OUI Type 1:
  838. * real WPA information element */
  839. elems->wpa_ie = pos;
  840. elems->wpa_ie_len = elen;
  841. break;
  842. case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
  843. if (elen < 5) {
  844. DBG_871X("short WME "
  845. "information element ignored "
  846. "(len=%lu)\n",
  847. (unsigned long) elen);
  848. return -1;
  849. }
  850. switch (pos[4]) {
  851. case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
  852. case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
  853. elems->wme = pos;
  854. elems->wme_len = elen;
  855. break;
  856. case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
  857. elems->wme_tspec = pos;
  858. elems->wme_tspec_len = elen;
  859. break;
  860. default:
  861. DBG_871X("unknown WME "
  862. "information element ignored "
  863. "(subtype=%d len=%lu)\n",
  864. pos[4], (unsigned long) elen);
  865. return -1;
  866. }
  867. break;
  868. case 4:
  869. /* Wi-Fi Protected Setup (WPS) IE */
  870. elems->wps_ie = pos;
  871. elems->wps_ie_len = elen;
  872. break;
  873. default:
  874. DBG_871X("Unknown Microsoft "
  875. "information element ignored "
  876. "(type=%d len=%lu)\n",
  877. pos[3], (unsigned long) elen);
  878. return -1;
  879. }
  880. break;
  881. case OUI_BROADCOM:
  882. switch (pos[3]) {
  883. case VENDOR_HT_CAPAB_OUI_TYPE:
  884. elems->vendor_ht_cap = pos;
  885. elems->vendor_ht_cap_len = elen;
  886. break;
  887. default:
  888. DBG_871X("Unknown Broadcom "
  889. "information element ignored "
  890. "(type=%d len=%lu)\n",
  891. pos[3], (unsigned long) elen);
  892. return -1;
  893. }
  894. break;
  895. default:
  896. DBG_871X("unknown vendor specific information "
  897. "element ignored (vendor OUI %02x:%02x:%02x "
  898. "len=%lu)\n",
  899. pos[0], pos[1], pos[2], (unsigned long) elen);
  900. return -1;
  901. }
  902. return 0;
  903. }
  904. /**
  905. * ieee802_11_parse_elems - Parse information elements in management frames
  906. * @start: Pointer to the start of IEs
  907. * @len: Length of IE buffer in octets
  908. * @elems: Data structure for parsed elements
  909. * @show_errors: Whether to show parsing errors in debug log
  910. * Returns: Parsing result
  911. */
  912. ParseRes rtw_ieee802_11_parse_elems(u8 *start, uint len,
  913. struct rtw_ieee802_11_elems *elems,
  914. int show_errors)
  915. {
  916. uint left = len;
  917. u8 *pos = start;
  918. int unknown = 0;
  919. _rtw_memset(elems, 0, sizeof(*elems));
  920. while (left >= 2) {
  921. u8 id, elen;
  922. id = *pos++;
  923. elen = *pos++;
  924. left -= 2;
  925. if (elen > left) {
  926. if (show_errors) {
  927. DBG_871X("IEEE 802.11 element "
  928. "parse failed (id=%d elen=%d "
  929. "left=%lu)\n",
  930. id, elen, (unsigned long) left);
  931. }
  932. return ParseFailed;
  933. }
  934. switch (id) {
  935. case WLAN_EID_SSID:
  936. elems->ssid = pos;
  937. elems->ssid_len = elen;
  938. break;
  939. case WLAN_EID_SUPP_RATES:
  940. elems->supp_rates = pos;
  941. elems->supp_rates_len = elen;
  942. break;
  943. case WLAN_EID_FH_PARAMS:
  944. elems->fh_params = pos;
  945. elems->fh_params_len = elen;
  946. break;
  947. case WLAN_EID_DS_PARAMS:
  948. elems->ds_params = pos;
  949. elems->ds_params_len = elen;
  950. break;
  951. case WLAN_EID_CF_PARAMS:
  952. elems->cf_params = pos;
  953. elems->cf_params_len = elen;
  954. break;
  955. case WLAN_EID_TIM:
  956. elems->tim = pos;
  957. elems->tim_len = elen;
  958. break;
  959. case WLAN_EID_IBSS_PARAMS:
  960. elems->ibss_params = pos;
  961. elems->ibss_params_len = elen;
  962. break;
  963. case WLAN_EID_CHALLENGE:
  964. elems->challenge = pos;
  965. elems->challenge_len = elen;
  966. break;
  967. case WLAN_EID_ERP_INFO:
  968. elems->erp_info = pos;
  969. elems->erp_info_len = elen;
  970. break;
  971. case WLAN_EID_EXT_SUPP_RATES:
  972. elems->ext_supp_rates = pos;
  973. elems->ext_supp_rates_len = elen;
  974. break;
  975. case WLAN_EID_VENDOR_SPECIFIC:
  976. if (rtw_ieee802_11_parse_vendor_specific(pos, elen,
  977. elems,
  978. show_errors))
  979. unknown++;
  980. break;
  981. case WLAN_EID_RSN:
  982. elems->rsn_ie = pos;
  983. elems->rsn_ie_len = elen;
  984. break;
  985. case WLAN_EID_PWR_CAPABILITY:
  986. elems->power_cap = pos;
  987. elems->power_cap_len = elen;
  988. break;
  989. case WLAN_EID_SUPPORTED_CHANNELS:
  990. elems->supp_channels = pos;
  991. elems->supp_channels_len = elen;
  992. break;
  993. case WLAN_EID_MOBILITY_DOMAIN:
  994. elems->mdie = pos;
  995. elems->mdie_len = elen;
  996. break;
  997. case WLAN_EID_FAST_BSS_TRANSITION:
  998. elems->ftie = pos;
  999. elems->ftie_len = elen;
  1000. break;
  1001. case WLAN_EID_TIMEOUT_INTERVAL:
  1002. elems->timeout_int = pos;
  1003. elems->timeout_int_len = elen;
  1004. break;
  1005. case WLAN_EID_HT_CAP:
  1006. elems->ht_capabilities = pos;
  1007. elems->ht_capabilities_len = elen;
  1008. break;
  1009. case WLAN_EID_HT_OPERATION:
  1010. elems->ht_operation = pos;
  1011. elems->ht_operation_len = elen;
  1012. break;
  1013. case WLAN_EID_VHT_CAPABILITY:
  1014. elems->vht_capabilities = pos;
  1015. elems->vht_capabilities_len = elen;
  1016. break;
  1017. case WLAN_EID_VHT_OPERATION:
  1018. elems->vht_operation = pos;
  1019. elems->vht_operation_len = elen;
  1020. break;
  1021. case WLAN_EID_VHT_OP_MODE_NOTIFY:
  1022. elems->vht_op_mode_notify = pos;
  1023. elems->vht_op_mode_notify_len = elen;
  1024. break;
  1025. default:
  1026. unknown++;
  1027. if (!show_errors)
  1028. break;
  1029. DBG_871X("IEEE 802.11 element parse "
  1030. "ignored unknown element (id=%d elen=%d)\n",
  1031. id, elen);
  1032. break;
  1033. }
  1034. left -= elen;
  1035. pos += elen;
  1036. }
  1037. if (left)
  1038. return ParseFailed;
  1039. return unknown ? ParseUnknown : ParseOK;
  1040. }
  1041. static u8 key_char2num(u8 ch);
  1042. static u8 key_char2num(u8 ch)
  1043. {
  1044. if((ch>='0')&&(ch<='9'))
  1045. return ch - '0';
  1046. else if ((ch>='a')&&(ch<='f'))
  1047. return ch - 'a' + 10;
  1048. else if ((ch>='A')&&(ch<='F'))
  1049. return ch - 'A' + 10;
  1050. else
  1051. return 0xff;
  1052. }
  1053. u8 str_2char2num(u8 hch, u8 lch);
  1054. u8 str_2char2num(u8 hch, u8 lch)
  1055. {
  1056. return ((key_char2num(hch) * 10 ) + key_char2num(lch));
  1057. }
  1058. u8 key_2char2num(u8 hch, u8 lch);
  1059. u8 key_2char2num(u8 hch, u8 lch)
  1060. {
  1061. return ((key_char2num(hch) << 4) | key_char2num(lch));
  1062. }
  1063. u8 convert_ip_addr(u8 hch, u8 mch, u8 lch)
  1064. {
  1065. return ((key_char2num(hch) * 100) + (key_char2num(mch) * 10 ) + key_char2num(lch));
  1066. }
  1067. extern char* rtw_initmac;
  1068. void rtw_macaddr_cfg(u8 *mac_addr)
  1069. {
  1070. u8 mac[ETH_ALEN];
  1071. if(mac_addr == NULL) return;
  1072. if ( rtw_initmac )
  1073. { // Users specify the mac address
  1074. int jj,kk;
  1075. for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
  1076. {
  1077. mac[jj] = key_2char2num(rtw_initmac[kk], rtw_initmac[kk+ 1]);
  1078. }
  1079. _rtw_memcpy(mac_addr, mac, ETH_ALEN);
  1080. }
  1081. else
  1082. { // Use the mac address stored in the Efuse
  1083. _rtw_memcpy(mac, mac_addr, ETH_ALEN);
  1084. }
  1085. if (((mac[0]==0xff) &&(mac[1]==0xff) && (mac[2]==0xff) &&
  1086. (mac[3]==0xff) && (mac[4]==0xff) &&(mac[5]==0xff)) ||
  1087. ((mac[0]==0x0) && (mac[1]==0x0) && (mac[2]==0x0) &&
  1088. (mac[3]==0x0) && (mac[4]==0x0) &&(mac[5]==0x0)))
  1089. {
  1090. mac[0] = 0x00;
  1091. mac[1] = 0xe0;
  1092. mac[2] = 0x4c;
  1093. mac[3] = 0x87;
  1094. mac[4] = 0x00;
  1095. mac[5] = 0x00;
  1096. // use default mac addresss
  1097. _rtw_memcpy(mac_addr, mac, ETH_ALEN);
  1098. DBG_871X("MAC Address from efuse error, assign default one !!!\n");
  1099. }
  1100. DBG_871X("rtw_macaddr_cfg MAC Address = "MAC_FMT"\n", MAC_ARG(mac_addr));
  1101. }
  1102. void dump_ies(u8 *buf, u32 buf_len) {
  1103. u8* pos = (u8*)buf;
  1104. u8 id, len;
  1105. while(pos-buf<=buf_len){
  1106. id = *pos;
  1107. len = *(pos+1);
  1108. DBG_871X("%s ID:%u, LEN:%u\n", __FUNCTION__, id, len);
  1109. #ifdef CONFIG_P2P
  1110. dump_p2p_ie(pos, len);
  1111. #endif
  1112. dump_wps_ie(pos, len);
  1113. pos+=(2+len);
  1114. }
  1115. }
  1116. void dump_wps_ie(u8 *ie, u32 ie_len) {
  1117. u8* pos = (u8*)ie;
  1118. u16 id;
  1119. u16 len;
  1120. u8 *wps_ie;
  1121. uint wps_ielen;
  1122. wps_ie = rtw_get_wps_ie(ie, ie_len, NULL, &wps_ielen);
  1123. if(wps_ie != ie || wps_ielen == 0)
  1124. return;
  1125. pos+=6;
  1126. while(pos-ie < ie_len){
  1127. id = RTW_GET_BE16(pos);
  1128. len = RTW_GET_BE16(pos + 2);
  1129. DBG_871X("%s ID:0x%04x, LEN:%u\n", __FUNCTION__, id, len);
  1130. pos+=(4+len);
  1131. }
  1132. }
  1133. #ifdef CONFIG_P2P
  1134. void dump_p2p_ie(u8 *ie, u32 ie_len) {
  1135. u8* pos = (u8*)ie;
  1136. u8 id;
  1137. u16 len;
  1138. u8 *p2p_ie;
  1139. uint p2p_ielen;
  1140. p2p_ie = rtw_get_p2p_ie(ie, ie_len, NULL, &p2p_ielen);
  1141. if(p2p_ie != ie || p2p_ielen == 0)
  1142. return;
  1143. pos+=6;
  1144. while(pos-ie < ie_len){
  1145. id = *pos;
  1146. len = RTW_GET_LE16(pos+1);
  1147. DBG_871X("%s ID:%u, LEN:%u\n", __FUNCTION__, id, len);
  1148. pos+=(3+len);
  1149. }
  1150. }
  1151. /**
  1152. * rtw_get_p2p_ie - Search P2P IE from a series of IEs
  1153. * @in_ie: Address of IEs to search
  1154. * @in_len: Length limit from in_ie
  1155. * @p2p_ie: If not NULL and P2P IE is found, P2P IE will be copied to the buf starting from p2p_ie
  1156. * @p2p_ielen: If not NULL and P2P IE is found, will set to the length of the entire P2P IE
  1157. *
  1158. * Returns: The address of the P2P IE found, or NULL
  1159. */
  1160. u8 *rtw_get_p2p_ie(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen)
  1161. {
  1162. uint cnt = 0;
  1163. u8 *p2p_ie_ptr;
  1164. u8 eid, p2p_oui[4]={0x50,0x6F,0x9A,0x09};
  1165. if ( p2p_ielen != NULL )
  1166. *p2p_ielen = 0;
  1167. while(cnt<in_len)
  1168. {
  1169. eid = in_ie[cnt];
  1170. if ((in_len < 0) || (cnt > MAX_IE_SZ)) {
  1171. rtw_dump_stack();
  1172. return NULL;
  1173. }
  1174. if( ( eid == _VENDOR_SPECIFIC_IE_ ) && ( _rtw_memcmp( &in_ie[cnt+2], p2p_oui, 4) == _TRUE ) )
  1175. {
  1176. p2p_ie_ptr = in_ie + cnt;
  1177. if ( p2p_ie != NULL )
  1178. {
  1179. _rtw_memcpy( p2p_ie, &in_ie[ cnt ], in_ie[ cnt + 1 ] + 2 );
  1180. }
  1181. if ( p2p_ielen != NULL )
  1182. {
  1183. *p2p_ielen = in_ie[ cnt + 1 ] + 2;
  1184. }
  1185. return p2p_ie_ptr;
  1186. break;
  1187. }
  1188. else
  1189. {
  1190. cnt += in_ie[ cnt + 1 ] +2; //goto next
  1191. }
  1192. }
  1193. return NULL;
  1194. }
  1195. /**
  1196. * rtw_get_p2p_attr - Search a specific P2P attribute from a given P2P IE
  1197. * @p2p_ie: Address of P2P IE to search
  1198. * @p2p_ielen: Length limit from p2p_ie
  1199. * @target_attr_id: The attribute ID of P2P attribute to search
  1200. * @buf_attr: If not NULL and the P2P attribute is found, P2P attribute will be copied to the buf starting from buf_attr
  1201. * @len_attr: If not NULL and the P2P attribute is found, will set to the length of the entire P2P attribute
  1202. *
  1203. * Returns: the address of the specific WPS attribute found, or NULL
  1204. */
  1205. u8 *rtw_get_p2p_attr(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id ,u8 *buf_attr, u32 *len_attr)
  1206. {
  1207. u8 *attr_ptr = NULL;
  1208. u8 *target_attr_ptr = NULL;
  1209. u8 p2p_oui[4]={0x50,0x6F,0x9A,0x09};
  1210. if(len_attr)
  1211. *len_attr = 0;
  1212. if ( !p2p_ie || ( p2p_ie[0] != _VENDOR_SPECIFIC_IE_ ) ||
  1213. ( _rtw_memcmp( p2p_ie + 2, p2p_oui , 4 ) != _TRUE ) )
  1214. {
  1215. return attr_ptr;
  1216. }
  1217. // 6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type)
  1218. attr_ptr = p2p_ie + 6; //goto first attr
  1219. while(attr_ptr - p2p_ie < p2p_ielen)
  1220. {
  1221. // 3 = 1(Attribute ID) + 2(Length)
  1222. u8 attr_id = *attr_ptr;
  1223. u16 attr_data_len = RTW_GET_LE16(attr_ptr + 1);
  1224. u16 attr_len = attr_data_len + 3;
  1225. //DBG_871X("%s attr_ptr:%p, id:%u, length:%u\n", __FUNCTION__, attr_ptr, attr_id, attr_data_len);
  1226. if( attr_id == target_attr_id )
  1227. {
  1228. target_attr_ptr = attr_ptr;
  1229. if(buf_attr)
  1230. _rtw_memcpy(buf_attr, attr_ptr, attr_len);
  1231. if(len_attr)
  1232. *len_attr = attr_len;
  1233. break;
  1234. }
  1235. else
  1236. {
  1237. attr_ptr += attr_len; //goto next
  1238. }
  1239. }
  1240. return target_attr_ptr;
  1241. }
  1242. /**
  1243. * rtw_get_p2p_attr_content - Search a specific P2P attribute content from a given P2P IE
  1244. * @p2p_ie: Address of P2P IE to search
  1245. * @p2p_ielen: Length limit from p2p_ie
  1246. * @target_attr_id: The attribute ID of P2P attribute to search
  1247. * @buf_content: If not NULL and the P2P attribute is found, P2P attribute content will be copied to the buf starting from buf_content
  1248. * @len_content: If not NULL and the P2P attribute is found, will set to the length of the P2P attribute content
  1249. *
  1250. * Returns: the address of the specific P2P attribute content found, or NULL
  1251. */
  1252. u8 *rtw_get_p2p_attr_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id ,u8 *buf_content, uint *len_content)
  1253. {
  1254. u8 *attr_ptr;
  1255. u32 attr_len;
  1256. if(len_content)
  1257. *len_content = 0;
  1258. attr_ptr = rtw_get_p2p_attr(p2p_ie, p2p_ielen, target_attr_id, NULL, &attr_len);
  1259. if(attr_ptr && attr_len)
  1260. {
  1261. if(buf_content)
  1262. _rtw_memcpy(buf_content, attr_ptr+3, attr_len-3);
  1263. if(len_content)
  1264. *len_content = attr_len-3;
  1265. return attr_ptr+3;
  1266. }
  1267. return NULL;
  1268. }
  1269. u32 rtw_set_p2p_attr_content(u8 *pbuf, u8 attr_id, u16 attr_len, u8 *pdata_attr)
  1270. {
  1271. u32 a_len;
  1272. *pbuf = attr_id;
  1273. //*(u16*)(pbuf + 1) = cpu_to_le16(attr_len);
  1274. RTW_PUT_LE16(pbuf + 1, attr_len);
  1275. if(pdata_attr)
  1276. _rtw_memcpy(pbuf + 3, pdata_attr, attr_len);
  1277. a_len = attr_len + 3;
  1278. return a_len;
  1279. }
  1280. static uint rtw_p2p_attr_remove(u8 *ie, uint ielen_ori, u8 attr_id)
  1281. {
  1282. u8 *target_attr;
  1283. u32 target_attr_len;
  1284. uint ielen = ielen_ori;
  1285. int index=0;
  1286. while(1) {
  1287. target_attr=rtw_get_p2p_attr(ie, ielen, attr_id, NULL, &target_attr_len);
  1288. if(target_attr && target_attr_len)
  1289. {
  1290. u8 *next_attr = target_attr+target_attr_len;
  1291. uint remain_len = ielen-(next_attr-ie);
  1292. //dump_ies(ie, ielen);
  1293. #if 0
  1294. DBG_871X("[%d] ie:%p, ielen:%u\n"
  1295. "target_attr:%p, target_attr_len:%u\n"
  1296. "next_attr:%p, remain_len:%u\n"
  1297. , index++
  1298. , ie, ielen
  1299. , target_attr, target_attr_len
  1300. , next_attr, remain_len
  1301. );
  1302. #endif
  1303. _rtw_memset(target_attr, 0, target_attr_len);
  1304. _rtw_memcpy(target_attr, next_attr, remain_len);
  1305. _rtw_memset(target_attr+remain_len, 0, target_attr_len);
  1306. *(ie+1) -= target_attr_len;
  1307. ielen-=target_attr_len;
  1308. }
  1309. else
  1310. {
  1311. //if(index>0)
  1312. // dump_ies(ie, ielen);
  1313. break;
  1314. }
  1315. }
  1316. return ielen;
  1317. }
  1318. void rtw_WLAN_BSSID_EX_remove_p2p_attr(WLAN_BSSID_EX *bss_ex, u8 attr_id)
  1319. {
  1320. u8 *p2p_ie;
  1321. uint p2p_ielen, p2p_ielen_ori;
  1322. int cnt;
  1323. if( (p2p_ie=rtw_get_p2p_ie(bss_ex->IEs+_FIXED_IE_LENGTH_, bss_ex->IELength-_FIXED_IE_LENGTH_, NULL, &p2p_ielen_ori)) )
  1324. {
  1325. #if 0
  1326. if(rtw_get_p2p_attr(p2p_ie, p2p_ielen_ori, attr_id, NULL, NULL)) {
  1327. DBG_871X("rtw_get_p2p_attr: GOT P2P_ATTR:%u!!!!!!!!\n", attr_id);
  1328. dump_ies(bss_ex->IEs+_FIXED_IE_LENGTH_, bss_ex->IELength-_FIXED_IE_LENGTH_);
  1329. }
  1330. #endif
  1331. p2p_ielen=rtw_p2p_attr_remove(p2p_ie, p2p_ielen_ori, attr_id);
  1332. if(p2p_ielen != p2p_ielen_ori) {
  1333. u8 *next_ie_ori = p2p_ie+p2p_ielen_ori;
  1334. u8 *next_ie = p2p_ie+p2p_ielen;
  1335. uint remain_len = bss_ex->IELength-(next_ie_ori-bss_ex->IEs);
  1336. _rtw_memcpy(next_ie, next_ie_ori, remain_len);
  1337. _rtw_memset(next_ie+remain_len, 0, p2p_ielen_ori-p2p_ielen);
  1338. bss_ex->IELength -= p2p_ielen_ori-p2p_ielen;
  1339. #if 0
  1340. DBG_871X("remove P2P_ATTR:%u!\n", attr_id);
  1341. dump_ies(bss_ex->IEs+_FIXED_IE_LENGTH_, bss_ex->IELength-_FIXED_IE_LENGTH_);
  1342. #endif
  1343. }
  1344. }
  1345. }
  1346. #endif //CONFIG_P2P
  1347. #ifdef CONFIG_WFD
  1348. int rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen)
  1349. {
  1350. int match;
  1351. uint cnt = 0;
  1352. u8 eid, wfd_oui[4]={0x50,0x6F,0x9A,0x0A};
  1353. match=_FALSE;
  1354. if ( in_len < 0 )
  1355. {
  1356. return match;
  1357. }
  1358. while(cnt<in_len)
  1359. {
  1360. eid = in_ie[cnt];
  1361. if( ( eid == _VENDOR_SPECIFIC_IE_ ) && ( _rtw_memcmp( &in_ie[cnt+2], wfd_oui, 4) == _TRUE ) )
  1362. {
  1363. if ( wfd_ie != NULL )
  1364. {
  1365. _rtw_memcpy( wfd_ie, &in_ie[ cnt ], in_ie[ cnt + 1 ] + 2 );
  1366. }
  1367. else
  1368. {
  1369. if ( wfd_ielen != NULL )
  1370. {
  1371. *wfd_ielen = 0;
  1372. }
  1373. }
  1374. if ( wfd_ielen != NULL )
  1375. {
  1376. *wfd_ielen = in_ie[ cnt + 1 ] + 2;
  1377. }
  1378. cnt += in_ie[ cnt + 1 ] + 2;
  1379. match = _TRUE;
  1380. break;
  1381. }
  1382. else
  1383. {
  1384. cnt += in_ie[ cnt + 1 ] +2; //goto next
  1385. }
  1386. }
  1387. if ( match == _TRUE )
  1388. {
  1389. match = cnt;
  1390. }
  1391. return match;
  1392. }
  1393. // attr_content: The output buffer, contains the "body field" of WFD attribute.
  1394. // attr_contentlen: The data length of the "body field" of WFD attribute.
  1395. int rtw_get_wfd_attr_content(u8 *wfd_ie, uint wfd_ielen, u8 target_attr_id ,u8 *attr_content, uint *attr_contentlen)
  1396. {
  1397. int match;
  1398. uint cnt = 0;
  1399. u8 attr_id, wfd_oui[4]={0x50,0x6F,0x9A,0x0A};
  1400. match=_FALSE;
  1401. if ( ( wfd_ie[ 0 ] != _VENDOR_SPECIFIC_IE_ ) ||
  1402. ( _rtw_memcmp( wfd_ie + 2, wfd_oui , 4 ) != _TRUE ) )
  1403. {
  1404. return( match );
  1405. }
  1406. // 1 ( WFD IE ) + 1 ( Length ) + 3 ( OUI ) + 1 ( OUI Type )
  1407. cnt = 6;
  1408. while( cnt < wfd_ielen )
  1409. {
  1410. u16 attrlen = RTW_GET_BE16(wfd_ie + cnt + 1);
  1411. attr_id = wfd_ie[cnt];
  1412. if( attr_id == target_attr_id )
  1413. {
  1414. // 3 -> 1 byte for attribute ID field, 2 bytes for length field
  1415. if(attr_content)
  1416. _rtw_memcpy( attr_content, &wfd_ie[ cnt + 3 ], attrlen );
  1417. if(attr_contentlen)
  1418. *attr_contentlen = attrlen;
  1419. cnt += attrlen + 3;
  1420. match = _TRUE;
  1421. break;
  1422. }
  1423. else
  1424. {
  1425. cnt += attrlen + 3; //goto next
  1426. }
  1427. }
  1428. return match;
  1429. }
  1430. #endif // CONFIG_WFD
  1431. //Baron adds to avoid FreeBSD warning
  1432. int ieee80211_is_empty_essid(const char *essid, int essid_len)
  1433. {
  1434. /* Single white space is for Linksys APs */
  1435. if (essid_len == 1 && essid[0] == ' ')
  1436. return 1;
  1437. /* Otherwise, if the entire essid is 0, we assume it is hidden */
  1438. while (essid_len) {
  1439. essid_len--;
  1440. if (essid[essid_len] != '\0')
  1441. return 0;
  1442. }
  1443. return 1;
  1444. }
  1445. int ieee80211_get_hdrlen(u16 fc)
  1446. {
  1447. int hdrlen = 24;
  1448. switch (WLAN_FC_GET_TYPE(fc)) {
  1449. case RTW_IEEE80211_FTYPE_DATA:
  1450. if (fc & RTW_IEEE80211_STYPE_QOS_DATA)
  1451. hdrlen += 2;
  1452. if ((fc & RTW_IEEE80211_FCTL_FROMDS) && (fc & RTW_IEEE80211_FCTL_TODS))
  1453. hdrlen += 6; /* Addr4 */
  1454. break;
  1455. case RTW_IEEE80211_FTYPE_CTL:
  1456. switch (WLAN_FC_GET_STYPE(fc)) {
  1457. case RTW_IEEE80211_STYPE_CTS:
  1458. case RTW_IEEE80211_STYPE_ACK:
  1459. hdrlen = 10;
  1460. break;
  1461. default:
  1462. hdrlen = 16;
  1463. break;
  1464. }
  1465. break;
  1466. }
  1467. return hdrlen;
  1468. }
  1469. int rtw_get_cipher_info(struct wlan_network *pnetwork)
  1470. {
  1471. u32 wpa_ielen;
  1472. unsigned char *pbuf;
  1473. int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
  1474. int ret = _FAIL;
  1475. pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
  1476. if(pbuf && (wpa_ielen>0)) {
  1477. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_cipher_info: wpa_ielen: %d", wpa_ielen));
  1478. if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) {
  1479. pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
  1480. pnetwork->BcnInfo.group_cipher = group_cipher;
  1481. pnetwork->BcnInfo.is_8021x = is8021x;
  1482. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("%s: pnetwork->pairwise_cipher: %d, is_8021x is %d",
  1483. __func__, pnetwork->BcnInfo.pairwise_cipher, pnetwork->BcnInfo.is_8021x));
  1484. ret = _SUCCESS;
  1485. }
  1486. } else {
  1487. pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
  1488. if(pbuf && (wpa_ielen>0)) {
  1489. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("get RSN IE\n"));
  1490. if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) {
  1491. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("get RSN IE OK!!!\n"));
  1492. pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
  1493. pnetwork->BcnInfo.group_cipher = group_cipher;
  1494. pnetwork->BcnInfo.is_8021x = is8021x;
  1495. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("%s: pnetwork->pairwise_cipher: %d,"
  1496. "pnetwork->group_cipher is %d, is_8021x is %d", __func__, pnetwork->BcnInfo.pairwise_cipher,
  1497. pnetwork->BcnInfo.group_cipher,pnetwork->BcnInfo.is_8021x));
  1498. ret = _SUCCESS;
  1499. }
  1500. }
  1501. }
  1502. return ret;
  1503. }
  1504. void rtw_get_bcn_info(struct wlan_network *pnetwork)
  1505. {
  1506. unsigned short cap = 0;
  1507. u8 bencrypt = 0;
  1508. //u8 wpa_ie[255],rsn_ie[255];
  1509. u16 wpa_len=0,rsn_len=0;
  1510. struct HT_info_element *pht_info = NULL;
  1511. struct rtw_ieee80211_ht_cap *pht_cap = NULL;
  1512. unsigned int len;
  1513. unsigned char *p;
  1514. _rtw_memcpy((u8 *)&cap, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
  1515. cap = le16_to_cpu(cap);
  1516. if (cap & WLAN_CAPABILITY_PRIVACY) {
  1517. bencrypt = 1;
  1518. pnetwork->network.Privacy = 1;
  1519. } else {
  1520. pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
  1521. }
  1522. rtw_get_sec_ie(pnetwork->network.IEs ,pnetwork->network.IELength,NULL,&rsn_len,NULL,&wpa_len);
  1523. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: ssid=%s\n",pnetwork->network.Ssid.Ssid));
  1524. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: wpa_len=%d rsn_len=%d\n",wpa_len,rsn_len));
  1525. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: ssid=%s\n",pnetwork->network.Ssid.Ssid));
  1526. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: wpa_len=%d rsn_len=%d\n",wpa_len,rsn_len));
  1527. if (rsn_len > 0) {
  1528. pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
  1529. } else if (wpa_len > 0) {
  1530. pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA;
  1531. } else {
  1532. if (bencrypt)
  1533. pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
  1534. }
  1535. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
  1536. pnetwork->BcnInfo.encryp_protocol));
  1537. RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
  1538. pnetwork->BcnInfo.encryp_protocol));
  1539. rtw_get_cipher_info(pnetwork);
  1540. /* get bwmode and ch_offset */
  1541. /* parsing HT_CAP_IE */
  1542. p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_);
  1543. if(p && len>0) {
  1544. pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2);
  1545. pnetwork->BcnInfo.ht_cap_info = pht_cap->cap_info;
  1546. } else {
  1547. pnetwork->BcnInfo.ht_cap_info = 0;
  1548. }
  1549. /* parsing HT_INFO_IE */
  1550. p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_);
  1551. if(p && len>0) {
  1552. pht_info = (struct HT_info_element *)(p + 2);
  1553. pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0];
  1554. } else {
  1555. pnetwork->BcnInfo.ht_info_infos_0 = 0;
  1556. }
  1557. }
  1558. //show MCS rate, unit: 100Kbps
  1559. u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsigned char * MCS_rate)
  1560. {
  1561. u16 max_rate = 0;
  1562. if(rf_type == RF_1T1R)
  1563. {
  1564. if(MCS_rate[0] & BIT(7))
  1565. max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):((short_GI_20)?722:650);
  1566. else if(MCS_rate[0] & BIT(6))
  1567. max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):((short_GI_20)?650:585);
  1568. else if(MCS_rate[0] & BIT(5))
  1569. max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520);
  1570. else if(MCS_rate[0] & BIT(4))
  1571. max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390);
  1572. else if(MCS_rate[0] & BIT(3))
  1573. max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260);
  1574. else if(MCS_rate[0] & BIT(2))
  1575. max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):((short_GI_20)?217:195);
  1576. else if(MCS_rate[0] & BIT(1))
  1577. max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130);
  1578. else if(MCS_rate[0] & BIT(0))
  1579. max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):((short_GI_20)?72:65);
  1580. }
  1581. else
  1582. {
  1583. if(MCS_rate[1])
  1584. {
  1585. if(MCS_rate[1] & BIT(7))
  1586. max_rate = (bw_40MHz) ? ((short_GI_40)?3000:2700):((short_GI_20)?1444:1300);
  1587. else if(MCS_rate[1] & BIT(6))
  1588. max_rate = (bw_40MHz) ? ((short_GI_40)?2700:2430):((short_GI_20)?1300:1170);
  1589. else if(MCS_rate[1] & BIT(5))
  1590. max_rate = (bw_40MHz) ? ((short_GI_40)?2400:2160):((short_GI_20)?1156:1040);
  1591. else if(MCS_rate[1] & BIT(4))
  1592. max_rate = (bw_40MHz) ? ((short_GI_40)?1800:1620):((short_GI_20)?867:780);
  1593. else if(MCS_rate[1] & BIT(3))
  1594. max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520);
  1595. else if(MCS_rate[1] & BIT(2))
  1596. max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390);
  1597. else if(MCS_rate[1] & BIT(1))
  1598. max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260);
  1599. else if(MCS_rate[1] & BIT(0))
  1600. max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130);
  1601. }
  1602. else
  1603. {
  1604. if(MCS_rate[0] & BIT(7))
  1605. max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):((short_GI_20)?722:650);
  1606. else if(MCS_rate[0] & BIT(6))
  1607. max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):((short_GI_20)?650:585);
  1608. else if(MCS_rate[0] & BIT(5))
  1609. max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520);
  1610. else if(MCS_rate[0] & BIT(4))
  1611. max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390);
  1612. else if(MCS_rate[0] & BIT(3))
  1613. max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260);
  1614. else if(MCS_rate[0] & BIT(2))
  1615. max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):((short_GI_20)?217:195);
  1616. else if(MCS_rate[0] & BIT(1))
  1617. max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130);
  1618. else if(MCS_rate[0] & BIT(0))
  1619. max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):((short_GI_20)?72:65);
  1620. }
  1621. }
  1622. return max_rate;
  1623. }
  1624. int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8* category, u8 *action)
  1625. {
  1626. const u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
  1627. u16 fc;
  1628. u8 c, a;
  1629. fc = le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)frame)->frame_ctl);
  1630. if ((fc & (RTW_IEEE80211_FCTL_FTYPE|RTW_IEEE80211_FCTL_STYPE))
  1631. != (RTW_IEEE80211_FTYPE_MGMT|RTW_IEEE80211_STYPE_ACTION)
  1632. )
  1633. {
  1634. return _FALSE;
  1635. }
  1636. c = frame_body[0];
  1637. switch(c) {
  1638. case RTW_WLAN_CATEGORY_P2P: /* vendor-specific */
  1639. break;
  1640. default:
  1641. a = frame_body[1];
  1642. }
  1643. if (category)
  1644. *category = c;
  1645. if (action)
  1646. *action = a;
  1647. return _TRUE;
  1648. }
  1649. static const char *_action_public_str[] = {
  1650. "ACT_PUB_BSSCOEXIST",
  1651. "ACT_PUB_DSE_ENABLE",
  1652. "ACT_PUB_DSE_DEENABLE",
  1653. "ACT_PUB_DSE_REG_LOCATION",
  1654. "ACT_PUB_EXT_CHL_SWITCH",
  1655. "ACT_PUB_DSE_MSR_REQ",
  1656. "ACT_PUB_DSE_MSR_RPRT",
  1657. "ACT_PUB_MP",
  1658. "ACT_PUB_DSE_PWR_CONSTRAINT",
  1659. "ACT_PUB_VENDOR",
  1660. "ACT_PUB_GAS_INITIAL_REQ",
  1661. "ACT_PUB_GAS_INITIAL_RSP",
  1662. "ACT_PUB_GAS_COMEBACK_REQ",
  1663. "ACT_PUB_GAS_COMEBACK_RSP",
  1664. "ACT_PUB_TDLS_DISCOVERY_RSP",
  1665. "ACT_PUB_LOCATION_TRACK",
  1666. "ACT_PUB_RSVD",
  1667. };
  1668. const char *action_public_str(u8 action)
  1669. {
  1670. action = (action >= ACT_PUBLIC_MAX) ? ACT_PUBLIC_MAX : action;
  1671. return _action_public_str[action];
  1672. }