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
22 #ifdef CONFIG_PLATFORM_INTEL_BYT
23 #include <linux/fs.h>
24 #endif
25 #include <drv_types.h>
26
27
28 u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
29 u16 RTW_WPA_VERSION = 1;
30 u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 };
31 u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 };
32 u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 };
33 u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 };
34 u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 };
35 u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 };
36 u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 };
37 u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 };
38 u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 };
39
40 u16 RSN_VERSION_BSD = 1;
41 u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 };
42 u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 };
43 u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 };
44 u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 };
45 u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 };
46 u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 };
47 u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 };
48 u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };
49 //-----------------------------------------------------------
50 // for adhoc-master to generate ie and provide supported-rate to fw
51 //-----------------------------------------------------------
52
53 static u8 WIFI_CCKRATES[] =
54 {(IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK),
55 (IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK),
56 (IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK),
57 (IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK)};
58
59 static u8 WIFI_OFDMRATES[] =
60 {(IEEE80211_OFDM_RATE_6MB),
61 (IEEE80211_OFDM_RATE_9MB),
62 (IEEE80211_OFDM_RATE_12MB),
63 (IEEE80211_OFDM_RATE_18MB),
64 (IEEE80211_OFDM_RATE_24MB),
65 IEEE80211_OFDM_RATE_36MB,
66 IEEE80211_OFDM_RATE_48MB,
67 IEEE80211_OFDM_RATE_54MB};
68
69
rtw_get_bit_value_from_ieee_value(u8 val)70 int rtw_get_bit_value_from_ieee_value(u8 val)
71 {
72 unsigned char dot11_rate_table[]={2,4,11,22,12,18,24,36,48,72,96,108,0}; // last element must be zero!!
73
74 int i=0;
75 while(dot11_rate_table[i] != 0) {
76 if (dot11_rate_table[i] == val)
77 return BIT(i);
78 i++;
79 }
80 return 0;
81 }
82
rtw_is_cckrates_included(u8 * rate)83 uint rtw_is_cckrates_included(u8 *rate)
84 {
85 u32 i = 0;
86
87 while(rate[i]!=0)
88 {
89 if ( (((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
90 (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22) )
91 return _TRUE;
92 i++;
93 }
94
95 return _FALSE;
96 }
97
rtw_is_cckratesonly_included(u8 * rate)98 uint rtw_is_cckratesonly_included(u8 *rate)
99 {
100 u32 i = 0;
101
102
103 while(rate[i]!=0)
104 {
105 if ( (((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
106 (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22) )
107 return _FALSE;
108
109 i++;
110 }
111
112 return _TRUE;
113
114 }
115
rtw_check_network_type(unsigned char * rate,int ratelen,int channel)116 int rtw_check_network_type(unsigned char *rate, int ratelen, int channel)
117 {
118 if (channel > 14)
119 {
120 if ((rtw_is_cckrates_included(rate)) == _TRUE)
121 return WIRELESS_INVALID;
122 else
123 return WIRELESS_11A;
124 }
125 else // could be pure B, pure G, or B/G
126 {
127 if ((rtw_is_cckratesonly_included(rate)) == _TRUE)
128 return WIRELESS_11B;
129 else if((rtw_is_cckrates_included(rate)) == _TRUE)
130 return WIRELESS_11BG;
131 else
132 return WIRELESS_11G;
133 }
134
135 }
136
rtw_set_fixed_ie(unsigned char * pbuf,unsigned int len,unsigned char * source,unsigned int * frlen)137 u8 *rtw_set_fixed_ie(unsigned char *pbuf, unsigned int len, unsigned char *source,
138 unsigned int *frlen)
139 {
140 _rtw_memcpy((void *)pbuf, (void *)source, len);
141 *frlen = *frlen + len;
142 return (pbuf + len);
143 }
144
145 // rtw_set_ie will update frame length
rtw_set_ie(u8 * pbuf,sint index,uint len,u8 * source,uint * frlen)146 u8 *rtw_set_ie
147 (
148 u8 *pbuf,
149 sint index,
150 uint len,
151 u8 *source,
152 uint *frlen //frame length
153 )
154 {
155 *pbuf = (u8)index;
156
157 *(pbuf + 1) = (u8)len;
158
159 if (len > 0)
160 _rtw_memcpy((void *)(pbuf + 2), (void *)source, len);
161
162 *frlen = *frlen + (len + 2);
163
164 return (pbuf + len + 2);
165 }
166
rtw_set_ie_ch_switch(u8 * buf,u32 * buf_len,u8 ch_switch_mode,u8 new_ch,u8 ch_switch_cnt)167 inline u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode,
168 u8 new_ch, u8 ch_switch_cnt)
169 {
170 u8 ie_data[3];
171
172 ie_data[0] = ch_switch_mode;
173 ie_data[1] = new_ch;
174 ie_data[2] = ch_switch_cnt;
175 return rtw_set_ie(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len);
176 }
177
secondary_ch_offset_to_hal_ch_offset(u8 ch_offset)178 inline u8 secondary_ch_offset_to_hal_ch_offset(u8 ch_offset)
179 {
180 if (ch_offset == SCN)
181 return HAL_PRIME_CHNL_OFFSET_DONT_CARE;
182 else if(ch_offset == SCA)
183 return HAL_PRIME_CHNL_OFFSET_UPPER;
184 else if(ch_offset == SCB)
185 return HAL_PRIME_CHNL_OFFSET_LOWER;
186
187 return HAL_PRIME_CHNL_OFFSET_DONT_CARE;
188 }
189
hal_ch_offset_to_secondary_ch_offset(u8 ch_offset)190 inline u8 hal_ch_offset_to_secondary_ch_offset(u8 ch_offset)
191 {
192 if (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
193 return SCN;
194 else if(ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
195 return SCB;
196 else if(ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
197 return SCA;
198
199 return SCN;
200 }
201
rtw_set_ie_secondary_ch_offset(u8 * buf,u32 * buf_len,u8 secondary_ch_offset)202 inline u8 *rtw_set_ie_secondary_ch_offset(u8 *buf, u32 *buf_len, u8 secondary_ch_offset)
203 {
204 return rtw_set_ie(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET, 1, &secondary_ch_offset, buf_len);
205 }
206
rtw_set_ie_mesh_ch_switch_parm(u8 * buf,u32 * buf_len,u8 ttl,u8 flags,u16 reason,u16 precedence)207 inline u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl,
208 u8 flags, u16 reason, u16 precedence)
209 {
210 u8 ie_data[6];
211
212 ie_data[0] = ttl;
213 ie_data[1] = flags;
214 RTW_PUT_LE16((u8*)&ie_data[2], reason);
215 RTW_PUT_LE16((u8*)&ie_data[4], precedence);
216
217 return rtw_set_ie(buf, 0x118, 6, ie_data, buf_len);
218 }
219
220 /*----------------------------------------------------------------------------
221 index: the information element id index, limit is the limit for search
222 -----------------------------------------------------------------------------*/
rtw_get_ie(u8 * pbuf,sint index,sint * len,sint limit)223 u8 *rtw_get_ie(u8 *pbuf, sint index, sint *len, sint limit)
224 {
225 sint tmp,i;
226 u8 *p;
227 _func_enter_;
228 if (limit < 1){
229 _func_exit_;
230 return NULL;
231 }
232
233 p = pbuf;
234 i = 0;
235 *len = 0;
236 while(1)
237 {
238 if (*p == index)
239 {
240 *len = *(p + 1);
241 return (p);
242 }
243 else
244 {
245 tmp = *(p + 1);
246 p += (tmp + 2);
247 i += (tmp + 2);
248 }
249 if (i >= limit)
250 break;
251 }
252 _func_exit_;
253 return NULL;
254 }
255
256 /**
257 * rtw_get_ie_ex - Search specific IE from a series of IEs
258 * @in_ie: Address of IEs to search
259 * @in_len: Length limit from in_ie
260 * @eid: Element ID to match
261 * @oui: OUI to match
262 * @oui_len: OUI length
263 * @ie: If not NULL and the specific IE is found, the IE will be copied to the buf starting from the specific IE
264 * @ielen: If not NULL and the specific IE is found, will set to the length of the entire IE
265 *
266 * Returns: The address of the specific IE found, or NULL
267 */
rtw_get_ie_ex(u8 * in_ie,uint in_len,u8 eid,u8 * oui,u8 oui_len,u8 * ie,uint * ielen)268 u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, uint *ielen)
269 {
270 uint cnt;
271 u8 *target_ie = NULL;
272
273
274 if(ielen)
275 *ielen = 0;
276
277 if(!in_ie || in_len<=0)
278 return target_ie;
279
280 cnt = 0;
281
282 while(cnt<in_len)
283 {
284 if(eid == in_ie[cnt]
285 && ( !oui || _rtw_memcmp(&in_ie[cnt+2], oui, oui_len) == _TRUE))
286 {
287 target_ie = &in_ie[cnt];
288
289 if(ie)
290 _rtw_memcpy(ie, &in_ie[cnt], in_ie[cnt+1]+2);
291
292 if(ielen)
293 *ielen = in_ie[cnt+1]+2;
294
295 break;
296 }
297 else
298 {
299 cnt+=in_ie[cnt+1]+2; //goto next
300 }
301
302 }
303
304 return target_ie;
305 }
306
307 /**
308 * rtw_ies_remove_ie - Find matching IEs and remove
309 * @ies: Address of IEs to search
310 * @ies_len: Pointer of length of ies, will update to new length
311 * @offset: The offset to start scarch
312 * @eid: Element ID to match
313 * @oui: OUI to match
314 * @oui_len: OUI length
315 *
316 * Returns: _SUCCESS: ies is updated, _FAIL: not updated
317 */
rtw_ies_remove_ie(u8 * ies,uint * ies_len,uint offset,u8 eid,u8 * oui,u8 oui_len)318 int rtw_ies_remove_ie(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u8 oui_len)
319 {
320 int ret = _FAIL;
321 u8 *target_ie;
322 u32 target_ielen;
323 u8 *start;
324 uint search_len;
325
326 if(!ies || !ies_len || *ies_len <= offset)
327 goto exit;
328
329 start = ies + offset;
330 search_len = *ies_len - offset;
331
332 while (1) {
333 target_ie = rtw_get_ie_ex(start, search_len, eid, oui, oui_len, NULL, &target_ielen);
334 if (target_ie && target_ielen) {
335 u8 buf[MAX_IE_SZ] = {0};
336 u8 *remain_ies = target_ie + target_ielen;
337 uint remain_len = search_len - (remain_ies - start);
338
339 _rtw_memcpy(buf, remain_ies, remain_len);
340 _rtw_memcpy(target_ie, buf, remain_len);
341 *ies_len = *ies_len - target_ielen;
342 ret = _SUCCESS;
343
344 start = target_ie;
345 search_len = remain_len;
346 } else {
347 break;
348 }
349 }
350 exit:
351 return ret;
352 }
353
rtw_set_supported_rate(u8 * SupportedRates,uint mode)354 void rtw_set_supported_rate(u8* SupportedRates, uint mode)
355 {
356 _func_enter_;
357
358 _rtw_memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
359
360 switch (mode)
361 {
362 case WIRELESS_11B:
363 _rtw_memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
364 break;
365
366 case WIRELESS_11G:
367 case WIRELESS_11A:
368 case WIRELESS_11_5N:
369 case WIRELESS_11A_5N://Todo: no basic rate for ofdm ?
370 case WIRELESS_11_5AC:
371 _rtw_memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
372 break;
373
374 case WIRELESS_11BG:
375 case WIRELESS_11G_24N:
376 case WIRELESS_11_24N:
377 case WIRELESS_11BG_24N:
378 _rtw_memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
379 _rtw_memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
380 break;
381
382 }
383 _func_exit_;
384 }
385
rtw_get_rateset_len(u8 * rateset)386 uint rtw_get_rateset_len(u8 *rateset)
387 {
388 uint i = 0;
389 _func_enter_;
390 while(1)
391 {
392 if ((rateset[i]) == 0)
393 break;
394
395 if (i > 12)
396 break;
397
398 i++;
399 }
400 _func_exit_;
401 return i;
402 }
403
rtw_generate_ie(struct registry_priv * pregistrypriv)404 int rtw_generate_ie(struct registry_priv *pregistrypriv)
405 {
406 u8 wireless_mode;
407 int sz = 0, rateLen;
408 WLAN_BSSID_EX* pdev_network = &pregistrypriv->dev_network;
409 u8* ie = pdev_network->IEs;
410
411 _func_enter_;
412
413 //timestamp will be inserted by hardware
414 sz += 8;
415 ie += sz;
416
417 //beacon interval : 2bytes
418 *(u16*)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);//BCN_INTERVAL;
419 sz += 2;
420 ie += 2;
421
422 //capability info
423 *(u16*)ie = 0;
424
425 *(u16*)ie |= cpu_to_le16(cap_IBSS);
426
427 if(pregistrypriv->preamble == PREAMBLE_SHORT)
428 *(u16*)ie |= cpu_to_le16(cap_ShortPremble);
429
430 if (pdev_network->Privacy)
431 *(u16*)ie |= cpu_to_le16(cap_Privacy);
432
433 sz += 2;
434 ie += 2;
435
436 //SSID
437 ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz);
438
439 //supported rates
440 if(pregistrypriv->wireless_mode == WIRELESS_11ABGN)
441 {
442 if(pdev_network->Configuration.DSConfig > 14)
443 wireless_mode = WIRELESS_11A_5N;
444 else
445 wireless_mode = WIRELESS_11BG_24N;
446 }
447 else
448 {
449 wireless_mode = pregistrypriv->wireless_mode;
450 }
451
452 rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode) ;
453
454 rateLen = rtw_get_rateset_len(pdev_network->SupportedRates);
455
456 if (rateLen > 8)
457 {
458 ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz);
459 //ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
460 }
461 else
462 {
463 ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz);
464 }
465
466 //DS parameter set
467 ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz);
468
469
470 //IBSS Parameter Set
471
472 ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz);
473
474 if (rateLen > 8)
475 {
476 ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
477 }
478
479 #ifdef CONFIG_80211N_HT
480 //HT Cap.
481 if(((pregistrypriv->wireless_mode&WIRELESS_11_5N)||(pregistrypriv->wireless_mode&WIRELESS_11_24N))
482 && (pregistrypriv->ht_enable==_TRUE))
483 {
484 //todo:
485 }
486 #endif //CONFIG_80211N_HT
487
488 //pdev_network->IELength = sz; //update IELength
489
490 _func_exit_;
491
492 //return _SUCCESS;
493
494 return sz;
495
496 }
497
rtw_regsty_adjust_chbw(struct registry_priv * regsty,u8 req_ch,u8 * req_bw,u8 * req_offset)498 bool rtw_regsty_adjust_chbw(struct registry_priv *regsty, u8 req_ch, u8 *req_bw, u8 *req_offset)
499 {
500 u8 regsty_allowed_bw;
501
502 if (req_ch <= 14)
503 regsty_allowed_bw = regsty->bw_mode & 0x0F;
504 else
505 regsty_allowed_bw = regsty->bw_mode >> 4;
506
507 if (regsty_allowed_bw == 2 && *req_bw > CHANNEL_WIDTH_80)
508 *req_bw = CHANNEL_WIDTH_80;
509 else if (regsty_allowed_bw == 1 && *req_bw > CHANNEL_WIDTH_40)
510 *req_bw = CHANNEL_WIDTH_40;
511 else if (regsty_allowed_bw == 0 && *req_bw > CHANNEL_WIDTH_20) {
512 *req_bw = CHANNEL_WIDTH_20;
513 *req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
514 } else
515 return _FALSE;
516
517 return _TRUE;
518 }
519
rtw_get_wpa_ie(unsigned char * pie,int * wpa_ie_len,int limit)520 unsigned char *rtw_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit)
521 {
522 int len;
523 u16 val16;
524 unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
525 u8 *pbuf = pie;
526 int limit_new = limit;
527
528 while(1)
529 {
530 pbuf = rtw_get_ie(pbuf, _WPA_IE_ID_, &len, limit_new);
531
532 if (pbuf) {
533
534 //check if oui matches...
535 if (_rtw_memcmp((pbuf + 2), wpa_oui_type, sizeof (wpa_oui_type)) == _FALSE) {
536
537 goto check_next_ie;
538 }
539
540 //check version...
541 _rtw_memcpy((u8 *)&val16, (pbuf + 6), sizeof(val16));
542
543 val16 = le16_to_cpu(val16);
544 if (val16 != 0x0001)
545 goto check_next_ie;
546
547 *wpa_ie_len = *(pbuf + 1);
548
549 return pbuf;
550
551 }
552 else {
553
554 *wpa_ie_len = 0;
555 return NULL;
556 }
557
558 check_next_ie:
559
560 limit_new = limit - (pbuf - pie) - 2 - len;
561
562 if (limit_new <= 0)
563 break;
564
565 pbuf += (2 + len);
566
567 }
568
569 *wpa_ie_len = 0;
570
571 return NULL;
572
573 }
574
rtw_get_wpa2_ie(unsigned char * pie,int * rsn_ie_len,int limit)575 unsigned char *rtw_get_wpa2_ie(unsigned char *pie, int *rsn_ie_len, int limit)
576 {
577
578 return rtw_get_ie(pie, _WPA2_IE_ID_,rsn_ie_len, limit);
579
580 }
581
rtw_get_wpa_cipher_suite(u8 * s)582 int rtw_get_wpa_cipher_suite(u8 *s)
583 {
584 if (_rtw_memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == _TRUE)
585 return WPA_CIPHER_NONE;
586 if (_rtw_memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == _TRUE)
587 return WPA_CIPHER_WEP40;
588 if (_rtw_memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == _TRUE)
589 return WPA_CIPHER_TKIP;
590 if (_rtw_memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == _TRUE)
591 return WPA_CIPHER_CCMP;
592 if (_rtw_memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == _TRUE)
593 return WPA_CIPHER_WEP104;
594
595 return 0;
596 }
597
rtw_get_wpa2_cipher_suite(u8 * s)598 int rtw_get_wpa2_cipher_suite(u8 *s)
599 {
600 if (_rtw_memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == _TRUE)
601 return WPA_CIPHER_NONE;
602 if (_rtw_memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == _TRUE)
603 return WPA_CIPHER_WEP40;
604 if (_rtw_memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == _TRUE)
605 return WPA_CIPHER_TKIP;
606 if (_rtw_memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == _TRUE)
607 return WPA_CIPHER_CCMP;
608 if (_rtw_memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == _TRUE)
609 return WPA_CIPHER_WEP104;
610
611 return 0;
612 }
613
614
rtw_parse_wpa_ie(u8 * wpa_ie,int wpa_ie_len,int * group_cipher,int * pairwise_cipher,int * is_8021x)615 int rtw_parse_wpa_ie(u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
616 {
617 int i, ret=_SUCCESS;
618 int left, count;
619 u8 *pos;
620 u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1};
621
622 if (wpa_ie_len <= 0) {
623 /* No WPA IE - fail silently */
624 return _FAIL;
625 }
626
627
628 if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie+1) != (u8)(wpa_ie_len - 2)) ||
629 (_rtw_memcmp(wpa_ie+2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN) != _TRUE) )
630 {
631 return _FAIL;
632 }
633
634 pos = wpa_ie;
635
636 pos += 8;
637 left = wpa_ie_len - 8;
638
639
640 //group_cipher
641 if (left >= WPA_SELECTOR_LEN) {
642
643 *group_cipher = rtw_get_wpa_cipher_suite(pos);
644
645 pos += WPA_SELECTOR_LEN;
646 left -= WPA_SELECTOR_LEN;
647
648 }
649 else if (left > 0)
650 {
651 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie length mismatch, %u too much", __FUNCTION__, left));
652
653 return _FAIL;
654 }
655
656
657 //pairwise_cipher
658 if (left >= 2)
659 {
660 //count = le16_to_cpu(*(u16*)pos);
661 count = RTW_GET_LE16(pos);
662 pos += 2;
663 left -= 2;
664
665 if (count == 0 || left < count * WPA_SELECTOR_LEN) {
666 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie count botch (pairwise), "
667 "count %u left %u", __FUNCTION__, count, left));
668 return _FAIL;
669 }
670
671 for (i = 0; i < count; i++)
672 {
673 *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos);
674
675 pos += WPA_SELECTOR_LEN;
676 left -= WPA_SELECTOR_LEN;
677 }
678
679 }
680 else if (left == 1)
681 {
682 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie too short (for key mgmt)", __FUNCTION__));
683 return _FAIL;
684 }
685
686 if (is_8021x) {
687 if (left >= 6) {
688 pos += 2;
689 if (_rtw_memcmp(pos, SUITE_1X, 4) == 1) {
690 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("%s : there has 802.1x auth\n", __FUNCTION__));
691 *is_8021x = 1;
692 }
693 }
694 }
695
696 return ret;
697
698 }
699
rtw_parse_wpa2_ie(u8 * rsn_ie,int rsn_ie_len,int * group_cipher,int * pairwise_cipher,int * is_8021x)700 int rtw_parse_wpa2_ie(u8* rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
701 {
702 int i, ret=_SUCCESS;
703 int left, count;
704 u8 *pos;
705 u8 SUITE_1X[4] = {0x00,0x0f, 0xac, 0x01};
706
707 if (rsn_ie_len <= 0) {
708 /* No RSN IE - fail silently */
709 return _FAIL;
710 }
711
712
713 if ((*rsn_ie!= _WPA2_IE_ID_) || (*(rsn_ie+1) != (u8)(rsn_ie_len - 2)))
714 {
715 return _FAIL;
716 }
717
718 pos = rsn_ie;
719 pos += 4;
720 left = rsn_ie_len - 4;
721
722 //group_cipher
723 if (left >= RSN_SELECTOR_LEN) {
724
725 *group_cipher = rtw_get_wpa2_cipher_suite(pos);
726
727 pos += RSN_SELECTOR_LEN;
728 left -= RSN_SELECTOR_LEN;
729
730 } else if (left > 0) {
731 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie length mismatch, %u too much", __FUNCTION__, left));
732 return _FAIL;
733 }
734
735 //pairwise_cipher
736 if (left >= 2)
737 {
738 //count = le16_to_cpu(*(u16*)pos);
739 count = RTW_GET_LE16(pos);
740 pos += 2;
741 left -= 2;
742
743 if (count == 0 || left < count * RSN_SELECTOR_LEN) {
744 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie count botch (pairwise), "
745 "count %u left %u", __FUNCTION__, count, left));
746 return _FAIL;
747 }
748
749 for (i = 0; i < count; i++)
750 {
751 *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos);
752
753 pos += RSN_SELECTOR_LEN;
754 left -= RSN_SELECTOR_LEN;
755 }
756
757 }
758 else if (left == 1)
759 {
760 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie too short (for key mgmt)", __FUNCTION__));
761
762 return _FAIL;
763 }
764
765 if (is_8021x) {
766 if (left >= 6) {
767 pos += 2;
768 if (_rtw_memcmp(pos, SUITE_1X, 4) == 1) {
769 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("%s (): there has 802.1x auth\n", __FUNCTION__));
770 *is_8021x = 1;
771 }
772 }
773 }
774
775 return ret;
776
777 }
778
779 //#ifdef CONFIG_WAPI_SUPPORT
rtw_get_wapi_ie(u8 * in_ie,uint in_len,u8 * wapi_ie,u16 * wapi_len)780 int rtw_get_wapi_ie(u8 *in_ie,uint in_len,u8 *wapi_ie,u16 *wapi_len)
781 {
782 int len = 0;
783 u8 authmode, i;
784 uint cnt;
785 u8 wapi_oui1[4]={0x0,0x14,0x72,0x01};
786 u8 wapi_oui2[4]={0x0,0x14,0x72,0x02};
787
788 _func_enter_;
789
790 if(wapi_len)
791 *wapi_len = 0;
792
793 if(!in_ie || in_len<=0)
794 return len;
795
796 cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
797
798 while(cnt<in_len)
799 {
800 authmode=in_ie[cnt];
801
802 //if(authmode==_WAPI_IE_)
803 if(authmode==_WAPI_IE_ && (_rtw_memcmp(&in_ie[cnt+6], wapi_oui1,4)==_TRUE ||
804 _rtw_memcmp(&in_ie[cnt+6], wapi_oui2,4)==_TRUE))
805 {
806 if (wapi_ie) {
807 _rtw_memcpy(wapi_ie, &in_ie[cnt],in_ie[cnt+1]+2);
808
809 for(i=0;i<(in_ie[cnt+1]+2);i=i+8){
810 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
811 wapi_ie[i],wapi_ie[i+1],wapi_ie[i+2],wapi_ie[i+3],wapi_ie[i+4],
812 wapi_ie[i+5],wapi_ie[i+6],wapi_ie[i+7]));
813 }
814 }
815
816 if(wapi_len)
817 *wapi_len=in_ie[cnt+1]+2;
818
819 cnt+=in_ie[cnt+1]+2; //get next
820 }
821 else
822 {
823 cnt+=in_ie[cnt+1]+2; //get next
824 }
825 }
826
827 if(wapi_len)
828 len = *wapi_len;
829
830 _func_exit_;
831
832 return len;
833
834 }
835 //#endif
836
rtw_get_sec_ie(u8 * in_ie,uint in_len,u8 * rsn_ie,u16 * rsn_len,u8 * wpa_ie,u16 * wpa_len)837 int rtw_get_sec_ie(u8 *in_ie,uint in_len,u8 *rsn_ie,u16 *rsn_len,u8 *wpa_ie,u16 *wpa_len)
838 {
839 u8 authmode, sec_idx, i;
840 u8 wpa_oui[4]={0x0,0x50,0xf2,0x01};
841 uint cnt;
842
843 _func_enter_;
844
845 //Search required WPA or WPA2 IE and copy to sec_ie[ ]
846
847 cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
848
849 sec_idx=0;
850
851 while(cnt<in_len)
852 {
853 authmode=in_ie[cnt];
854
855 if((authmode==_WPA_IE_ID_)&&(_rtw_memcmp(&in_ie[cnt+2], &wpa_oui[0],4)==_TRUE))
856 {
857 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));
858
859 if (wpa_ie) {
860 _rtw_memcpy(wpa_ie, &in_ie[cnt],in_ie[cnt+1]+2);
861
862 for(i=0;i<(in_ie[cnt+1]+2);i=i+8){
863 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
864 wpa_ie[i],wpa_ie[i+1],wpa_ie[i+2],wpa_ie[i+3],wpa_ie[i+4],
865 wpa_ie[i+5],wpa_ie[i+6],wpa_ie[i+7]));
866 }
867 }
868
869 *wpa_len=in_ie[cnt+1]+2;
870 cnt+=in_ie[cnt+1]+2; //get next
871 }
872 else
873 {
874 if(authmode==_WPA2_IE_ID_)
875 {
876 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));
877
878 if (rsn_ie) {
879 _rtw_memcpy(rsn_ie, &in_ie[cnt],in_ie[cnt+1]+2);
880
881 for(i=0;i<(in_ie[cnt+1]+2);i=i+8){
882 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
883 rsn_ie[i],rsn_ie[i+1],rsn_ie[i+2],rsn_ie[i+3],rsn_ie[i+4],
884 rsn_ie[i+5],rsn_ie[i+6],rsn_ie[i+7]));
885 }
886 }
887
888 *rsn_len=in_ie[cnt+1]+2;
889 cnt+=in_ie[cnt+1]+2; //get next
890 }
891 else
892 {
893 cnt+=in_ie[cnt+1]+2; //get next
894 }
895 }
896
897 }
898
899 _func_exit_;
900
901 return (*rsn_len+*wpa_len);
902
903 }
904
rtw_is_wps_ie(u8 * ie_ptr,uint * wps_ielen)905 u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen)
906 {
907 u8 match = _FALSE;
908 u8 eid, wps_oui[4]={0x0,0x50,0xf2,0x04};
909
910 if(ie_ptr == NULL) return match;
911
912 eid = ie_ptr[0];
913
914 if((eid==_WPA_IE_ID_)&&(_rtw_memcmp(&ie_ptr[2], wps_oui, 4)==_TRUE))
915 {
916 //DBG_8192C("==> found WPS_IE.....\n");
917 *wps_ielen = ie_ptr[1]+2;
918 match=_TRUE;
919 }
920 return match;
921 }
922
rtw_get_wps_ie_from_scan_queue(u8 * in_ie,uint in_len,u8 * wps_ie,uint * wps_ielen,u8 frame_type)923 u8 *rtw_get_wps_ie_from_scan_queue(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen, u8 frame_type)
924 {
925 u8* wps = NULL;
926
927 DBG_871X( "[%s] frame_type = %d\n", __FUNCTION__, frame_type );
928 switch( frame_type )
929 {
930 case 1:
931 case 3:
932 { // Beacon or Probe Response
933 wps = rtw_get_wps_ie(in_ie + _PROBERSP_IE_OFFSET_, in_len - _PROBERSP_IE_OFFSET_, wps_ie, wps_ielen);
934 break;
935 }
936 case 2:
937 { // Probe Request
938 wps = rtw_get_wps_ie(in_ie + _PROBEREQ_IE_OFFSET_ , in_len - _PROBEREQ_IE_OFFSET_ , wps_ie, wps_ielen);
939 break;
940 }
941 }
942 return wps;
943 }
944
945 /**
946 * rtw_get_wps_ie - Search WPS IE from a series of IEs
947 * @in_ie: Address of IEs to search
948 * @in_len: Length limit from in_ie
949 * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie
950 * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE
951 *
952 * Returns: The address of the WPS IE found, or NULL
953 */
rtw_get_wps_ie(u8 * in_ie,uint in_len,u8 * wps_ie,uint * wps_ielen)954 u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
955 {
956 uint cnt;
957 u8 *wpsie_ptr = NULL;
958 u8 eid, wps_oui[4] = {0x00, 0x50, 0xf2, 0x04};
959
960 if (wps_ielen)
961 *wps_ielen = 0;
962
963 if (!in_ie) {
964 rtw_warn_on(1);
965 return wpsie_ptr;
966 }
967
968 if (in_len <= 0)
969 return wpsie_ptr;
970
971 cnt = 0;
972
973 while (cnt + 1 + 4 < in_len) {
974 eid = in_ie[cnt];
975
976 if (cnt + 1 + 4 >= MAX_IE_SZ) {
977 rtw_warn_on(1);
978 return NULL;
979 }
980
981 if (eid == WLAN_EID_VENDOR_SPECIFIC && _rtw_memcmp(&in_ie[cnt + 2], wps_oui, 4) == _TRUE) {
982 wpsie_ptr = in_ie + cnt;
983
984 if (wps_ie)
985 _rtw_memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
986
987 if (wps_ielen)
988 *wps_ielen = in_ie[cnt + 1] + 2;
989
990 break;
991 } else {
992 cnt += in_ie[cnt + 1] + 2;
993 }
994
995 }
996
997 return wpsie_ptr;
998 }
999
1000 /**
1001 * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE
1002 * @wps_ie: Address of WPS IE to search
1003 * @wps_ielen: Length limit from wps_ie
1004 * @target_attr_id: The attribute ID of WPS attribute to search
1005 * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr
1006 * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute
1007 *
1008 * Returns: the address of the specific WPS attribute found, or NULL
1009 */
rtw_get_wps_attr(u8 * wps_ie,uint wps_ielen,u16 target_attr_id,u8 * buf_attr,u32 * len_attr)1010 u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_attr, u32 *len_attr)
1011 {
1012 u8 *attr_ptr = NULL;
1013 u8 * target_attr_ptr = NULL;
1014 u8 wps_oui[4]={0x00,0x50,0xF2,0x04};
1015
1016 if(len_attr)
1017 *len_attr = 0;
1018
1019 if ( ( wps_ie[0] != _VENDOR_SPECIFIC_IE_ ) ||
1020 ( _rtw_memcmp( wps_ie + 2, wps_oui , 4 ) != _TRUE ) )
1021 {
1022 return attr_ptr;
1023 }
1024
1025 // 6 = 1(Element ID) + 1(Length) + 4(WPS OUI)
1026 attr_ptr = wps_ie + 6; //goto first attr
1027
1028 while(attr_ptr - wps_ie < wps_ielen)
1029 {
1030 // 4 = 2(Attribute ID) + 2(Length)
1031 u16 attr_id = RTW_GET_BE16(attr_ptr);
1032 u16 attr_data_len = RTW_GET_BE16(attr_ptr + 2);
1033 u16 attr_len = attr_data_len + 4;
1034
1035 //DBG_871X("%s attr_ptr:%p, id:%u, length:%u\n", __FUNCTION__, attr_ptr, attr_id, attr_data_len);
1036 if( attr_id == target_attr_id )
1037 {
1038 target_attr_ptr = attr_ptr;
1039
1040 if(buf_attr)
1041 _rtw_memcpy(buf_attr, attr_ptr, attr_len);
1042
1043 if(len_attr)
1044 *len_attr = attr_len;
1045
1046 break;
1047 }
1048 else
1049 {
1050 attr_ptr += attr_len; //goto next
1051 }
1052
1053 }
1054
1055 return target_attr_ptr;
1056 }
1057
1058 /**
1059 * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE
1060 * @wps_ie: Address of WPS IE to search
1061 * @wps_ielen: Length limit from wps_ie
1062 * @target_attr_id: The attribute ID of WPS attribute to search
1063 * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content
1064 * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content
1065 *
1066 * Returns: the address of the specific WPS attribute content found, or NULL
1067 */
rtw_get_wps_attr_content(u8 * wps_ie,uint wps_ielen,u16 target_attr_id,u8 * buf_content,uint * len_content)1068 u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_content, uint *len_content)
1069 {
1070 u8 *attr_ptr;
1071 u32 attr_len;
1072
1073 if(len_content)
1074 *len_content = 0;
1075
1076 attr_ptr = rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &attr_len);
1077
1078 if(attr_ptr && attr_len)
1079 {
1080 if(buf_content)
1081 _rtw_memcpy(buf_content, attr_ptr+4, attr_len-4);
1082
1083 if(len_content)
1084 *len_content = attr_len-4;
1085
1086 return attr_ptr+4;
1087 }
1088
1089 return NULL;
1090 }
1091
rtw_ieee802_11_parse_vendor_specific(u8 * pos,uint elen,struct rtw_ieee802_11_elems * elems,int show_errors)1092 static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
1093 struct rtw_ieee802_11_elems *elems,
1094 int show_errors)
1095 {
1096 unsigned int oui;
1097
1098 /* first 3 bytes in vendor specific information element are the IEEE
1099 * OUI of the vendor. The following byte is used a vendor specific
1100 * sub-type. */
1101 if (elen < 4) {
1102 if (show_errors) {
1103 DBG_871X("short vendor specific "
1104 "information element ignored (len=%lu)\n",
1105 (unsigned long) elen);
1106 }
1107 return -1;
1108 }
1109
1110 oui = RTW_GET_BE24(pos);
1111 switch (oui) {
1112 case OUI_MICROSOFT:
1113 /* Microsoft/Wi-Fi information elements are further typed and
1114 * subtyped */
1115 switch (pos[3]) {
1116 case 1:
1117 /* Microsoft OUI (00:50:F2) with OUI Type 1:
1118 * real WPA information element */
1119 elems->wpa_ie = pos;
1120 elems->wpa_ie_len = elen;
1121 break;
1122 case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
1123 if (elen < 5) {
1124 DBG_871X("short WME "
1125 "information element ignored "
1126 "(len=%lu)\n",
1127 (unsigned long) elen);
1128 return -1;
1129 }
1130 switch (pos[4]) {
1131 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
1132 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
1133 elems->wme = pos;
1134 elems->wme_len = elen;
1135 break;
1136 case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
1137 elems->wme_tspec = pos;
1138 elems->wme_tspec_len = elen;
1139 break;
1140 default:
1141 DBG_871X_LEVEL(_drv_warning_, "unknown WME "
1142 "information element ignored "
1143 "(subtype=%d len=%lu)\n",
1144 pos[4], (unsigned long) elen);
1145 return -1;
1146 }
1147 break;
1148 case 4:
1149 /* Wi-Fi Protected Setup (WPS) IE */
1150 elems->wps_ie = pos;
1151 elems->wps_ie_len = elen;
1152 break;
1153 default:
1154 DBG_871X_LEVEL(_drv_warning_, "Unknown Microsoft "
1155 "information element ignored "
1156 "(type=%d len=%lu)\n",
1157 pos[3], (unsigned long) elen);
1158 return -1;
1159 }
1160 break;
1161
1162 case OUI_BROADCOM:
1163 switch (pos[3]) {
1164 case VENDOR_HT_CAPAB_OUI_TYPE:
1165 elems->vendor_ht_cap = pos;
1166 elems->vendor_ht_cap_len = elen;
1167 break;
1168 default:
1169 DBG_871X_LEVEL(_drv_warning_, "Unknown Broadcom "
1170 "information element ignored "
1171 "(type=%d len=%lu)\n",
1172 pos[3], (unsigned long) elen);
1173 return -1;
1174 }
1175 break;
1176
1177 default:
1178 DBG_871X_LEVEL(_drv_warning_, "unknown vendor specific information "
1179 "element ignored (vendor OUI %02x:%02x:%02x "
1180 "len=%lu)\n",
1181 pos[0], pos[1], pos[2], (unsigned long) elen);
1182 return -1;
1183 }
1184
1185 return 0;
1186
1187 }
1188
1189 /**
1190 * ieee802_11_parse_elems - Parse information elements in management frames
1191 * @start: Pointer to the start of IEs
1192 * @len: Length of IE buffer in octets
1193 * @elems: Data structure for parsed elements
1194 * @show_errors: Whether to show parsing errors in debug log
1195 * Returns: Parsing result
1196 */
rtw_ieee802_11_parse_elems(u8 * start,uint len,struct rtw_ieee802_11_elems * elems,int show_errors)1197 ParseRes rtw_ieee802_11_parse_elems(u8 *start, uint len,
1198 struct rtw_ieee802_11_elems *elems,
1199 int show_errors)
1200 {
1201 uint left = len;
1202 u8 *pos = start;
1203 int unknown = 0;
1204
1205 _rtw_memset(elems, 0, sizeof(*elems));
1206
1207 while (left >= 2) {
1208 u8 id, elen;
1209
1210 id = *pos++;
1211 elen = *pos++;
1212 left -= 2;
1213
1214 if (elen > left) {
1215 if (show_errors) {
1216 DBG_871X("IEEE 802.11 element "
1217 "parse failed (id=%d elen=%d "
1218 "left=%lu)\n",
1219 id, elen, (unsigned long) left);
1220 }
1221 return ParseFailed;
1222 }
1223
1224 switch (id) {
1225 case WLAN_EID_SSID:
1226 elems->ssid = pos;
1227 elems->ssid_len = elen;
1228 break;
1229 case WLAN_EID_SUPP_RATES:
1230 elems->supp_rates = pos;
1231 elems->supp_rates_len = elen;
1232 break;
1233 case WLAN_EID_FH_PARAMS:
1234 elems->fh_params = pos;
1235 elems->fh_params_len = elen;
1236 break;
1237 case WLAN_EID_DS_PARAMS:
1238 elems->ds_params = pos;
1239 elems->ds_params_len = elen;
1240 break;
1241 case WLAN_EID_CF_PARAMS:
1242 elems->cf_params = pos;
1243 elems->cf_params_len = elen;
1244 break;
1245 case WLAN_EID_TIM:
1246 elems->tim = pos;
1247 elems->tim_len = elen;
1248 break;
1249 case WLAN_EID_IBSS_PARAMS:
1250 elems->ibss_params = pos;
1251 elems->ibss_params_len = elen;
1252 break;
1253 case WLAN_EID_CHALLENGE:
1254 elems->challenge = pos;
1255 elems->challenge_len = elen;
1256 break;
1257 case WLAN_EID_ERP_INFO:
1258 elems->erp_info = pos;
1259 elems->erp_info_len = elen;
1260 break;
1261 case WLAN_EID_EXT_SUPP_RATES:
1262 elems->ext_supp_rates = pos;
1263 elems->ext_supp_rates_len = elen;
1264 break;
1265 case WLAN_EID_VENDOR_SPECIFIC:
1266 if (rtw_ieee802_11_parse_vendor_specific(pos, elen,
1267 elems,
1268 show_errors))
1269 unknown++;
1270 break;
1271 case WLAN_EID_RSN:
1272 elems->rsn_ie = pos;
1273 elems->rsn_ie_len = elen;
1274 break;
1275 case WLAN_EID_PWR_CAPABILITY:
1276 elems->power_cap = pos;
1277 elems->power_cap_len = elen;
1278 break;
1279 case WLAN_EID_SUPPORTED_CHANNELS:
1280 elems->supp_channels = pos;
1281 elems->supp_channels_len = elen;
1282 break;
1283 case WLAN_EID_MOBILITY_DOMAIN:
1284 elems->mdie = pos;
1285 elems->mdie_len = elen;
1286 break;
1287 case WLAN_EID_FAST_BSS_TRANSITION:
1288 elems->ftie = pos;
1289 elems->ftie_len = elen;
1290 break;
1291 case WLAN_EID_TIMEOUT_INTERVAL:
1292 elems->timeout_int = pos;
1293 elems->timeout_int_len = elen;
1294 break;
1295 case WLAN_EID_HT_CAP:
1296 elems->ht_capabilities = pos;
1297 elems->ht_capabilities_len = elen;
1298 break;
1299 case WLAN_EID_HT_OPERATION:
1300 elems->ht_operation = pos;
1301 elems->ht_operation_len = elen;
1302 break;
1303 case WLAN_EID_VHT_CAPABILITY:
1304 elems->vht_capabilities = pos;
1305 elems->vht_capabilities_len = elen;
1306 break;
1307 case WLAN_EID_VHT_OPERATION:
1308 elems->vht_operation = pos;
1309 elems->vht_operation_len = elen;
1310 break;
1311 case WLAN_EID_VHT_OP_MODE_NOTIFY:
1312 elems->vht_op_mode_notify = pos;
1313 elems->vht_op_mode_notify_len = elen;
1314 break;
1315 default:
1316 unknown++;
1317 if (!show_errors)
1318 break;
1319 DBG_871X_LEVEL(_drv_warning_,
1320 "IEEE 802.11 element parse "
1321 "ignored unknown element (id=%d elen=%d)\n",
1322 id, elen);
1323 break;
1324 }
1325
1326 left -= elen;
1327 pos += elen;
1328 }
1329
1330 if (left)
1331 return ParseFailed;
1332
1333 return unknown ? ParseUnknown : ParseOK;
1334
1335 }
1336
1337 static u8 key_char2num(u8 ch);
key_char2num(u8 ch)1338 static u8 key_char2num(u8 ch)
1339 {
1340 if((ch>='0')&&(ch<='9'))
1341 return ch - '0';
1342 else if ((ch>='a')&&(ch<='f'))
1343 return ch - 'a' + 10;
1344 else if ((ch>='A')&&(ch<='F'))
1345 return ch - 'A' + 10;
1346 else
1347 return 0xff;
1348 }
1349
1350 u8 str_2char2num(u8 hch, u8 lch);
str_2char2num(u8 hch,u8 lch)1351 u8 str_2char2num(u8 hch, u8 lch)
1352 {
1353 return ((key_char2num(hch) * 10 ) + key_char2num(lch));
1354 }
1355
1356 u8 key_2char2num(u8 hch, u8 lch);
key_2char2num(u8 hch,u8 lch)1357 u8 key_2char2num(u8 hch, u8 lch)
1358 {
1359 return ((key_char2num(hch) << 4) | key_char2num(lch));
1360 }
1361
1362 void macstr2num(u8 *dst, u8 *src);
macstr2num(u8 * dst,u8 * src)1363 void macstr2num(u8 *dst, u8 *src)
1364 {
1365 int jj, kk;
1366 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
1367 {
1368 dst[jj] = key_2char2num(src[kk], src[kk + 1]);
1369 }
1370 }
1371
convert_ip_addr(u8 hch,u8 mch,u8 lch)1372 u8 convert_ip_addr(u8 hch, u8 mch, u8 lch)
1373 {
1374 return ((key_char2num(hch) * 100) + (key_char2num(mch) * 10 ) + key_char2num(lch));
1375 }
1376
1377 #ifdef CONFIG_PLATFORM_INTEL_BYT
1378 #define MAC_ADDRESS_LEN 12
1379
rtw_get_mac_addr_intel(unsigned char * buf)1380 int rtw_get_mac_addr_intel(unsigned char *buf)
1381 {
1382 int ret = 0;
1383 int i;
1384 struct file *fp = NULL;
1385 mm_segment_t oldfs;
1386 unsigned char c_mac[MAC_ADDRESS_LEN];
1387 char fname[]="/config/wifi/mac.txt";
1388 int jj,kk;
1389
1390 DBG_871X("%s Enter\n", __FUNCTION__);
1391
1392 ret = rtw_retrieve_from_file(fname, c_mac, MAC_ADDRESS_LEN);
1393 if(ret < MAC_ADDRESS_LEN)
1394 {
1395 return -1;
1396 }
1397
1398 for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 2 )
1399 {
1400 buf[jj] = key_2char2num(c_mac[kk], c_mac[kk+ 1]);
1401 }
1402
1403 DBG_871X("%s: read from file mac address: "MAC_FMT"\n",
1404 __FUNCTION__, MAC_ARG(buf));
1405
1406 return 0;
1407 }
1408 #endif //CONFIG_PLATFORM_INTEL_BYT
1409
1410 /*
1411 * Description:
1412 * rtw_check_invalid_mac_address:
1413 * This is only used for checking mac address valid or not.
1414 *
1415 * Input:
1416 * adapter: mac_address pointer.
1417 *
1418 * Output:
1419 * _TRUE: The mac address is invalid.
1420 * _FALSE: The mac address is valid.
1421 *
1422 * Auther: Isaac.Li
1423 */
rtw_check_invalid_mac_address(u8 * mac_addr)1424 u8 rtw_check_invalid_mac_address(u8 *mac_addr)
1425 {
1426 u8 null_mac_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
1427 u8 multi_mac_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1428 u8 res = _FALSE;
1429
1430 if (_rtw_memcmp(mac_addr, null_mac_addr, ETH_ALEN)) {
1431 res = _TRUE;
1432 goto func_exit;
1433 }
1434
1435 if (_rtw_memcmp(mac_addr, multi_mac_addr, ETH_ALEN)) {
1436 res = _TRUE;
1437 goto func_exit;
1438 }
1439
1440 if (mac_addr[0] & BIT0) {
1441 res = _TRUE;
1442 goto func_exit;
1443 }
1444
1445 if (mac_addr[0] & BIT1) {
1446 res = _TRUE;
1447 goto func_exit;
1448 }
1449
1450 func_exit:
1451 return res;
1452 }
1453
1454 extern char *rtw_initmac;
1455 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
1456 #include <linux/rfkill-wlan.h>
1457 #else
1458 extern int rk29sdk_wifi_mac_addr(unsigned char *buf);
1459 #endif
1460 /**
1461 * rtw_macaddr_cfg - Decide the mac address used
1462 * @out: buf to store mac address decided
1463 * @hw_mac_addr: mac address from efuse/epprom
1464 */
rtw_macaddr_cfg(u8 * out,const u8 * hw_mac_addr)1465 void rtw_macaddr_cfg(u8 *out, const u8 *hw_mac_addr)
1466 {
1467 #define DEFAULT_RANDOM_MACADDR 1
1468 u8 mac[ETH_ALEN];
1469
1470 if (out == NULL) {
1471 rtw_warn_on(1);
1472 return;
1473 }
1474
1475 /* Users specify the mac address */
1476 if (rtw_initmac) {
1477 int jj,kk;
1478
1479 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
1480 mac[jj] = key_2char2num(rtw_initmac[kk], rtw_initmac[kk + 1]);
1481
1482 goto err_chk;
1483 }
1484
1485 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
1486 if (!rockchip_wifi_mac_addr(mac)) {
1487 printk("=========> get mac address from flash=[%02x:%02x:%02x:%02x:%02x:%02x]\n", mac[0], mac[1],
1488 mac[2], mac[3], mac[4], mac[5]);
1489 //_rtw_memcpy(mac_addr, mac, ETH_ALEN);
1490 goto err_chk;
1491 }
1492 #else
1493 #ifndef CONFIG_ANDROID_4_2
1494 {
1495 u8 macbuf[30] = {0};
1496 if (!rk29sdk_wifi_mac_addr(macbuf)) {
1497 int jj,kk;
1498 printk("=========> get mac address from flash %s\n", macbuf);
1499 for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 )
1500 mac[jj] = key_2char2num(macbuf[kk], macbuf[kk+ 1]);
1501 goto err_chk;
1502 }
1503 }
1504 #endif
1505 #endif
1506
1507 /* platform specified */
1508 #ifdef CONFIG_PLATFORM_INTEL_BYT
1509 if (rtw_get_mac_addr_intel(mac) == 0)
1510 goto err_chk;
1511 #endif
1512
1513 /* Use the mac address stored in the Efuse */
1514 if (hw_mac_addr) {
1515 _rtw_memcpy(mac, hw_mac_addr, ETH_ALEN);
1516 goto err_chk;
1517 }
1518
1519 err_chk:
1520 if (rtw_check_invalid_mac_address(mac) == _TRUE) {
1521 #if DEFAULT_RANDOM_MACADDR
1522 DBG_871X_LEVEL(_drv_err_, "invalid mac addr:"MAC_FMT", assign random MAC\n", MAC_ARG(mac));
1523 *((u32 *)(&mac[2])) = rtw_random32();
1524 mac[0] = 0x00;
1525 mac[1] = 0xe0;
1526 mac[2] = 0x4c;
1527 #else
1528 DBG_871X_LEVEL(_drv_err_, "invalid mac addr:"MAC_FMT", assign default one\n", MAC_ARG(mac));
1529 mac[0] = 0x00;
1530 mac[1] = 0xe0;
1531 mac[2] = 0x4c;
1532 mac[3] = 0x87;
1533 mac[4] = 0x00;
1534 mac[5] = 0x00;
1535 #endif
1536 }
1537
1538 _rtw_memcpy(out, mac, ETH_ALEN);
1539 DBG_871X("%s mac addr:"MAC_FMT"\n", __func__, MAC_ARG(out));
1540 }
1541
1542 #ifdef CONFIG_80211N_HT
dump_ht_cap_ie_content(void * sel,u8 * buf,u32 buf_len)1543 void dump_ht_cap_ie_content(void *sel, u8 *buf, u32 buf_len)
1544 {
1545 if (buf_len != 26) {
1546 DBG_871X_SEL_NL(sel, "Invalid HT capability IE len:%d != %d\n", buf_len, 26);
1547 return;
1548 }
1549
1550 DBG_871X_SEL_NL(sel, "HT Capabilities Info:%02x%02x\n", *(buf), *(buf+1));
1551 DBG_871X_SEL_NL(sel, "A-MPDU Parameters:"HT_AMPDU_PARA_FMT"\n"
1552 , HT_AMPDU_PARA_ARG(HT_CAP_ELE_AMPDU_PARA(buf)));
1553 DBG_871X_SEL_NL(sel, "Supported MCS Set:"HT_SUP_MCS_SET_FMT"\n"
1554 , HT_SUP_MCS_SET_ARG(HT_CAP_ELE_SUP_MCS_SET(buf)));
1555 }
1556
dump_ht_cap_ie(void * sel,u8 * ie,u32 ie_len)1557 void dump_ht_cap_ie(void *sel, u8 *ie, u32 ie_len)
1558 {
1559 u8* pos = (u8*)ie;
1560 u16 id;
1561 u16 len;
1562
1563 u8 *ht_cap_ie;
1564 sint ht_cap_ielen;
1565
1566 ht_cap_ie = rtw_get_ie(ie, _HT_CAPABILITY_IE_, &ht_cap_ielen, ie_len);
1567 if(!ie || ht_cap_ie != ie)
1568 return;
1569
1570 dump_ht_cap_ie_content(sel, ht_cap_ie+2, ht_cap_ielen);
1571 }
1572 #endif /* CONFIG_80211N_HT */
1573
dump_ies(void * sel,u8 * buf,u32 buf_len)1574 void dump_ies(void *sel, u8 *buf, u32 buf_len)
1575 {
1576 u8* pos = (u8*)buf;
1577 u8 id, len;
1578
1579 while(pos-buf+1<buf_len){
1580 id = *pos;
1581 len = *(pos+1);
1582
1583 DBG_871X_SEL_NL(sel, "%s ID:%u, LEN:%u\n", __FUNCTION__, id, len);
1584 #ifdef CONFIG_80211N_HT
1585 dump_ht_cap_ie(sel, pos, len);
1586 #endif
1587 dump_wps_ie(sel, pos, len);
1588 #ifdef CONFIG_P2P
1589 dump_p2p_ie(sel, pos, len);
1590 #ifdef CONFIG_WFD
1591 dump_wfd_ie(sel, pos, len);
1592 #endif
1593 #endif
1594
1595 pos+=(2+len);
1596 }
1597 }
1598
dump_wps_ie(void * sel,u8 * ie,u32 ie_len)1599 void dump_wps_ie(void *sel, u8 *ie, u32 ie_len)
1600 {
1601 u8* pos = (u8*)ie;
1602 u16 id;
1603 u16 len;
1604
1605 u8 *wps_ie;
1606 uint wps_ielen;
1607
1608 wps_ie = rtw_get_wps_ie(ie, ie_len, NULL, &wps_ielen);
1609 if(wps_ie != ie || wps_ielen == 0)
1610 return;
1611
1612 pos+=6;
1613 while(pos-ie < ie_len){
1614 id = RTW_GET_BE16(pos);
1615 len = RTW_GET_BE16(pos + 2);
1616
1617 DBG_871X_SEL_NL(sel, "%s ID:0x%04x, LEN:%u\n", __FUNCTION__, id, len);
1618
1619 pos+=(4+len);
1620 }
1621 }
1622
1623 /**
1624 * rtw_ies_get_chbw - get operation ch, bw, offset from IEs of BSS.
1625 * @ies: pointer of the first tlv IE
1626 * @ies_len: length of @ies
1627 * @ch: pointer of ch, used as output
1628 * @bw: pointer of bw, used as output
1629 * @offset: pointer of offset, used as output
1630 */
rtw_ies_get_chbw(u8 * ies,int ies_len,u8 * ch,u8 * bw,u8 * offset)1631 void rtw_ies_get_chbw(u8 *ies, int ies_len, u8 *ch, u8 *bw, u8 *offset)
1632 {
1633 u8 *p;
1634 int ie_len;
1635
1636 *ch = 0;
1637 *bw = CHANNEL_WIDTH_20;
1638 *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1639
1640 p = rtw_get_ie(ies, _DSSET_IE_, &ie_len, ies_len);
1641 if (p && ie_len > 0)
1642 *ch = *(p + 2);
1643
1644 #ifdef CONFIG_80211N_HT
1645 {
1646 u8 *ht_cap_ie, *ht_op_ie;
1647 int ht_cap_ielen, ht_op_ielen;
1648
1649 ht_cap_ie = rtw_get_ie(ies, EID_HTCapability, &ht_cap_ielen, ies_len);
1650 if (ht_cap_ie && ht_cap_ielen) {
1651 if (GET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2))
1652 *bw = CHANNEL_WIDTH_40;
1653 }
1654
1655 ht_op_ie = rtw_get_ie(ies, EID_HTInfo, &ht_op_ielen, ies_len);
1656 if (ht_op_ie && ht_op_ielen) {
1657 if (*ch == 0) {
1658 *ch = GET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2);
1659 } else if (*ch != 0 && *ch != GET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2)) {
1660 DBG_871X("%s ch inconsistent, DSSS:%u, HT primary:%u\n"
1661 , __func__, *ch, GET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2));
1662 }
1663
1664 if (!GET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2))
1665 *bw = CHANNEL_WIDTH_20;
1666
1667 if (*bw == CHANNEL_WIDTH_40) {
1668 switch (GET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2)) {
1669 case SCA:
1670 *offset = HAL_PRIME_CHNL_OFFSET_LOWER;
1671 break;
1672 case SCB:
1673 *offset = HAL_PRIME_CHNL_OFFSET_UPPER;
1674 break;
1675 }
1676 }
1677 }
1678 }
1679 #endif /* CONFIG_80211N_HT */
1680 #ifdef CONFIG_80211AC_VHT
1681 {
1682 u8 *vht_op_ie;
1683 int vht_op_ielen;
1684
1685 vht_op_ie = rtw_get_ie(ies, EID_VHTOperation, &vht_op_ielen, ies_len);
1686 if (vht_op_ie && vht_op_ielen) {
1687 if (GET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2) >= 1)
1688 *bw = CHANNEL_WIDTH_80;
1689 }
1690 }
1691 #endif
1692 }
1693
rtw_bss_get_chbw(WLAN_BSSID_EX * bss,u8 * ch,u8 * bw,u8 * offset)1694 void rtw_bss_get_chbw(WLAN_BSSID_EX *bss, u8 *ch, u8 *bw, u8 *offset)
1695 {
1696 rtw_ies_get_chbw(bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)
1697 , bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)
1698 , ch, bw, offset);
1699
1700 if (*ch == 0) {
1701 *ch = bss->Configuration.DSConfig;
1702 } else if (*ch != bss->Configuration.DSConfig) {
1703 DBG_871X("inconsistent ch - ies:%u bss->Configuration.DSConfig:%u\n"
1704 , *ch, bss->Configuration.DSConfig);
1705 *ch = bss->Configuration.DSConfig;
1706 rtw_warn_on(1);
1707 }
1708 }
1709
1710 /**
1711 * rtw_is_chbw_grouped - test if the two ch settings can be grouped together
1712 * @ch_a: ch of set a
1713 * @bw_a: bw of set a
1714 * @offset_a: offset of set a
1715 * @ch_b: ch of set b
1716 * @bw_b: bw of set b
1717 * @offset_b: offset of set b
1718 */
rtw_is_chbw_grouped(u8 ch_a,u8 bw_a,u8 offset_a,u8 ch_b,u8 bw_b,u8 offset_b)1719 bool rtw_is_chbw_grouped(u8 ch_a, u8 bw_a, u8 offset_a
1720 , u8 ch_b, u8 bw_b, u8 offset_b)
1721 {
1722 bool is_grouped = _FALSE;
1723
1724 if (ch_a != ch_b) {
1725 /* ch is different */
1726 goto exit;
1727 } else if ((bw_a == CHANNEL_WIDTH_40 || bw_a == CHANNEL_WIDTH_80)
1728 && (bw_b == CHANNEL_WIDTH_40 || bw_b == CHANNEL_WIDTH_80)
1729 ) {
1730 if (offset_a != offset_b)
1731 goto exit;
1732 }
1733
1734 is_grouped = _TRUE;
1735
1736 exit:
1737 return is_grouped;
1738 }
1739
1740 /**
1741 * rtw_sync_chbw - obey g_ch, adjust g_bw, g_offset, bw, offset
1742 * @req_ch: pointer of the request ch, may be modified further
1743 * @req_bw: pointer of the request bw, may be modified further
1744 * @req_offset: pointer of the request offset, may be modified further
1745 * @g_ch: pointer of the ongoing group ch
1746 * @g_bw: pointer of the ongoing group bw, may be modified further
1747 * @g_offset: pointer of the ongoing group offset, may be modified further
1748 */
rtw_sync_chbw(u8 * req_ch,u8 * req_bw,u8 * req_offset,u8 * g_ch,u8 * g_bw,u8 * g_offset)1749 void rtw_sync_chbw(u8 *req_ch, u8 *req_bw, u8 *req_offset
1750 , u8 *g_ch, u8 *g_bw, u8 *g_offset)
1751 {
1752
1753 *req_ch = *g_ch;
1754
1755 if (*req_bw == CHANNEL_WIDTH_80 && *g_ch <= 14) {
1756 /*2.4G ch, downgrade to 40Mhz */
1757 *req_bw = CHANNEL_WIDTH_40;
1758 }
1759
1760 switch (*req_bw) {
1761 case CHANNEL_WIDTH_80:
1762 if (*g_bw == CHANNEL_WIDTH_40 || *g_bw == CHANNEL_WIDTH_80)
1763 *req_offset = *g_offset;
1764 else if (*g_bw == CHANNEL_WIDTH_20)
1765 *req_offset = rtw_get_offset_by_ch(*req_ch);
1766
1767 if (*req_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) {
1768 DBG_871X_LEVEL(_drv_err_, "%s req 80MHz BW without offset, down to 20MHz\n", __func__);
1769 rtw_warn_on(1);
1770 *req_bw = CHANNEL_WIDTH_20;
1771 }
1772 break;
1773 case CHANNEL_WIDTH_40:
1774 if (*g_bw == CHANNEL_WIDTH_40 || *g_bw == CHANNEL_WIDTH_80)
1775 *req_offset = *g_offset;
1776 else if (*g_bw == CHANNEL_WIDTH_20)
1777 *req_offset = rtw_get_offset_by_ch(*req_ch);
1778
1779 if (*req_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) {
1780 DBG_871X_LEVEL(_drv_err_, "%s req 40MHz BW without offset, down to 20MHz\n", __func__);
1781 rtw_warn_on(1);
1782 *req_bw = CHANNEL_WIDTH_20;
1783 }
1784 break;
1785 case CHANNEL_WIDTH_20:
1786 *req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1787 break;
1788 default:
1789 DBG_871X_LEVEL(_drv_err_, "%s req unsupported BW:%u\n", __func__, *req_bw);
1790 rtw_warn_on(1);
1791 }
1792
1793 if (*req_bw > *g_bw) {
1794 *g_bw = *req_bw;
1795 *g_offset = *req_offset;
1796 }
1797 }
1798
1799 #ifdef CONFIG_P2P
1800 /**
1801 * rtw_get_p2p_merged_len - Get merged ie length from muitiple p2p ies.
1802 * @in_ie: Pointer of the first p2p ie
1803 * @in_len: Total len of muiltiple p2p ies
1804 * Returns: Length of merged p2p ie length
1805 */
rtw_get_p2p_merged_ies_len(u8 * in_ie,u32 in_len)1806 u32 rtw_get_p2p_merged_ies_len(u8 *in_ie, u32 in_len)
1807 {
1808 PNDIS_802_11_VARIABLE_IEs pIE;
1809 u8 OUI[4] = { 0x50, 0x6f, 0x9a, 0x09 };
1810 int i=0;
1811 int j=0, len=0;
1812
1813 while( i < in_len)
1814 {
1815 pIE = (PNDIS_802_11_VARIABLE_IEs)(in_ie+ i);
1816
1817 if( pIE->ElementID == _VENDOR_SPECIFIC_IE_ && _rtw_memcmp(pIE->data, OUI, 4) )
1818 {
1819 len += pIE->Length-4; // 4 is P2P OUI length, don't count it in this loop
1820 }
1821
1822 i += (pIE->Length + 2);
1823 }
1824
1825 return len + 4; // Append P2P OUI length at last.
1826 }
1827
1828 /**
1829 * rtw_p2p_merge_ies - Merge muitiple p2p ies into one
1830 * @in_ie: Pointer of the first p2p ie
1831 * @in_len: Total len of muiltiple p2p ies
1832 * @merge_ie: Pointer of merged ie
1833 * Returns: Length of merged p2p ie
1834 */
rtw_p2p_merge_ies(u8 * in_ie,u32 in_len,u8 * merge_ie)1835 int rtw_p2p_merge_ies(u8 *in_ie, u32 in_len, u8 *merge_ie)
1836 {
1837 PNDIS_802_11_VARIABLE_IEs pIE;
1838 u8 len = 0;
1839 u8 OUI[4] = { 0x50, 0x6f, 0x9a, 0x09 };
1840 u8 ELOUI[6] = { 0xDD, 0x00, 0x50, 0x6f, 0x9a, 0x09 }; //EID;Len;OUI, Len would copy at the end of function
1841 int i=0;
1842
1843 if( merge_ie != NULL)
1844 {
1845 //Set first P2P OUI
1846 _rtw_memcpy(merge_ie, ELOUI, 6);
1847 merge_ie += 6;
1848
1849 while( i < in_len)
1850 {
1851 pIE = (PNDIS_802_11_VARIABLE_IEs)(in_ie+ i);
1852
1853 // Take out the rest of P2P OUIs
1854 if( pIE->ElementID == _VENDOR_SPECIFIC_IE_ && _rtw_memcmp(pIE->data, OUI, 4) )
1855 {
1856 _rtw_memcpy( merge_ie, pIE->data +4, pIE->Length -4);
1857 len += pIE->Length-4;
1858 merge_ie += pIE->Length-4;
1859 }
1860
1861 i += (pIE->Length + 2);
1862 }
1863
1864 return len + 4; // 4 is for P2P OUI
1865
1866 }
1867
1868 return 0;
1869 }
1870
dump_p2p_ie(void * sel,u8 * ie,u32 ie_len)1871 void dump_p2p_ie(void *sel, u8 *ie, u32 ie_len) {
1872 u8* pos = (u8*)ie;
1873 u8 id;
1874 u16 len;
1875
1876 u8 *p2p_ie;
1877 uint p2p_ielen;
1878
1879 p2p_ie = rtw_get_p2p_ie(ie, ie_len, NULL, &p2p_ielen);
1880 if(p2p_ie != ie || p2p_ielen == 0)
1881 return;
1882
1883 pos+=6;
1884 while(pos-ie < ie_len){
1885 id = *pos;
1886 len = RTW_GET_LE16(pos+1);
1887
1888 DBG_871X_SEL_NL(sel, "%s ID:%u, LEN:%u\n", __FUNCTION__, id, len);
1889
1890 pos+=(3+len);
1891 }
1892 }
1893
rtw_get_p2p_ie_from_scan_queue(u8 * in_ie,int in_len,u8 * p2p_ie,uint * p2p_ielen,u8 frame_type)1894 u8 *rtw_get_p2p_ie_from_scan_queue(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen, u8 frame_type)
1895 {
1896 u8* p2p = NULL;
1897
1898 DBG_871X( "[%s] frame_type = %d\n", __FUNCTION__, frame_type );
1899 switch( frame_type )
1900 {
1901 case 1:
1902 case 3:
1903 { // Beacon or Probe Response
1904 p2p = rtw_get_p2p_ie(in_ie + _PROBERSP_IE_OFFSET_, in_len - _PROBERSP_IE_OFFSET_, p2p_ie, p2p_ielen);
1905 break;
1906 }
1907 case 2:
1908 { // Probe Request
1909 p2p = rtw_get_p2p_ie(in_ie + _PROBEREQ_IE_OFFSET_ , in_len - _PROBEREQ_IE_OFFSET_ , p2p_ie, p2p_ielen);
1910 break;
1911 }
1912 }
1913 return p2p;
1914 }
1915
1916 /**
1917 * rtw_get_p2p_ie - Search P2P IE from a series of IEs
1918 * @in_ie: Address of IEs to search
1919 * @in_len: Length limit from in_ie
1920 * @p2p_ie: If not NULL and P2P IE is found, P2P IE will be copied to the buf starting from p2p_ie
1921 * @p2p_ielen: If not NULL and P2P IE is found, will set to the length of the entire P2P IE
1922 *
1923 * Returns: The address of the P2P IE found, or NULL
1924 */
rtw_get_p2p_ie(u8 * in_ie,int in_len,u8 * p2p_ie,uint * p2p_ielen)1925 u8 *rtw_get_p2p_ie(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen)
1926 {
1927 uint cnt;
1928 u8 *p2p_ie_ptr = NULL;
1929 u8 eid, p2p_oui[4] = {0x50, 0x6F, 0x9A, 0x09};
1930
1931 if (p2p_ielen)
1932 *p2p_ielen = 0;
1933
1934 if (!in_ie || in_len < 0) {
1935 rtw_warn_on(1);
1936 return p2p_ie_ptr;
1937 }
1938
1939 if (in_len <= 0)
1940 return p2p_ie_ptr;
1941
1942 cnt = 0;
1943
1944 while (cnt + 1 + 4 < in_len) {
1945 eid = in_ie[cnt];
1946
1947 if (cnt + 1 + 4 >= MAX_IE_SZ) {
1948 rtw_warn_on(1);
1949 return NULL;
1950 }
1951
1952 if (eid == WLAN_EID_VENDOR_SPECIFIC && _rtw_memcmp(&in_ie[cnt + 2], p2p_oui, 4) == _TRUE) {
1953 p2p_ie_ptr = in_ie + cnt;
1954
1955 if (p2p_ie)
1956 _rtw_memcpy(p2p_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
1957
1958 if (p2p_ielen)
1959 *p2p_ielen = in_ie[cnt + 1] + 2;
1960
1961 break;
1962 } else {
1963 cnt += in_ie[cnt + 1] + 2;
1964 }
1965
1966 }
1967
1968 return p2p_ie_ptr;
1969 }
1970
1971 /**
1972 * rtw_get_p2p_attr - Search a specific P2P attribute from a given P2P IE
1973 * @p2p_ie: Address of P2P IE to search
1974 * @p2p_ielen: Length limit from p2p_ie
1975 * @target_attr_id: The attribute ID of P2P attribute to search
1976 * @buf_attr: If not NULL and the P2P attribute is found, P2P attribute will be copied to the buf starting from buf_attr
1977 * @len_attr: If not NULL and the P2P attribute is found, will set to the length of the entire P2P attribute
1978 *
1979 * Returns: the address of the specific WPS attribute found, or NULL
1980 */
rtw_get_p2p_attr(u8 * p2p_ie,uint p2p_ielen,u8 target_attr_id,u8 * buf_attr,u32 * len_attr)1981 u8 *rtw_get_p2p_attr(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id ,u8 *buf_attr, u32 *len_attr)
1982 {
1983 u8 *attr_ptr = NULL;
1984 u8 *target_attr_ptr = NULL;
1985 u8 p2p_oui[4]={0x50,0x6F,0x9A,0x09};
1986
1987 if(len_attr)
1988 *len_attr = 0;
1989
1990 if ( !p2p_ie || ( p2p_ie[0] != _VENDOR_SPECIFIC_IE_ ) ||
1991 ( _rtw_memcmp( p2p_ie + 2, p2p_oui , 4 ) != _TRUE ) )
1992 {
1993 return attr_ptr;
1994 }
1995
1996 // 6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type)
1997 attr_ptr = p2p_ie + 6; //goto first attr
1998
1999 while(attr_ptr - p2p_ie < p2p_ielen)
2000 {
2001 // 3 = 1(Attribute ID) + 2(Length)
2002 u8 attr_id = *attr_ptr;
2003 u16 attr_data_len = RTW_GET_LE16(attr_ptr + 1);
2004 u16 attr_len = attr_data_len + 3;
2005
2006 //DBG_871X("%s attr_ptr:%p, id:%u, length:%u\n", __FUNCTION__, attr_ptr, attr_id, attr_data_len);
2007 if( attr_id == target_attr_id )
2008 {
2009 target_attr_ptr = attr_ptr;
2010
2011 if(buf_attr)
2012 _rtw_memcpy(buf_attr, attr_ptr, attr_len);
2013
2014 if(len_attr)
2015 *len_attr = attr_len;
2016
2017 break;
2018 }
2019 else
2020 {
2021 attr_ptr += attr_len; //goto next
2022 }
2023
2024 }
2025
2026 return target_attr_ptr;
2027 }
2028
2029 /**
2030 * rtw_get_p2p_attr_content - Search a specific P2P attribute content from a given P2P IE
2031 * @p2p_ie: Address of P2P IE to search
2032 * @p2p_ielen: Length limit from p2p_ie
2033 * @target_attr_id: The attribute ID of P2P attribute to search
2034 * @buf_content: If not NULL and the P2P attribute is found, P2P attribute content will be copied to the buf starting from buf_content
2035 * @len_content: If not NULL and the P2P attribute is found, will set to the length of the P2P attribute content
2036 *
2037 * Returns: the address of the specific P2P attribute content found, or NULL
2038 */
rtw_get_p2p_attr_content(u8 * p2p_ie,uint p2p_ielen,u8 target_attr_id,u8 * buf_content,uint * len_content)2039 u8 *rtw_get_p2p_attr_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id ,u8 *buf_content, uint *len_content)
2040 {
2041 u8 *attr_ptr;
2042 u32 attr_len;
2043
2044 if(len_content)
2045 *len_content = 0;
2046
2047 attr_ptr = rtw_get_p2p_attr(p2p_ie, p2p_ielen, target_attr_id, NULL, &attr_len);
2048
2049 if(attr_ptr && attr_len)
2050 {
2051 if(buf_content)
2052 _rtw_memcpy(buf_content, attr_ptr+3, attr_len-3);
2053
2054 if(len_content)
2055 *len_content = attr_len-3;
2056
2057 return attr_ptr+3;
2058 }
2059
2060 return NULL;
2061 }
2062
rtw_set_p2p_attr_content(u8 * pbuf,u8 attr_id,u16 attr_len,u8 * pdata_attr)2063 u32 rtw_set_p2p_attr_content(u8 *pbuf, u8 attr_id, u16 attr_len, u8 *pdata_attr)
2064 {
2065 u32 a_len;
2066
2067 *pbuf = attr_id;
2068
2069 //*(u16*)(pbuf + 1) = cpu_to_le16(attr_len);
2070 RTW_PUT_LE16(pbuf + 1, attr_len);
2071
2072 if(pdata_attr)
2073 _rtw_memcpy(pbuf + 3, pdata_attr, attr_len);
2074
2075 a_len = attr_len + 3;
2076
2077 return a_len;
2078 }
2079
rtw_p2p_attr_remove(u8 * ie,uint ielen_ori,u8 attr_id)2080 static uint rtw_p2p_attr_remove(u8 *ie, uint ielen_ori, u8 attr_id)
2081 {
2082 u8 *target_attr;
2083 u32 target_attr_len;
2084 uint ielen = ielen_ori;
2085 int index=0;
2086
2087 while(1) {
2088 target_attr=rtw_get_p2p_attr(ie, ielen, attr_id, NULL, &target_attr_len);
2089 if(target_attr && target_attr_len)
2090 {
2091 u8 *next_attr = target_attr+target_attr_len;
2092 uint remain_len = ielen-(next_attr-ie);
2093 //dump_ies(RTW_DBGDUMP, ie, ielen);
2094 #if 0
2095 DBG_871X("[%d] ie:%p, ielen:%u\n"
2096 "target_attr:%p, target_attr_len:%u\n"
2097 "next_attr:%p, remain_len:%u\n"
2098 , index++
2099 , ie, ielen
2100 , target_attr, target_attr_len
2101 , next_attr, remain_len
2102 );
2103 #endif
2104
2105 _rtw_memset(target_attr, 0, target_attr_len);
2106 _rtw_memcpy(target_attr, next_attr, remain_len);
2107 _rtw_memset(target_attr+remain_len, 0, target_attr_len);
2108 *(ie+1) -= target_attr_len;
2109 ielen-=target_attr_len;
2110 }
2111 else
2112 {
2113 //if(index>0)
2114 // dump_ies(RTW_DBGDUMP, ie, ielen);
2115 break;
2116 }
2117 }
2118
2119 return ielen;
2120 }
2121
rtw_WLAN_BSSID_EX_remove_p2p_attr(WLAN_BSSID_EX * bss_ex,u8 attr_id)2122 void rtw_WLAN_BSSID_EX_remove_p2p_attr(WLAN_BSSID_EX *bss_ex, u8 attr_id)
2123 {
2124 u8 *p2p_ie;
2125 uint p2p_ielen, p2p_ielen_ori;
2126 int cnt;
2127
2128 if( (p2p_ie=rtw_get_p2p_ie(bss_ex->IEs+_FIXED_IE_LENGTH_, bss_ex->IELength-_FIXED_IE_LENGTH_, NULL, &p2p_ielen_ori)) )
2129 {
2130 if (0)
2131 if(rtw_get_p2p_attr(p2p_ie, p2p_ielen_ori, attr_id, NULL, NULL)) {
2132 DBG_871X("rtw_get_p2p_attr: GOT P2P_ATTR:%u!!!!!!!!\n", attr_id);
2133 dump_ies(RTW_DBGDUMP, bss_ex->IEs+_FIXED_IE_LENGTH_, bss_ex->IELength-_FIXED_IE_LENGTH_);
2134 }
2135
2136 p2p_ielen=rtw_p2p_attr_remove(p2p_ie, p2p_ielen_ori, attr_id);
2137 if(p2p_ielen != p2p_ielen_ori) {
2138
2139 u8 *next_ie_ori = p2p_ie+p2p_ielen_ori;
2140 u8 *next_ie = p2p_ie+p2p_ielen;
2141 uint remain_len = bss_ex->IELength-(next_ie_ori-bss_ex->IEs);
2142
2143 _rtw_memcpy(next_ie, next_ie_ori, remain_len);
2144 _rtw_memset(next_ie+remain_len, 0, p2p_ielen_ori-p2p_ielen);
2145 bss_ex->IELength -= p2p_ielen_ori-p2p_ielen;
2146
2147 if (0) {
2148 DBG_871X("remove P2P_ATTR:%u!\n", attr_id);
2149 dump_ies(RTW_DBGDUMP, bss_ex->IEs+_FIXED_IE_LENGTH_, bss_ex->IELength-_FIXED_IE_LENGTH_);
2150 }
2151 }
2152 }
2153 }
2154
2155 #endif //CONFIG_P2P
2156
2157 #ifdef CONFIG_WFD
dump_wfd_ie(void * sel,u8 * ie,u32 ie_len)2158 void dump_wfd_ie(void *sel, u8 *ie, u32 ie_len)
2159 {
2160 u8* pos = (u8*)ie;
2161 u8 id;
2162 u16 len;
2163
2164 u8 *wfd_ie;
2165 uint wfd_ielen;
2166
2167 if(rtw_get_wfd_ie(ie, ie_len, NULL, &wfd_ielen) == _FALSE)
2168 return;
2169
2170 pos+=6;
2171 while(pos-ie < ie_len){
2172 id = *pos;
2173 len = RTW_GET_BE16(pos+1);
2174
2175 DBG_871X_SEL_NL(sel, "%s ID:%u, LEN:%u\n", __FUNCTION__, id, len);
2176
2177 pos+=(3+len);
2178 }
2179 }
2180
rtw_get_wfd_ie(u8 * in_ie,int in_len,u8 * wfd_ie,uint * wfd_ielen)2181 int rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen)
2182 {
2183 int match;
2184 uint cnt = 0;
2185 u8 eid, wfd_oui[4]={0x50,0x6F,0x9A,0x0A};
2186
2187
2188 match=_FALSE;
2189
2190 if ( in_len < 0 )
2191 {
2192 return match;
2193 }
2194
2195 while(cnt<in_len)
2196 {
2197 eid = in_ie[cnt];
2198
2199 if( ( eid == _VENDOR_SPECIFIC_IE_ ) && ( _rtw_memcmp( &in_ie[cnt+2], wfd_oui, 4) == _TRUE ) )
2200 {
2201 if ( wfd_ie != NULL )
2202 {
2203 _rtw_memcpy( wfd_ie, &in_ie[ cnt ], in_ie[ cnt + 1 ] + 2 );
2204
2205 }
2206 else
2207 {
2208 if ( wfd_ielen != NULL )
2209 {
2210 *wfd_ielen = 0;
2211 }
2212 }
2213
2214 if ( wfd_ielen != NULL )
2215 {
2216 *wfd_ielen = in_ie[ cnt + 1 ] + 2;
2217 }
2218
2219 cnt += in_ie[ cnt + 1 ] + 2;
2220
2221 match = _TRUE;
2222 break;
2223 }
2224 else
2225 {
2226 cnt += in_ie[ cnt + 1 ] +2; //goto next
2227 }
2228
2229 }
2230
2231 if ( match == _TRUE )
2232 {
2233 match = cnt;
2234 }
2235
2236 return match;
2237
2238 }
2239
rtw_get_wfd_ie_from_scan_queue(u8 * in_ie,int in_len,u8 * wfd_ie,uint * wfd_ielen,u8 frame_type)2240 int rtw_get_wfd_ie_from_scan_queue(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen, u8 frame_type)
2241 {
2242 int match;
2243
2244 match=_FALSE;
2245
2246 DBG_871X( "[%s] frame_type = %d\n", __FUNCTION__, frame_type );
2247 switch( frame_type )
2248 {
2249 case 1:
2250 case 3:
2251 { // Beacon or Probe Response
2252 match = rtw_get_wfd_ie(in_ie + _PROBERSP_IE_OFFSET_, in_len - _PROBERSP_IE_OFFSET_, wfd_ie, wfd_ielen);
2253 break;
2254 }
2255 case 2:
2256 { // Probe Request
2257 match = rtw_get_wfd_ie(in_ie + _PROBEREQ_IE_OFFSET_ , in_len - _PROBEREQ_IE_OFFSET_ , wfd_ie, wfd_ielen);
2258 break;
2259 }
2260 }
2261 return match;
2262 }
2263
2264 // attr_content: The output buffer, contains the "body field" of WFD attribute.
2265 // attr_contentlen: The data length of the "body field" of WFD attribute.
rtw_get_wfd_attr_content(u8 * wfd_ie,uint wfd_ielen,u8 target_attr_id,u8 * attr_content,uint * attr_contentlen)2266 int rtw_get_wfd_attr_content(u8 *wfd_ie, uint wfd_ielen, u8 target_attr_id ,u8 *attr_content, uint *attr_contentlen)
2267 {
2268 int match;
2269 uint cnt = 0;
2270 u8 attr_id, wfd_oui[4]={0x50,0x6F,0x9A,0x0A};
2271
2272
2273 match=_FALSE;
2274
2275 if ( ( wfd_ie[ 0 ] != _VENDOR_SPECIFIC_IE_ ) ||
2276 ( _rtw_memcmp( wfd_ie + 2, wfd_oui , 4 ) != _TRUE ) )
2277 {
2278 return( match );
2279 }
2280
2281 // 1 ( WFD IE ) + 1 ( Length ) + 3 ( OUI ) + 1 ( OUI Type )
2282 cnt = 6;
2283 while( cnt < wfd_ielen )
2284 {
2285 u16 attrlen = RTW_GET_BE16(wfd_ie + cnt + 1);
2286
2287 attr_id = wfd_ie[cnt];
2288 if( attr_id == target_attr_id )
2289 {
2290 // 3 -> 1 byte for attribute ID field, 2 bytes for length field
2291 if(attr_content)
2292 _rtw_memcpy( attr_content, &wfd_ie[ cnt + 3 ], attrlen );
2293
2294 if(attr_contentlen)
2295 *attr_contentlen = attrlen;
2296
2297 cnt += attrlen + 3;
2298
2299 match = _TRUE;
2300 break;
2301 }
2302 else
2303 {
2304 cnt += attrlen + 3; //goto next
2305 }
2306
2307 }
2308
2309 return match;
2310
2311 }
2312 #endif // CONFIG_WFD
2313
2314 //Baron adds to avoid FreeBSD warning
ieee80211_is_empty_essid(const char * essid,int essid_len)2315 int ieee80211_is_empty_essid(const char *essid, int essid_len)
2316 {
2317 /* Single white space is for Linksys APs */
2318 if (essid_len == 1 && essid[0] == ' ')
2319 return 1;
2320
2321 /* Otherwise, if the entire essid is 0, we assume it is hidden */
2322 while (essid_len) {
2323 essid_len--;
2324 if (essid[essid_len] != '\0')
2325 return 0;
2326 }
2327
2328 return 1;
2329 }
2330
ieee80211_get_hdrlen(u16 fc)2331 int ieee80211_get_hdrlen(u16 fc)
2332 {
2333 int hdrlen = 24;
2334
2335 switch (WLAN_FC_GET_TYPE(fc)) {
2336 case RTW_IEEE80211_FTYPE_DATA:
2337 if (fc & RTW_IEEE80211_STYPE_QOS_DATA)
2338 hdrlen += 2;
2339 if ((fc & RTW_IEEE80211_FCTL_FROMDS) && (fc & RTW_IEEE80211_FCTL_TODS))
2340 hdrlen += 6; /* Addr4 */
2341 break;
2342 case RTW_IEEE80211_FTYPE_CTL:
2343 switch (WLAN_FC_GET_STYPE(fc)) {
2344 case RTW_IEEE80211_STYPE_CTS:
2345 case RTW_IEEE80211_STYPE_ACK:
2346 hdrlen = 10;
2347 break;
2348 default:
2349 hdrlen = 16;
2350 break;
2351 }
2352 break;
2353 }
2354
2355 return hdrlen;
2356 }
2357
rtw_get_cipher_info(struct wlan_network * pnetwork)2358 int rtw_get_cipher_info(struct wlan_network *pnetwork)
2359 {
2360 u32 wpa_ielen;
2361 unsigned char *pbuf;
2362 int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
2363 int ret = _FAIL;
2364 pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
2365
2366 if(pbuf && (wpa_ielen>0)) {
2367 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_cipher_info: wpa_ielen: %d", wpa_ielen));
2368 if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) {
2369
2370 pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
2371 pnetwork->BcnInfo.group_cipher = group_cipher;
2372 pnetwork->BcnInfo.is_8021x = is8021x;
2373 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("%s: pnetwork->pairwise_cipher: %d, is_8021x is %d",
2374 __func__, pnetwork->BcnInfo.pairwise_cipher, pnetwork->BcnInfo.is_8021x));
2375 ret = _SUCCESS;
2376 }
2377 } else {
2378
2379 pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
2380
2381 if(pbuf && (wpa_ielen>0)) {
2382 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("get RSN IE\n"));
2383 if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) {
2384 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("get RSN IE OK!!!\n"));
2385 pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
2386 pnetwork->BcnInfo.group_cipher = group_cipher;
2387 pnetwork->BcnInfo.is_8021x = is8021x;
2388 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("%s: pnetwork->pairwise_cipher: %d,"
2389 "pnetwork->group_cipher is %d, is_8021x is %d", __func__, pnetwork->BcnInfo.pairwise_cipher,
2390 pnetwork->BcnInfo.group_cipher,pnetwork->BcnInfo.is_8021x));
2391 ret = _SUCCESS;
2392 }
2393 }
2394 }
2395
2396 return ret;
2397 }
2398
rtw_get_bcn_info(struct wlan_network * pnetwork)2399 void rtw_get_bcn_info(struct wlan_network *pnetwork)
2400 {
2401 unsigned short cap = 0;
2402 u8 bencrypt = 0;
2403 //u8 wpa_ie[255],rsn_ie[255];
2404 u16 wpa_len=0,rsn_len=0;
2405 struct HT_info_element *pht_info = NULL;
2406 struct rtw_ieee80211_ht_cap *pht_cap = NULL;
2407 unsigned int len;
2408 unsigned char *p;
2409
2410 _rtw_memcpy((u8 *)&cap, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
2411 cap = le16_to_cpu(cap);
2412 if (cap & WLAN_CAPABILITY_PRIVACY) {
2413 bencrypt = 1;
2414 pnetwork->network.Privacy = 1;
2415 } else {
2416 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
2417 }
2418 rtw_get_sec_ie(pnetwork->network.IEs ,pnetwork->network.IELength,NULL,&rsn_len,NULL,&wpa_len);
2419 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: ssid=%s\n",pnetwork->network.Ssid.Ssid));
2420 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: wpa_len=%d rsn_len=%d\n",wpa_len,rsn_len));
2421 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: ssid=%s\n",pnetwork->network.Ssid.Ssid));
2422 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: wpa_len=%d rsn_len=%d\n",wpa_len,rsn_len));
2423
2424 if (rsn_len > 0) {
2425 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
2426 } else if (wpa_len > 0) {
2427 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA;
2428 } else {
2429 if (bencrypt)
2430 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
2431 }
2432 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
2433 pnetwork->BcnInfo.encryp_protocol));
2434 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
2435 pnetwork->BcnInfo.encryp_protocol));
2436 rtw_get_cipher_info(pnetwork);
2437
2438 /* get bwmode and ch_offset */
2439 /* parsing HT_CAP_IE */
2440 p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_);
2441 if(p && len>0) {
2442 pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2);
2443 pnetwork->BcnInfo.ht_cap_info = pht_cap->cap_info;
2444 } else {
2445 pnetwork->BcnInfo.ht_cap_info = 0;
2446 }
2447 /* parsing HT_INFO_IE */
2448 p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_);
2449 if(p && len>0) {
2450 pht_info = (struct HT_info_element *)(p + 2);
2451 pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0];
2452 } else {
2453 pnetwork->BcnInfo.ht_info_infos_0 = 0;
2454 }
2455 }
2456
rtw_ht_mcsset_to_nss(u8 * supp_mcs_set)2457 u8 rtw_ht_mcsset_to_nss(u8 *supp_mcs_set)
2458 {
2459 u8 nss = 1;
2460
2461 if (supp_mcs_set[3])
2462 nss = 4;
2463 else if (supp_mcs_set[2])
2464 nss = 3;
2465 else if (supp_mcs_set[1])
2466 nss = 2;
2467 else if (supp_mcs_set[0])
2468 nss = 1;
2469 else
2470 DBG_871X("%s,%d, warning! supp_mcs_set is zero\n", __func__, __LINE__);
2471 /* DBG_871X("%s HT: %dSS\n", __FUNCTION__, nss); */
2472 return nss;
2473 }
2474
2475 //show MCS rate, unit: 100Kbps
rtw_mcs_rate(u8 rf_type,u8 bw_40MHz,u8 short_GI,unsigned char * MCS_rate)2476 u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI, unsigned char * MCS_rate)
2477 {
2478 u16 max_rate = 0;
2479
2480 if(rf_type == RF_1T1R)
2481 {
2482 if(MCS_rate[0] & BIT(7))
2483 max_rate = (bw_40MHz) ? ((short_GI)?1500:1350):((short_GI)?722:650);
2484 else if(MCS_rate[0] & BIT(6))
2485 max_rate = (bw_40MHz) ? ((short_GI)?1350:1215):((short_GI)?650:585);
2486 else if(MCS_rate[0] & BIT(5))
2487 max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520);
2488 else if(MCS_rate[0] & BIT(4))
2489 max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390);
2490 else if(MCS_rate[0] & BIT(3))
2491 max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260);
2492 else if(MCS_rate[0] & BIT(2))
2493 max_rate = (bw_40MHz) ? ((short_GI)?450:405):((short_GI)?217:195);
2494 else if(MCS_rate[0] & BIT(1))
2495 max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
2496 else if(MCS_rate[0] & BIT(0))
2497 max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
2498 }
2499 else
2500 {
2501 if(MCS_rate[1])
2502 {
2503 if(MCS_rate[1] & BIT(7))
2504 max_rate = (bw_40MHz) ? ((short_GI)?3000:2700):((short_GI)?1444:1300);
2505 else if(MCS_rate[1] & BIT(6))
2506 max_rate = (bw_40MHz) ? ((short_GI)?2700:2430):((short_GI)?1300:1170);
2507 else if(MCS_rate[1] & BIT(5))
2508 max_rate = (bw_40MHz) ? ((short_GI)?2400:2160):((short_GI)?1156:1040);
2509 else if(MCS_rate[1] & BIT(4))
2510 max_rate = (bw_40MHz) ? ((short_GI)?1800:1620):((short_GI)?867:780);
2511 else if(MCS_rate[1] & BIT(3))
2512 max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520);
2513 else if(MCS_rate[1] & BIT(2))
2514 max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390);
2515 else if(MCS_rate[1] & BIT(1))
2516 max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260);
2517 else if(MCS_rate[1] & BIT(0))
2518 max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
2519 }
2520 else
2521 {
2522 if(MCS_rate[0] & BIT(7))
2523 max_rate = (bw_40MHz) ? ((short_GI)?1500:1350):((short_GI)?722:650);
2524 else if(MCS_rate[0] & BIT(6))
2525 max_rate = (bw_40MHz) ? ((short_GI)?1350:1215):((short_GI)?650:585);
2526 else if(MCS_rate[0] & BIT(5))
2527 max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520);
2528 else if(MCS_rate[0] & BIT(4))
2529 max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390);
2530 else if(MCS_rate[0] & BIT(3))
2531 max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260);
2532 else if(MCS_rate[0] & BIT(2))
2533 max_rate = (bw_40MHz) ? ((short_GI)?450:405):((short_GI)?217:195);
2534 else if(MCS_rate[0] & BIT(1))
2535 max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
2536 else if(MCS_rate[0] & BIT(0))
2537 max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
2538 }
2539 }
2540 return max_rate;
2541 }
2542
rtw_action_frame_parse(const u8 * frame,u32 frame_len,u8 * category,u8 * action)2543 int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8* category, u8 *action)
2544 {
2545 const u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
2546 u16 fc;
2547 u8 c;
2548 u8 a = ACT_PUBLIC_MAX;
2549
2550 fc = le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)frame)->frame_ctl);
2551
2552 if ((fc & (RTW_IEEE80211_FCTL_FTYPE|RTW_IEEE80211_FCTL_STYPE))
2553 != (RTW_IEEE80211_FTYPE_MGMT|RTW_IEEE80211_STYPE_ACTION)
2554 )
2555 {
2556 return _FALSE;
2557 }
2558
2559 c = frame_body[0];
2560
2561 switch(c) {
2562 case RTW_WLAN_CATEGORY_P2P: /* vendor-specific */
2563 break;
2564 default:
2565 a = frame_body[1];
2566 }
2567
2568 if (category)
2569 *category = c;
2570 if (action)
2571 *action = a;
2572
2573 return _TRUE;
2574 }
2575
2576 static const char *_action_public_str[] = {
2577 "ACT_PUB_BSSCOEXIST",
2578 "ACT_PUB_DSE_ENABLE",
2579 "ACT_PUB_DSE_DEENABLE",
2580 "ACT_PUB_DSE_REG_LOCATION",
2581 "ACT_PUB_EXT_CHL_SWITCH",
2582 "ACT_PUB_DSE_MSR_REQ",
2583 "ACT_PUB_DSE_MSR_RPRT",
2584 "ACT_PUB_MP",
2585 "ACT_PUB_DSE_PWR_CONSTRAINT",
2586 "ACT_PUB_VENDOR",
2587 "ACT_PUB_GAS_INITIAL_REQ",
2588 "ACT_PUB_GAS_INITIAL_RSP",
2589 "ACT_PUB_GAS_COMEBACK_REQ",
2590 "ACT_PUB_GAS_COMEBACK_RSP",
2591 "ACT_PUB_TDLS_DISCOVERY_RSP",
2592 "ACT_PUB_LOCATION_TRACK",
2593 "ACT_PUB_RSVD",
2594 };
2595
action_public_str(u8 action)2596 const char *action_public_str(u8 action)
2597 {
2598 action = (action >= ACT_PUBLIC_MAX) ? ACT_PUBLIC_MAX : action;
2599 return _action_public_str[action];
2600 }
2601
2602