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