forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_iw.c
....@@ -1,15 +1,16 @@
1
-/* SPDX-License-Identifier: GPL-2.0 */
21 /*
32 * Linux Wireless Extensions support
43 *
5
- * Copyright (C) 1999-2019, Broadcom Corporation
6
- *
4
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
5
+ *
6
+ * Copyright (C) 1999-2017, Broadcom Corporation
7
+ *
78 * Unless you and Broadcom execute a separate written software license
89 * agreement governing use of this software, this software is licensed to you
910 * under the terms of the GNU General Public License version 2 (the "GPL"),
1011 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
1112 * following added to such license:
12
- *
13
+ *
1314 * As a special exception, the copyright holders of this software give you
1415 * permission to link this software with independent modules, and to copy and
1516 * distribute the resulting executable under terms of your choice, provided that
....@@ -17,7 +18,7 @@
1718 * the license of that module. An independent module is a module which is not
1819 * derived from this software. The special exception does not apply to any
1920 * modifications of the software.
20
- *
21
+ *
2122 * Notwithstanding the above, under no circumstances may you combine this
2223 * software in any way with any other Broadcom software provided under a license
2324 * other than the GPL, without Broadcom's express prior written consent.
....@@ -25,7 +26,7 @@
2526 *
2627 * <<Broadcom-WL-IPTag/Open:>>
2728 *
28
- * $Id: wl_iw.c 709309 2019-01-17 09:04:00Z $
29
+ * $Id: wl_iw.c 693575 2017-04-04 06:45:00Z $
2930 */
3031
3132 #if defined(USE_IW)
....@@ -37,15 +38,14 @@
3738
3839 #include <bcmutils.h>
3940 #include <bcmendian.h>
40
-#include <proto/ethernet.h>
41
-
42
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
43
-#include <linux/sched/signal.h>
44
-#endif
41
+#include <ethernet.h>
4542
4643 #include <linux/if_arp.h>
47
-#include <linux/uaccess.h>
48
-
44
+#include <asm/uaccess.h>
45
+#include <linux/signal.h>
46
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
47
+#include <linux/sched/signal.h>
48
+#endif // endif
4949 #include <wlioctl.h>
5050 #include <wlioctl_utils.h>
5151
....@@ -54,35 +54,60 @@
5454 #include <wl_dbg.h>
5555 #include <wl_iw.h>
5656
57
+#ifdef BCMWAPI_WPI
58
+/* these items should evetually go into wireless.h of the linux system headfile dir */
59
+#ifndef IW_ENCODE_ALG_SM4
60
+#define IW_ENCODE_ALG_SM4 0x20
61
+#endif // endif
62
+
63
+#ifndef IW_AUTH_WAPI_ENABLED
64
+#define IW_AUTH_WAPI_ENABLED 0x20
65
+#endif // endif
66
+
67
+#ifndef IW_AUTH_WAPI_VERSION_1
68
+#define IW_AUTH_WAPI_VERSION_1 0x00000008
69
+#endif // endif
70
+
71
+#ifndef IW_AUTH_CIPHER_SMS4
72
+#define IW_AUTH_CIPHER_SMS4 0x00000020
73
+#endif // endif
74
+
75
+#ifndef IW_AUTH_KEY_MGMT_WAPI_PSK
76
+#define IW_AUTH_KEY_MGMT_WAPI_PSK 4
77
+#endif // endif
78
+
79
+#ifndef IW_AUTH_KEY_MGMT_WAPI_CERT
80
+#define IW_AUTH_KEY_MGMT_WAPI_CERT 8
81
+#endif // endif
82
+#endif /* BCMWAPI_WPI */
5783
5884 /* Broadcom extensions to WEXT, linux upstream has obsoleted WEXT */
5985 #ifndef IW_AUTH_KEY_MGMT_FT_802_1X
6086 #define IW_AUTH_KEY_MGMT_FT_802_1X 0x04
61
-#endif
87
+#endif // endif
6288
6389 #ifndef IW_AUTH_KEY_MGMT_FT_PSK
6490 #define IW_AUTH_KEY_MGMT_FT_PSK 0x08
65
-#endif
91
+#endif // endif
6692
6793 #ifndef IW_ENC_CAPA_FW_ROAM_ENABLE
6894 #define IW_ENC_CAPA_FW_ROAM_ENABLE 0x00000020
69
-#endif
70
-
95
+#endif // endif
7196
7297 /* FC9: wireless.h 2.6.25-14.fc9.i686 is missing these, even though WIRELESS_EXT is set to latest
7398 * version 22.
7499 */
75100 #ifndef IW_ENCODE_ALG_PMK
76101 #define IW_ENCODE_ALG_PMK 4
77
-#endif
102
+#endif // endif
78103 #ifndef IW_ENC_CAPA_4WAY_HANDSHAKE
79104 #define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010
80
-#endif
105
+#endif // endif
81106 /* End FC9. */
82107
83108 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
84109 #include <linux/rtnetlink.h>
85
-#endif
110
+#endif // endif
86111 #if defined(SOFTAP)
87112 struct net_device *ap_net_dev = NULL;
88113 tsk_ctl_t ap_eth_ctl; /* apsta AP netdev waiter thread */
....@@ -93,7 +118,7 @@
93118
94119 uint wl_msg_level = WL_ERROR_VAL;
95120
96
-#define MAX_WLIW_IOCTL_LEN 1024
121
+#define MAX_WLIW_IOCTL_LEN WLC_IOCTL_MEDLEN
97122
98123 /* IOCTL swapping mode for Big Endian host with Little Endian dongle. Default to off */
99124 #define htod32(i) (i)
....@@ -110,7 +135,6 @@
110135 #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
111136 #define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
112137 #endif /* WIRELESS_EXT < 19 */
113
-
114138
115139 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
116140 #define DAEMONIZE(a) do { \
....@@ -143,7 +167,7 @@
143167
144168 typedef struct iscan_info {
145169 struct net_device *dev;
146
- struct timer_list timer;
170
+ timer_list_compat_t timer;
147171 uint32 timer_ms;
148172 uint32 timer_on;
149173 int iscan_state;
....@@ -153,11 +177,10 @@
153177 /* Thread to work on iscan */
154178 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
155179 struct task_struct *kthread;
156
-#endif
180
+#endif // endif
157181 long sysioc_pid;
158182 struct semaphore sysioc_sem;
159183 struct completion sysioc_exited;
160
-
161184
162185 char ioctlbuf[WLC_IOCTL_SMLEN];
163186 } iscan_info_t;
....@@ -176,7 +199,7 @@
176199 #define WL_DEV_LINK(dev) (priv_link_t*)(dev->priv)
177200 #else
178201 #define WL_DEV_LINK(dev) (priv_link_t*)netdev_priv(dev)
179
-#endif
202
+#endif // endif
180203
181204 /* dev to wl_iw_t */
182205 #define IW_DEV_IF(dev) ((wl_iw_t*)(WL_DEV_LINK(dev))->wliw)
....@@ -217,7 +240,9 @@
217240 {
218241 struct ifreq ifr;
219242 wl_ioctl_t ioc;
243
+#if defined(KERNEL_DS) && defined(USER_DS)
220244 mm_segment_t fs;
245
+#endif /* KERNEL_DS && USER_DS */
221246 int ret;
222247
223248 memset(&ioc, 0, sizeof(ioc));
....@@ -229,14 +254,20 @@
229254 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
230255 ifr.ifr_data = (caddr_t) &ioc;
231256
257
+#if defined(KERNEL_DS) && defined(USER_DS)
232258 fs = get_fs();
233
- set_fs(KERNEL_DS);
259
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 0, 21)
260
+ set_fs(get_ds());
261
+#endif // endif
262
+#endif /* KERNEL_DS && USER_DS */
234263 #if defined(WL_USE_NETDEV_OPS)
235264 ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
236265 #else
237266 ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
238
-#endif
267
+#endif // endif
268
+#if defined(KERNEL_DS) && defined(USER_DS)
239269 set_fs(fs);
270
+#endif /* KERNEL_DS && USER_DS */
240271
241272 return ret;
242273 }
....@@ -576,9 +607,10 @@
576607 while (fwrq->e++ < 6)
577608 fwrq->m /= 10;
578609 }
579
- /* handle 4.9GHz frequencies as Japan 4 GHz based channelization */
580
- if (fwrq->m > 4000 && fwrq->m < 5000)
581
- sf = WF_CHAN_FACTOR_4_G; /* start factor for 4 GHz */
610
+ /* handle 4.9GHz frequencies as Japan 4 GHz based channelization */
611
+ if (fwrq->m > 4000 && fwrq->m < 5000) {
612
+ sf = WF_CHAN_FACTOR_4_G; /* start factor for 4 GHz */
613
+ }
582614
583615 chan = wf_mhz2channel(fwrq->m, sf);
584616 }
....@@ -683,17 +715,10 @@
683715 static int channels[MAXCHANNEL+1];
684716 wl_uint32_list_t *list = (wl_uint32_list_t *) channels;
685717 wl_rateset_t rateset;
686
- int error, i, k;
718
+ int error, i;
687719 uint sf, ch;
688720
689721 int phytype;
690
- int bw_cap = 0, sgi_tx = 0, nmode = 0;
691
- channel_info_t ci;
692
- uint8 nrate_list2copy = 0;
693
- uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130},
694
- {14, 29, 43, 58, 87, 116, 130, 144},
695
- {27, 54, 81, 108, 162, 216, 243, 270},
696
- {30, 60, 90, 120, 180, 240, 270, 300}};
697722 int fbt_cap = 0;
698723
699724 WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name));
....@@ -750,41 +775,8 @@
750775 range->num_bitrates = rateset.count;
751776 for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
752777 range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000; /* convert to bps */
753
- if ((error = dev_wlc_intvar_get(dev, "nmode", &nmode)))
754
- return error;
755778 if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype))))
756779 return error;
757
- if (nmode == 1 && (((phytype == WLC_PHY_TYPE_LCN) ||
758
- (phytype == WLC_PHY_TYPE_LCN40)))) {
759
- if ((error = dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap)))
760
- return error;
761
- if ((error = dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx)))
762
- return error;
763
- if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t))))
764
- return error;
765
- ci.hw_channel = dtoh32(ci.hw_channel);
766
-
767
- if (bw_cap == 0 ||
768
- (bw_cap == 2 && ci.hw_channel <= 14)) {
769
- if (sgi_tx == 0)
770
- nrate_list2copy = 0;
771
- else
772
- nrate_list2copy = 1;
773
- }
774
- if (bw_cap == 1 ||
775
- (bw_cap == 2 && ci.hw_channel >= 36)) {
776
- if (sgi_tx == 0)
777
- nrate_list2copy = 2;
778
- else
779
- nrate_list2copy = 3;
780
- }
781
- range->num_bitrates += 8;
782
- ASSERT(range->num_bitrates < IW_MAX_BITRATES);
783
- for (k = 0; i < range->num_bitrates; k++, i++) {
784
- /* convert to bps */
785
- range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000;
786
- }
787
- }
788780
789781 /* Set an indication of the max TCP throughput
790782 * in bit/s that we can expect using this interface.
....@@ -812,7 +804,7 @@
812804 range->encoding_size[2] = TKIP_KEY_SIZE;
813805 #else
814806 range->encoding_size[2] = 0;
815
-#endif
807
+#endif // endif
816808 range->encoding_size[3] = AES_KEY_SIZE;
817809
818810 /* Do not support power micro-management */
....@@ -878,7 +870,7 @@
878870 #if WIRELESS_EXT >= 22 && defined(IW_SCAN_CAPA_ESSID)
879871 /* FC7 wireless.h defines EXT 22 but doesn't define scan_capa bits */
880872 range->scan_capa = IW_SCAN_CAPA_ESSID;
881
-#endif
873
+#endif // endif
882874 #endif /* WIRELESS_EXT > 17 */
883875
884876 return 0;
....@@ -1091,7 +1083,8 @@
10911083 ASSERT(list->version == WL_BSS_INFO_VERSION);
10921084
10931085 for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
1094
- bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
1086
+ bi = (bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) :
1087
+ (wl_bss_info_t*)list->bss_info);
10951088 ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
10961089 buflen));
10971090
....@@ -1222,7 +1215,7 @@
12221215 ssid.SSID_len = htod32(ssid.SSID_len);
12231216 }
12241217 }
1225
-#endif
1218
+#endif // endif
12261219 /* Ignore error (most likely scan in progress) */
12271220 (void) dev_wlc_ioctl(dev, WLC_SCAN, &ssid, sizeof(ssid));
12281221
....@@ -1263,16 +1256,18 @@
12631256 ssid.SSID_len = htod32(ssid.SSID_len);
12641257 }
12651258 }
1266
-#endif
1259
+#endif // endif
12671260
12681261 iscan->list_cur = iscan->list_hdr;
12691262 iscan->iscan_state = ISCAN_STATE_SCANING;
12701263
1271
-
12721264 wl_iw_set_event_mask(dev);
12731265 wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
1274
-
1266
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
12751267 iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms);
1268
+#else
1269
+ iscan->timer.timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms);
1270
+#endif // endif
12761271 add_timer(&iscan->timer);
12771272 iscan->timer_on = 1;
12781273
....@@ -1325,6 +1320,42 @@
13251320 }
13261321 #endif /* WIRELESS_EXT > 17 */
13271322
1323
+#ifdef BCMWAPI_WPI
1324
+static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
1325
+ size_t len, int uppercase)
1326
+{
1327
+ size_t i;
1328
+ char *pos = buf, *end = buf + buf_size;
1329
+ int ret;
1330
+ if (buf_size == 0)
1331
+ return 0;
1332
+ for (i = 0; i < len; i++) {
1333
+ ret = snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
1334
+ data[i]);
1335
+ if (ret < 0 || ret >= end - pos) {
1336
+ end[-1] = '\0';
1337
+ return pos - buf;
1338
+ }
1339
+ pos += ret;
1340
+ }
1341
+ end[-1] = '\0';
1342
+ return pos - buf;
1343
+}
1344
+
1345
+/**
1346
+ * wpa_snprintf_hex - Print data as a hex string into a buffer
1347
+ * @buf: Memory area to use as the output buffer
1348
+ * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
1349
+ * @data: Data to be printed
1350
+ * @len: Length of data in bytes
1351
+ * Returns: Number of bytes written
1352
+ */
1353
+static int
1354
+wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
1355
+{
1356
+ return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
1357
+}
1358
+#endif /* BCMWAPI_WPI */
13281359
13291360 static int
13301361 wl_iw_handle_scanresults_ies(char **event_p, char *end,
....@@ -1333,13 +1364,17 @@
13331364 #if WIRELESS_EXT > 17
13341365 struct iw_event iwe;
13351366 char *event;
1367
+#ifdef BCMWAPI_WPI
1368
+ char *buf;
1369
+ int custom_event_len;
1370
+#endif // endif
13361371
13371372 event = *event_p;
13381373 if (bi->ie_length) {
13391374 /* look for wpa/rsn ies in the ie list... */
13401375 bcm_tlv_t *ie;
13411376 uint8 *ptr = ((uint8 *)bi) + bi->ie_offset;
1342
- int ptr_len = bi->ie_length;
1377
+ uint ptr_len = bi->ie_length;
13431378
13441379 /* OSEN IE */
13451380 if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_VS_ID)) &&
....@@ -1387,6 +1422,38 @@
13871422 }
13881423 }
13891424
1425
+#ifdef BCMWAPI_WPI
1426
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
1427
+ ptr_len = bi->ie_length;
1428
+
1429
+ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WAPI_ID))) {
1430
+ WL_TRACE(("%s: found a WAPI IE...\n", __FUNCTION__));
1431
+#ifdef WAPI_IE_USE_GENIE
1432
+ iwe.cmd = IWEVGENIE;
1433
+ iwe.u.data.length = ie->len + 2;
1434
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
1435
+#else /* using CUSTOM event */
1436
+ iwe.cmd = IWEVCUSTOM;
1437
+ custom_event_len = strlen("wapi_ie=") + 2*(ie->len + 2);
1438
+ iwe.u.data.length = custom_event_len;
1439
+
1440
+ buf = kmalloc(custom_event_len+1, GFP_KERNEL);
1441
+ if (buf == NULL)
1442
+ {
1443
+ WL_ERROR(("malloc(%d) returned NULL...\n", custom_event_len));
1444
+ break;
1445
+ }
1446
+
1447
+ memcpy(buf, "wapi_ie=", 8);
1448
+ wpa_snprintf_hex(buf + 8, 2+1, &(ie->id), 1);
1449
+ wpa_snprintf_hex(buf + 10, 2+1, &(ie->len), 1);
1450
+ wpa_snprintf_hex(buf + 12, 2*ie->len+1, ie->data, ie->len);
1451
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, buf);
1452
+ kfree(buf);
1453
+#endif /* WAPI_IE_USE_GENIE */
1454
+ break;
1455
+ }
1456
+#endif /* BCMWAPI_WPI */
13901457 *event_p = event;
13911458 }
13921459
....@@ -1438,7 +1505,8 @@
14381505 ASSERT(list->version == WL_BSS_INFO_VERSION);
14391506
14401507 for (i = 0; i < list->count && i < IW_MAX_AP; i++) {
1441
- bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
1508
+ bi = (bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) :
1509
+ (wl_bss_info_t *)list->bss_info);
14421510 ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
14431511 buflen));
14441512
....@@ -1480,7 +1548,6 @@
14801548 iwe.u.qual.noise = 0x100 + bi->phy_noise;
14811549 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
14821550
1483
- /* WPA, WPA2, WPS, WAPI IEs */
14841551 wl_iw_handle_scanresults_ies(&event, end, info, bi);
14851552
14861553 /* Encryption */
....@@ -1604,7 +1671,6 @@
16041671 iwe.u.qual.noise = 0x100 + bi->phy_noise;
16051672 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
16061673
1607
- /* WPA, WPA2, WPS, WAPI IEs */
16081674 wl_iw_handle_scanresults_ies(&event, end, info, bi);
16091675
16101676 /* Encryption */
....@@ -1644,7 +1710,6 @@
16441710
16451711 #endif /* WIRELESS_EXT > 13 */
16461712
1647
-
16481713 static int
16491714 wl_iw_set_essid(
16501715 struct net_device *dev,
....@@ -1665,7 +1730,7 @@
16651730 ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length);
16661731 #else
16671732 ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length-1);
1668
-#endif
1733
+#endif // endif
16691734 memcpy(ssid.SSID, extra, ssid.SSID_len);
16701735 ssid.SSID_len = htod32(ssid.SSID_len);
16711736
....@@ -1705,8 +1770,16 @@
17051770
17061771 ssid.SSID_len = dtoh32(ssid.SSID_len);
17071772
1773
+ /* Max SSID length check */
1774
+ if (ssid.SSID_len > IW_ESSID_MAX_SIZE) {
1775
+ ssid.SSID_len = IW_ESSID_MAX_SIZE;
1776
+ }
1777
+
17081778 /* Get the current SSID */
17091779 memcpy(extra, ssid.SSID, ssid.SSID_len);
1780
+
1781
+ /* NULL terminating as length of extra buffer is IW_ESSID_MAX_SIZE ie 32 */
1782
+ extra[IW_ESSID_MAX_SIZE] = '\0';
17101783
17111784 dwrq->length = ssid.SSID_len;
17121785
....@@ -1974,7 +2047,6 @@
19742047 if (vwrq->value > 0xffff) txpwrmw = 0xffff;
19752048 else txpwrmw = (uint16)vwrq->value;
19762049
1977
-
19782050 error = dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw)));
19792051 return error;
19802052 }
....@@ -2161,7 +2233,7 @@
21612233 case TKIP_KEY_SIZE:
21622234 key.algo = CRYPTO_ALGO_TKIP;
21632235 break;
2164
-#endif
2236
+#endif // endif
21652237 case AES_KEY_SIZE:
21662238 key.algo = CRYPTO_ALGO_AES_CCM;
21672239 break;
....@@ -2299,6 +2371,21 @@
22992371 char *extra
23002372 )
23012373 {
2374
+#if defined(BCMWAPI_WPI)
2375
+ uchar buf[WLC_IOCTL_SMLEN] = {0};
2376
+ uchar *p = buf;
2377
+ int wapi_ie_size;
2378
+
2379
+ WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name));
2380
+
2381
+ if (extra[0] == DOT11_MNG_WAPI_ID)
2382
+ {
2383
+ wapi_ie_size = iwp->length;
2384
+ memcpy(p, extra, iwp->length);
2385
+ dev_wlc_bufvar_set(dev, "wapiie", buf, wapi_ie_size);
2386
+ }
2387
+ else
2388
+#endif // endif
23022389 dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
23032390
23042391 return 0;
....@@ -2441,6 +2528,14 @@
24412528 case IW_ENCODE_ALG_CCMP:
24422529 key.algo = CRYPTO_ALGO_AES_CCM;
24432530 break;
2531
+#ifdef BCMWAPI_WPI
2532
+ case IW_ENCODE_ALG_SM4:
2533
+ key.algo = CRYPTO_ALGO_SMS4;
2534
+ if (iwe->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
2535
+ key.flags &= ~WL_PRIMARY_KEY;
2536
+ }
2537
+ break;
2538
+#endif // endif
24442539 default:
24452540 break;
24462541 }
....@@ -2454,7 +2549,6 @@
24542549 }
24552550 return 0;
24562551 }
2457
-
24582552
24592553 #if WIRELESS_EXT > 17
24602554 struct {
....@@ -2590,6 +2684,10 @@
25902684 val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
25912685 else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
25922686 val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
2687
+#ifdef BCMWAPI_WPI
2688
+ else if (paramval & IW_AUTH_WAPI_VERSION_1)
2689
+ val = WAPI_AUTH_UNSPECIFIED;
2690
+#endif // endif
25932691 WL_TRACE(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
25942692 if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
25952693 return error;
....@@ -2617,6 +2715,11 @@
26172715 val |= TKIP_ENABLED;
26182716 if (cipher_combined & IW_AUTH_CIPHER_CCMP)
26192717 val |= AES_ENABLED;
2718
+#ifdef BCMWAPI_WPI
2719
+ val &= ~SMS4_ENABLED;
2720
+ if (cipher_combined & IW_AUTH_CIPHER_SMS4)
2721
+ val |= SMS4_ENABLED;
2722
+#endif // endif
26202723
26212724 if (iw->privacy_invoked && !val) {
26222725 WL_WSEC(("%s: %s: 'Privacy invoked' TRUE but clearing wsec, assuming "
....@@ -2673,6 +2776,10 @@
26732776 if (paramval & (IW_AUTH_KEY_MGMT_FT_802_1X | IW_AUTH_KEY_MGMT_FT_PSK))
26742777 val |= WPA2_AUTH_FT;
26752778 }
2779
+#ifdef BCMWAPI_WPI
2780
+ if (paramval & (IW_AUTH_KEY_MGMT_WAPI_PSK | IW_AUTH_KEY_MGMT_WAPI_CERT))
2781
+ val = WAPI_AUTH_UNSPECIFIED;
2782
+#endif // endif
26762783 WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
26772784 if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
26782785 return error;
....@@ -2752,9 +2859,31 @@
27522859 break;
27532860 }
27542861
2755
-
27562862 #endif /* WIRELESS_EXT > 17 */
27572863
2864
+#ifdef BCMWAPI_WPI
2865
+
2866
+ case IW_AUTH_WAPI_ENABLED:
2867
+ if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
2868
+ return error;
2869
+ if (paramval) {
2870
+ val |= SMS4_ENABLED;
2871
+ if ((error = dev_wlc_intvar_set(dev, "wsec", val))) {
2872
+ WL_ERROR(("%s: setting wsec to 0x%0x returned error %d\n",
2873
+ __FUNCTION__, val, error));
2874
+ return error;
2875
+ }
2876
+ if ((error = dev_wlc_intvar_set(dev, "wpa_auth", WAPI_AUTH_UNSPECIFIED))) {
2877
+ WL_ERROR(("%s: setting wpa_auth(%d) returned %d\n",
2878
+ __FUNCTION__, WAPI_AUTH_UNSPECIFIED,
2879
+ error));
2880
+ return error;
2881
+ }
2882
+ }
2883
+
2884
+ break;
2885
+
2886
+#endif /* BCMWAPI_WPI */
27582887
27592888 default:
27602889 break;
....@@ -2888,7 +3017,7 @@
28883017 (iw_handler) wl_iw_mlme, /* SIOCSIWMLME */
28893018 #else
28903019 (iw_handler) NULL, /* -- hole -- */
2891
-#endif
3020
+#endif // endif
28923021 (iw_handler) wl_iw_iscan_get_aplist, /* SIOCGIWAPLIST */
28933022 #if WIRELESS_EXT > 13
28943023 (iw_handler) wl_iw_iscan_set_scan, /* SIOCSIWSCAN */
....@@ -3022,7 +3151,7 @@
30223151 #if WIRELESS_EXT > 17
30233152 case SIOCSIWENCODEEXT:
30243153 case SIOCGIWENCODEEXT:
3025
-#endif
3154
+#endif // endif
30263155 max_tokens = IW_ENCODING_TOKEN_MAX;
30273156 break;
30283157
....@@ -3037,10 +3166,13 @@
30373166
30383167 #if WIRELESS_EXT > 13
30393168 case SIOCGIWSCAN:
3040
- if (g_iscan)
3169
+ if (g_iscan) {
30413170 max_tokens = wrq->u.data.length;
3171
+ }
30423172 else
3043
- max_tokens = IW_SCAN_MAX_DATA;
3173
+ {
3174
+ max_tokens = IW_SCAN_MAX_DATA;
3175
+ }
30443176 break;
30453177 #endif /* WIRELESS_EXT > 13 */
30463178
....@@ -3317,7 +3449,7 @@
33173449 case WLC_E_SCAN_COMPLETE:
33183450 #if WIRELESS_EXT > 14
33193451 cmd = SIOCGIWSCAN;
3320
-#endif
3452
+#endif // endif
33213453 WL_TRACE(("event WLC_E_SCAN_COMPLETE\n"));
33223454 if ((g_iscan) && (g_iscan->sysioc_pid >= 0) &&
33233455 (g_iscan->iscan_state != ISCAN_STATE_IDLE))
....@@ -3351,14 +3483,15 @@
33513483 #endif /* WIRELESS_EXT > 13 */
33523484 }
33533485
3354
-static int wl_iw_get_wireless_stats_cbfn(void *ctx, uint8 *data, uint16 type, uint16 len)
3486
+static int wl_iw_get_wireless_stats_cbfn(void *ctx, const uint8 *data,
3487
+ uint16 type, uint16 len)
33553488 {
33563489 struct iw_statistics *wstats = ctx;
33573490 int res = BCME_OK;
33583491
33593492 switch (type) {
33603493 case WL_CNT_XTLV_WLC: {
3361
- wl_cnt_wlc_t *cnt = (wl_cnt_wlc_t *)data;
3494
+ const wl_cnt_wlc_t *cnt = (const wl_cnt_wlc_t *)data;
33623495 if (len > sizeof(wl_cnt_wlc_t)) {
33633496 printf("counter structure length invalid! %d > %d\n",
33643497 len, (int)sizeof(wl_cnt_wlc_t));
....@@ -3391,7 +3524,7 @@
33913524 * wl_cnt_v_le10_mcst_t, wl_cnt_lt40mcst_v1_t, and wl_cnt_ge40mcst_v1_t.
33923525 * So we can just cast to wl_cnt_v_le10_mcst_t here.
33933526 */
3394
- wl_cnt_v_le10_mcst_t *cnt = (wl_cnt_v_le10_mcst_t *)data;
3527
+ const wl_cnt_v_le10_mcst_t *cnt = (const wl_cnt_v_le10_mcst_t *)data;
33953528 if (len != WL_CNT_MCST_STRUCT_SZ) {
33963529 printf("counter structure length mismatch! %d != %d\n",
33973530 len, WL_CNT_MCST_STRUCT_SZ);
....@@ -3459,24 +3592,16 @@
34593592 #endif /* WIRELESS_EXT > 18 */
34603593
34613594 #if WIRELESS_EXT > 11
3462
- WL_TRACE(("wl_iw_get_wireless_stats counters=%d\n *****", WL_CNTBUF_MAX_SIZE));
3595
+ WL_TRACE(("wl_iw_get_wireless_stats counters\n *****"));
34633596
3464
- if (WL_CNTBUF_MAX_SIZE > MAX_WLIW_IOCTL_LEN)
3465
- {
3466
- WL_ERROR(("wl_iw_get_wireless_stats buffer too short %d < %d\n",
3467
- WL_CNTBUF_MAX_SIZE, MAX_WLIW_IOCTL_LEN));
3468
- res = BCME_BUFTOOSHORT;
3469
- goto done;
3470
- }
3471
-
3472
- cntbuf = kmalloc(WL_CNTBUF_MAX_SIZE, GFP_KERNEL);
3597
+ cntbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL);
34733598 if (!cntbuf) {
34743599 res = BCME_NOMEM;
34753600 goto done;
34763601 }
34773602
3478
- memset(cntbuf, 0, WL_CNTBUF_MAX_SIZE);
3479
- res = dev_wlc_bufvar_get(dev, "counters", cntbuf, WL_CNTBUF_MAX_SIZE);
3603
+ memset(cntbuf, 0, MAX_WLIW_IOCTL_LEN);
3604
+ res = dev_wlc_bufvar_get(dev, "counters", cntbuf, MAX_WLIW_IOCTL_LEN);
34803605 if (res)
34813606 {
34823607 WL_ERROR(("wl_iw_get_wireless_stats counters failed error=%d ****** \n", res));
....@@ -3487,6 +3612,7 @@
34873612 cntinfo->version = dtoh16(cntinfo->version);
34883613 cntinfo->datalen = dtoh16(cntinfo->datalen);
34893614 ver = cntinfo->version;
3615
+ CHK_CNTBUF_DATALEN(cntbuf, MAX_WLIW_IOCTL_LEN);
34903616 if (ver > WL_CNT_T_VERSION) {
34913617 WL_TRACE(("\tIncorrect version of counters struct: expected %d; got %d\n",
34923618 WL_CNT_T_VERSION, ver));
....@@ -3505,7 +3631,7 @@
35053631 corerev = dtoh32(revinfo.corerev);
35063632 }
35073633
3508
- res = wl_cntbuf_to_xtlv_format(NULL, cntinfo, WL_CNTBUF_MAX_SIZE, corerev);
3634
+ res = wl_cntbuf_to_xtlv_format(NULL, cntinfo, MAX_WLIW_IOCTL_LEN, corerev);
35093635 if (res) {
35103636 WL_ERROR(("%s: wl_cntbuf_to_xtlv_format failed %d\n", __FUNCTION__, res));
35113637 goto done;
....@@ -3691,25 +3817,30 @@
36913817
36923818 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
36933819 rtnl_lock();
3694
-#endif
3820
+#endif // endif
36953821 status = wl_iw_iscan_get(iscan);
36963822 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
36973823 rtnl_unlock();
3698
-#endif
3824
+#endif // endif
36993825
37003826 switch (status) {
37013827 case WL_SCAN_RESULTS_PARTIAL:
37023828 WL_TRACE(("iscanresults incomplete\n"));
37033829 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
37043830 rtnl_lock();
3705
-#endif
3831
+#endif // endif
37063832 /* make sure our buffer size is enough before going next round */
37073833 wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
37083834 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
37093835 rtnl_unlock();
3710
-#endif
3836
+#endif // endif
37113837 /* Reschedule the timer */
3838
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
37123839 iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms);
3840
+#else
3841
+ iscan->timer.timer.expires = jiffies +
3842
+ msecs_to_jiffies(iscan->timer_ms);
3843
+#endif // endif
37133844 add_timer(&iscan->timer);
37143845 iscan->timer_on = 1;
37153846 break;
....@@ -3721,7 +3852,12 @@
37213852 case WL_SCAN_RESULTS_PENDING:
37223853 WL_TRACE(("iscanresults pending\n"));
37233854 /* Reschedule the timer */
3855
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
37243856 iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms);
3857
+#else
3858
+ iscan->timer.timer.expires = jiffies +
3859
+ msecs_to_jiffies(iscan->timer_ms);
3860
+#endif // endif
37253861 add_timer(&iscan->timer);
37263862 iscan->timer_on = 1;
37273863 break;
....@@ -3752,20 +3888,22 @@
37523888 memset(iscan, 0, sizeof(iscan_info_t));
37533889 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
37543890 iscan->kthread = NULL;
3755
-#endif
3891
+#endif // endif
37563892 iscan->sysioc_pid = -1;
37573893 /* we only care about main interface so save a global here */
37583894 g_iscan = iscan;
37593895 iscan->dev = dev;
37603896 iscan->iscan_state = ISCAN_STATE_IDLE;
37613897
3762
-
37633898 /* Set up the timer */
37643899 iscan->timer_ms = 2000;
3900
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0))
37653901 init_timer(&iscan->timer);
37663902 iscan->timer.data = (ulong)iscan;
37673903 iscan->timer.function = wl_iw_timerfunc;
3768
-
3904
+#else
3905
+ init_timer_compat(&iscan->timer, wl_iw_timerfunc, iscan);
3906
+#endif // endif
37693907 sema_init(&iscan->sysioc_sem, 0);
37703908 init_completion(&iscan->sysioc_exited);
37713909 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
....@@ -3773,7 +3911,7 @@
37733911 iscan->sysioc_pid = iscan->kthread->pid;
37743912 #else
37753913 iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0);
3776
-#endif
3914
+#endif // endif
37773915 if (iscan->sysioc_pid < 0)
37783916 return -ENOMEM;
37793917 return 0;
....@@ -3785,6 +3923,11 @@
37853923 iscan_info_t *iscan = g_iscan;
37863924 if (!iscan)
37873925 return;
3926
+ /* Delete iscan timer */
3927
+ if (iscan->timer_on) {
3928
+ del_timer_sync(&iscan->timer);
3929
+ iscan->timer_on = 0;
3930
+ }
37883931 if (iscan->sysioc_pid >= 0) {
37893932 KILL_PROC(iscan->sysioc_pid, SIGTERM);
37903933 wait_for_completion(&iscan->sysioc_exited);