GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / staging / rtl8188eu / core / rtw_ieee80211.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #define _IEEE80211_C
8
9 #include <linux/ieee80211.h>
10
11 #include <drv_types.h>
12 #include <osdep_intf.h>
13 #include <ieee80211.h>
14 #include <wifi.h>
15 #include <osdep_service.h>
16 #include <wlan_bssdef.h>
17
18 u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
19 u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 };
20 u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 };
21 u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 };
22 u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 };
23 u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 };
24 u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 };
25 u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 };
26 u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 };
27 u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 };
28
29 u16 RSN_VERSION_BSD = 1;
30 u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 };
31 u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 };
32 u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 };
33 u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 };
34 u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 };
35 u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 };
36 u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 };
37 u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };
38 /*  */
39 /*  for adhoc-master to generate ie and provide supported-rate to fw */
40 /*  */
41
42 static u8 WIFI_CCKRATES[] = {
43         IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK,
44         IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
45         IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK,
46         IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK
47 };
48
49 static u8 WIFI_OFDMRATES[] = {
50          IEEE80211_OFDM_RATE_6MB,
51          IEEE80211_OFDM_RATE_9MB,
52          IEEE80211_OFDM_RATE_12MB,
53          IEEE80211_OFDM_RATE_18MB,
54          IEEE80211_OFDM_RATE_24MB,
55          IEEE80211_OFDM_RATE_36MB,
56          IEEE80211_OFDM_RATE_48MB,
57          IEEE80211_OFDM_RATE_54MB
58 };
59
60 int rtw_get_bit_value_from_ieee_value(u8 val)
61 {
62         unsigned char dot11_rate_table[] = {
63                 2, 4, 11, 22, 12, 18, 24, 36, 48,
64                 72, 96, 108, 0}; /*  last element must be zero!! */
65         int i = 0;
66
67         while (dot11_rate_table[i] != 0) {
68                 if (dot11_rate_table[i] == val)
69                         return BIT(i);
70                 i++;
71         }
72         return 0;
73 }
74
75 bool rtw_is_cckrates_included(u8 *rate)
76 {
77         while (*rate) {
78                 u8 r = *rate & 0x7f;
79
80                 if (r == 2 || r == 4 || r == 11 || r == 22)
81                         return true;
82                 rate++;
83         }
84
85         return false;
86 }
87
88 bool rtw_is_cckratesonly_included(u8 *rate)
89 {
90         while (*rate) {
91                 u8 r = *rate & 0x7f;
92
93                 if (r != 2 && r != 4 && r != 11 && r != 22)
94                         return false;
95                 rate++;
96         }
97
98         return true;
99 }
100
101 int rtw_check_network_type(unsigned char *rate, int ratelen, int channel)
102 {
103         if (channel > 14) {
104                 if (rtw_is_cckrates_included(rate))
105                         return WIRELESS_INVALID;
106                 else
107                         return WIRELESS_11A;
108         } else {  /*  could be pure B, pure G, or B/G */
109                 if (rtw_is_cckratesonly_included(rate))
110                         return WIRELESS_11B;
111                 else if (rtw_is_cckrates_included(rate))
112                         return  WIRELESS_11BG;
113                 else
114                         return WIRELESS_11G;
115         }
116 }
117
118 u8 *rtw_set_fixed_ie(void *pbuf, unsigned int len, void *source,
119                      unsigned int *frlen)
120 {
121         memcpy(pbuf, source, len);
122         *frlen = *frlen + len;
123         return ((u8 *)pbuf) + len;
124 }
125
126 /*  rtw_set_ie will update frame length */
127 u8 *rtw_set_ie
128 (
129         u8 *pbuf,
130         int index,
131         uint len,
132         u8 *source,
133         uint *frlen /* frame length */
134 )
135 {
136         *pbuf = (u8)index;
137
138         *(pbuf + 1) = (u8)len;
139
140         if (len > 0)
141                 memcpy((void *)(pbuf + 2), (void *)source, len);
142
143         *frlen = *frlen + (len + 2);
144
145         return pbuf + len + 2;
146 }
147
148 /*----------------------------------------------------------------------------
149 index: the information element id index, limit is the limit for search
150 -----------------------------------------------------------------------------*/
151 u8 *rtw_get_ie(u8 *pbuf, int index, uint *len, int limit)
152 {
153         int tmp, i;
154         u8 *p;
155
156         if (limit < 1)
157                 return NULL;
158
159         p = pbuf;
160         i = 0;
161         *len = 0;
162         while (1) {
163                 if (*p == index) {
164                         *len = *(p + 1);
165                         return p;
166                 } else {
167                         tmp = *(p + 1);
168                         p += (tmp + 2);
169                         i += (tmp + 2);
170                 }
171                 if (i >= limit)
172                         break;
173         }
174         return NULL;
175 }
176
177 void rtw_set_supported_rate(u8 *SupportedRates, uint mode)
178 {
179         memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
180
181         switch (mode) {
182         case WIRELESS_11B:
183                 memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
184                 break;
185         case WIRELESS_11G:
186         case WIRELESS_11A:
187         case WIRELESS_11_5N:
188         case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */
189                 memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
190                 break;
191         case WIRELESS_11BG:
192         case WIRELESS_11G_24N:
193         case WIRELESS_11_24N:
194         case WIRELESS_11BG_24N:
195                 memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
196                 memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
197                 break;
198         }
199 }
200
201 uint rtw_get_rateset_len(u8 *rateset)
202 {
203         uint i;
204
205         for (i = 0; i < 13; i++)
206                 if (rateset[i] == 0)
207                         break;
208         return i;
209 }
210
211 int rtw_generate_ie(struct registry_priv *pregistrypriv)
212 {
213         u8 wireless_mode;
214         int rateLen;
215         uint sz = 0;
216         struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
217         u8 *ie = pdev_network->ies;
218
219         /* timestamp will be inserted by hardware */
220         sz += 8;
221         ie += sz;
222
223         /* beacon interval : 2bytes */
224         *(__le16 *)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);/* BCN_INTERVAL; */
225         sz += 2;
226         ie += 2;
227
228         /* capability info */
229         *(u16 *)ie = 0;
230
231         *(__le16 *)ie |= cpu_to_le16(cap_IBSS);
232
233         if (pregistrypriv->preamble == PREAMBLE_SHORT)
234                 *(__le16 *)ie |= cpu_to_le16(cap_ShortPremble);
235
236         if (pdev_network->Privacy)
237                 *(__le16 *)ie |= cpu_to_le16(cap_Privacy);
238
239         sz += 2;
240         ie += 2;
241
242         /* SSID */
243         ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz);
244
245         /* supported rates */
246         if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) {
247                 if (pdev_network->Configuration.DSConfig > 14)
248                         wireless_mode = WIRELESS_11A_5N;
249                 else
250                         wireless_mode = WIRELESS_11BG_24N;
251         } else {
252                 wireless_mode = pregistrypriv->wireless_mode;
253         }
254
255                 rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode);
256
257         rateLen = rtw_get_rateset_len(pdev_network->SupportedRates);
258
259         if (rateLen > 8) {
260                 ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz);
261                 /* ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */
262         } else {
263                 ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz);
264         }
265
266         /* DS parameter set */
267         ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz);
268
269         /* IBSS Parameter Set */
270
271         ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz);
272
273         if (rateLen > 8)
274                 ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
275
276         return sz;
277 }
278
279 unsigned char *rtw_get_wpa_ie(unsigned char *pie, uint *wpa_ie_len, int limit)
280 {
281         uint len;
282         u16 val16;
283         __le16 le_tmp;
284         unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
285         u8 *pbuf = pie;
286         int limit_new = limit;
287
288         while (1) {
289                 pbuf = rtw_get_ie(pbuf, _WPA_IE_ID_, &len, limit_new);
290
291                 if (pbuf) {
292                         /* check if oui matches... */
293                         if (!memcmp((pbuf + 2), wpa_oui_type, sizeof(wpa_oui_type)) == false)
294                                 goto check_next_ie;
295
296                         /* check version... */
297                         memcpy((u8 *)&le_tmp, (pbuf + 6), sizeof(val16));
298
299                         val16 = le16_to_cpu(le_tmp);
300                         if (val16 != 0x0001)
301                                 goto check_next_ie;
302                         *wpa_ie_len = *(pbuf + 1);
303                         return pbuf;
304                 } else {
305                         *wpa_ie_len = 0;
306                         return NULL;
307                 }
308
309 check_next_ie:
310                 limit_new = limit - (pbuf - pie) - 2 - len;
311                 if (limit_new <= 0)
312                         break;
313                 pbuf += (2 + len);
314         }
315         *wpa_ie_len = 0;
316         return NULL;
317 }
318
319 unsigned char *rtw_get_wpa2_ie(unsigned char *pie, uint *rsn_ie_len, int limit)
320 {
321         return rtw_get_ie(pie, _WPA2_IE_ID_, rsn_ie_len, limit);
322 }
323
324 int rtw_get_wpa_cipher_suite(u8 *s)
325 {
326         if (!memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN))
327                 return WPA_CIPHER_NONE;
328         if (!memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN))
329                 return WPA_CIPHER_WEP40;
330         if (!memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN))
331                 return WPA_CIPHER_TKIP;
332         if (!memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN))
333                 return WPA_CIPHER_CCMP;
334         if (!memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN))
335                 return WPA_CIPHER_WEP104;
336
337         return 0;
338 }
339
340 int rtw_get_wpa2_cipher_suite(u8 *s)
341 {
342         if (!memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN))
343                 return WPA_CIPHER_NONE;
344         if (!memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN))
345                 return WPA_CIPHER_WEP40;
346         if (!memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN))
347                 return WPA_CIPHER_TKIP;
348         if (!memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN))
349                 return WPA_CIPHER_CCMP;
350         if (!memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN))
351                 return WPA_CIPHER_WEP104;
352
353         return 0;
354 }
355
356 int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
357 {
358         int i, ret = _SUCCESS;
359         int left, count;
360         u8 *pos;
361         u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1};
362
363         if (wpa_ie_len <= 0) {
364                 /* No WPA IE - fail silently */
365                 return _FAIL;
366         }
367
368         if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie + 1) != (u8)(wpa_ie_len - 2)) ||
369             (memcmp(wpa_ie + 2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN)))
370                 return _FAIL;
371
372         pos = wpa_ie;
373
374         pos += 8;
375         left = wpa_ie_len - 8;
376
377         /* group_cipher */
378         if (left >= WPA_SELECTOR_LEN) {
379                 *group_cipher = rtw_get_wpa_cipher_suite(pos);
380                 pos += WPA_SELECTOR_LEN;
381                 left -= WPA_SELECTOR_LEN;
382         } else if (left > 0) {
383                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie length mismatch, %u too much", __func__, left));
384                 return _FAIL;
385         }
386
387         /* pairwise_cipher */
388         if (left >= 2) {
389                 count = get_unaligned_le16(pos);
390                 pos += 2;
391                 left -= 2;
392
393                 if (count == 0 || left < count * WPA_SELECTOR_LEN) {
394                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), "
395                                                 "count %u left %u", __func__, count, left));
396                         return _FAIL;
397                 }
398
399                 for (i = 0; i < count; i++) {
400                         *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos);
401
402                         pos += WPA_SELECTOR_LEN;
403                         left -= WPA_SELECTOR_LEN;
404                 }
405         } else if (left == 1) {
406                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie too short (for key mgmt)",   __func__));
407                 return _FAIL;
408         }
409
410         if (is_8021x) {
411                 if (left >= 6) {
412                         pos += 2;
413                         if (!memcmp(pos, SUITE_1X, 4)) {
414                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s : there has 802.1x auth\n", __func__));
415                                 *is_8021x = 1;
416                         }
417                 }
418         }
419
420         return ret;
421 }
422
423 int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
424 {
425         int i, ret = _SUCCESS;
426         int left, count;
427         u8 *pos;
428         u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01};
429
430         if (rsn_ie_len <= 0) {
431                 /* No RSN IE - fail silently */
432                 return _FAIL;
433         }
434
435         if ((*rsn_ie != _WPA2_IE_ID_) || (*(rsn_ie + 1) != (u8)(rsn_ie_len - 2)))
436                 return _FAIL;
437
438         pos = rsn_ie;
439         pos += 4;
440         left = rsn_ie_len - 4;
441
442         /* group_cipher */
443         if (left >= RSN_SELECTOR_LEN) {
444                 *group_cipher = rtw_get_wpa2_cipher_suite(pos);
445
446                 pos += RSN_SELECTOR_LEN;
447                 left -= RSN_SELECTOR_LEN;
448
449         } else if (left > 0) {
450                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie length mismatch, %u too much", __func__, left));
451                 return _FAIL;
452         }
453
454         /* pairwise_cipher */
455         if (left >= 2) {
456                 count = get_unaligned_le16(pos);
457                 pos += 2;
458                 left -= 2;
459
460                 if (count == 0 || left < count * RSN_SELECTOR_LEN) {
461                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), "
462                                                  "count %u left %u", __func__, count, left));
463                         return _FAIL;
464                 }
465
466                 for (i = 0; i < count; i++) {
467                         *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos);
468
469                         pos += RSN_SELECTOR_LEN;
470                         left -= RSN_SELECTOR_LEN;
471                 }
472
473         } else if (left == 1) {
474                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie too short (for key mgmt)",  __func__));
475
476                 return _FAIL;
477         }
478
479         if (is_8021x) {
480                 if (left >= 6) {
481                         pos += 2;
482                         if (!memcmp(pos, SUITE_1X, 4)) {
483                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s (): there has 802.1x auth\n", __func__));
484                                 *is_8021x = 1;
485                         }
486                 }
487         }
488         return ret;
489 }
490
491 int rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie, u16 *wpa_len)
492 {
493         u8 authmode, sec_idx, i;
494         u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
495         uint cnt;
496
497         /* Search required WPA or WPA2 IE and copy to sec_ie[] */
498
499         cnt = _TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_;
500
501         sec_idx = 0;
502
503         while (cnt < in_len) {
504                 authmode = in_ie[cnt];
505
506                 if ((authmode == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
507                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
508                                          ("\n rtw_get_wpa_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n",
509                                          sec_idx, in_ie[cnt + 1] + 2));
510
511                                 if (wpa_ie) {
512                                         memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
513
514                                         for (i = 0; i < (in_ie[cnt + 1] + 2); i += 8) {
515                                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
516                                                          ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
517                                                          wpa_ie[i], wpa_ie[i + 1], wpa_ie[i + 2], wpa_ie[i + 3], wpa_ie[i + 4],
518                                                          wpa_ie[i + 5], wpa_ie[i + 6], wpa_ie[i + 7]));
519                                         }
520                                 }
521
522                                 *wpa_len = in_ie[cnt + 1] + 2;
523                                 cnt += in_ie[cnt + 1] + 2;  /* get next */
524                 } else {
525                         if (authmode == _WPA2_IE_ID_) {
526                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
527                                          ("\n get_rsn_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n",
528                                          sec_idx, in_ie[cnt + 1] + 2));
529
530                                 if (rsn_ie) {
531                                         memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
532
533                                         for (i = 0; i < (in_ie[cnt + 1] + 2); i += 8) {
534                                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
535                                                          ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
536                                                          rsn_ie[i], rsn_ie[i + 1], rsn_ie[i + 2], rsn_ie[i + 3], rsn_ie[i + 4],
537                                                          rsn_ie[i + 5], rsn_ie[i + 6], rsn_ie[i + 7]));
538                                                 }
539                                 }
540
541                                 *rsn_len = in_ie[cnt + 1] + 2;
542                                 cnt += in_ie[cnt + 1] + 2;  /* get next */
543                         } else {
544                                 cnt += in_ie[cnt + 1] + 2;   /* get next */
545                         }
546                 }
547         }
548
549         return *rsn_len + *wpa_len;
550 }
551
552 u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen)
553 {
554         u8 match = false;
555         u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
556
557         if (!ie_ptr)
558                 return match;
559
560         eid = ie_ptr[0];
561
562         if ((eid == _WPA_IE_ID_) && (!memcmp(&ie_ptr[2], wps_oui, 4))) {
563                 *wps_ielen = ie_ptr[1] + 2;
564                 match = true;
565         }
566         return match;
567 }
568
569 /**
570  * rtw_get_wps_ie - Search WPS IE from a series of ies
571  * @in_ie: Address of ies to search
572  * @in_len: Length limit from in_ie
573  * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie
574  * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE
575  *
576  * Returns: The address of the WPS IE found, or NULL
577  */
578 u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
579 {
580         uint cnt;
581         u8 *wpsie_ptr = NULL;
582         u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
583
584         if (wps_ielen)
585                 *wps_ielen = 0;
586
587         if (!in_ie || in_len <= 0)
588                 return wpsie_ptr;
589
590         cnt = 0;
591
592         while (cnt < in_len) {
593                 eid = in_ie[cnt];
594
595                 if ((eid == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt + 2], wps_oui, 4))) {
596                         wpsie_ptr = &in_ie[cnt];
597
598                         if (wps_ie)
599                                 memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
600
601                         if (wps_ielen)
602                                 *wps_ielen = in_ie[cnt + 1] + 2;
603
604                         cnt += in_ie[cnt + 1] + 2;
605
606                         break;
607                 } else {
608                         cnt += in_ie[cnt + 1] + 2; /* goto next */
609                 }
610         }
611         return wpsie_ptr;
612 }
613
614 /**
615  * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE
616  * @wps_ie: Address of WPS IE to search
617  * @wps_ielen: Length limit from wps_ie
618  * @target_attr_id: The attribute ID of WPS attribute to search
619  * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr
620  * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute
621  *
622  * Returns: the address of the specific WPS attribute found, or NULL
623  */
624 u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_attr, u32 *len_attr)
625 {
626         u8 *attr_ptr = NULL;
627         u8 *target_attr_ptr = NULL;
628         u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04};
629
630         if (len_attr)
631                 *len_attr = 0;
632
633         if ((wps_ie[0] != _VENDOR_SPECIFIC_IE_) ||
634             (memcmp(wps_ie + 2, wps_oui, 4)))
635                 return attr_ptr;
636
637         /*  6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
638         attr_ptr = wps_ie + 6; /* goto first attr */
639
640         while (attr_ptr - wps_ie < wps_ielen) {
641                 /*  4 = 2(Attribute ID) + 2(Length) */
642                 u16 attr_id = get_unaligned_be16(attr_ptr);
643                 u16 attr_data_len = get_unaligned_be16(attr_ptr + 2);
644                 u16 attr_len = attr_data_len + 4;
645
646                 if (attr_id == target_attr_id) {
647                         target_attr_ptr = attr_ptr;
648                         if (buf_attr)
649                                 memcpy(buf_attr, attr_ptr, attr_len);
650                         if (len_attr)
651                                 *len_attr = attr_len;
652                         break;
653                 } else {
654                         attr_ptr += attr_len; /* goto next */
655                 }
656         }
657         return target_attr_ptr;
658 }
659
660 /**
661  * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE
662  * @wps_ie: Address of WPS IE to search
663  * @wps_ielen: Length limit from wps_ie
664  * @target_attr_id: The attribute ID of WPS attribute to search
665  * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content
666  * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content
667  *
668  * Returns: the address of the specific WPS attribute content found, or NULL
669  */
670 u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_content, uint *len_content)
671 {
672         u8 *attr_ptr;
673         u32 attr_len;
674
675         if (len_content)
676                 *len_content = 0;
677
678         attr_ptr = rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &attr_len);
679
680         if (attr_ptr && attr_len) {
681                 if (buf_content)
682                         memcpy(buf_content, attr_ptr + 4, attr_len - 4);
683
684                 if (len_content)
685                         *len_content = attr_len - 4;
686
687                 return attr_ptr + 4;
688         }
689
690         return NULL;
691 }
692
693 static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
694                                             struct rtw_ieee802_11_elems *elems,
695                                             int show_errors)
696 {
697         unsigned int oui;
698
699         /* first 3 bytes in vendor specific information element are the IEEE
700          * OUI of the vendor. The following byte is used a vendor specific
701          * sub-type. */
702         if (elen < 4) {
703                 if (show_errors) {
704                         DBG_88E("short vendor specific information element ignored (len=%lu)\n",
705                                 (unsigned long)elen);
706                 }
707                 return -1;
708         }
709
710         oui = RTW_GET_BE24(pos);
711         switch (oui) {
712         case OUI_MICROSOFT:
713                 /* Microsoft/Wi-Fi information elements are further typed and
714                  * subtyped */
715                 switch (pos[3]) {
716                 case 1:
717                         /* Microsoft OUI (00:50:F2) with OUI Type 1:
718                          * real WPA information element */
719                         elems->wpa_ie = pos;
720                         elems->wpa_ie_len = elen;
721                         break;
722                 case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
723                         if (elen < 5) {
724                                 DBG_88E("short WME information element ignored (len=%lu)\n",
725                                         (unsigned long)elen);
726                                 return -1;
727                         }
728                         switch (pos[4]) {
729                         case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
730                         case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
731                                 elems->wme = pos;
732                                 elems->wme_len = elen;
733                                 break;
734                         case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
735                                 elems->wme_tspec = pos;
736                                 elems->wme_tspec_len = elen;
737                                 break;
738                         default:
739                                 DBG_88E("unknown WME information element ignored (subtype=%d len=%lu)\n",
740                                         pos[4], (unsigned long)elen);
741                                 return -1;
742                         }
743                         break;
744                 case 4:
745                         /* Wi-Fi Protected Setup (WPS) IE */
746                         elems->wps_ie = pos;
747                         elems->wps_ie_len = elen;
748                         break;
749                 default:
750                         DBG_88E("Unknown Microsoft information element ignored (type=%d len=%lu)\n",
751                                 pos[3], (unsigned long)elen);
752                         return -1;
753                 }
754                 break;
755
756         case OUI_BROADCOM:
757                 switch (pos[3]) {
758                 case VENDOR_HT_CAPAB_OUI_TYPE:
759                         elems->vendor_ht_cap = pos;
760                         elems->vendor_ht_cap_len = elen;
761                         break;
762                 default:
763                         DBG_88E("Unknown Broadcom information element ignored (type=%d len=%lu)\n",
764                                 pos[3], (unsigned long)elen);
765                         return -1;
766                 }
767                 break;
768         default:
769                 DBG_88E("unknown vendor specific information element ignored (vendor OUI %3phC len=%lu)\n",
770                         pos, (unsigned long)elen);
771                 return -1;
772         }
773         return 0;
774 }
775
776 /**
777  * ieee802_11_parse_elems - Parse information elements in management frames
778  * @start: Pointer to the start of ies
779  * @len: Length of IE buffer in octets
780  * @elems: Data structure for parsed elements
781  * @show_errors: Whether to show parsing errors in debug log
782  * Returns: Parsing result
783  */
784 enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len,
785                                 struct rtw_ieee802_11_elems *elems,
786                                 int show_errors)
787 {
788         uint left = len;
789         u8 *pos = start;
790         int unknown = 0;
791
792         memset(elems, 0, sizeof(*elems));
793
794         while (left >= 2) {
795                 u8 id, elen;
796
797                 id = *pos++;
798                 elen = *pos++;
799                 left -= 2;
800
801                 if (elen > left) {
802                         if (show_errors) {
803                                 DBG_88E("IEEE 802.11 element parse failed (id=%d elen=%d left=%lu)\n",
804                                         id, elen, (unsigned long)left);
805                         }
806                         return ParseFailed;
807                 }
808
809                 switch (id) {
810                 case WLAN_EID_SSID:
811                         elems->ssid = pos;
812                         elems->ssid_len = elen;
813                         break;
814                 case WLAN_EID_SUPP_RATES:
815                         elems->supp_rates = pos;
816                         elems->supp_rates_len = elen;
817                         break;
818                 case WLAN_EID_FH_PARAMS:
819                         elems->fh_params = pos;
820                         elems->fh_params_len = elen;
821                         break;
822                 case WLAN_EID_DS_PARAMS:
823                         elems->ds_params = pos;
824                         elems->ds_params_len = elen;
825                         break;
826                 case WLAN_EID_CF_PARAMS:
827                         elems->cf_params = pos;
828                         elems->cf_params_len = elen;
829                         break;
830                 case WLAN_EID_TIM:
831                         elems->tim = pos;
832                         elems->tim_len = elen;
833                         break;
834                 case WLAN_EID_IBSS_PARAMS:
835                         elems->ibss_params = pos;
836                         elems->ibss_params_len = elen;
837                         break;
838                 case WLAN_EID_CHALLENGE:
839                         elems->challenge = pos;
840                         elems->challenge_len = elen;
841                         break;
842                 case WLAN_EID_ERP_INFO:
843                         elems->erp_info = pos;
844                         elems->erp_info_len = elen;
845                         break;
846                 case WLAN_EID_EXT_SUPP_RATES:
847                         elems->ext_supp_rates = pos;
848                         elems->ext_supp_rates_len = elen;
849                         break;
850                 case WLAN_EID_VENDOR_SPECIFIC:
851                         if (rtw_ieee802_11_parse_vendor_specific(pos, elen, elems, show_errors))
852                                 unknown++;
853                         break;
854                 case WLAN_EID_RSN:
855                         elems->rsn_ie = pos;
856                         elems->rsn_ie_len = elen;
857                         break;
858                 case WLAN_EID_PWR_CAPABILITY:
859                         elems->power_cap = pos;
860                         elems->power_cap_len = elen;
861                         break;
862                 case WLAN_EID_SUPPORTED_CHANNELS:
863                         elems->supp_channels = pos;
864                         elems->supp_channels_len = elen;
865                         break;
866                 case WLAN_EID_MOBILITY_DOMAIN:
867                         elems->mdie = pos;
868                         elems->mdie_len = elen;
869                         break;
870                 case WLAN_EID_FAST_BSS_TRANSITION:
871                         elems->ftie = pos;
872                         elems->ftie_len = elen;
873                         break;
874                 case WLAN_EID_TIMEOUT_INTERVAL:
875                         elems->timeout_int = pos;
876                         elems->timeout_int_len = elen;
877                         break;
878                 case WLAN_EID_HT_CAPABILITY:
879                         elems->ht_capabilities = pos;
880                         elems->ht_capabilities_len = elen;
881                         break;
882                 case WLAN_EID_HT_OPERATION:
883                         elems->ht_operation = pos;
884                         elems->ht_operation_len = elen;
885                         break;
886                 default:
887                         unknown++;
888                         if (!show_errors)
889                                 break;
890                         DBG_88E("IEEE 802.11 element parse ignored unknown element (id=%d elen=%d)\n",
891                                 id, elen);
892                         break;
893                 }
894                 left -= elen;
895                 pos += elen;
896         }
897         if (left)
898                 return ParseFailed;
899         return unknown ? ParseUnknown : ParseOK;
900 }
901
902 void rtw_macaddr_cfg(u8 *mac_addr)
903 {
904         u8 mac[ETH_ALEN];
905
906         if (!mac_addr)
907                 return;
908
909         if (rtw_initmac && mac_pton(rtw_initmac, mac)) {
910                 /* Users specify the mac address */
911                 ether_addr_copy(mac_addr, mac);
912         } else {
913                 /* Use the mac address stored in the Efuse */
914                 ether_addr_copy(mac, mac_addr);
915         }
916
917         if (is_broadcast_ether_addr(mac) || is_zero_ether_addr(mac)) {
918                 eth_random_addr(mac_addr);
919                 DBG_88E("MAC Address from efuse error, assign random one !!!\n");
920         }
921
922         DBG_88E("%s MAC Address  = %pM\n", __func__, mac_addr);
923 }
924
925 static int rtw_get_cipher_info(struct wlan_network *pnetwork)
926 {
927         uint wpa_ielen;
928         unsigned char *pbuf;
929         int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
930         int ret = _FAIL;
931
932         pbuf = rtw_get_wpa_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length - 12);
933
934         if (pbuf && (wpa_ielen > 0)) {
935                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_ielen: %d", __func__, wpa_ielen));
936                 if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x)) {
937                         pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
938                         pnetwork->BcnInfo.group_cipher = group_cipher;
939                         pnetwork->BcnInfo.is_8021x = is8021x;
940                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d, is_8021x is %d",
941                                  __func__, pnetwork->BcnInfo.pairwise_cipher, pnetwork->BcnInfo.is_8021x));
942                         ret = _SUCCESS;
943                 }
944         } else {
945                 pbuf = rtw_get_wpa2_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length - 12);
946
947                 if (pbuf && (wpa_ielen > 0)) {
948                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE\n"));
949                         if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x)) {
950                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE  OK!!!\n"));
951                                 pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
952                                 pnetwork->BcnInfo.group_cipher = group_cipher;
953                                 pnetwork->BcnInfo.is_8021x = is8021x;
954                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d,"
955                                                         "pnetwork->group_cipher is %d, is_8021x is %d", __func__, pnetwork->BcnInfo.pairwise_cipher,
956                                                         pnetwork->BcnInfo.group_cipher, pnetwork->BcnInfo.is_8021x));
957                                 ret = _SUCCESS;
958                         }
959                 }
960         }
961
962         return ret;
963 }
964
965 void rtw_get_bcn_info(struct wlan_network *pnetwork)
966 {
967         unsigned short cap = 0;
968         u8 bencrypt = 0;
969         __le16 le_tmp;
970         u16 wpa_len = 0, rsn_len = 0;
971         struct HT_info_element *pht_info = NULL;
972         uint len;
973         unsigned char *p;
974
975         memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.ies), 2);
976         cap = le16_to_cpu(le_tmp);
977         if (cap & WLAN_CAPABILITY_PRIVACY) {
978                 bencrypt = 1;
979                 pnetwork->network.Privacy = 1;
980         } else {
981                 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
982         }
983         rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, NULL, &rsn_len, NULL, &wpa_len);
984         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.Ssid.Ssid));
985         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_len =%d rsn_len =%d\n", __func__, wpa_len, rsn_len));
986         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.Ssid.Ssid));
987         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_len =%d rsn_len =%d\n", __func__, wpa_len, rsn_len));
988
989         if (rsn_len > 0) {
990                 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
991         } else if (wpa_len > 0) {
992                 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA;
993         } else {
994                 if (bencrypt)
995                         pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
996         }
997         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
998                  pnetwork->BcnInfo.encryp_protocol));
999         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
1000                  pnetwork->BcnInfo.encryp_protocol));
1001         rtw_get_cipher_info(pnetwork);
1002
1003         /* get bwmode and ch_offset */
1004         /* parsing HT_CAP_IE */
1005         p = rtw_get_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pnetwork->network.ie_length - _FIXED_IE_LENGTH_);
1006         if (p && len > 0) {
1007                 struct ieee80211_ht_cap *ht_cap =
1008                         (struct ieee80211_ht_cap *)(p + 2);
1009
1010                 pnetwork->BcnInfo.ht_cap_info = le16_to_cpu(ht_cap->cap_info);
1011         } else {
1012                 pnetwork->BcnInfo.ht_cap_info = 0;
1013         }
1014         /* parsing HT_INFO_IE */
1015         p = rtw_get_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, pnetwork->network.ie_length - _FIXED_IE_LENGTH_);
1016         if (p && len > 0) {
1017                         pht_info = (struct HT_info_element *)(p + 2);
1018                         pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0];
1019         } else {
1020                         pnetwork->BcnInfo.ht_info_infos_0 = 0;
1021         }
1022 }
1023
1024 /* show MCS rate, unit: 100Kbps */
1025 u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsigned char *MCS_rate)
1026 {
1027         u16 max_rate = 0;
1028
1029         if (rf_type == RF_1T1R) {
1030                 if (MCS_rate[0] & BIT(7))
1031                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650);
1032                 else if (MCS_rate[0] & BIT(6))
1033                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585);
1034                 else if (MCS_rate[0] & BIT(5))
1035                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
1036                 else if (MCS_rate[0] & BIT(4))
1037                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
1038                 else if (MCS_rate[0] & BIT(3))
1039                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
1040                 else if (MCS_rate[0] & BIT(2))
1041                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195);
1042                 else if (MCS_rate[0] & BIT(1))
1043                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
1044                 else if (MCS_rate[0] & BIT(0))
1045                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65);
1046         } else {
1047                 if (MCS_rate[1]) {
1048                         if (MCS_rate[1] & BIT(7))
1049                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 3000 : 2700) : ((short_GI_20) ? 1444 : 1300);
1050                         else if (MCS_rate[1] & BIT(6))
1051                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 2700 : 2430) : ((short_GI_20) ? 1300 : 1170);
1052                         else if (MCS_rate[1] & BIT(5))
1053                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 2400 : 2160) : ((short_GI_20) ? 1156 : 1040);
1054                         else if (MCS_rate[1] & BIT(4))
1055                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 1800 : 1620) : ((short_GI_20) ? 867 : 780);
1056                         else if (MCS_rate[1] & BIT(3))
1057                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
1058                         else if (MCS_rate[1] & BIT(2))
1059                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
1060                         else if (MCS_rate[1] & BIT(1))
1061                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
1062                         else if (MCS_rate[1] & BIT(0))
1063                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
1064                 } else {
1065                         if (MCS_rate[0] & BIT(7))
1066                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650);
1067                         else if (MCS_rate[0] & BIT(6))
1068                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585);
1069                         else if (MCS_rate[0] & BIT(5))
1070                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
1071                         else if (MCS_rate[0] & BIT(4))
1072                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
1073                         else if (MCS_rate[0] & BIT(3))
1074                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
1075                         else if (MCS_rate[0] & BIT(2))
1076                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195);
1077                         else if (MCS_rate[0] & BIT(1))
1078                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
1079                         else if (MCS_rate[0] & BIT(0))
1080                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65);
1081                 }
1082         }
1083         return max_rate;
1084 }