1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
14 ******************************************************************************/
17 #include <drv_types.h>
18 #include <linux/ieee80211.h>
19 #include <ieee80211.h>
21 #include <osdep_service.h>
22 #include <wlan_bssdef.h>
24 u8 RTW_WPA_OUI23A_TYPE
[] = { 0x00, 0x50, 0xf2, 1 };
25 u16 RTW_WPA_VERSION23A
= 1;
26 u8 WPA_AUTH_KEY_MGMT_NONE23A
[] = { 0x00, 0x50, 0xf2, 0 };
27 u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X23A
[] = { 0x00, 0x50, 0xf2, 1 };
28 u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X23A
[] = { 0x00, 0x50, 0xf2, 2 };
29 u8 WPA_CIPHER_SUITE_NONE23A
[] = { 0x00, 0x50, 0xf2, 0 };
30 u8 WPA_CIPHER_SUITE_WEP4023A
[] = { 0x00, 0x50, 0xf2, 1 };
31 u8 WPA_CIPHER_SUITE_TKIP23A
[] = { 0x00, 0x50, 0xf2, 2 };
32 u8 WPA_CIPHER_SUITE_WRAP23A
[] = { 0x00, 0x50, 0xf2, 3 };
33 u8 WPA_CIPHER_SUITE_CCMP23A
[] = { 0x00, 0x50, 0xf2, 4 };
34 u8 WPA_CIPHER_SUITE_WEP10423A
[] = { 0x00, 0x50, 0xf2, 5 };
36 u16 RSN_VERSION_BSD23A
= 1;
37 u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X23A
[] = { 0x00, 0x0f, 0xac, 1 };
38 u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X23A
[] = { 0x00, 0x0f, 0xac, 2 };
39 u8 RSN_CIPHER_SUITE_NONE23A
[] = { 0x00, 0x0f, 0xac, 0 };
40 u8 RSN_CIPHER_SUITE_WEP4023A
[] = { 0x00, 0x0f, 0xac, 1 };
41 u8 RSN_CIPHER_SUITE_TKIP23A
[] = { 0x00, 0x0f, 0xac, 2 };
42 u8 RSN_CIPHER_SUITE_WRAP23A
[] = { 0x00, 0x0f, 0xac, 3 };
43 u8 RSN_CIPHER_SUITE_CCMP23A
[] = { 0x00, 0x0f, 0xac, 4 };
44 u8 RSN_CIPHER_SUITE_WEP10423A
[] = { 0x00, 0x0f, 0xac, 5 };
46 /* for adhoc-master to generate ie and provide supported-rate to fw */
49 static u8 WIFI_CCKRATES
[] =
50 {(IEEE80211_CCK_RATE_1MB
| IEEE80211_BASIC_RATE_MASK
),
51 (IEEE80211_CCK_RATE_2MB
| IEEE80211_BASIC_RATE_MASK
),
52 (IEEE80211_CCK_RATE_5MB
| IEEE80211_BASIC_RATE_MASK
),
53 (IEEE80211_CCK_RATE_11MB
| IEEE80211_BASIC_RATE_MASK
)};
55 static u8 WIFI_OFDMRATES
[] =
56 {(IEEE80211_OFDM_RATE_6MB
),
57 (IEEE80211_OFDM_RATE_9MB
),
58 (IEEE80211_OFDM_RATE_12MB
),
59 (IEEE80211_OFDM_RATE_18MB
),
60 (IEEE80211_OFDM_RATE_24MB
),
61 IEEE80211_OFDM_RATE_36MB
,
62 IEEE80211_OFDM_RATE_48MB
,
63 IEEE80211_OFDM_RATE_54MB
};
65 int rtw_get_bit_value_from_ieee_value23a(u8 val
)
67 unsigned char dot11_rate_table
[]=
68 {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0};
71 while (dot11_rate_table
[i
] != 0) {
72 if (dot11_rate_table
[i
] == val
)
79 uint
rtw_is_cckrates_included23a(u8
*rate
)
83 while (rate
[i
] != 0) {
84 if ((((rate
[i
]) & 0x7f) == 2) || (((rate
[i
]) & 0x7f) == 4) ||
85 (((rate
[i
]) & 0x7f) == 11) || (((rate
[i
]) & 0x7f) == 22))
93 uint
rtw_is_cckratesonly_included23a(u8
*rate
)
97 while (rate
[i
] != 0) {
98 if ((((rate
[i
]) & 0x7f) != 2) && (((rate
[i
]) & 0x7f) != 4) &&
99 (((rate
[i
]) & 0x7f) != 11) && (((rate
[i
]) & 0x7f) != 22))
108 int rtw_check_network_type23a(unsigned char *rate
, int ratelen
, int channel
)
111 if ((rtw_is_cckrates_included23a(rate
)) == true)
112 return WIRELESS_INVALID
;
115 } else { /* could be pure B, pure G, or B/G */
116 if ((rtw_is_cckratesonly_included23a(rate
)) == true)
118 else if ((rtw_is_cckrates_included23a(rate
)) == true)
119 return WIRELESS_11BG
;
125 u8
*rtw_set_fixed_ie23a(unsigned char *pbuf
, unsigned int len
,
126 unsigned char *source
, unsigned int *frlen
)
128 memcpy((void *)pbuf
, (void *)source
, len
);
129 *frlen
= *frlen
+ len
;
133 /* rtw_set_ie23a will update frame length */
134 u8
*rtw_set_ie23a(u8
*pbuf
, int index
, uint len
, const u8
*source
, uint
*frlen
)
139 *(pbuf
+ 1) = (u8
)len
;
142 memcpy((void *)(pbuf
+ 2), (void *)source
, len
);
144 *frlen
= *frlen
+ (len
+ 2);
147 return pbuf
+ len
+ 2;
150 inline u8
*rtw_set_ie23a_ch_switch (u8
*buf
, u32
*buf_len
, u8 ch_switch_mode
,
151 u8 new_ch
, u8 ch_switch_cnt
)
155 ie_data
[0] = ch_switch_mode
;
157 ie_data
[2] = ch_switch_cnt
;
158 return rtw_set_ie23a(buf
, WLAN_EID_CHANNEL_SWITCH
, 3, ie_data
, buf_len
);
161 inline u8
secondary_ch_offset_to_hal_ch_offset23a(u8 ch_offset
)
163 if (ch_offset
== SCN
)
164 return HAL_PRIME_CHNL_OFFSET_DONT_CARE
;
165 else if (ch_offset
== SCA
)
166 return HAL_PRIME_CHNL_OFFSET_UPPER
;
167 else if (ch_offset
== SCB
)
168 return HAL_PRIME_CHNL_OFFSET_LOWER
;
170 return HAL_PRIME_CHNL_OFFSET_DONT_CARE
;
173 inline u8
hal_ch_offset_to_secondary_ch_offset23a(u8 ch_offset
)
175 if (ch_offset
== HAL_PRIME_CHNL_OFFSET_DONT_CARE
)
177 else if (ch_offset
== HAL_PRIME_CHNL_OFFSET_LOWER
)
179 else if (ch_offset
== HAL_PRIME_CHNL_OFFSET_UPPER
)
185 inline u8
*rtw_set_ie23a_secondary_ch_offset(u8
*buf
, u32
*buf_len
,
186 u8 secondary_ch_offset
)
188 return rtw_set_ie23a(buf
, WLAN_EID_SECONDARY_CHANNEL_OFFSET
,
189 1, &secondary_ch_offset
, buf_len
);
192 inline u8
*rtw_set_ie23a_mesh_ch_switch_parm(u8
*buf
, u32
*buf_len
, u8 ttl
,
193 u8 flags
, u16 reason
, u16 precedence
)
199 put_unaligned_le16(reason
, (u8
*)&ie_data
[2]);
200 put_unaligned_le16(precedence
, (u8
*)&ie_data
[4]);
202 return rtw_set_ie23a(buf
, 0x118, 6, ie_data
, buf_len
);
205 /*----------------------------------------------------------------------------
206 index: the information element id index, limit is the limit for search
207 -----------------------------------------------------------------------------*/
208 u8
*rtw_get_ie23a(u8
*pbuf
, int index
, int *len
, int limit
)
238 * rtw_get_ie23a_ex - Search specific IE from a series of IEs
239 * @in_ie: Address of IEs to search
240 * @in_len: Length limit from in_ie
241 * @eid: Element ID to match
243 * @oui_len: OUI length
244 * @ie: If not NULL and the specific IE is found, the IE will be copied
245 * to the buf starting from the specific IE
246 * @ielen: If not NULL and the specific IE is found, will set to the length
249 * Returns: The address of the specific IE found, or NULL
251 u8
*rtw_get_ie23a_ex(u8
*in_ie
, uint in_len
, u8 eid
, u8
*oui
, u8 oui_len
,
255 u8
*target_ie
= NULL
;
260 if (!in_ie
|| in_len
<= 0)
265 while (cnt
< in_len
) {
266 if (eid
== in_ie
[cnt
] &&
267 (!oui
|| !memcmp(&in_ie
[cnt
+2], oui
, oui_len
))) {
268 target_ie
= &in_ie
[cnt
];
271 memcpy(ie
, &in_ie
[cnt
], in_ie
[cnt
+1]+2);
274 *ielen
= in_ie
[cnt
+1]+2;
277 cnt
+= in_ie
[cnt
+ 1] + 2; /* goto next */
285 * rtw_ies_remove_ie23a - Find matching IEs and remove
286 * @ies: Address of IEs to search
287 * @ies_len: Pointer of length of ies, will update to new length
288 * @offset: The offset to start scarch
289 * @eid: Element ID to match
291 * @oui_len: OUI length
293 * Returns: _SUCCESS: ies is updated, _FAIL: not updated
295 int rtw_ies_remove_ie23a(u8
*ies
, uint
*ies_len
, uint offset
, u8 eid
,
304 if (!ies
|| !ies_len
|| *ies_len
<= offset
)
307 start
= ies
+ offset
;
308 search_len
= *ies_len
- offset
;
311 target_ie
= rtw_get_ie23a_ex(start
, search_len
, eid
, oui
, oui_len
,
312 NULL
, &target_ielen
);
313 if (target_ie
&& target_ielen
) {
314 u8 buf
[MAX_IE_SZ
] = {0};
315 u8
*remain_ies
= target_ie
+ target_ielen
;
316 uint remain_len
= search_len
- (remain_ies
- start
);
318 memcpy(buf
, remain_ies
, remain_len
);
319 memcpy(target_ie
, buf
, remain_len
);
320 *ies_len
= *ies_len
- target_ielen
;
324 search_len
= remain_len
;
333 void rtw_set_supported_rate23a(u8
* SupportedRates
, uint mode
)
337 memset(SupportedRates
, 0, NDIS_802_11_LENGTH_RATES_EX
);
342 memcpy(SupportedRates
, WIFI_CCKRATES
, IEEE80211_CCK_RATE_LEN
);
348 case WIRELESS_11A_5N
:/* Todo: no basic rate for ofdm ? */
349 memcpy(SupportedRates
, WIFI_OFDMRATES
,
350 IEEE80211_NUM_OFDM_RATESLEN
);
354 case WIRELESS_11G_24N
:
355 case WIRELESS_11_24N
:
356 case WIRELESS_11BG_24N
:
357 memcpy(SupportedRates
, WIFI_CCKRATES
, IEEE80211_CCK_RATE_LEN
);
358 memcpy(SupportedRates
+ IEEE80211_CCK_RATE_LEN
, WIFI_OFDMRATES
,
359 IEEE80211_NUM_OFDM_RATESLEN
);
365 uint
rtw_get_rateset_len23a(u8
*rateset
)
370 if ((rateset
[i
]) == 0)
382 int rtw_generate_ie23a(struct registry_priv
*pregistrypriv
)
386 struct wlan_bssid_ex
* pdev_network
= &pregistrypriv
->dev_network
;
387 u8
* ie
= pdev_network
->IEs
;
391 /* timestamp will be inserted by hardware */
395 /* beacon interval : 2bytes */
397 *(u16
*)ie
= cpu_to_le16((u16
)pdev_network
->Configuration
.BeaconPeriod
);
401 /* capability info */
404 *(u16
*)ie
|= cpu_to_le16(cap_IBSS
);
406 if (pregistrypriv
->preamble
== PREAMBLE_SHORT
)
407 *(u16
*)ie
|= cpu_to_le16(cap_ShortPremble
);
409 if (pdev_network
->Privacy
)
410 *(u16
*)ie
|= cpu_to_le16(cap_Privacy
);
416 ie
= rtw_set_ie23a(ie
, _SSID_IE_
, pdev_network
->Ssid
.ssid_len
,
417 pdev_network
->Ssid
.ssid
, &sz
);
419 /* supported rates */
420 if (pregistrypriv
->wireless_mode
== WIRELESS_11ABGN
) {
421 if (pdev_network
->Configuration
.DSConfig
> 14)
422 wireless_mode
= WIRELESS_11A_5N
;
424 wireless_mode
= WIRELESS_11BG_24N
;
426 wireless_mode
= pregistrypriv
->wireless_mode
;
429 rtw_set_supported_rate23a(pdev_network
->SupportedRates
, wireless_mode
) ;
431 rateLen
= rtw_get_rateset_len23a(pdev_network
->SupportedRates
);
434 ie
= rtw_set_ie23a(ie
, _SUPPORTEDRATES_IE_
, 8,
435 pdev_network
->SupportedRates
, &sz
);
436 /* ie = rtw_set_ie23a(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */
438 ie
= rtw_set_ie23a(ie
, _SUPPORTEDRATES_IE_
, rateLen
,
439 pdev_network
->SupportedRates
, &sz
);
442 /* DS parameter set */
443 ie
= rtw_set_ie23a(ie
, _DSSET_IE_
, 1,
444 (u8
*)&pdev_network
->Configuration
.DSConfig
, &sz
);
446 /* IBSS Parameter Set */
448 ie
= rtw_set_ie23a(ie
, _IBSS_PARA_IE_
, 2,
449 (u8
*)&pdev_network
->Configuration
.ATIMWindow
, &sz
);
452 ie
= rtw_set_ie23a(ie
, _EXT_SUPPORTEDRATES_IE_
, (rateLen
- 8),
453 (pdev_network
->SupportedRates
+ 8), &sz
);
458 /* return _SUCCESS; */
463 unsigned char *rtw_get_wpa_ie23a(unsigned char *pie
, int *wpa_ie_len
, int limit
)
467 unsigned char wpa_oui_type
[] = {0x00, 0x50, 0xf2, 0x01};
469 int limit_new
= limit
;
472 pbuf
= rtw_get_ie23a(pbuf
, WLAN_EID_VENDOR_SPECIFIC
,
476 /* check if oui matches... */
477 if (memcmp((pbuf
+ 2), wpa_oui_type
,
478 sizeof(wpa_oui_type
))) {
482 /* check version... */
483 memcpy((u8
*)&val16
, (pbuf
+ 6), sizeof(val16
));
485 val16
= le16_to_cpu(val16
);
489 *wpa_ie_len
= *(pbuf
+ 1);
499 limit_new
= limit
- (pbuf
- pie
) - 2 - len
;
512 unsigned char *rtw_get_wpa2_ie23a(unsigned char *pie
, int *rsn_ie_len
, int limit
)
514 return rtw_get_ie23a(pie
, _WPA2_IE_ID_
, rsn_ie_len
, limit
);
517 int rtw_get_wpa_cipher_suite23a(u8
*s
)
519 if (!memcmp(s
, WPA_CIPHER_SUITE_NONE23A
, WPA_SELECTOR_LEN
))
520 return WPA_CIPHER_NONE
;
521 if (!memcmp(s
, WPA_CIPHER_SUITE_WEP4023A
, WPA_SELECTOR_LEN
))
522 return WPA_CIPHER_WEP40
;
523 if (!memcmp(s
, WPA_CIPHER_SUITE_TKIP23A
, WPA_SELECTOR_LEN
))
524 return WPA_CIPHER_TKIP
;
525 if (!memcmp(s
, WPA_CIPHER_SUITE_CCMP23A
, WPA_SELECTOR_LEN
))
526 return WPA_CIPHER_CCMP
;
527 if (!memcmp(s
, WPA_CIPHER_SUITE_WEP10423A
, WPA_SELECTOR_LEN
))
528 return WPA_CIPHER_WEP104
;
533 int rtw_get_wpa2_cipher_suite23a(u8
*s
)
535 if (!memcmp(s
, RSN_CIPHER_SUITE_NONE23A
, RSN_SELECTOR_LEN
))
536 return WPA_CIPHER_NONE
;
537 if (!memcmp(s
, RSN_CIPHER_SUITE_WEP4023A
, RSN_SELECTOR_LEN
))
538 return WPA_CIPHER_WEP40
;
539 if (!memcmp(s
, RSN_CIPHER_SUITE_TKIP23A
, RSN_SELECTOR_LEN
))
540 return WPA_CIPHER_TKIP
;
541 if (!memcmp(s
, RSN_CIPHER_SUITE_CCMP23A
, RSN_SELECTOR_LEN
))
542 return WPA_CIPHER_CCMP
;
543 if (!memcmp(s
, RSN_CIPHER_SUITE_WEP10423A
, RSN_SELECTOR_LEN
))
544 return WPA_CIPHER_WEP104
;
549 int rtw_parse_wpa_ie23a(u8
* wpa_ie
, int wpa_ie_len
, int *group_cipher
, int *pairwise_cipher
, int *is_8021x
)
551 int i
, ret
= _SUCCESS
;
554 u8 SUITE_1X
[4] = {0x00, 0x50, 0xf2, 1};
556 if (wpa_ie_len
<= 0) {
557 /* No WPA IE - fail silently */
561 if ((*wpa_ie
!= WLAN_EID_VENDOR_SPECIFIC
) ||
562 (*(wpa_ie
+1) != (u8
)(wpa_ie_len
- 2)) ||
563 memcmp(wpa_ie
+ 2, RTW_WPA_OUI23A_TYPE
, WPA_SELECTOR_LEN
)) {
570 left
= wpa_ie_len
- 8;
573 if (left
>= WPA_SELECTOR_LEN
) {
575 *group_cipher
= rtw_get_wpa_cipher_suite23a(pos
);
577 pos
+= WPA_SELECTOR_LEN
;
578 left
-= WPA_SELECTOR_LEN
;
579 } else if (left
> 0) {
580 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_err_
,
581 ("%s: ie length mismatch, %u too much",
587 /* pairwise_cipher */
589 /* count = le16_to_cpu(*(u16*)pos); */
590 count
= get_unaligned_le16(pos
);
594 if (count
== 0 || left
< count
* WPA_SELECTOR_LEN
) {
595 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_err_
,
596 ("%s: ie count botch (pairwise), "
597 "count %u left %u", __func__
,
602 for (i
= 0; i
< count
; i
++) {
603 *pairwise_cipher
|= rtw_get_wpa_cipher_suite23a(pos
);
605 pos
+= WPA_SELECTOR_LEN
;
606 left
-= WPA_SELECTOR_LEN
;
608 } else if (left
== 1) {
609 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_err_
,
610 ("%s: ie too short (for key mgmt)", __func__
));
617 if (!memcmp(pos
, SUITE_1X
, 4)) {
618 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
619 ("%s : there has 802.1x auth\n",
629 int rtw_parse_wpa2_ie23a(u8
* rsn_ie
, int rsn_ie_len
, int *group_cipher
,
630 int *pairwise_cipher
, int *is_8021x
)
632 int i
, ret
= _SUCCESS
;
635 u8 SUITE_1X
[4] = {0x00, 0x0f, 0xac, 0x01};
637 if (rsn_ie_len
<= 0) {
638 /* No RSN IE - fail silently */
642 if ((*rsn_ie
!= _WPA2_IE_ID_
) || (*(rsn_ie
+1) != (u8
)(rsn_ie_len
- 2))) {
648 left
= rsn_ie_len
- 4;
651 if (left
>= RSN_SELECTOR_LEN
) {
652 *group_cipher
= rtw_get_wpa2_cipher_suite23a(pos
);
654 pos
+= RSN_SELECTOR_LEN
;
655 left
-= RSN_SELECTOR_LEN
;
656 } else if (left
> 0) {
657 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_err_
,
658 ("%s: ie length mismatch, %u too much",
663 /* pairwise_cipher */
665 /* count = le16_to_cpu(*(u16*)pos); */
666 count
= get_unaligned_le16(pos
);
670 if (count
== 0 || left
< count
* RSN_SELECTOR_LEN
) {
671 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_err_
,
672 ("%s: ie count botch (pairwise), "
674 __func__
, count
, left
));
678 for (i
= 0; i
< count
; i
++) {
679 *pairwise_cipher
|= rtw_get_wpa2_cipher_suite23a(pos
);
681 pos
+= RSN_SELECTOR_LEN
;
682 left
-= RSN_SELECTOR_LEN
;
684 } else if (left
== 1) {
685 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_err_
,
686 ("%s: ie too short (for key mgmt)", __func__
));
694 if (!memcmp(pos
, SUITE_1X
, 4)) {
695 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
696 ("%s (): there has 802.1x auth\n",
706 int rtw_get_sec_ie23a(u8
*in_ie
, uint in_len
, u8
*rsn_ie
, u16
*rsn_len
,
707 u8
*wpa_ie
, u16
*wpa_len
)
709 u8 authmode
, sec_idx
, i
;
710 u8 wpa_oui
[4] = {0x0, 0x50, 0xf2, 0x01};
715 /* Search required WPA or WPA2 IE and copy to sec_ie[ ] */
717 cnt
= (_TIMESTAMP_
+ _BEACON_ITERVAL_
+ _CAPABILITY_
);
721 while(cnt
< in_len
) {
722 authmode
= in_ie
[cnt
];
724 if ((authmode
== WLAN_EID_VENDOR_SPECIFIC
) &&
725 !memcmp(&in_ie
[cnt
+2], &wpa_oui
[0], 4)) {
726 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
727 ("\n rtw_get_wpa_ie23a: sec_idx =%d "
728 "in_ie[cnt+1]+2 =%d\n",
729 sec_idx
, in_ie
[cnt
+ 1] + 2));
732 memcpy(wpa_ie
, &in_ie
[cnt
], in_ie
[cnt
+1]+2);
734 for (i
= 0; i
< (in_ie
[cnt
+ 1] + 2); i
= i
+ 8) {
735 RT_TRACE(_module_rtl871x_mlme_c_
,
737 ("\n %2x,%2x,%2x,%2x,%2x,%2x,"
738 "%2x,%2x\n", wpa_ie
[i
],
739 wpa_ie
[i
+ 1], wpa_ie
[i
+ 2],
740 wpa_ie
[i
+ 3], wpa_ie
[i
+ 4],
741 wpa_ie
[i
+ 5], wpa_ie
[i
+ 6],
746 *wpa_len
= in_ie
[cnt
+ 1] + 2;
747 cnt
+= in_ie
[cnt
+ 1] + 2; /* get next */
749 if (authmode
== _WPA2_IE_ID_
) {
750 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
751 ("\n get_rsn_ie: sec_idx =%d in_ie"
752 "[cnt+1]+2 =%d\n", sec_idx
,
753 in_ie
[cnt
+ 1] + 2));
756 memcpy(rsn_ie
, &in_ie
[cnt
], in_ie
[cnt
+ 1] + 2);
758 for (i
= 0; i
< (in_ie
[cnt
+ 1] + 2); i
= i
+ 8) {
759 RT_TRACE(_module_rtl871x_mlme_c_
,
761 ("\n %2x,%2x,%2x,%2x,%2x,%2x,"
762 "%2x,%2x\n", rsn_ie
[i
],
763 rsn_ie
[i
+ 1], rsn_ie
[i
+ 2],
764 rsn_ie
[i
+ 3], rsn_ie
[i
+ 4],
765 rsn_ie
[i
+ 5], rsn_ie
[i
+ 6],
770 *rsn_len
= in_ie
[cnt
+ 1] + 2;
771 cnt
+= in_ie
[cnt
+ 1] + 2; /* get next */
773 cnt
+= in_ie
[cnt
+ 1] + 2; /* get next */
780 return *rsn_len
+ *wpa_len
;
783 u8
rtw_is_wps_ie23a(u8
*ie_ptr
, uint
*wps_ielen
)
786 u8 eid
, wps_oui
[4]= {0x0, 0x50, 0xf2, 0x04};
793 if ((eid
== WLAN_EID_VENDOR_SPECIFIC
) &&
794 !memcmp(&ie_ptr
[2], wps_oui
, 4)) {
795 /* DBG_8723A("==> found WPS_IE.....\n"); */
796 *wps_ielen
= ie_ptr
[1] + 2;
803 * rtw_get_wps_ie23a - Search WPS IE from a series of IEs
804 * @in_ie: Address of IEs to search
805 * @in_len: Length limit from in_ie
806 * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the
807 * buf starting from wps_ie
808 * @wps_ielen: If not NULL and WPS IE is found, will set to the length of
811 * Returns: The address of the WPS IE found, or NULL
813 u8
*rtw_get_wps_ie23a(u8
*in_ie
, uint in_len
, u8
*wps_ie
, uint
*wps_ielen
)
816 u8
*wpsie_ptr
= NULL
;
817 u8 eid
, wps_oui
[4] = {0x0, 0x50, 0xf2, 0x04};
822 if (!in_ie
|| in_len
<= 0)
827 while (cnt
< in_len
) {
830 if ((eid
== WLAN_EID_VENDOR_SPECIFIC
) &&
831 !memcmp(&in_ie
[cnt
+2], wps_oui
, 4)) {
832 wpsie_ptr
= &in_ie
[cnt
];
835 memcpy(wps_ie
, &in_ie
[cnt
], in_ie
[cnt
+ 1] + 2);
838 *wps_ielen
= in_ie
[cnt
+ 1] + 2;
840 cnt
+= in_ie
[cnt
+ 1] + 2;
844 cnt
+= in_ie
[cnt
+ 1] + 2; /* goto next */
852 * rtw_get_wps_attr23a - Search a specific WPS attribute from a given WPS IE
853 * @wps_ie: Address of WPS IE to search
854 * @wps_ielen: Length limit from wps_ie
855 * @target_attr_id: The attribute ID of WPS attribute to search
856 * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute
857 * will be copied to the buf starting from buf_attr
858 * @len_attr: If not NULL and the WPS attribute is found, will set to the
859 * length of the entire WPS attribute
861 * Returns: the address of the specific WPS attribute found, or NULL
863 u8
*rtw_get_wps_attr23a(u8
*wps_ie
, uint wps_ielen
, u16 target_attr_id
,
864 u8
*buf_attr
, u32
*len_attr
)
867 u8
* target_attr_ptr
= NULL
;
868 u8 wps_oui
[4] = {0x00, 0x50, 0xF2, 0x04};
873 if ((wps_ie
[0] != WLAN_EID_VENDOR_SPECIFIC
) ||
874 memcmp(wps_ie
+ 2, wps_oui
, 4)) {
878 /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
879 attr_ptr
= wps_ie
+ 6; /* goto first attr */
881 while (attr_ptr
- wps_ie
< wps_ielen
) {
882 /* 4 = 2(Attribute ID) + 2(Length) */
883 u16 attr_id
= get_unaligned_be16(attr_ptr
);
884 u16 attr_data_len
= get_unaligned_be16(attr_ptr
+ 2);
885 u16 attr_len
= attr_data_len
+ 4;
887 /* DBG_8723A("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); */
888 if (attr_id
== target_attr_id
) {
889 target_attr_ptr
= attr_ptr
;
892 memcpy(buf_attr
, attr_ptr
, attr_len
);
895 *len_attr
= attr_len
;
899 attr_ptr
+= attr_len
; /* goto next */
903 return target_attr_ptr
;
907 * rtw_get_wps_attr_content23a - Search a specific WPS attribute content
908 * from a given WPS IE
909 * @wps_ie: Address of WPS IE to search
910 * @wps_ielen: Length limit from wps_ie
911 * @target_attr_id: The attribute ID of WPS attribute to search
912 * @buf_content: If not NULL and the WPS attribute is found, WPS attribute
913 * content will be copied to the buf starting from buf_content
914 * @len_content: If not NULL and the WPS attribute is found, will set to the
915 * length of the WPS attribute content
917 * Returns: the address of the specific WPS attribute content found, or NULL
919 u8
*rtw_get_wps_attr_content23a(u8
*wps_ie
, uint wps_ielen
, u16 target_attr_id
,
920 u8
*buf_content
, uint
*len_content
)
928 attr_ptr
= rtw_get_wps_attr23a(wps_ie
, wps_ielen
, target_attr_id
,
931 if (attr_ptr
&& attr_len
) {
933 memcpy(buf_content
, attr_ptr
+ 4, attr_len
- 4);
936 *len_content
= attr_len
- 4;
945 rtw_ieee802_11_parse_vendor_specific(u8
*pos
, uint elen
,
946 struct rtw_ieee802_11_elems
*elems
,
951 /* first 3 bytes in vendor specific information element are the IEEE
952 * OUI of the vendor. The following byte is used a vendor specific
956 DBG_8723A("short vendor specific "
957 "information element ignored (len =%lu)\n",
958 (unsigned long) elen
);
963 oui
= RTW_GET_BE24(pos
);
965 case WLAN_OUI_MICROSOFT
:
966 /* Microsoft/Wi-Fi information elements are further typed and
970 /* Microsoft OUI (00:50:F2) with OUI Type 1:
971 * real WPA information element */
973 elems
->wpa_ie_len
= elen
;
975 case WME_OUI_TYPE
: /* this is a Wi-Fi WME info. element */
977 DBG_8723A("short WME "
978 "information element ignored "
980 (unsigned long) elen
);
984 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT
:
985 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT
:
987 elems
->wme_len
= elen
;
989 case WME_OUI_SUBTYPE_TSPEC_ELEMENT
:
990 elems
->wme_tspec
= pos
;
991 elems
->wme_tspec_len
= elen
;
994 DBG_8723A("unknown WME "
995 "information element ignored "
996 "(subtype =%d len =%lu)\n",
997 pos
[4], (unsigned long) elen
);
1002 /* Wi-Fi Protected Setup (WPS) IE */
1003 elems
->wps_ie
= pos
;
1004 elems
->wps_ie_len
= elen
;
1007 DBG_8723A("Unknown Microsoft "
1008 "information element ignored "
1009 "(type =%d len =%lu)\n",
1010 pos
[3], (unsigned long) elen
);
1017 case VENDOR_HT_CAPAB_OUI_TYPE
:
1018 elems
->vendor_ht_cap
= pos
;
1019 elems
->vendor_ht_cap_len
= elen
;
1022 DBG_8723A("Unknown Broadcom "
1023 "information element ignored "
1024 "(type =%d len =%lu)\n",
1025 pos
[3], (unsigned long) elen
);
1031 DBG_8723A("unknown vendor specific information "
1032 "element ignored (vendor OUI %02x:%02x:%02x "
1034 pos
[0], pos
[1], pos
[2], (unsigned long) elen
);
1042 * ieee802_11_parse_elems - Parse information elements in management frames
1043 * @start: Pointer to the start of IEs
1044 * @len: Length of IE buffer in octets
1045 * @elems: Data structure for parsed elements
1046 * @show_errors: Whether to show parsing errors in debug log
1047 * Returns: Parsing result
1049 enum parse_res
rtw_ieee802_11_parse_elems23a(u8
*start
, uint len
,
1050 struct rtw_ieee802_11_elems
*elems
,
1057 memset(elems
, 0, sizeof(*elems
));
1068 DBG_8723A("IEEE 802.11 element "
1069 "parse failed (id =%d elen =%d "
1071 id
, elen
, (unsigned long) left
);
1079 elems
->ssid_len
= elen
;
1081 case WLAN_EID_SUPP_RATES
:
1082 elems
->supp_rates
= pos
;
1083 elems
->supp_rates_len
= elen
;
1085 case WLAN_EID_FH_PARAMS
:
1086 elems
->fh_params
= pos
;
1087 elems
->fh_params_len
= elen
;
1089 case WLAN_EID_DS_PARAMS
:
1090 elems
->ds_params
= pos
;
1091 elems
->ds_params_len
= elen
;
1093 case WLAN_EID_CF_PARAMS
:
1094 elems
->cf_params
= pos
;
1095 elems
->cf_params_len
= elen
;
1099 elems
->tim_len
= elen
;
1101 case WLAN_EID_IBSS_PARAMS
:
1102 elems
->ibss_params
= pos
;
1103 elems
->ibss_params_len
= elen
;
1105 case WLAN_EID_CHALLENGE
:
1106 elems
->challenge
= pos
;
1107 elems
->challenge_len
= elen
;
1109 case WLAN_EID_ERP_INFO
:
1110 elems
->erp_info
= pos
;
1111 elems
->erp_info_len
= elen
;
1113 case WLAN_EID_EXT_SUPP_RATES
:
1114 elems
->ext_supp_rates
= pos
;
1115 elems
->ext_supp_rates_len
= elen
;
1117 case WLAN_EID_VENDOR_SPECIFIC
:
1118 if (rtw_ieee802_11_parse_vendor_specific(pos
, elen
,
1124 elems
->rsn_ie
= pos
;
1125 elems
->rsn_ie_len
= elen
;
1127 case WLAN_EID_PWR_CAPABILITY
:
1128 elems
->power_cap
= pos
;
1129 elems
->power_cap_len
= elen
;
1131 case WLAN_EID_SUPPORTED_CHANNELS
:
1132 elems
->supp_channels
= pos
;
1133 elems
->supp_channels_len
= elen
;
1135 case WLAN_EID_MOBILITY_DOMAIN
:
1137 elems
->mdie_len
= elen
;
1139 case WLAN_EID_FAST_BSS_TRANSITION
:
1141 elems
->ftie_len
= elen
;
1143 case WLAN_EID_TIMEOUT_INTERVAL
:
1144 elems
->timeout_int
= pos
;
1145 elems
->timeout_int_len
= elen
;
1147 case WLAN_EID_HT_CAPABILITY
:
1148 elems
->ht_capabilities
= pos
;
1149 elems
->ht_capabilities_len
= elen
;
1151 case WLAN_EID_HT_OPERATION
:
1152 elems
->ht_operation
= pos
;
1153 elems
->ht_operation_len
= elen
;
1159 DBG_8723A("IEEE 802.11 element parse "
1160 "ignored unknown element (id =%d elen =%d)\n",
1172 return unknown
? ParseUnknown
: ParseOK
;
1175 static u8
key_char2num(u8 ch
)
1177 if ((ch
>= '0') && (ch
<= '9'))
1179 else if ((ch
>= 'a') && (ch
<= 'f'))
1180 return ch
- 'a' + 10;
1181 else if ((ch
>= 'A') && (ch
<= 'F'))
1182 return ch
- 'A' + 10;
1187 u8
str_2char2num23a(u8 hch
, u8 lch
)
1189 return (key_char2num(hch
) * 10) + key_char2num(lch
);
1192 u8
key_2char2num23a(u8 hch
, u8 lch
)
1194 return (key_char2num(hch
) << 4) | key_char2num(lch
);
1197 void rtw_macaddr_cfg23a(u8
*mac_addr
)
1203 memcpy(mac
, mac_addr
, ETH_ALEN
);
1205 if (is_broadcast_ether_addr(mac
) || is_zero_ether_addr(mac
)) {
1212 /* use default mac addresss */
1213 memcpy(mac_addr
, mac
, ETH_ALEN
);
1214 DBG_8723A("MAC Address from efuse error, assign default "
1217 DBG_8723A("rtw_macaddr_cfg23a MAC Address = "MAC_FMT
"\n",
1221 void dump_ies23a(u8
*buf
, u32 buf_len
) {
1225 while (pos
-buf
<= buf_len
) {
1229 DBG_8723A("%s ID:%u, LEN:%u\n", __func__
, id
, len
);
1230 #ifdef CONFIG_8723AU_P2P
1231 dump_p2p_ie23a(pos
, len
);
1233 dump_wps_ie23a(pos
, len
);
1239 void dump_wps_ie23a(u8
*ie
, u32 ie_len
) {
1247 wps_ie
= rtw_get_wps_ie23a(ie
, ie_len
, NULL
, &wps_ielen
);
1248 if (wps_ie
!= ie
|| wps_ielen
== 0)
1252 while (pos
-ie
< ie_len
) {
1253 id
= get_unaligned_be16(pos
);
1254 len
= get_unaligned_be16(pos
+ 2);
1256 DBG_8723A("%s ID:0x%04x, LEN:%u\n", __func__
, id
, len
);
1262 #ifdef CONFIG_8723AU_P2P
1263 void dump_p2p_ie23a(u8
*ie
, u32 ie_len
) {
1271 p2p_ie
= rtw_get_p2p_ie23a(ie
, ie_len
, NULL
, &p2p_ielen
);
1272 if (p2p_ie
!= ie
|| p2p_ielen
== 0)
1276 while (pos
-ie
< ie_len
) {
1278 len
= get_unaligned_le16(pos
+1);
1280 DBG_8723A("%s ID:%u, LEN:%u\n", __func__
, id
, len
);
1287 * rtw_get_p2p_ie23a - Search P2P IE from a series of IEs
1288 * @in_ie: Address of IEs to search
1289 * @in_len: Length limit from in_ie
1290 * @p2p_ie: If not NULL and P2P IE is found, P2P IE will be copied to the
1291 * buf starting from p2p_ie
1292 * @p2p_ielen: If not NULL and P2P IE is found, will set to the length of
1295 * Returns: The address of the P2P IE found, or NULL
1297 u8
*rtw_get_p2p_ie23a(u8
*in_ie
, int in_len
, u8
*p2p_ie
, uint
*p2p_ielen
)
1301 u8 eid
, p2p_oui
[4]={0x50, 0x6F, 0x9A, 0x09};
1306 while (cnt
<in_len
) {
1308 if ((in_len
< 0) || (cnt
> MAX_IE_SZ
)) {
1312 if ((eid
== WLAN_EID_VENDOR_SPECIFIC
) &&
1313 !memcmp(&in_ie
[cnt
+ 2], p2p_oui
, 4)) {
1314 p2p_ie_ptr
= in_ie
+ cnt
;
1316 if (p2p_ie
!= NULL
) {
1317 memcpy(p2p_ie
, &in_ie
[cnt
],
1318 in_ie
[cnt
+ 1] + 2);
1321 if (p2p_ielen
!= NULL
) {
1322 *p2p_ielen
= in_ie
[cnt
+ 1] + 2;
1329 cnt
+= in_ie
[cnt
+ 1] + 2; /* goto next */
1337 * rtw_get_p2p_attr23a - Search a specific P2P attribute from a given P2P IE
1338 * @p2p_ie: Address of P2P IE to search
1339 * @p2p_ielen: Length limit from p2p_ie
1340 * @target_attr_id: The attribute ID of P2P attribute to search
1341 * @buf_attr: If not NULL and the P2P attribute is found, P2P attribute will
1342 * be copied to the buf starting from buf_attr
1343 * @len_attr: If not NULL and the P2P attribute is found, will set to the
1344 * length of the entire P2P attribute
1346 * Returns: the address of the specific WPS attribute found, or NULL
1348 u8
*rtw_get_p2p_attr23a(u8
*p2p_ie
, uint p2p_ielen
, u8 target_attr_id
,
1349 u8
*buf_attr
, u32
*len_attr
)
1351 u8
*attr_ptr
= NULL
;
1352 u8
*target_attr_ptr
= NULL
;
1353 u8 p2p_oui
[4]={0x50, 0x6F, 0x9A, 0x09};
1358 if (!p2p_ie
|| (p2p_ie
[0] != WLAN_EID_VENDOR_SPECIFIC
) ||
1359 memcmp(p2p_ie
+ 2, p2p_oui
, 4)) {
1363 /* 6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type) */
1364 attr_ptr
= p2p_ie
+ 6; /* goto first attr */
1366 while (attr_ptr
- p2p_ie
< p2p_ielen
) {
1367 /* 3 = 1(Attribute ID) + 2(Length) */
1368 u8 attr_id
= *attr_ptr
;
1369 u16 attr_data_len
= get_unaligned_le16(attr_ptr
+ 1);
1370 u16 attr_len
= attr_data_len
+ 3;
1372 /* DBG_8723A("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); */
1373 if (attr_id
== target_attr_id
) {
1374 target_attr_ptr
= attr_ptr
;
1377 memcpy(buf_attr
, attr_ptr
, attr_len
);
1380 *len_attr
= attr_len
;
1384 attr_ptr
+= attr_len
; /* goto next */
1388 return target_attr_ptr
;
1392 * rtw_get_p2p_attr23a_content - Search a specific P2P attribute content from
1394 * @p2p_ie: Address of P2P IE to search
1395 * @p2p_ielen: Length limit from p2p_ie
1396 * @target_attr_id: The attribute ID of P2P attribute to search
1397 * @buf_content: If not NULL and the P2P attribute is found, P2P attribute
1398 * content will be copied to the buf starting from buf_content
1399 * @len_content: If not NULL and the P2P attribute is found, will set to the
1400 * length of the P2P attribute content
1402 * Returns: the address of the specific P2P attribute content found, or NULL
1404 u8
*rtw_get_p2p_attr23a_content(u8
*p2p_ie
, uint p2p_ielen
, u8 target_attr_id
,
1405 u8
*buf_content
, uint
*len_content
)
1413 attr_ptr
= rtw_get_p2p_attr23a(p2p_ie
, p2p_ielen
, target_attr_id
,
1416 if (attr_ptr
&& attr_len
) {
1418 memcpy(buf_content
, attr_ptr
+ 3, attr_len
- 3);
1421 *len_content
= attr_len
- 3;
1429 u32
rtw_set_p2p_attr_content23a(u8
*pbuf
, u8 attr_id
, u16 attr_len
, u8
*pdata_attr
)
1435 /* u16*)(pbuf + 1) = cpu_to_le16(attr_len); */
1436 put_unaligned_le16(attr_len
, pbuf
+ 1);
1439 memcpy(pbuf
+ 3, pdata_attr
, attr_len
);
1441 a_len
= attr_len
+ 3;
1446 static uint
rtw_p2p_attr_remove(u8
*ie
, uint ielen_ori
, u8 attr_id
)
1449 u32 target_attr_len
;
1450 uint ielen
= ielen_ori
;
1453 target_attr
= rtw_get_p2p_attr23a(ie
, ielen
, attr_id
, NULL
,
1455 if (target_attr
&& target_attr_len
) {
1456 u8
*next_attr
= target_attr
+target_attr_len
;
1457 uint remain_len
= ielen
-(next_attr
-ie
);
1458 /* dump_ies23a(ie, ielen); */
1460 memset(target_attr
, 0, target_attr_len
);
1461 memcpy(target_attr
, next_attr
, remain_len
);
1462 memset(target_attr
+remain_len
, 0, target_attr_len
);
1463 *(ie
+ 1) -= target_attr_len
;
1464 ielen
-= target_attr_len
;
1467 /* dump_ies23a(ie, ielen); */
1475 void rtw_wlan_bssid_ex_remove_p2p_attr23a(struct wlan_bssid_ex
*bss_ex
, u8 attr_id
)
1478 uint p2p_ielen
, p2p_ielen_ori
;
1480 if ((p2p_ie
= rtw_get_p2p_ie23a(bss_ex
->IEs
+ _FIXED_IE_LENGTH_
,
1481 bss_ex
->IELength
- _FIXED_IE_LENGTH_
,
1482 NULL
, &p2p_ielen_ori
))) {
1483 p2p_ielen
= rtw_p2p_attr_remove(p2p_ie
, p2p_ielen_ori
, attr_id
);
1484 if (p2p_ielen
!= p2p_ielen_ori
) {
1485 u8
*next_ie_ori
= p2p_ie
+p2p_ielen_ori
;
1486 u8
*next_ie
= p2p_ie
+p2p_ielen
;
1488 remain_len
= bss_ex
->IELength
-(next_ie_ori
-bss_ex
->IEs
);
1490 memcpy(next_ie
, next_ie_ori
, remain_len
);
1491 memset(next_ie
+remain_len
, 0, p2p_ielen_ori
-p2p_ielen
);
1492 bss_ex
->IELength
-= p2p_ielen_ori
-p2p_ielen
;
1497 #endif /* CONFIG_8723AU_P2P */
1499 #ifdef CONFIG_8723AU_P2P
1500 int rtw_get_wfd_ie(u8
*in_ie
, int in_len
, u8
*wfd_ie
, uint
*wfd_ielen
)
1510 ie
= cfg80211_find_vendor_ie(0x506F9A, 0x0A, in_ie
, in_len
);
1511 if (ie
&& (ie
[1] <= (MAX_WFD_IE_LEN
- 2))) {
1513 *wfd_ielen
= ie
[1] + 2;
1514 memcpy(wfd_ie
, ie
, ie
[1] + 2);
1525 /* attr_content: The output buffer, contains the "body field" of
1527 /* attr_contentlen: The data length of the "body field" of WFD
1529 int rtw_get_wfd_attr_content(u8
*wfd_ie
, uint wfd_ielen
, u8 target_attr_id
,
1530 u8
*attr_content
, uint
*attr_contentlen
)
1534 u8 attr_id
, wfd_oui
[4] = {0x50, 0x6F, 0x9A, 0x0A};
1538 if ((wfd_ie
[0] != WLAN_EID_VENDOR_SPECIFIC
) ||
1539 memcmp(wfd_ie
+ 2, wfd_oui
, 4)) {
1543 /* 1 (WFD IE) + 1 (Length) + 3 (OUI) + 1 (OUI Type) */
1545 while (cnt
< wfd_ielen
) {
1546 u16 attrlen
= get_unaligned_be16(wfd_ie
+ cnt
+ 1);
1548 attr_id
= wfd_ie
[cnt
];
1549 if (attr_id
== target_attr_id
) {
1550 /* 3 -> 1 byte for attribute ID field, 2
1551 bytes for length field */
1553 memcpy(attr_content
, &wfd_ie
[cnt
+ 3], attrlen
);
1555 if (attr_contentlen
)
1556 *attr_contentlen
= attrlen
;
1563 cnt
+= attrlen
+ 3; /* goto next */
1569 #endif /* CONFIG_8723AU_P2P */
1571 /* Baron adds to avoid FreeBSD warning */
1572 int ieee80211_is_empty_essid23a(const char *essid
, int essid_len
)
1574 /* Single white space is for Linksys APs */
1575 if (essid_len
== 1 && essid
[0] == ' ')
1578 /* Otherwise, if the entire essid is 0, we assume it is hidden */
1581 if (essid
[essid_len
] != '\0')
1588 static int rtw_get_cipher_info(struct wlan_network
*pnetwork
)
1591 unsigned char *pbuf
;
1592 int group_cipher
= 0, pairwise_cipher
= 0, is8021x
= 0;
1595 pbuf
= rtw_get_wpa_ie23a(&pnetwork
->network
.IEs
[12], &wpa_ielen
,
1596 pnetwork
->network
.IELength
- 12);
1598 if (pbuf
&& (wpa_ielen
> 0)) {
1599 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
1600 ("rtw_get_cipher_info: wpa_ielen: %d", wpa_ielen
));
1601 r
= rtw_parse_wpa_ie23a(pbuf
, wpa_ielen
+ 2, &group_cipher
,
1602 &pairwise_cipher
, &is8021x
);
1603 if (r
== _SUCCESS
) {
1604 pnetwork
->BcnInfo
.pairwise_cipher
= pairwise_cipher
;
1605 pnetwork
->BcnInfo
.group_cipher
= group_cipher
;
1606 pnetwork
->BcnInfo
.is_8021x
= is8021x
;
1607 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
1608 ("%s: pnetwork->pairwise_cipher: %d, is_"
1609 "8021x is %d", __func__
,
1610 pnetwork
->BcnInfo
.pairwise_cipher
,
1611 pnetwork
->BcnInfo
.is_8021x
));
1615 pbuf
= rtw_get_wpa2_ie23a(&pnetwork
->network
.IEs
[12], &wpa_ielen
,
1616 pnetwork
->network
.IELength
- 12);
1618 if (pbuf
&& (wpa_ielen
> 0)) {
1619 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
1621 r
= rtw_parse_wpa2_ie23a(pbuf
, wpa_ielen
+ 2,
1622 &group_cipher
, &pairwise_cipher
,
1624 if (r
== _SUCCESS
) {
1625 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
1626 ("get RSN IE OK!!!\n"));
1627 pnetwork
->BcnInfo
.pairwise_cipher
=
1629 pnetwork
->BcnInfo
.group_cipher
= group_cipher
;
1630 pnetwork
->BcnInfo
.is_8021x
= is8021x
;
1631 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
1632 ("%s: pnetwork->pairwise_cipher: %d,"
1633 "pnetwork->group_cipher is %d, "
1634 "is_8021x is %d", __func__
,
1635 pnetwork
->BcnInfo
.pairwise_cipher
,
1636 pnetwork
->BcnInfo
.group_cipher
,
1637 pnetwork
->BcnInfo
.is_8021x
));
1646 void rtw_get_bcn_info23a(struct wlan_network
*pnetwork
)
1648 unsigned short cap
= 0;
1650 /* u8 wpa_ie[255], rsn_ie[255]; */
1651 u16 wpa_len
= 0, rsn_len
= 0;
1652 struct HT_info_element
*pht_info
= NULL
;
1653 struct ieee80211_ht_cap
*pht_cap
= NULL
;
1657 memcpy(&cap
, rtw_get_capability23a_from_ie(pnetwork
->network
.IEs
), 2);
1658 cap
= le16_to_cpu(cap
);
1659 if (cap
& WLAN_CAPABILITY_PRIVACY
) {
1661 pnetwork
->network
.Privacy
= 1;
1663 pnetwork
->BcnInfo
.encryp_protocol
= ENCRYP_PROTOCOL_OPENSYS
;
1665 rtw_get_sec_ie23a(pnetwork
->network
.IEs
, pnetwork
->network
.IELength
,
1666 NULL
, &rsn_len
, NULL
, &wpa_len
);
1667 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
1668 ("rtw_get_bcn_info23a: ssid =%s\n", pnetwork
->network
.Ssid
.ssid
));
1669 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
1670 ("rtw_get_bcn_info23a: wpa_len =%d rsn_len =%d\n",
1672 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
1673 ("rtw_get_bcn_info23a: ssid =%s\n", pnetwork
->network
.Ssid
.ssid
));
1674 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
1675 ("rtw_get_bcn_info23a: wpa_len =%d rsn_len =%d\n",
1679 pnetwork
->BcnInfo
.encryp_protocol
= ENCRYP_PROTOCOL_WPA2
;
1680 } else if (wpa_len
> 0) {
1681 pnetwork
->BcnInfo
.encryp_protocol
= ENCRYP_PROTOCOL_WPA
;
1684 pnetwork
->BcnInfo
.encryp_protocol
= ENCRYP_PROTOCOL_WEP
;
1686 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
1687 ("rtw_get_bcn_info23a: pnetwork->encryp_protocol is %x\n",
1688 pnetwork
->BcnInfo
.encryp_protocol
));
1689 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
1690 ("rtw_get_bcn_info23a: pnetwork->encryp_protocol is %x\n",
1691 pnetwork
->BcnInfo
.encryp_protocol
));
1692 rtw_get_cipher_info(pnetwork
);
1694 /* get bwmode and ch_offset */
1695 /* parsing HT_CAP_IE */
1696 p
= rtw_get_ie23a(pnetwork
->network
.IEs
+ _FIXED_IE_LENGTH_
,
1697 _HT_CAPABILITY_IE_
, &len
,
1698 pnetwork
->network
.IELength
- _FIXED_IE_LENGTH_
);
1700 pht_cap
= (struct ieee80211_ht_cap
*)(p
+ 2);
1701 pnetwork
->BcnInfo
.ht_cap_info
= pht_cap
->cap_info
;
1703 pnetwork
->BcnInfo
.ht_cap_info
= 0;
1705 /* parsing HT_INFO_IE */
1706 p
= rtw_get_ie23a(pnetwork
->network
.IEs
+ _FIXED_IE_LENGTH_
,
1707 _HT_ADD_INFO_IE_
, &len
,
1708 pnetwork
->network
.IELength
- _FIXED_IE_LENGTH_
);
1710 pht_info
= (struct HT_info_element
*)(p
+ 2);
1711 pnetwork
->BcnInfo
.ht_info_infos_0
= pht_info
->infos
[0];
1713 pnetwork
->BcnInfo
.ht_info_infos_0
= 0;
1717 /* show MCS rate, unit: 100Kbps */
1718 u16
rtw_mcs_rate23a(u8 rf_type
, u8 bw_40MHz
, u8 short_GI_20
, u8 short_GI_40
,
1719 unsigned char * MCS_rate
)
1723 if (rf_type
== RF_1T1R
) {
1724 if (MCS_rate
[0] & BIT(7))
1725 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?1500:1350):
1726 ((short_GI_20
)?722:650);
1727 else if (MCS_rate
[0] & BIT(6))
1728 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?1350:1215):
1729 ((short_GI_20
)?650:585);
1730 else if (MCS_rate
[0] & BIT(5))
1731 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?1200:1080):
1732 ((short_GI_20
)?578:520);
1733 else if (MCS_rate
[0] & BIT(4))
1734 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?900:810):
1735 ((short_GI_20
)?433:390);
1736 else if (MCS_rate
[0] & BIT(3))
1737 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?600:540):
1738 ((short_GI_20
)?289:260);
1739 else if (MCS_rate
[0] & BIT(2))
1740 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?450:405):
1741 ((short_GI_20
)?217:195);
1742 else if (MCS_rate
[0] & BIT(1))
1743 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?300:270):
1744 ((short_GI_20
)?144:130);
1745 else if (MCS_rate
[0] & BIT(0))
1746 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?150:135):
1747 ((short_GI_20
)?72:65);
1750 if (MCS_rate
[1] & BIT(7))
1751 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?3000:2700):((short_GI_20
)?1444:1300);
1752 else if (MCS_rate
[1] & BIT(6))
1753 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?2700:2430):((short_GI_20
)?1300:1170);
1754 else if (MCS_rate
[1] & BIT(5))
1755 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?2400:2160):((short_GI_20
)?1156:1040);
1756 else if (MCS_rate
[1] & BIT(4))
1757 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?1800:1620):((short_GI_20
)?867:780);
1758 else if (MCS_rate
[1] & BIT(3))
1759 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?1200:1080):((short_GI_20
)?578:520);
1760 else if (MCS_rate
[1] & BIT(2))
1761 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?900:810):((short_GI_20
)?433:390);
1762 else if (MCS_rate
[1] & BIT(1))
1763 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?600:540):((short_GI_20
)?289:260);
1764 else if (MCS_rate
[1] & BIT(0))
1765 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?300:270):((short_GI_20
)?144:130);
1767 if (MCS_rate
[0] & BIT(7))
1768 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?1500:1350):((short_GI_20
)?722:650);
1769 else if (MCS_rate
[0] & BIT(6))
1770 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?1350:1215):((short_GI_20
)?650:585);
1771 else if (MCS_rate
[0] & BIT(5))
1772 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?1200:1080):((short_GI_20
)?578:520);
1773 else if (MCS_rate
[0] & BIT(4))
1774 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?900:810):((short_GI_20
)?433:390);
1775 else if (MCS_rate
[0] & BIT(3))
1776 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?600:540):((short_GI_20
)?289:260);
1777 else if (MCS_rate
[0] & BIT(2))
1778 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?450:405):((short_GI_20
)?217:195);
1779 else if (MCS_rate
[0] & BIT(1))
1780 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?300:270):((short_GI_20
)?144:130);
1781 else if (MCS_rate
[0] & BIT(0))
1782 max_rate
= (bw_40MHz
) ? ((short_GI_40
)?150:135):((short_GI_20
)?72:65);
1788 int rtw_action_frame_parse23a(const u8
*frame
, u32 frame_len
, u8
* category
,
1791 const u8
*frame_body
= frame
+ sizeof(struct ieee80211_hdr_3addr
);
1795 fc
= le16_to_cpu(((struct ieee80211_hdr_3addr
*)frame
)->frame_control
);
1797 if ((fc
& (IEEE80211_FCTL_FTYPE
|IEEE80211_FCTL_STYPE
)) !=
1798 (IEEE80211_FTYPE_MGMT
|IEEE80211_STYPE_ACTION
)) {
1805 case WLAN_CATEGORY_VENDOR_SPECIFIC
: /* vendor-specific */
1819 static const char *_action_public_str23a
[] = {
1820 "ACT_PUB_BSSCOEXIST",
1821 "ACT_PUB_DSE_ENABLE",
1822 "ACT_PUB_DSE_DEENABLE",
1823 "ACT_PUB_DSE_REG_LOCATION",
1824 "ACT_PUB_EXT_CHL_SWITCH",
1825 "ACT_PUB_DSE_MSR_REQ",
1826 "ACT_PUB_DSE_MSR_RPRT",
1828 "ACT_PUB_DSE_PWR_CONSTRAINT",
1830 "ACT_PUB_GAS_INITIAL_REQ",
1831 "ACT_PUB_GAS_INITIAL_RSP",
1832 "ACT_PUB_GAS_COMEBACK_REQ",
1833 "ACT_PUB_GAS_COMEBACK_RSP",
1834 "ACT_PUB_TDLS_DISCOVERY_RSP",
1835 "ACT_PUB_LOCATION_TRACK",
1839 const char *action_public_str23a(u8 action
)
1841 action
= (action
>= ACT_PUBLIC_MAX
) ? ACT_PUBLIC_MAX
: action
;
1842 return _action_public_str23a
[action
];