blob: f925170aa63046da3db2ab2942e051c031c09381 [file] [log] [blame]
Larry Fingerb1925ad2014-03-28 21:37:40 -05001/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _IOCTL_CFG80211_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
Larry Fingerb1925ad2014-03-28 21:37:40 -050019#include <xmit_osdep.h>
20
21#include "ioctl_cfg80211.h"
Larry Fingerb1925ad2014-03-28 21:37:40 -050022
23#define RTW_MAX_MGMT_TX_CNT 8
24
25#define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 65535 /* ms */
26#define RTW_MAX_NUM_PMKIDS 4
27
Larry Fingerb1925ad2014-03-28 21:37:40 -050028static const u32 rtw_cipher_suites[] = {
29 WLAN_CIPHER_SUITE_WEP40,
30 WLAN_CIPHER_SUITE_WEP104,
31 WLAN_CIPHER_SUITE_TKIP,
32 WLAN_CIPHER_SUITE_CCMP,
33};
34
35#define RATETAB_ENT(_rate, _rateid, _flags) { \
36 .bitrate = (_rate), \
37 .hw_value = (_rateid), \
38 .flags = (_flags), \
39}
40
41#define CHAN2G(_channel, _freq, _flags) { \
42 .band = IEEE80211_BAND_2GHZ, \
43 .center_freq = (_freq), \
44 .hw_value = (_channel), \
45 .flags = (_flags), \
46 .max_antenna_gain = 0, \
47 .max_power = 30, \
48}
49
50#define CHAN5G(_channel, _flags) { \
51 .band = IEEE80211_BAND_5GHZ, \
52 .center_freq = 5000 + (5 * (_channel)), \
53 .hw_value = (_channel), \
54 .flags = (_flags), \
55 .max_antenna_gain = 0, \
56 .max_power = 30, \
57}
58
59static struct ieee80211_rate rtw_rates[] = {
60 RATETAB_ENT(10, 0x1, 0),
61 RATETAB_ENT(20, 0x2, 0),
62 RATETAB_ENT(55, 0x4, 0),
63 RATETAB_ENT(110, 0x8, 0),
64 RATETAB_ENT(60, 0x10, 0),
65 RATETAB_ENT(90, 0x20, 0),
66 RATETAB_ENT(120, 0x40, 0),
67 RATETAB_ENT(180, 0x80, 0),
68 RATETAB_ENT(240, 0x100, 0),
69 RATETAB_ENT(360, 0x200, 0),
70 RATETAB_ENT(480, 0x400, 0),
71 RATETAB_ENT(540, 0x800, 0),
72};
73
74#define rtw_a_rates (rtw_rates + 4)
75#define RTW_A_RATES_NUM 8
76#define rtw_g_rates (rtw_rates + 0)
77#define RTW_G_RATES_NUM 12
78
79#define RTW_2G_CHANNELS_NUM 14
80#define RTW_5G_CHANNELS_NUM 37
81
82static struct ieee80211_channel rtw_2ghz_channels[] = {
83 CHAN2G(1, 2412, 0),
84 CHAN2G(2, 2417, 0),
85 CHAN2G(3, 2422, 0),
86 CHAN2G(4, 2427, 0),
87 CHAN2G(5, 2432, 0),
88 CHAN2G(6, 2437, 0),
89 CHAN2G(7, 2442, 0),
90 CHAN2G(8, 2447, 0),
91 CHAN2G(9, 2452, 0),
92 CHAN2G(10, 2457, 0),
93 CHAN2G(11, 2462, 0),
94 CHAN2G(12, 2467, 0),
95 CHAN2G(13, 2472, 0),
96 CHAN2G(14, 2484, 0),
97};
98
99static struct ieee80211_channel rtw_5ghz_a_channels[] = {
100 CHAN5G(34, 0), CHAN5G(36, 0),
101 CHAN5G(38, 0), CHAN5G(40, 0),
102 CHAN5G(42, 0), CHAN5G(44, 0),
103 CHAN5G(46, 0), CHAN5G(48, 0),
104 CHAN5G(52, 0), CHAN5G(56, 0),
105 CHAN5G(60, 0), CHAN5G(64, 0),
106 CHAN5G(100, 0), CHAN5G(104, 0),
107 CHAN5G(108, 0), CHAN5G(112, 0),
108 CHAN5G(116, 0), CHAN5G(120, 0),
109 CHAN5G(124, 0), CHAN5G(128, 0),
110 CHAN5G(132, 0), CHAN5G(136, 0),
111 CHAN5G(140, 0), CHAN5G(149, 0),
112 CHAN5G(153, 0), CHAN5G(157, 0),
113 CHAN5G(161, 0), CHAN5G(165, 0),
114 CHAN5G(184, 0), CHAN5G(188, 0),
115 CHAN5G(192, 0), CHAN5G(196, 0),
116 CHAN5G(200, 0), CHAN5G(204, 0),
117 CHAN5G(208, 0), CHAN5G(212, 0),
118 CHAN5G(216, 0),
119};
120
121static void rtw_2g_channels_init(struct ieee80211_channel *channels)
122{
123 memcpy((void *)channels, (void *)rtw_2ghz_channels,
124 sizeof(struct ieee80211_channel) * RTW_2G_CHANNELS_NUM);
125}
126
127static void rtw_5g_channels_init(struct ieee80211_channel *channels)
128{
129 memcpy((void *)channels, (void *)rtw_5ghz_a_channels,
130 sizeof(struct ieee80211_channel) * RTW_5G_CHANNELS_NUM);
131}
132
133static void rtw_2g_rates_init(struct ieee80211_rate *rates)
134{
135 memcpy(rates, rtw_g_rates,
136 sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM);
137}
138
139static void rtw_5g_rates_init(struct ieee80211_rate *rates)
140{
141 memcpy(rates, rtw_a_rates,
142 sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM);
143}
144
145static struct ieee80211_supported_band *
146rtw_spt_band_alloc(enum ieee80211_band band)
147{
148 struct ieee80211_supported_band *spt_band = NULL;
149 int n_channels, n_bitrates;
150
151 if (band == IEEE80211_BAND_2GHZ) {
152 n_channels = RTW_2G_CHANNELS_NUM;
153 n_bitrates = RTW_G_RATES_NUM;
154 } else if (band == IEEE80211_BAND_5GHZ) {
155 n_channels = RTW_5G_CHANNELS_NUM;
156 n_bitrates = RTW_A_RATES_NUM;
157 } else {
158 goto exit;
159 }
160 spt_band = kzalloc(sizeof(struct ieee80211_supported_band) +
161 sizeof(struct ieee80211_channel) * n_channels +
162 sizeof(struct ieee80211_rate) * n_bitrates,
163 GFP_KERNEL);
164 if (!spt_band)
165 goto exit;
166
167 spt_band->channels =
168 (struct ieee80211_channel *)(((u8 *) spt_band) +
169 sizeof(struct
170 ieee80211_supported_band));
171 spt_band->bitrates =
172 (struct ieee80211_rate *)(((u8 *) spt_band->channels) +
173 sizeof(struct ieee80211_channel) *
174 n_channels);
175 spt_band->band = band;
176 spt_band->n_channels = n_channels;
177 spt_band->n_bitrates = n_bitrates;
178
179 if (band == IEEE80211_BAND_2GHZ) {
180 rtw_2g_channels_init(spt_band->channels);
181 rtw_2g_rates_init(spt_band->bitrates);
182 } else if (band == IEEE80211_BAND_5GHZ) {
183 rtw_5g_channels_init(spt_band->channels);
184 rtw_5g_rates_init(spt_band->bitrates);
185 }
186
187 /* spt_band.ht_cap */
188
189exit:
190 return spt_band;
191}
192
193static const struct ieee80211_txrx_stypes
194rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
195 [NL80211_IFTYPE_ADHOC] = {
196 .tx = 0xffff,
197 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
198 },
199 [NL80211_IFTYPE_STATION] = {
200 .tx = 0xffff,
201 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
202 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
203 },
204 [NL80211_IFTYPE_AP] = {
205 .tx = 0xffff,
206 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
207 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
208 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
209 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
210 BIT(IEEE80211_STYPE_AUTH >> 4) |
211 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
212 BIT(IEEE80211_STYPE_ACTION >> 4)
213 },
214 [NL80211_IFTYPE_AP_VLAN] = {
215 /* copy AP */
216 .tx = 0xffff,
217 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
218 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
219 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
220 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
221 BIT(IEEE80211_STYPE_AUTH >> 4) |
222 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
223 BIT(IEEE80211_STYPE_ACTION >> 4)
224 },
225 [NL80211_IFTYPE_P2P_CLIENT] = {
226 .tx = 0xffff,
227 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
228 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
229 },
230 [NL80211_IFTYPE_P2P_GO] = {
231 .tx = 0xffff,
232 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
233 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
234 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
235 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
236 BIT(IEEE80211_STYPE_AUTH >> 4) |
237 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
238 BIT(IEEE80211_STYPE_ACTION >> 4)
239 },
240};
241
Larry Fingerb1925ad2014-03-28 21:37:40 -0500242static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter,
243 struct wlan_network *pnetwork)
244{
245 int ret = 0;
246 struct ieee80211_channel *notify_channel;
247 struct cfg80211_bss *bss;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500248 u16 channel;
249 u32 freq;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500250 u8 *notify_ie;
251 size_t notify_ielen;
252 s32 notify_signal;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500253 struct wireless_dev *wdev = padapter->rtw_wdev;
254 struct wiphy *wiphy = wdev->wiphy;
255 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
256
Jes Sorensen37cb9822014-05-21 09:37:40 +0200257 channel = pnetwork->network.DSConfig;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500258 if (channel <= RTW_CH_MAX_2G_CHANNEL)
259 freq = ieee80211_channel_to_frequency(channel,
260 IEEE80211_BAND_2GHZ);
261 else
262 freq = ieee80211_channel_to_frequency(channel,
263 IEEE80211_BAND_5GHZ);
264
265 notify_channel = ieee80211_get_channel(wiphy, freq);
266
Jes Sorensen1de65cc2014-06-24 15:03:30 +0200267 notify_ie = pnetwork->network.IEs;
268 notify_ielen = pnetwork->network.IELength;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500269
270 /* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM:
271 * signal strength in mBm (100*dBm)
272 */
273 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
274 is_same_network23a(&pmlmepriv->cur_network.network,
275 &pnetwork->network)) {
276 notify_signal = 100 * translate_percentage_to_dbm(padapter->recvpriv.signal_strength); /* dbm */
277 } else {
Jes Sorensen60b152c2014-10-10 21:41:36 +0200278 notify_signal = 100 * translate_percentage_to_dbm(
279 pnetwork->network.SignalStrength); /* dbm */
Larry Fingerb1925ad2014-03-28 21:37:40 -0500280 }
Larry Fingerb1925ad2014-03-28 21:37:40 -0500281
Jes Sorensen4062f7a2014-06-19 11:37:17 +0200282 bss = cfg80211_inform_bss(wiphy, notify_channel,
Johannes Berg5bc8c1f2014-08-12 21:01:28 +0200283 CFG80211_BSS_FTYPE_UNKNOWN,
Jes Sorensen993c52b2014-06-19 11:37:18 +0200284 pnetwork->network.MacAddress,
285 pnetwork->network.tsf,
Jes Sorensen11a80e82014-06-19 11:37:21 +0200286 pnetwork->network.capability,
Jes Sorensen143ced22014-06-19 11:37:22 +0200287 pnetwork->network.beacon_interval,
Jes Sorensen4062f7a2014-06-19 11:37:17 +0200288 notify_ie, notify_ielen,
289 notify_signal, GFP_ATOMIC);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500290
291 if (unlikely(!bss)) {
292 DBG_8723A("rtw_cfg80211_inform_bss error\n");
293 return -EINVAL;
294 }
295
296 cfg80211_put_bss(wiphy, bss);
297
Larry Fingerb1925ad2014-03-28 21:37:40 -0500298 return ret;
299}
300
301void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter)
302{
303 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
304 struct wlan_network *cur_network = &pmlmepriv->cur_network;
305 struct wireless_dev *pwdev = padapter->rtw_wdev;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500306
307 DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
308
309 if (pwdev->iftype != NL80211_IFTYPE_STATION &&
310 pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
311 return;
312
313 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
314 return;
315
Jes Sorensen56828792014-04-15 19:44:46 +0200316 if (padapter->mlmepriv.to_roaming > 0) {
Larry Fingerb1925ad2014-03-28 21:37:40 -0500317 struct wiphy *wiphy = pwdev->wiphy;
318 struct ieee80211_channel *notify_channel;
319 u32 freq;
Jes Sorensen37cb9822014-05-21 09:37:40 +0200320 u16 channel = cur_network->network.DSConfig;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500321
322 if (channel <= RTW_CH_MAX_2G_CHANNEL)
323 freq =
324 ieee80211_channel_to_frequency(channel,
325 IEEE80211_BAND_2GHZ);
326 else
327 freq =
328 ieee80211_channel_to_frequency(channel,
329 IEEE80211_BAND_5GHZ);
330
331 notify_channel = ieee80211_get_channel(wiphy, freq);
332
333 DBG_8723A("%s call cfg80211_roamed\n", __func__);
334 cfg80211_roamed(padapter->pnetdev, notify_channel,
335 cur_network->network.MacAddress,
336 pmlmepriv->assoc_req +
337 sizeof(struct ieee80211_hdr_3addr) + 2,
338 pmlmepriv->assoc_req_len -
339 sizeof(struct ieee80211_hdr_3addr) - 2,
340 pmlmepriv->assoc_rsp +
341 sizeof(struct ieee80211_hdr_3addr) + 6,
342 pmlmepriv->assoc_rsp_len -
343 sizeof(struct ieee80211_hdr_3addr) - 6,
344 GFP_ATOMIC);
345 } else {
346 cfg80211_connect_result(padapter->pnetdev,
347 cur_network->network.MacAddress,
348 pmlmepriv->assoc_req +
349 sizeof(struct ieee80211_hdr_3addr) + 2,
350 pmlmepriv->assoc_req_len -
351 sizeof(struct ieee80211_hdr_3addr) - 2,
352 pmlmepriv->assoc_rsp +
353 sizeof(struct ieee80211_hdr_3addr) + 6,
354 pmlmepriv->assoc_rsp_len -
355 sizeof(struct ieee80211_hdr_3addr) - 6,
356 WLAN_STATUS_SUCCESS, GFP_ATOMIC);
357 }
358}
359
360void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter)
361{
362 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
363 struct wireless_dev *pwdev = padapter->rtw_wdev;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500364
365 DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
366
367 if (pwdev->iftype != NL80211_IFTYPE_STATION &&
368 pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
369 return;
370
371 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
372 return;
373
Larry Fingerb1925ad2014-03-28 21:37:40 -0500374 if (!padapter->mlmepriv.not_indic_disco) {
375 if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING)) {
376 cfg80211_connect_result(padapter->pnetdev, NULL, NULL,
377 0, NULL, 0,
378 WLAN_STATUS_UNSPECIFIED_FAILURE,
379 GFP_ATOMIC);
380 } else {
381 cfg80211_disconnected(padapter->pnetdev, 0, NULL,
382 0, GFP_ATOMIC);
383 }
384 }
385}
386
387#ifdef CONFIG_8723AU_AP_MODE
Jes Sorensen16b96322014-05-16 10:04:41 +0200388static int set_pairwise_key(struct rtw_adapter *padapter, struct sta_info *psta)
Larry Fingerb1925ad2014-03-28 21:37:40 -0500389{
390 struct cmd_obj *ph2c;
391 struct set_stakey_parm *psetstakey_para;
392 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
Jes Sorensen16b96322014-05-16 10:04:41 +0200393 int res = _SUCCESS;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500394
395 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
396 if (ph2c == NULL) {
397 res = _FAIL;
398 goto exit;
399 }
400
401 psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
402 if (psetstakey_para == NULL) {
403 kfree(ph2c);
404 res = _FAIL;
405 goto exit;
406 }
407
408 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
409
Jes Sorensen7989bcf2014-05-21 09:37:31 +0200410 psetstakey_para->algorithm = psta->dot118021XPrivacy;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500411
Jes Sorensen888df442014-05-25 22:43:11 +0200412 ether_addr_copy(psetstakey_para->addr, psta->hwaddr);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500413
414 memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
415
416 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
417
418exit:
419 return res;
420}
421
Jes Sorensen2dcf6b42014-06-24 15:03:54 +0200422static int set_group_key(struct rtw_adapter *padapter, struct key_params *parms,
423 u32 alg, u8 keyid)
Larry Fingerb1925ad2014-03-28 21:37:40 -0500424{
Larry Fingerb1925ad2014-03-28 21:37:40 -0500425 struct cmd_obj *pcmd;
426 struct setkey_parm *psetkeyparm;
427 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
428 int res = _SUCCESS;
429
430 DBG_8723A("%s\n", __func__);
431
Jes Sorensen4e489d92014-05-09 15:04:16 +0200432 if (keyid >= 4) {
433 res = _FAIL;
434 goto exit;
435 }
436
Larry Fingerb1925ad2014-03-28 21:37:40 -0500437 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
438 if (!pcmd) {
439 res = _FAIL;
440 goto exit;
441 }
442 psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
443 if (!psetkeyparm) {
444 kfree(pcmd);
445 res = _FAIL;
446 goto exit;
447 }
448
Jes Sorensen4e489d92014-05-09 15:04:16 +0200449 psetkeyparm->keyid = keyid;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500450 if (is_wep_enc(alg))
Jes Sorensen4e489d92014-05-09 15:04:16 +0200451 padapter->mlmepriv.key_mask |= BIT(psetkeyparm->keyid);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500452
453 psetkeyparm->algorithm = alg;
454
455 psetkeyparm->set_tx = 1;
456
Jes Sorensen2dcf6b42014-06-24 15:03:54 +0200457 memcpy(&psetkeyparm->key, parms->key, parms->key_len);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500458
459 pcmd->cmdcode = _SetKey_CMD_;
460 pcmd->parmbuf = (u8 *) psetkeyparm;
461 pcmd->cmdsz = (sizeof(struct setkey_parm));
462 pcmd->rsp = NULL;
463 pcmd->rspsz = 0;
464
Larry Fingerb1925ad2014-03-28 21:37:40 -0500465 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
466
467exit:
468 return res;
469}
470
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200471static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, u8 key_index,
Jes Sorensenf88ab542014-06-24 15:03:50 +0200472 int set_tx, const u8 *sta_addr,
Jes Sorensen5dab9e72014-06-24 15:03:35 +0200473 struct key_params *keyparms)
Larry Fingerb1925ad2014-03-28 21:37:40 -0500474{
Jes Sorensenc36e1222014-06-24 15:03:37 +0200475 int key_len;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500476 struct sta_info *psta = NULL, *pbcmc_sta = NULL;
477 struct rtw_adapter *padapter = netdev_priv(dev);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500478 struct security_priv *psecuritypriv = &padapter->securitypriv;
479 struct sta_priv *pstapriv = &padapter->stapriv;
480
481 DBG_8723A("%s\n", __func__);
482
Jes Sorensen7ef27432014-06-24 15:03:53 +0200483 if (!is_broadcast_ether_addr(sta_addr)) {
Jes Sorensenf88ab542014-06-24 15:03:50 +0200484 psta = rtw_get_stainfo23a(pstapriv, sta_addr);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500485 if (!psta) {
486 /* ret = -EINVAL; */
487 DBG_8723A("rtw_set_encryption(), sta has already "
488 "been removed or never been added\n");
489 goto exit;
490 }
491 }
492
Jes Sorensenc36e1222014-06-24 15:03:37 +0200493 key_len = keyparms->key_len;
494
Jes Sorensen5dab9e72014-06-24 15:03:35 +0200495 if (!psta && (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
496 keyparms->cipher == WLAN_CIPHER_SUITE_WEP104)) {
Larry Fingerb1925ad2014-03-28 21:37:40 -0500497 DBG_8723A("r871x_set_encryption, crypt.alg = WEP\n");
498
Larry Fingerb1925ad2014-03-28 21:37:40 -0500499 DBG_8723A("r871x_set_encryption, wep_key_idx =%d, len =%d\n",
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200500 key_index, key_len);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500501
Larry Fingerb1925ad2014-03-28 21:37:40 -0500502 if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
503 /* wep default key has not been set, so use
504 this key index as default key. */
505
506 psecuritypriv->ndisencryptstatus =
507 Ndis802_11Encryption1Enabled;
Jes Sorensen55db5d02014-06-24 15:03:39 +0200508 psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher;
509 psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500510
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200511 psecuritypriv->dot11PrivacyKeyIndex = key_index;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500512 }
513
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200514 memcpy(&psecuritypriv->wep_key[key_index].key,
Jes Sorensenc36e1222014-06-24 15:03:37 +0200515 keyparms->key, key_len);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500516
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200517 psecuritypriv->wep_key[key_index].keylen = key_len;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500518
Jes Sorensen2dcf6b42014-06-24 15:03:54 +0200519 set_group_key(padapter, keyparms, keyparms->cipher, key_index);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500520
521 goto exit;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500522 }
523
Jes Sorensen4e297c22014-06-24 15:03:36 +0200524 if (!psta) { /* group key */
Jes Sorensen0996cf92014-06-24 15:03:47 +0200525 if (set_tx == 0) { /* group key */
Jes Sorensen5dab9e72014-06-24 15:03:35 +0200526 if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
527 keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
Jes Sorensen9cd613c2014-05-09 15:04:03 +0200528 DBG_8723A("%s, set group_key, WEP\n", __func__);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500529
530 memcpy(psecuritypriv->
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200531 dot118021XGrpKey[key_index].skey,
Jes Sorensen7ef27432014-06-24 15:03:53 +0200532 keyparms->key, key_len);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500533
Jes Sorensen55db5d02014-06-24 15:03:39 +0200534 psecuritypriv->dot118021XGrpPrivacy =
535 keyparms->cipher;
Jes Sorensen5dab9e72014-06-24 15:03:35 +0200536 } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) {
Larry Fingerb1925ad2014-03-28 21:37:40 -0500537 DBG_8723A("%s, set group_key, TKIP\n",
538 __func__);
539
Jes Sorensen4e297c22014-06-24 15:03:36 +0200540 psecuritypriv->dot118021XGrpPrivacy =
541 WLAN_CIPHER_SUITE_TKIP;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500542
543 memcpy(psecuritypriv->
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200544 dot118021XGrpKey[key_index].skey,
Jes Sorensenfd381872014-06-24 15:03:46 +0200545 keyparms->key,
Jes Sorensenc36e1222014-06-24 15:03:37 +0200546 (key_len > 16 ? 16 : key_len));
Larry Fingerb1925ad2014-03-28 21:37:40 -0500547
Larry Fingerb1925ad2014-03-28 21:37:40 -0500548 /* set mic key */
549 memcpy(psecuritypriv->
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200550 dot118021XGrptxmickey[key_index].skey,
Jes Sorensenfd381872014-06-24 15:03:46 +0200551 &keyparms->key[16], 8);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500552 memcpy(psecuritypriv->
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200553 dot118021XGrprxmickey[key_index].skey,
Jes Sorensenfd381872014-06-24 15:03:46 +0200554 &keyparms->key[24], 8);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500555
Jes Sorensen9216c512014-05-21 09:37:29 +0200556 psecuritypriv->busetkipkey = 1;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500557
Jes Sorensen5dab9e72014-06-24 15:03:35 +0200558 } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) {
559 DBG_8723A("%s, set group_key, CCMP\n",
Larry Fingerb1925ad2014-03-28 21:37:40 -0500560 __func__);
561
Jes Sorensen4e297c22014-06-24 15:03:36 +0200562 psecuritypriv->dot118021XGrpPrivacy =
563 WLAN_CIPHER_SUITE_CCMP;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500564
565 memcpy(psecuritypriv->
Jes Sorensenfd381872014-06-24 15:03:46 +0200566 dot118021XGrpKey[key_index].skey,
567 keyparms->key,
Jes Sorensenc36e1222014-06-24 15:03:37 +0200568 (key_len > 16 ? 16 : key_len));
Larry Fingerb1925ad2014-03-28 21:37:40 -0500569 } else {
570 DBG_8723A("%s, set group_key, none\n",
571 __func__);
572
Jes Sorensen7ef27432014-06-24 15:03:53 +0200573 psecuritypriv->dot118021XGrpPrivacy = 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500574 }
575
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200576 psecuritypriv->dot118021XGrpKeyid = key_index;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500577
Jes Sorensen9216c512014-05-21 09:37:29 +0200578 psecuritypriv->binstallGrpkey = 1;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500579
580 psecuritypriv->dot11PrivacyAlgrthm =
581 psecuritypriv->dot118021XGrpPrivacy;
582
Jes Sorensen2dcf6b42014-06-24 15:03:54 +0200583 set_group_key(padapter, keyparms,
Larry Fingerb1925ad2014-03-28 21:37:40 -0500584 psecuritypriv->dot118021XGrpPrivacy,
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200585 key_index);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500586
587 pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
588 if (pbcmc_sta) {
589 pbcmc_sta->ieee8021x_blocked = false;
590 /* rx will use bmc_sta's dot118021XPrivacy */
591 pbcmc_sta->dot118021XPrivacy =
592 psecuritypriv->dot118021XGrpPrivacy;
593
594 }
595
596 }
597
598 goto exit;
599 }
600
Jes Sorensen4e297c22014-06-24 15:03:36 +0200601 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) {
602 /* psk/802_1x */
Jes Sorensen0996cf92014-06-24 15:03:47 +0200603 if (set_tx == 1) {
Jes Sorensen4e297c22014-06-24 15:03:36 +0200604 /* pairwise key */
605 memcpy(psta->dot118021x_UncstKey.skey,
Jes Sorensenfd381872014-06-24 15:03:46 +0200606 keyparms->key, (key_len > 16 ? 16 : key_len));
Jes Sorensen4e297c22014-06-24 15:03:36 +0200607
608 if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
609 keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
610 DBG_8723A("%s, set pairwise key, WEP\n",
611 __func__);
612
Jes Sorensen55db5d02014-06-24 15:03:39 +0200613 psecuritypriv->dot118021XGrpPrivacy =
614 keyparms->cipher;
Jes Sorensen4e297c22014-06-24 15:03:36 +0200615 } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) {
616 DBG_8723A("%s, set pairwise key, TKIP\n",
617 __func__);
618
619 psta->dot118021XPrivacy =
620 WLAN_CIPHER_SUITE_TKIP;
621
Jes Sorensen4e297c22014-06-24 15:03:36 +0200622 /* set mic key */
623 memcpy(psta->dot11tkiptxmickey.skey,
Jes Sorensenfd381872014-06-24 15:03:46 +0200624 &keyparms->key[16], 8);
Jes Sorensen4e297c22014-06-24 15:03:36 +0200625 memcpy(psta->dot11tkiprxmickey.skey,
Jes Sorensenfd381872014-06-24 15:03:46 +0200626 &keyparms->key[24], 8);
Jes Sorensen4e297c22014-06-24 15:03:36 +0200627
628 psecuritypriv->busetkipkey = 1;
629
630 } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) {
631 DBG_8723A("%s, set pairwise key, CCMP\n",
632 __func__);
633
634 psta->dot118021XPrivacy =
635 WLAN_CIPHER_SUITE_CCMP;
636 } else {
637 DBG_8723A("%s, set pairwise key, none\n",
638 __func__);
639
640 psta->dot118021XPrivacy = 0;
641 }
642
643 set_pairwise_key(padapter, psta);
644
645 psta->ieee8021x_blocked = false;
646
647 psta->bpairwise_key_installed = true;
648 } else { /* group key??? */
649 if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
650 keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
651 memcpy(psecuritypriv->
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200652 dot118021XGrpKey[key_index].skey,
Jes Sorensen7ef27432014-06-24 15:03:53 +0200653 keyparms->key, key_len);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500654
Jes Sorensen4e297c22014-06-24 15:03:36 +0200655 psecuritypriv->dot118021XGrpPrivacy =
Jes Sorensen55db5d02014-06-24 15:03:39 +0200656 keyparms->cipher;
Jes Sorensen4e297c22014-06-24 15:03:36 +0200657 } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) {
658 psecuritypriv->dot118021XGrpPrivacy =
659 WLAN_CIPHER_SUITE_TKIP;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500660
Jes Sorensen4e297c22014-06-24 15:03:36 +0200661 memcpy(psecuritypriv->
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200662 dot118021XGrpKey[key_index].skey,
Jes Sorensenfd381872014-06-24 15:03:46 +0200663 keyparms->key,
Jes Sorensenc36e1222014-06-24 15:03:37 +0200664 (key_len > 16 ? 16 : key_len));
Larry Fingerb1925ad2014-03-28 21:37:40 -0500665
Jes Sorensen4e297c22014-06-24 15:03:36 +0200666 /* set mic key */
667 memcpy(psecuritypriv->
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200668 dot118021XGrptxmickey[key_index].skey,
Jes Sorensenfd381872014-06-24 15:03:46 +0200669 &keyparms->key[16], 8);
Jes Sorensen4e297c22014-06-24 15:03:36 +0200670 memcpy(psecuritypriv->
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200671 dot118021XGrprxmickey[key_index].skey,
Jes Sorensenfd381872014-06-24 15:03:46 +0200672 &keyparms->key[24], 8);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500673
Jes Sorensen4e297c22014-06-24 15:03:36 +0200674 psecuritypriv->busetkipkey = 1;
Jes Sorensen4e297c22014-06-24 15:03:36 +0200675 } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) {
676 psecuritypriv->dot118021XGrpPrivacy =
677 WLAN_CIPHER_SUITE_CCMP;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500678
Jes Sorensen4e297c22014-06-24 15:03:36 +0200679 memcpy(psecuritypriv->
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200680 dot118021XGrpKey[key_index].skey,
Jes Sorensenfd381872014-06-24 15:03:46 +0200681 keyparms->key,
Jes Sorensenc36e1222014-06-24 15:03:37 +0200682 (key_len > 16 ? 16 : key_len));
Jes Sorensen4e297c22014-06-24 15:03:36 +0200683 } else {
684 psecuritypriv->dot118021XGrpPrivacy = 0;
685 }
Larry Fingerb1925ad2014-03-28 21:37:40 -0500686
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200687 psecuritypriv->dot118021XGrpKeyid = key_index;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500688
Jes Sorensen4e297c22014-06-24 15:03:36 +0200689 psecuritypriv->binstallGrpkey = 1;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500690
Jes Sorensen4e297c22014-06-24 15:03:36 +0200691 psecuritypriv->dot11PrivacyAlgrthm =
692 psecuritypriv->dot118021XGrpPrivacy;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500693
Jes Sorensen2dcf6b42014-06-24 15:03:54 +0200694 set_group_key(padapter, keyparms,
Jes Sorensen4e297c22014-06-24 15:03:36 +0200695 psecuritypriv->dot118021XGrpPrivacy,
Jes Sorensenf7ce87c2014-06-24 15:03:45 +0200696 key_index);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500697
Jes Sorensen4e297c22014-06-24 15:03:36 +0200698 pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
699 if (pbcmc_sta) {
700 /* rx will use bmc_sta's
701 dot118021XPrivacy */
702 pbcmc_sta->ieee8021x_blocked = false;
703 pbcmc_sta->dot118021XPrivacy =
Larry Fingerb1925ad2014-03-28 21:37:40 -0500704 psecuritypriv->dot118021XGrpPrivacy;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500705 }
706 }
707 }
708
709exit:
710
Heena Sirwani911f2922014-10-07 14:45:56 +0530711 return 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500712}
713#endif
714
Jes Sorensen5292a892014-06-24 15:03:44 +0200715static int rtw_cfg80211_set_encryption(struct net_device *dev, u8 key_index,
Jes Sorensenf88ab542014-06-24 15:03:50 +0200716 int set_tx, const u8 *sta_addr,
Jes Sorensena9e346f2014-06-24 15:03:40 +0200717 struct key_params *keyparms)
Larry Fingerb1925ad2014-03-28 21:37:40 -0500718{
719 int ret = 0;
Jes Sorensend0dc2662014-06-24 15:03:41 +0200720 int key_len;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500721 struct rtw_adapter *padapter = netdev_priv(dev);
722 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
723 struct security_priv *psecuritypriv = &padapter->securitypriv;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500724
725 DBG_8723A("%s\n", __func__);
726
Jes Sorensend0dc2662014-06-24 15:03:41 +0200727 key_len = keyparms->key_len;
728
Jes Sorensen8188b1c2014-06-24 15:03:42 +0200729 if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
730 keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
Larry Fingerb1925ad2014-03-28 21:37:40 -0500731 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
732 ("wpa_set_encryption, crypt.alg = WEP\n"));
733 DBG_8723A("wpa_set_encryption, crypt.alg = WEP\n");
734
Larry Fingerb1925ad2014-03-28 21:37:40 -0500735 if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
736 /* wep default key has not been set, so use this
737 key index as default key. */
738
Larry Fingerb1925ad2014-03-28 21:37:40 -0500739 psecuritypriv->ndisencryptstatus =
740 Ndis802_11Encryption1Enabled;
Jes Sorensen7ef27432014-06-24 15:03:53 +0200741 psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher;
742 psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500743
Jes Sorensen5292a892014-06-24 15:03:44 +0200744 psecuritypriv->dot11PrivacyKeyIndex = key_index;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500745 }
746
Jes Sorensen5292a892014-06-24 15:03:44 +0200747 memcpy(&psecuritypriv->wep_key[key_index].key,
Jes Sorensene1343f92014-06-24 15:03:43 +0200748 keyparms->key, key_len);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500749
Jes Sorensen5292a892014-06-24 15:03:44 +0200750 psecuritypriv->wep_key[key_index].keylen = key_len;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500751
Jes Sorensen5292a892014-06-24 15:03:44 +0200752 rtw_set_key23a(padapter, psecuritypriv, key_index, 0);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500753
754 goto exit;
755 }
756
757 if (padapter->securitypriv.dot11AuthAlgrthm ==
758 dot11AuthAlgrthm_8021X) { /* 802_1x */
759 struct sta_info *psta, *pbcmc_sta;
760 struct sta_priv *pstapriv = &padapter->stapriv;
761
762 if (check_fwstate(pmlmepriv,
763 WIFI_STATION_STATE | WIFI_MP_STATE)) {
764 /* sta mode */
765 psta = rtw_get_stainfo23a(pstapriv, get_bssid(pmlmepriv));
766 if (psta == NULL) {
767 DBG_8723A("%s, : Obtain Sta_info fail\n",
768 __func__);
769 } else {
770 /* Jeff: don't disable ieee8021x_blocked
771 while clearing key */
Jes Sorensenefd42162014-06-24 15:03:49 +0200772 if (keyparms->cipher != IW_AUTH_CIPHER_NONE &&
773 keyparms->cipher != 0)
Larry Fingerb1925ad2014-03-28 21:37:40 -0500774 psta->ieee8021x_blocked = false;
775
776 if ((padapter->securitypriv.ndisencryptstatus ==
777 Ndis802_11Encryption2Enabled) ||
778 (padapter->securitypriv.ndisencryptstatus ==
779 Ndis802_11Encryption3Enabled)) {
780 psta->dot118021XPrivacy =
781 padapter->securitypriv.
782 dot11PrivacyAlgrthm;
783 }
784
Jes Sorensen0996cf92014-06-24 15:03:47 +0200785 if (set_tx == 1) {
Larry Fingerb1925ad2014-03-28 21:37:40 -0500786 /* pairwise key */
Jes Sorensen0996cf92014-06-24 15:03:47 +0200787 DBG_8723A("%s, : set_tx == 1\n",
788 __func__);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500789
790 memcpy(psta->dot118021x_UncstKey.skey,
Jes Sorensene1343f92014-06-24 15:03:43 +0200791 keyparms->key,
Jes Sorensend0dc2662014-06-24 15:03:41 +0200792 (key_len > 16 ? 16 : key_len));
Larry Fingerb1925ad2014-03-28 21:37:40 -0500793
Jes Sorensen8188b1c2014-06-24 15:03:42 +0200794 if (keyparms->cipher ==
795 WLAN_CIPHER_SUITE_TKIP) {
Larry Fingerb1925ad2014-03-28 21:37:40 -0500796 memcpy(psta->dot11tkiptxmickey.
797 skey,
Jes Sorensene1343f92014-06-24 15:03:43 +0200798 &keyparms->key[16], 8);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500799 memcpy(psta->dot11tkiprxmickey.
800 skey,
Jes Sorensene1343f92014-06-24 15:03:43 +0200801 &keyparms->key[24], 8);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500802
803 padapter->securitypriv.
Jes Sorensen9216c512014-05-21 09:37:29 +0200804 busetkipkey = 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500805 }
806 DBG_8723A(" ~~~~set sta key:unicastkey\n");
807
808 rtw_setstakey_cmd23a(padapter,
809 (unsigned char *)psta,
810 true);
811 } else { /* group key */
812 memcpy(padapter->securitypriv.
Jes Sorensen5292a892014-06-24 15:03:44 +0200813 dot118021XGrpKey[key_index].skey,
Jes Sorensene1343f92014-06-24 15:03:43 +0200814 keyparms->key,
Jes Sorensend0dc2662014-06-24 15:03:41 +0200815 (key_len > 16 ? 16 : key_len));
Larry Fingerb1925ad2014-03-28 21:37:40 -0500816 memcpy(padapter->securitypriv.
Jes Sorensen5292a892014-06-24 15:03:44 +0200817 dot118021XGrptxmickey[key_index].
Jes Sorensene1343f92014-06-24 15:03:43 +0200818 skey, &keyparms->key[16], 8);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500819 memcpy(padapter->securitypriv.
Jes Sorensen5292a892014-06-24 15:03:44 +0200820 dot118021XGrprxmickey[key_index].
Jes Sorensene1343f92014-06-24 15:03:43 +0200821 skey, &keyparms->key[24], 8);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500822 padapter->securitypriv.binstallGrpkey =
Jes Sorensen9216c512014-05-21 09:37:29 +0200823 1;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500824 DBG_8723A
825 (" ~~~~set sta key:groupkey\n");
826
827 padapter->securitypriv.
Jes Sorensen5292a892014-06-24 15:03:44 +0200828 dot118021XGrpKeyid = key_index;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500829
830 rtw_set_key23a(padapter,
831 &padapter->securitypriv,
Jes Sorensen5292a892014-06-24 15:03:44 +0200832 key_index, 1);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500833 }
834 }
835
836 pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
837 if (pbcmc_sta) {
838 /* Jeff: don't disable ieee8021x_blocked
839 while clearing key */
Jes Sorensenefd42162014-06-24 15:03:49 +0200840 if (keyparms->cipher != IW_AUTH_CIPHER_NONE &&
841 keyparms->cipher != 0)
Larry Fingerb1925ad2014-03-28 21:37:40 -0500842 pbcmc_sta->ieee8021x_blocked = false;
843
844 if ((padapter->securitypriv.ndisencryptstatus ==
845 Ndis802_11Encryption2Enabled) ||
846 (padapter->securitypriv.ndisencryptstatus ==
847 Ndis802_11Encryption3Enabled)) {
848 pbcmc_sta->dot118021XPrivacy =
849 padapter->securitypriv.
850 dot11PrivacyAlgrthm;
851 }
852 }
Larry Fingerb1925ad2014-03-28 21:37:40 -0500853 }
854 }
855
856exit:
857
858 DBG_8723A("%s, ret =%d\n", __func__, ret);
859
860
861
862 return ret;
863}
864
865static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
866 u8 key_index, bool pairwise,
867 const u8 *mac_addr, struct key_params *params)
868{
Jes Sorensen0996cf92014-06-24 15:03:47 +0200869 int set_tx, ret = 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500870 struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
871 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
872 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Jes Sorensenf88ab542014-06-24 15:03:50 +0200873 u8 sta_addr[ETH_ALEN];
Larry Fingerb1925ad2014-03-28 21:37:40 -0500874
Jes Sorensena790d582014-05-09 15:04:04 +0200875 DBG_8723A("%s(%s): adding key for %pM\n", __func__, ndev->name,
Larry Fingerb1925ad2014-03-28 21:37:40 -0500876 mac_addr);
877 DBG_8723A("cipher = 0x%x\n", params->cipher);
878 DBG_8723A("key_len = 0x%x\n", params->key_len);
879 DBG_8723A("seq_len = 0x%x\n", params->seq_len);
880 DBG_8723A("key_index =%d\n", key_index);
881 DBG_8723A("pairwise =%d\n", pairwise);
882
Jes Sorensenefd42162014-06-24 15:03:49 +0200883 switch (params->cipher) {
884 case IW_AUTH_CIPHER_NONE:
885 case WLAN_CIPHER_SUITE_WEP40:
Jes Sorensen7ef27432014-06-24 15:03:53 +0200886 if (params->key_len != WLAN_KEY_LEN_WEP40) {
887 ret = -EINVAL;
888 goto exit;
889 }
Jes Sorensenefd42162014-06-24 15:03:49 +0200890 case WLAN_CIPHER_SUITE_WEP104:
Jes Sorensen7ef27432014-06-24 15:03:53 +0200891 if (params->key_len != WLAN_KEY_LEN_WEP104) {
892 ret = -EINVAL;
893 goto exit;
894 }
Jes Sorensenefd42162014-06-24 15:03:49 +0200895 case WLAN_CIPHER_SUITE_TKIP:
896 case WLAN_CIPHER_SUITE_CCMP:
897 break;
898 default:
899 ret = -ENOTSUPP;
900 goto exit;
901 }
902
Jes Sorensen7ef27432014-06-24 15:03:53 +0200903 if (key_index >= WEP_KEYS || params->key_len < 0) {
904 ret = -EINVAL;
905 goto exit;
906 }
907
Jes Sorensenf88ab542014-06-24 15:03:50 +0200908 eth_broadcast_addr(sta_addr);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500909
Jes Sorensen0996cf92014-06-24 15:03:47 +0200910 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
911 set_tx = 0; /* for wpa/wpa2 group key */
912 else
913 set_tx = 1; /* for wpa/wpa2 pairwise key */
Larry Fingerb1925ad2014-03-28 21:37:40 -0500914
Larry Fingerb1925ad2014-03-28 21:37:40 -0500915 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
Jes Sorensen0996cf92014-06-24 15:03:47 +0200916 ret = rtw_cfg80211_set_encryption(ndev, key_index, set_tx,
Jes Sorensenf0bf8dd2014-06-24 15:03:51 +0200917 sta_addr, params);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500918 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
919#ifdef CONFIG_8723AU_AP_MODE
920 if (mac_addr)
Jes Sorensenf88ab542014-06-24 15:03:50 +0200921 ether_addr_copy(sta_addr, mac_addr);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500922
Jes Sorensen0996cf92014-06-24 15:03:47 +0200923 ret = rtw_cfg80211_ap_set_encryption(ndev, key_index, set_tx,
Jes Sorensenf0bf8dd2014-06-24 15:03:51 +0200924 sta_addr, params);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500925#endif
926 } else {
927 DBG_8723A("error! fw_state = 0x%x, iftype =%d\n",
928 pmlmepriv->fw_state, rtw_wdev->iftype);
929
930 }
931
Jes Sorensenefd42162014-06-24 15:03:49 +0200932exit:
Larry Fingerb1925ad2014-03-28 21:37:40 -0500933 return ret;
934}
935
936static int
937cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,
938 u8 key_index, bool pairwise, const u8 *mac_addr,
939 void *cookie,
940 void (*callback) (void *cookie, struct key_params *))
941{
Jes Sorensena790d582014-05-09 15:04:04 +0200942 DBG_8723A("%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500943 return 0;
944}
945
946static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
947 u8 key_index, bool pairwise,
948 const u8 *mac_addr)
949{
950 struct rtw_adapter *padapter = netdev_priv(ndev);
951 struct security_priv *psecuritypriv = &padapter->securitypriv;
952
Jes Sorensena790d582014-05-09 15:04:04 +0200953 DBG_8723A("%s(%s): key_index =%d\n", __func__, ndev->name, key_index);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500954
955 if (key_index == psecuritypriv->dot11PrivacyKeyIndex) {
956 /* clear the flag of wep default key set. */
957 psecuritypriv->bWepDefaultKeyIdxSet = 0;
958 }
959
960 return 0;
961}
962
963static int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
964 struct net_device *ndev, u8 key_index,
965 bool unicast, bool multicast)
966{
967 struct rtw_adapter *padapter = netdev_priv(ndev);
968 struct security_priv *psecuritypriv = &padapter->securitypriv;
969
Jes Sorensena790d582014-05-09 15:04:04 +0200970 DBG_8723A("%s(%s): key_index =%d, unicast =%d, multicast =%d.\n",
971 __func__, ndev->name, key_index, unicast, multicast);
Larry Fingerb1925ad2014-03-28 21:37:40 -0500972
Jes Sorensene0827902014-05-21 09:37:35 +0200973 if (key_index < NUM_WEP_KEYS &&
974 (psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP40 ||
975 psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP104)) {
Larry Fingerb1925ad2014-03-28 21:37:40 -0500976 /* set wep default key */
977 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
978
979 psecuritypriv->dot11PrivacyKeyIndex = key_index;
980
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200981 psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
982 psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
Jes Sorensene0827902014-05-21 09:37:35 +0200983 if (psecuritypriv->wep_key[key_index].keylen == 13) {
984 psecuritypriv->dot11PrivacyAlgrthm =
985 WLAN_CIPHER_SUITE_WEP104;
986 psecuritypriv->dot118021XGrpPrivacy =
987 WLAN_CIPHER_SUITE_WEP104;
Larry Fingerb1925ad2014-03-28 21:37:40 -0500988 }
989
990 /* set the flag to represent that wep default key
991 has been set */
992 psecuritypriv->bWepDefaultKeyIdxSet = 1;
993 }
994
995 return 0;
996}
997
Jes Sorensen27fd7312014-06-09 15:17:03 +0200998static u16 rtw_get_cur_max_rate(struct rtw_adapter *adapter)
999{
1000 int i = 0;
1001 const u8 *p;
1002 u16 rate = 0, max_rate = 0;
1003 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
1004 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1005 struct registry_priv *pregistrypriv = &adapter->registrypriv;
1006 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1007 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1008 struct ieee80211_ht_cap *pht_capie;
1009 u8 rf_type = 0;
1010 u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
1011 u16 mcs_rate = 0;
1012
Jes Sorensen1d33b072014-06-24 15:03:19 +02001013 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
Jes Sorensen1de65cc2014-06-24 15:03:30 +02001014 pcur_bss->IEs, pcur_bss->IELength);
Jes Sorensen27fd7312014-06-09 15:17:03 +02001015 if (p && p[1] > 0) {
1016 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1017
1018 memcpy(&mcs_rate, &pht_capie->mcs, 2);
1019
1020 /* bw_40MHz = (pht_capie->cap_info&
1021 IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1:0; */
1022 /* cur_bwmod is updated by beacon, pmlmeinfo is
1023 updated by association response */
1024 bw_40MHz = (pmlmeext->cur_bwmode &&
1025 (pmlmeinfo->HT_info.ht_param &
1026 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) ? 1:0;
1027
1028 /* short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP
1029 _SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; */
1030 short_GI_20 = (pmlmeinfo->ht_cap.cap_info &
1031 cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) ? 1:0;
1032 short_GI_40 = (pmlmeinfo->ht_cap.cap_info &
1033 cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) ? 1:0;
1034
1035 rf_type = rtl8723a_get_rf_type(adapter);
1036 max_rate = rtw_mcs_rate23a(rf_type, bw_40MHz &
1037 pregistrypriv->cbw40_enable,
1038 short_GI_20, short_GI_40,
1039 &pmlmeinfo->ht_cap.mcs);
1040 } else {
1041 while (pcur_bss->SupportedRates[i] != 0 &&
1042 pcur_bss->SupportedRates[i] != 0xFF) {
1043 rate = pcur_bss->SupportedRates[i] & 0x7F;
1044 if (rate>max_rate)
1045 max_rate = rate;
1046 i++;
1047 }
1048
1049 max_rate = max_rate * 10 / 2;
1050 }
1051
1052 return max_rate;
1053}
1054
Larry Fingerb1925ad2014-03-28 21:37:40 -05001055static int cfg80211_rtw_get_station(struct wiphy *wiphy,
1056 struct net_device *ndev,
Linus Torvaldsf9da4552014-06-12 14:27:40 -07001057 const u8 *mac, struct station_info *sinfo)
Larry Fingerb1925ad2014-03-28 21:37:40 -05001058{
1059 int ret = 0;
1060 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1061 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1062 struct sta_info *psta = NULL;
1063 struct sta_priv *pstapriv = &padapter->stapriv;
1064
1065 sinfo->filled = 0;
1066
1067 if (!mac) {
Jes Sorensena790d582014-05-09 15:04:04 +02001068 DBG_8723A("%s(%s): mac ==%p\n", __func__, ndev->name, mac);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001069 ret = -ENOENT;
1070 goto exit;
1071 }
1072
1073 psta = rtw_get_stainfo23a(pstapriv, mac);
1074 if (psta == NULL) {
1075 DBG_8723A("%s, sta_info is null\n", __func__);
1076 ret = -ENOENT;
1077 goto exit;
1078 }
Joe Perchesea072782015-03-24 11:10:09 -07001079 DBG_8723A("%s(%s): mac=%pM\n", __func__, ndev->name, mac);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001080
1081 /* for infra./P2PClient mode */
1082 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
1083 check_fwstate(pmlmepriv, _FW_LINKED)) {
1084 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1085
Jes Sorensencc2db7c2014-05-25 22:43:12 +02001086 if (!ether_addr_equal(mac, cur_network->network.MacAddress)) {
Joe Perchesea072782015-03-24 11:10:09 -07001087 DBG_8723A("%s, mismatch bssid=%pM\n",
1088 __func__, cur_network->network.MacAddress);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001089 ret = -ENOENT;
1090 goto exit;
1091 }
1092
Johannes Berg319090b2014-11-17 14:08:11 +01001093 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001094 sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.
1095 signal_strength);
1096
Johannes Berg319090b2014-11-17 14:08:11 +01001097 sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
Jes Sorensen27fd7312014-06-09 15:17:03 +02001098 sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001099
Johannes Berg319090b2014-11-17 14:08:11 +01001100 sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001101 sinfo->rx_packets = sta_rx_data_pkts(psta);
1102
Johannes Berg319090b2014-11-17 14:08:11 +01001103 sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001104 sinfo->tx_packets = psta->sta_stats.tx_pkts;
1105 }
1106
1107 /* for Ad-Hoc/AP mode */
1108 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
1109 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1110 check_fwstate(pmlmepriv, WIFI_AP_STATE)) &&
1111 check_fwstate(pmlmepriv, _FW_LINKED)
1112 ) {
1113 /* TODO: should acquire station info... */
1114 }
1115
1116exit:
1117 return ret;
1118}
1119
Rahul Garg1da2a442014-09-25 07:16:59 +05301120static int cfg80211_infrastructure_mode(struct rtw_adapter *padapter,
Jes Sorensenefc71442014-05-21 09:37:26 +02001121 enum nl80211_iftype ifmode)
1122{
1123 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1124 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1125 enum nl80211_iftype old_mode;
1126
1127 old_mode = cur_network->network.ifmode;
1128
1129 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
1130 ("+%s: old =%d new =%d fw_state = 0x%08x\n", __func__,
1131 old_mode, ifmode, get_fwstate(pmlmepriv)));
1132
1133 if (old_mode != ifmode) {
1134 spin_lock_bh(&pmlmepriv->lock);
1135
1136 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1137 (" change mode!"));
1138
1139 if (old_mode == NL80211_IFTYPE_AP ||
1140 old_mode == NL80211_IFTYPE_P2P_GO) {
1141 /* change to other mode from Ndis802_11APMode */
1142 cur_network->join_res = -1;
1143
1144#ifdef CONFIG_8723AU_AP_MODE
1145 stop_ap_mode23a(padapter);
1146#endif
1147 }
1148
1149 if (check_fwstate(pmlmepriv, _FW_LINKED) ||
1150 old_mode == NL80211_IFTYPE_ADHOC)
1151 rtw_disassoc_cmd23a(padapter, 0, true);
1152
1153 if (check_fwstate(pmlmepriv, _FW_LINKED) ||
1154 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
1155 rtw_free_assoc_resources23a(padapter, 1);
1156
1157 if (old_mode == NL80211_IFTYPE_STATION ||
1158 old_mode == NL80211_IFTYPE_P2P_CLIENT ||
1159 old_mode == NL80211_IFTYPE_ADHOC) {
1160 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1161 /* will clr Linked_state; before this function,
1162 we must have chked whether issue
1163 dis-assoc_cmd or not */
1164 rtw_indicate_disconnect23a(padapter);
1165 }
1166 }
1167
1168 cur_network->network.ifmode = ifmode;
1169
1170 _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
1171
1172 switch (ifmode) {
1173 case NL80211_IFTYPE_ADHOC:
1174 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
1175 break;
1176
1177 case NL80211_IFTYPE_P2P_CLIENT:
1178 case NL80211_IFTYPE_STATION:
1179 set_fwstate(pmlmepriv, WIFI_STATION_STATE);
1180 break;
1181
1182 case NL80211_IFTYPE_P2P_GO:
1183 case NL80211_IFTYPE_AP:
1184 set_fwstate(pmlmepriv, WIFI_AP_STATE);
1185#ifdef CONFIG_8723AU_AP_MODE
1186 start_ap_mode23a(padapter);
1187 /* rtw_indicate_connect23a(padapter); */
1188#endif
1189 break;
1190
1191 default:
1192 break;
1193 }
1194
1195 /* SecClearAllKeys(adapter); */
1196
1197 /* RT_TRACE(COMP_OID_SET, DBG_LOUD,
1198 ("set_infrastructure: fw_state:%x after changing mode\n", */
1199 /* get_fwstate(pmlmepriv))); */
1200
1201 spin_unlock_bh(&pmlmepriv->lock);
1202 }
1203
1204 return _SUCCESS;
1205}
1206
Larry Fingerb1925ad2014-03-28 21:37:40 -05001207static int cfg80211_rtw_change_iface(struct wiphy *wiphy,
1208 struct net_device *ndev,
1209 enum nl80211_iftype type, u32 *flags,
1210 struct vif_params *params)
1211{
1212 enum nl80211_iftype old_type;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001213 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1214 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1215 struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001216 int ret = 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001217
Jes Sorensena790d582014-05-09 15:04:04 +02001218 DBG_8723A("%s(%s): call netdev_open23a\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001219
1220 old_type = rtw_wdev->iftype;
Jes Sorensena790d582014-05-09 15:04:04 +02001221 DBG_8723A("%s(%s): old_iftype =%d, new_iftype =%d\n",
1222 __func__, ndev->name, old_type, type);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001223
1224 if (old_type != type) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05001225 pmlmeext->action_public_rxseq = 0xffff;
1226 pmlmeext->action_public_dialog_token = 0xff;
1227 }
1228
1229 switch (type) {
1230 case NL80211_IFTYPE_ADHOC:
Larry Fingerb1925ad2014-03-28 21:37:40 -05001231 case NL80211_IFTYPE_P2P_CLIENT:
1232 case NL80211_IFTYPE_STATION:
Larry Fingerb1925ad2014-03-28 21:37:40 -05001233 case NL80211_IFTYPE_P2P_GO:
1234 case NL80211_IFTYPE_AP:
Jes Sorensenefc71442014-05-21 09:37:26 +02001235 case NL80211_IFTYPE_UNSPECIFIED:
Larry Fingerb1925ad2014-03-28 21:37:40 -05001236 break;
1237 default:
1238 return -EOPNOTSUPP;
1239 }
1240
1241 rtw_wdev->iftype = type;
1242
Jes Sorensenefc71442014-05-21 09:37:26 +02001243 if (cfg80211_infrastructure_mode(padapter, type) != _SUCCESS) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05001244 rtw_wdev->iftype = old_type;
1245 ret = -EPERM;
1246 goto exit;
1247 }
1248
Jes Sorensenefc71442014-05-21 09:37:26 +02001249 rtw_setopmode_cmd23a(padapter, type);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001250
1251exit:
1252 return ret;
1253}
1254
1255void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
1256 bool aborted)
1257{
1258 spin_lock_bh(&pwdev_priv->scan_req_lock);
1259 if (pwdev_priv->scan_request != NULL) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05001260 DBG_8723A("%s with scan req\n", __func__);
Jes Sorensen141bd352014-04-09 23:20:59 +02001261
Larry Fingerb1925ad2014-03-28 21:37:40 -05001262 if (pwdev_priv->scan_request->wiphy !=
1263 pwdev_priv->rtw_wdev->wiphy)
1264 DBG_8723A("error wiphy compare\n");
1265 else
1266 cfg80211_scan_done(pwdev_priv->scan_request, aborted);
1267
1268 pwdev_priv->scan_request = NULL;
1269 } else {
Larry Fingerb1925ad2014-03-28 21:37:40 -05001270 DBG_8723A("%s without scan req\n", __func__);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001271 }
1272 spin_unlock_bh(&pwdev_priv->scan_req_lock);
1273}
1274
1275void rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter)
1276{
1277 struct list_head *plist, *phead, *ptmp;
1278 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1279 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1280 struct wlan_network *pnetwork;
1281
Larry Fingerb1925ad2014-03-28 21:37:40 -05001282 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1283
1284 phead = get_list_head(queue);
1285
1286 list_for_each_safe(plist, ptmp, phead) {
1287 pnetwork = container_of(plist, struct wlan_network, list);
1288
1289 /* report network only if the current channel set
1290 contains the channel to which this network belongs */
1291 if (rtw_ch_set_search_ch23a
1292 (padapter->mlmeextpriv.channel_set,
Jes Sorensen37cb9822014-05-21 09:37:40 +02001293 pnetwork->network.DSConfig) >= 0)
Larry Fingerb1925ad2014-03-28 21:37:40 -05001294 rtw_cfg80211_inform_bss(padapter, pnetwork);
1295 }
1296
1297 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1298
1299 /* call this after other things have been done */
1300 rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev),
1301 false);
1302}
1303
1304static int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter,
1305 char *buf, int len)
1306{
1307 int ret = 0;
Jes Sorensend3797af2014-06-09 15:15:56 +02001308 const u8 *wps_ie;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001309 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1310
Larry Fingerb1925ad2014-03-28 21:37:40 -05001311 DBG_8723A("%s, ielen =%d\n", __func__, len);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001312
1313 if (len > 0) {
Jes Sorensend3797af2014-06-09 15:15:56 +02001314 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1315 WLAN_OUI_TYPE_MICROSOFT_WPS,
1316 buf, len);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001317 if (wps_ie) {
Jes Sorensend3797af2014-06-09 15:15:56 +02001318 DBG_8723A("probe_req_wps_ielen =%d\n", wps_ie[1]);
Jes Sorensen141bd352014-04-09 23:20:59 +02001319
Larry Fingerb1925ad2014-03-28 21:37:40 -05001320 if (pmlmepriv->wps_probe_req_ie) {
1321 pmlmepriv->wps_probe_req_ie_len = 0;
1322 kfree(pmlmepriv->wps_probe_req_ie);
1323 pmlmepriv->wps_probe_req_ie = NULL;
1324 }
1325
Jes Sorensend3797af2014-06-09 15:15:56 +02001326 pmlmepriv->wps_probe_req_ie = kmemdup(wps_ie, wps_ie[1],
Benoit Taine4a6eea42014-05-22 15:08:33 +02001327 GFP_KERNEL);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001328 if (pmlmepriv->wps_probe_req_ie == NULL) {
1329 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
1330 __func__, __LINE__);
1331 return -EINVAL;
1332 }
Jes Sorensend3797af2014-06-09 15:15:56 +02001333 pmlmepriv->wps_probe_req_ie_len = wps_ie[1];
Larry Fingerb1925ad2014-03-28 21:37:40 -05001334 }
Larry Fingerb1925ad2014-03-28 21:37:40 -05001335 }
1336
1337 return ret;
1338}
1339
1340static int cfg80211_rtw_scan(struct wiphy *wiphy,
1341 struct cfg80211_scan_request *request)
1342{
1343 int i;
1344 u8 _status = false;
1345 int ret = 0;
1346 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1347 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1348 struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1349 struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
Larry Fingerb1925ad2014-03-28 21:37:40 -05001350 struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
1351 struct cfg80211_ssid *ssids = request->ssids;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001352 bool need_indicate_scan_done = false;
1353
Jes Sorensena790d582014-05-09 15:04:04 +02001354 DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001355
1356 spin_lock_bh(&pwdev_priv->scan_req_lock);
1357 pwdev_priv->scan_request = request;
1358 spin_unlock_bh(&pwdev_priv->scan_req_lock);
1359
1360 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05001361 DBG_8723A("%s under WIFI_AP_STATE\n", __func__);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001362 /* need_indicate_scan_done = true; */
1363 /* goto check_need_indicate_scan_done; */
1364 }
1365
1366 if (rtw_pwr_wakeup(padapter) == _FAIL) {
1367 need_indicate_scan_done = true;
1368 goto check_need_indicate_scan_done;
1369 }
Larry Fingerb1925ad2014-03-28 21:37:40 -05001370
1371 if (request->ie && request->ie_len > 0) {
1372 rtw_cfg80211_set_probe_req_wpsp2pie(padapter,
1373 (u8 *) request->ie,
1374 request->ie_len);
1375 }
1376
1377 if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) {
1378 DBG_8723A("%s, bBusyTraffic == true\n", __func__);
1379 need_indicate_scan_done = true;
1380 goto check_need_indicate_scan_done;
1381 }
1382 if (rtw_is_scan_deny(padapter)) {
Jes Sorensen9cd613c2014-05-09 15:04:03 +02001383 DBG_8723A("%s(%s): scan deny\n", __func__,
1384 padapter->pnetdev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001385 need_indicate_scan_done = true;
1386 goto check_need_indicate_scan_done;
1387 }
1388
1389 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ==
1390 true) {
1391 DBG_8723A("%s, fwstate = 0x%x\n", __func__, pmlmepriv->fw_state);
1392 need_indicate_scan_done = true;
1393 goto check_need_indicate_scan_done;
1394 }
Larry Fingerb1925ad2014-03-28 21:37:40 -05001395
1396 memset(ssid, 0, sizeof(struct cfg80211_ssid) * RTW_SSID_SCAN_AMOUNT);
1397 /* parsing request ssids, n_ssids */
1398 for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05001399 DBG_8723A("ssid =%s, len =%d\n", ssids[i].ssid,
1400 ssids[i].ssid_len);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001401 memcpy(ssid[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
1402 ssid[i].ssid_len = ssids[i].ssid_len;
1403 }
1404
1405 /* parsing channels, n_channels */
1406 memset(ch, 0,
1407 sizeof(struct rtw_ieee80211_channel) * RTW_CHANNEL_SCAN_AMOUNT);
1408
1409 if (request->n_channels == 1) {
1410 for (i = 0; i < request->n_channels &&
1411 i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
Jes Sorensen9cd613c2014-05-09 15:04:03 +02001412 DBG_8723A("%s:(%s):" CHAN_FMT "\n",
1413 __func__, padapter->pnetdev->name,
Larry Fingerb1925ad2014-03-28 21:37:40 -05001414 CHAN_ARG(request->channels[i]));
Larry Fingerb1925ad2014-03-28 21:37:40 -05001415 ch[i].hw_value = request->channels[i]->hw_value;
1416 ch[i].flags = request->channels[i]->flags;
1417 }
1418 }
1419
1420 spin_lock_bh(&pmlmepriv->lock);
1421 if (request->n_channels == 1) {
1422 memcpy(&ch[1], &ch[0], sizeof(struct rtw_ieee80211_channel));
1423 memcpy(&ch[2], &ch[0], sizeof(struct rtw_ieee80211_channel));
1424 _status = rtw_sitesurvey_cmd23a(padapter, ssid,
1425 RTW_SSID_SCAN_AMOUNT, ch, 3);
1426 } else {
1427 _status = rtw_sitesurvey_cmd23a(padapter, ssid,
1428 RTW_SSID_SCAN_AMOUNT, NULL, 0);
1429 }
1430 spin_unlock_bh(&pmlmepriv->lock);
1431
1432 if (_status == false)
1433 ret = -1;
1434
1435check_need_indicate_scan_done:
1436 if (need_indicate_scan_done)
1437 rtw_cfg80211_surveydone_event_callback(padapter);
1438 return ret;
1439}
1440
1441static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1442{
1443 DBG_8723A("%s\n", __func__);
1444 return 0;
1445}
1446
1447static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
1448 struct cfg80211_ibss_params *params)
1449{
Jes Sorensena790d582014-05-09 15:04:04 +02001450 DBG_8723A("%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001451 return 0;
1452}
1453
1454static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1455{
Jes Sorensena790d582014-05-09 15:04:04 +02001456 DBG_8723A("%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001457 return 0;
1458}
1459
1460static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv,
1461 u32 wpa_version)
1462{
1463 DBG_8723A("%s, wpa_version =%d\n", __func__, wpa_version);
1464
1465 if (!wpa_version) {
1466 psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
1467 return 0;
1468 }
1469
Dean Michael Ancajas3895ed02014-12-08 13:55:21 -07001470 if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
Larry Fingerb1925ad2014-03-28 21:37:40 -05001471 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001472
1473/*
1474 if (wpa_version & NL80211_WPA_VERSION_2)
1475 {
1476 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;
1477 }
1478*/
1479
1480 return 0;
1481}
1482
1483static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
1484 enum nl80211_auth_type sme_auth_type)
1485{
1486 DBG_8723A("%s, nl80211_auth_type =%d\n", __func__, sme_auth_type);
1487
1488 switch (sme_auth_type) {
1489 case NL80211_AUTHTYPE_AUTOMATIC:
1490 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1491
1492 break;
1493 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1494 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1495
1496 if (psecuritypriv->ndisauthtype > Ndis802_11AuthModeWPA)
1497 psecuritypriv->dot11AuthAlgrthm =
1498 dot11AuthAlgrthm_8021X;
1499 break;
1500 case NL80211_AUTHTYPE_SHARED_KEY:
1501 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1502
1503 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1504 break;
1505 default:
1506 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1507 /* return -ENOTSUPP; */
1508 }
1509
1510 return 0;
1511}
1512
1513static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv,
1514 u32 cipher, bool ucast)
1515{
1516 u32 ndisencryptstatus = Ndis802_11EncryptionDisabled;
1517
1518 u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :
1519 &psecuritypriv->dot118021XGrpPrivacy;
1520
1521 DBG_8723A("%s, ucast =%d, cipher = 0x%x\n", __func__, ucast, cipher);
1522
1523 if (!cipher) {
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001524 *profile_cipher = 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001525 psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1526 return 0;
1527 }
1528
1529 switch (cipher) {
1530 case IW_AUTH_CIPHER_NONE:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001531 *profile_cipher = 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001532 ndisencryptstatus = Ndis802_11EncryptionDisabled;
1533 break;
1534 case WLAN_CIPHER_SUITE_WEP40:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001535 *profile_cipher = WLAN_CIPHER_SUITE_WEP40;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001536 ndisencryptstatus = Ndis802_11Encryption1Enabled;
1537 break;
1538 case WLAN_CIPHER_SUITE_WEP104:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001539 *profile_cipher = WLAN_CIPHER_SUITE_WEP104;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001540 ndisencryptstatus = Ndis802_11Encryption1Enabled;
1541 break;
1542 case WLAN_CIPHER_SUITE_TKIP:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001543 *profile_cipher = WLAN_CIPHER_SUITE_TKIP;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001544 ndisencryptstatus = Ndis802_11Encryption2Enabled;
1545 break;
1546 case WLAN_CIPHER_SUITE_CCMP:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001547 *profile_cipher = WLAN_CIPHER_SUITE_CCMP;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001548 ndisencryptstatus = Ndis802_11Encryption3Enabled;
1549 break;
1550 default:
1551 DBG_8723A("Unsupported cipher: 0x%x\n", cipher);
1552 return -ENOTSUPP;
1553 }
1554
1555 if (ucast)
1556 psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1557
1558 return 0;
1559}
1560
1561static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv,
1562 u32 key_mgt)
1563{
1564 DBG_8723A("%s, key_mgt = 0x%x\n", __func__, key_mgt);
1565
1566 if (key_mgt == WLAN_AKM_SUITE_8021X)
1567 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1568 else if (key_mgt == WLAN_AKM_SUITE_PSK)
1569 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1570 else
1571 DBG_8723A("Invalid key mgt: 0x%x\n", key_mgt);
1572
1573 return 0;
1574}
1575
1576static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
1577 size_t ielen)
1578{
Jes Sorensend3797af2014-06-09 15:15:56 +02001579 const u8 *wps_ie;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001580 int group_cipher = 0, pairwise_cipher = 0;
1581 int ret = 0;
Jes Sorensen58aedb42014-04-15 19:44:07 +02001582 const u8 *pwpa, *pwpa2;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001583 int i;
1584
1585 if (!pie || !ielen) {
1586 /* Treat this as normal case, but need to clear
1587 WIFI_UNDER_WPS */
1588 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1589 goto exit;
1590 }
1591 if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) {
1592 ret = -EINVAL;
1593 goto exit;
1594 }
Larry Fingerb1925ad2014-03-28 21:37:40 -05001595
1596 /* dump */
1597 DBG_8723A("set wpa_ie(length:%zu):\n", ielen);
1598 for (i = 0; i < ielen; i = i + 8)
Jes Sorensen7579a7e2014-06-09 15:17:08 +02001599 DBG_8723A("0x%.2x 0x%.2x 0x%.2x 0x%.2x "
1600 "0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
1601 pie[i], pie[i + 1], pie[i + 2], pie[i + 3],
1602 pie[i + 4], pie[i + 5], pie[i + 6], pie[i + 7]);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001603 if (ielen < RSN_HEADER_LEN) {
1604 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
1605 ("Ie len too short %d\n", (int)ielen));
1606 ret = -1;
1607 goto exit;
1608 }
1609
Jes Sorensen58aedb42014-04-15 19:44:07 +02001610 pwpa = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1611 WLAN_OUI_TYPE_MICROSOFT_WPA,
Jes Sorensen7579a7e2014-06-09 15:17:08 +02001612 pie, ielen);
Jes Sorensen58aedb42014-04-15 19:44:07 +02001613 if (pwpa && pwpa[1] > 0) {
1614 if (rtw_parse_wpa_ie23a(pwpa, pwpa[1] + 2, &group_cipher,
1615 &pairwise_cipher, NULL) == _SUCCESS) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05001616 padapter->securitypriv.dot11AuthAlgrthm =
1617 dot11AuthAlgrthm_8021X;
1618 padapter->securitypriv.ndisauthtype =
1619 Ndis802_11AuthModeWPAPSK;
Jes Sorensen58aedb42014-04-15 19:44:07 +02001620 memcpy(padapter->securitypriv.supplicant_ie, pwpa,
1621 pwpa[1] + 2);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001622
Jes Sorensen58aedb42014-04-15 19:44:07 +02001623 DBG_8723A("got wpa_ie, wpa_ielen:%u\n", pwpa[1]);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001624 }
1625 }
1626
Jes Sorensen7579a7e2014-06-09 15:17:08 +02001627 pwpa2 = cfg80211_find_ie(WLAN_EID_RSN, pie, ielen);
Jes Sorensen58aedb42014-04-15 19:44:07 +02001628 if (pwpa2 && pwpa2[1] > 0) {
1629 if (rtw_parse_wpa2_ie23a (pwpa2, pwpa2[1] + 2, &group_cipher,
1630 &pairwise_cipher, NULL) == _SUCCESS) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05001631 padapter->securitypriv.dot11AuthAlgrthm =
1632 dot11AuthAlgrthm_8021X;
1633 padapter->securitypriv.ndisauthtype =
1634 Ndis802_11AuthModeWPA2PSK;
Jes Sorensen58aedb42014-04-15 19:44:07 +02001635 memcpy(padapter->securitypriv.supplicant_ie, pwpa2,
1636 pwpa2[1] + 2);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001637
Jes Sorensen58aedb42014-04-15 19:44:07 +02001638 DBG_8723A("got wpa2_ie, wpa2_ielen:%u\n", pwpa2[1]);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001639 }
1640 }
1641
1642 if (group_cipher == 0) {
1643 group_cipher = WPA_CIPHER_NONE;
1644 }
1645 if (pairwise_cipher == 0) {
1646 pairwise_cipher = WPA_CIPHER_NONE;
1647 }
1648
1649 switch (group_cipher) {
1650 case WPA_CIPHER_NONE:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001651 padapter->securitypriv.dot118021XGrpPrivacy = 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001652 padapter->securitypriv.ndisencryptstatus =
1653 Ndis802_11EncryptionDisabled;
1654 break;
1655 case WPA_CIPHER_WEP40:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001656 padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001657 padapter->securitypriv.ndisencryptstatus =
1658 Ndis802_11Encryption1Enabled;
1659 break;
1660 case WPA_CIPHER_TKIP:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001661 padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_TKIP;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001662 padapter->securitypriv.ndisencryptstatus =
1663 Ndis802_11Encryption2Enabled;
1664 break;
1665 case WPA_CIPHER_CCMP:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001666 padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_CCMP;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001667 padapter->securitypriv.ndisencryptstatus =
1668 Ndis802_11Encryption3Enabled;
1669 break;
1670 case WPA_CIPHER_WEP104:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001671 padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001672 padapter->securitypriv.ndisencryptstatus =
1673 Ndis802_11Encryption1Enabled;
1674 break;
1675 }
1676
1677 switch (pairwise_cipher) {
1678 case WPA_CIPHER_NONE:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001679 padapter->securitypriv.dot11PrivacyAlgrthm = 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001680 padapter->securitypriv.ndisencryptstatus =
1681 Ndis802_11EncryptionDisabled;
1682 break;
1683 case WPA_CIPHER_WEP40:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001684 padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001685 padapter->securitypriv.ndisencryptstatus =
1686 Ndis802_11Encryption1Enabled;
1687 break;
1688 case WPA_CIPHER_TKIP:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001689 padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_TKIP;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001690 padapter->securitypriv.ndisencryptstatus =
1691 Ndis802_11Encryption2Enabled;
1692 break;
1693 case WPA_CIPHER_CCMP:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001694 padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_CCMP;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001695 padapter->securitypriv.ndisencryptstatus =
1696 Ndis802_11Encryption3Enabled;
1697 break;
1698 case WPA_CIPHER_WEP104:
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001699 padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001700 padapter->securitypriv.ndisencryptstatus =
1701 Ndis802_11Encryption1Enabled;
1702 break;
1703 }
1704
Jes Sorensend3797af2014-06-09 15:15:56 +02001705 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1706 WLAN_OUI_TYPE_MICROSOFT_WPS,
Jes Sorensen7579a7e2014-06-09 15:17:08 +02001707 pie, ielen);
Jes Sorensend3797af2014-06-09 15:15:56 +02001708 if (wps_ie && wps_ie[1] > 0) {
1709 DBG_8723A("got wps_ie, wps_ielen:%u\n", wps_ie[1]);
1710 padapter->securitypriv.wps_ie_len = wps_ie[1];
1711 memcpy(padapter->securitypriv.wps_ie, wps_ie,
1712 padapter->securitypriv.wps_ie_len);
1713 set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
1714 } else {
1715 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001716 }
1717
Larry Fingerb1925ad2014-03-28 21:37:40 -05001718 /* TKIP and AES disallow multicast packets until installing group key */
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001719 if (padapter->securitypriv.dot11PrivacyAlgrthm ==
1720 WLAN_CIPHER_SUITE_TKIP ||
1721 padapter->securitypriv.dot11PrivacyAlgrthm ==
1722 WLAN_CIPHER_SUITE_CCMP)
Larry Fingerb1925ad2014-03-28 21:37:40 -05001723 /* WPS open need to enable multicast */
1724 /* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true)*/
Jes Sorensen763b4242014-04-09 23:20:14 +02001725 rtl8723a_off_rcr_am(padapter);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001726
1727 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1728 ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->"
1729 "securitypriv.ndisencryptstatus =%d padapter->"
1730 "securitypriv.ndisauthtype =%d\n", pairwise_cipher,
1731 padapter->securitypriv.ndisencryptstatus,
1732 padapter->securitypriv.ndisauthtype));
1733
1734exit:
Larry Fingerb1925ad2014-03-28 21:37:40 -05001735 if (ret)
1736 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1737 return ret;
1738}
1739
Jes Sorensen6893c8e2014-05-21 09:37:37 +02001740static int rtw_cfg80211_add_wep(struct rtw_adapter *padapter,
Jes Sorensendeff1152014-05-21 09:37:38 +02001741 struct rtw_wep_key *wep, u8 keyid)
Jes Sorensen1e6e7f62014-05-21 09:37:36 +02001742{
Jes Sorensendeff1152014-05-21 09:37:38 +02001743 int res;
Jes Sorensen1e6e7f62014-05-21 09:37:36 +02001744 struct security_priv *psecuritypriv = &padapter->securitypriv;
1745
Jes Sorensendeff1152014-05-21 09:37:38 +02001746 if (keyid >= NUM_WEP_KEYS) {
Jes Sorensen1e6e7f62014-05-21 09:37:36 +02001747 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
1748 ("%s:keyid>4 =>fail\n", __func__));
1749 res = _FAIL;
1750 goto exit;
1751 }
1752
Jes Sorensendeff1152014-05-21 09:37:38 +02001753 switch (wep->keylen) {
Jes Sorensen4d9c63b2014-06-09 15:16:45 +02001754 case WLAN_KEY_LEN_WEP40:
Jes Sorensen1e6e7f62014-05-21 09:37:36 +02001755 psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
1756 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1757 ("%s:wep->KeyLength = 5\n", __func__));
1758 break;
Jes Sorensen4d9c63b2014-06-09 15:16:45 +02001759 case WLAN_KEY_LEN_WEP104:
Jes Sorensen1e6e7f62014-05-21 09:37:36 +02001760 psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
1761 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1762 ("%s:wep->KeyLength = 13\n", __func__));
1763 break;
1764 default:
1765 psecuritypriv->dot11PrivacyAlgrthm = 0;
1766 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1767 ("%s:wep->KeyLength!= 5 or 13\n", __func__));
1768 res = _FAIL;
1769 goto exit;
1770 }
1771
1772 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
Jes Sorensendeff1152014-05-21 09:37:38 +02001773 ("%s:before memcpy, wep->KeyLength = 0x%x keyid =%x\n",
1774 __func__, wep->keylen, keyid));
Jes Sorensen1e6e7f62014-05-21 09:37:36 +02001775
Jes Sorensendeff1152014-05-21 09:37:38 +02001776 memcpy(&psecuritypriv->wep_key[keyid], wep, sizeof(struct rtw_wep_key));
Jes Sorensen1e6e7f62014-05-21 09:37:36 +02001777
1778 psecuritypriv->dot11PrivacyKeyIndex = keyid;
1779
1780 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1781 ("%s:security key material : "
1782 "%x %x %x %x %x %x %x %x %x %x %x %x %x\n", __func__,
1783 psecuritypriv->wep_key[keyid].key[0],
1784 psecuritypriv->wep_key[keyid].key[1],
1785 psecuritypriv->wep_key[keyid].key[2],
1786 psecuritypriv->wep_key[keyid].key[3],
1787 psecuritypriv->wep_key[keyid].key[4],
1788 psecuritypriv->wep_key[keyid].key[5],
1789 psecuritypriv->wep_key[keyid].key[6],
1790 psecuritypriv->wep_key[keyid].key[7],
1791 psecuritypriv->wep_key[keyid].key[8],
1792 psecuritypriv->wep_key[keyid].key[9],
1793 psecuritypriv->wep_key[keyid].key[10],
1794 psecuritypriv->wep_key[keyid].key[11],
1795 psecuritypriv->wep_key[keyid].key[12]));
1796
1797 res = rtw_set_key23a(padapter, psecuritypriv, keyid, 1);
1798
1799exit:
1800
1801 return res;
1802}
1803
Jes Sorensene73d82e2014-06-09 15:16:43 +02001804static int rtw_set_ssid(struct rtw_adapter *padapter,
1805 struct wlan_network *newnetwork)
Jes Sorensen97c43612014-06-09 15:16:39 +02001806{
1807 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1808 struct wlan_network *pnetwork = &pmlmepriv->cur_network;
1809 int status = _SUCCESS;
1810 u32 cur_time = 0;
1811
1812 DBG_8723A_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n",
Jes Sorensene73d82e2014-06-09 15:16:43 +02001813 newnetwork->network.Ssid.ssid, get_fwstate(pmlmepriv));
Jes Sorensen97c43612014-06-09 15:16:39 +02001814
1815 if (padapter->hw_init_completed == false) {
1816 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
1817 ("set_ssid: hw_init_completed == false =>exit!!!\n"));
1818 status = _FAIL;
1819 goto exit;
1820 }
1821
1822 spin_lock_bh(&pmlmepriv->lock);
1823
1824 DBG_8723A("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
1825 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1826 goto handle_tkip_countermeasure;
Jes Sorensen97c43612014-06-09 15:16:39 +02001827
1828 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1829 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1830 ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
1831
Jes Sorensene73d82e2014-06-09 15:16:43 +02001832 if (pmlmepriv->assoc_ssid.ssid_len ==
1833 newnetwork->network.Ssid.ssid_len &&
1834 !memcmp(&pmlmepriv->assoc_ssid.ssid,
1835 newnetwork->network.Ssid.ssid,
1836 newnetwork->network.Ssid.ssid_len)) {
Jes Sorensen97c43612014-06-09 15:16:39 +02001837 if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1838 RT_TRACE(_module_rtl871x_ioctl_set_c_,
1839 _drv_err_, ("New SSID is same SSID, "
1840 "fw_state = 0x%08x\n",
1841 get_fwstate(pmlmepriv)));
1842
1843 if (rtw_is_same_ibss23a(padapter, pnetwork)) {
1844 /*
1845 * it means driver is in
1846 * WIFI_ADHOC_MASTER_STATE, we needn't
1847 * create bss again.
1848 */
1849 goto release_mlme_lock;
1850 }
1851
1852 /*
1853 * if in WIFI_ADHOC_MASTER_STATE |
1854 * WIFI_ADHOC_STATE, create bss or
1855 * rejoin again
1856 */
1857 rtw_disassoc_cmd23a(padapter, 0, true);
1858
1859 if (check_fwstate(pmlmepriv, _FW_LINKED))
1860 rtw_indicate_disconnect23a(padapter);
1861
1862 rtw_free_assoc_resources23a(padapter, 1);
1863
1864 if (check_fwstate(pmlmepriv,
1865 WIFI_ADHOC_MASTER_STATE)) {
1866 _clr_fwstate_(pmlmepriv,
1867 WIFI_ADHOC_MASTER_STATE);
1868 set_fwstate(pmlmepriv,
1869 WIFI_ADHOC_STATE);
1870 }
1871 } else {
1872 rtw_lps_ctrl_wk_cmd23a(padapter,
1873 LPS_CTRL_JOINBSS, 1);
1874 }
1875 } else {
1876 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1877 ("Set SSID not the same ssid\n"));
1878 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
Jes Sorensene73d82e2014-06-09 15:16:43 +02001879 ("set_ssid =[%s] len = 0x%x\n",
1880 newnetwork->network.Ssid.ssid,
1881 newnetwork->network.Ssid.ssid_len));
Jes Sorensen97c43612014-06-09 15:16:39 +02001882 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1883 ("assoc_ssid =[%s] len = 0x%x\n",
1884 pmlmepriv->assoc_ssid.ssid,
1885 pmlmepriv->assoc_ssid.ssid_len));
1886
1887 rtw_disassoc_cmd23a(padapter, 0, true);
1888
1889 if (check_fwstate(pmlmepriv, _FW_LINKED))
1890 rtw_indicate_disconnect23a(padapter);
1891
1892 rtw_free_assoc_resources23a(padapter, 1);
1893
1894 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1895 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
1896 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
1897 }
1898 }
1899 }
1900
1901handle_tkip_countermeasure:
1902
1903 if (padapter->securitypriv.btkip_countermeasure == true) {
1904 cur_time = jiffies;
1905
1906 if ((cur_time -
1907 padapter->securitypriv.btkip_countermeasure_time) >
1908 60 * HZ) {
1909 padapter->securitypriv.btkip_countermeasure = false;
1910 padapter->securitypriv.btkip_countermeasure_time = 0;
1911 } else {
1912 status = _FAIL;
1913 goto release_mlme_lock;
1914 }
1915 }
1916
Jes Sorensene73d82e2014-06-09 15:16:43 +02001917 memcpy(&pmlmepriv->assoc_ssid, &newnetwork->network.Ssid,
1918 sizeof(struct cfg80211_ssid));
1919
Jes Sorensen97c43612014-06-09 15:16:39 +02001920 pmlmepriv->assoc_by_bssid = false;
1921
Jes Sorensen72795e92014-06-09 15:16:58 +02001922 pmlmepriv->to_join = true;
Jes Sorensen97c43612014-06-09 15:16:39 +02001923
Jes Sorensen72795e92014-06-09 15:16:58 +02001924 if (!check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
1925 pmlmepriv->cur_network.join_res = -2;
1926
1927 status = rtw_do_join_network(padapter, newnetwork);
1928 if (status == _SUCCESS) {
1929 pmlmepriv->to_join = false;
1930 } else {
1931 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1932 /* switch to ADHOC_MASTER */
1933 status = rtw_do_join_adhoc(padapter);
1934 if (status != _SUCCESS)
1935 goto release_mlme_lock;
1936 } else {
1937 /* can't associate ; reset under-linking */
1938 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1939 status = _FAIL;
1940 pmlmepriv->to_join = false;
1941 }
1942 }
1943 }
Jes Sorensen97c43612014-06-09 15:16:39 +02001944release_mlme_lock:
1945 spin_unlock_bh(&pmlmepriv->lock);
1946
1947exit:
1948 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
1949 ("-%s: status =%d\n", __func__, status));
1950
1951 return status;
1952}
1953
Larry Fingerb1925ad2014-03-28 21:37:40 -05001954static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
1955 struct cfg80211_connect_params *sme)
1956{
1957 int ret = 0;
1958 struct list_head *phead, *plist, *ptmp;
1959 struct wlan_network *pnetwork = NULL;
Larry Fingerb1925ad2014-03-28 21:37:40 -05001960 /* u8 matched_by_bssid = false; */
1961 /* u8 matched_by_ssid = false; */
1962 u8 matched = false;
1963 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1964 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1965 struct security_priv *psecuritypriv = &padapter->securitypriv;
1966 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1967
Jes Sorensena790d582014-05-09 15:04:04 +02001968 DBG_8723A("=>" "%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001969 DBG_8723A("privacy =%d, key =%p, key_len =%d, key_idx =%d\n",
1970 sme->privacy, sme->key, sme->key_len, sme->key_idx);
1971
Larry Fingerb1925ad2014-03-28 21:37:40 -05001972 if (_FAIL == rtw_pwr_wakeup(padapter)) {
1973 ret = -EPERM;
1974 goto exit;
1975 }
1976
1977 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1978 ret = -EPERM;
1979 goto exit;
1980 }
1981
Jes Sorensenc5178b02014-06-09 15:16:40 +02001982 if (!sme->ssid || !sme->ssid_len ||
1983 sme->ssid_len > IEEE80211_MAX_SSID_LEN) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05001984 ret = -EINVAL;
1985 goto exit;
1986 }
1987
Jes Sorensenc5178b02014-06-09 15:16:40 +02001988 DBG_8723A("ssid =%s, len =%zu\n", sme->ssid, sme->ssid_len);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001989
1990 if (sme->bssid)
Joe Perchesea072782015-03-24 11:10:09 -07001991 DBG_8723A("bssid=%pM\n", sme->bssid);
Larry Fingerb1925ad2014-03-28 21:37:40 -05001992
1993 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
1994 ret = -EBUSY;
1995 DBG_8723A("%s, fw_state = 0x%x, goto exit\n", __func__,
1996 pmlmepriv->fw_state);
1997 goto exit;
1998 }
1999 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
2000 rtw_scan_abort23a(padapter);
2001 }
2002
2003 spin_lock_bh(&queue->lock);
2004
2005 phead = get_list_head(queue);
2006
2007 list_for_each_safe(plist, ptmp, phead) {
2008 pnetwork = container_of(plist, struct wlan_network, list);
2009
Larry Fingerb1925ad2014-03-28 21:37:40 -05002010 if (sme->bssid) {
Jes Sorensencc2db7c2014-05-25 22:43:12 +02002011 if (!ether_addr_equal(pnetwork->network.MacAddress,
2012 sme->bssid))
Larry Fingerb1925ad2014-03-28 21:37:40 -05002013 continue;
2014 }
2015
2016 if (sme->ssid && sme->ssid_len) {
2017 if (pnetwork->network.Ssid.ssid_len != sme->ssid_len ||
2018 memcmp(pnetwork->network.Ssid.ssid, sme->ssid,
2019 sme->ssid_len))
2020 continue;
2021 }
2022
2023 if (sme->bssid) {
Jes Sorensen9ab98d42014-06-09 15:16:41 +02002024 if (ether_addr_equal(pnetwork->network.MacAddress,
2025 sme->bssid)) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05002026 DBG_8723A("matched by bssid\n");
2027
Larry Fingerb1925ad2014-03-28 21:37:40 -05002028 matched = true;
2029 break;
2030 }
Larry Fingerb1925ad2014-03-28 21:37:40 -05002031 } else if (sme->ssid && sme->ssid_len) {
Jes Sorensen9ab98d42014-06-09 15:16:41 +02002032 if (!memcmp(pnetwork->network.Ssid.ssid,
2033 sme->ssid, sme->ssid_len) &&
Jes Sorensenc5178b02014-06-09 15:16:40 +02002034 pnetwork->network.Ssid.ssid_len == sme->ssid_len) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05002035 DBG_8723A("matched by ssid\n");
Jes Sorensenc5178b02014-06-09 15:16:40 +02002036
Larry Fingerb1925ad2014-03-28 21:37:40 -05002037 matched = true;
2038 break;
2039 }
2040 }
2041 }
2042
2043 spin_unlock_bh(&queue->lock);
2044
Jes Sorensenc5178b02014-06-09 15:16:40 +02002045 if (!matched || !pnetwork) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05002046 ret = -ENOENT;
2047 DBG_8723A("connect, matched == false, goto exit\n");
2048 goto exit;
2049 }
2050
Jes Sorensenefc71442014-05-21 09:37:26 +02002051 if (cfg80211_infrastructure_mode(
2052 padapter, pnetwork->network.ifmode) != _SUCCESS) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05002053 ret = -EPERM;
2054 goto exit;
2055 }
2056
2057 psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02002058 psecuritypriv->dot11PrivacyAlgrthm = 0;
2059 psecuritypriv->dot118021XGrpPrivacy = 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002060 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
2061 psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
2062
Jes Sorensenc5178b02014-06-09 15:16:40 +02002063 ret = rtw_cfg80211_set_wpa_version(psecuritypriv,
2064 sme->crypto.wpa_versions);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002065 if (ret < 0)
2066 goto exit;
2067
2068 ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type);
2069
2070 if (ret < 0)
2071 goto exit;
2072
2073 DBG_8723A("%s, ie_len =%zu\n", __func__, sme->ie_len);
2074
2075 ret = rtw_cfg80211_set_wpa_ie(padapter, sme->ie, sme->ie_len);
2076 if (ret < 0)
2077 goto exit;
2078
2079 if (sme->crypto.n_ciphers_pairwise) {
2080 ret = rtw_cfg80211_set_cipher(psecuritypriv,
2081 sme->crypto.ciphers_pairwise[0],
2082 true);
2083 if (ret < 0)
2084 goto exit;
2085 }
2086
2087 /* For WEP Shared auth */
2088 if ((psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Shared ||
2089 psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Auto) &&
2090 sme->key) {
Jes Sorensendeff1152014-05-21 09:37:38 +02002091 struct rtw_wep_key wep_key;
2092 u8 wep_key_idx, wep_key_len;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002093 DBG_8723A("%s(): Shared/Auto WEP\n", __func__);
2094
2095 wep_key_idx = sme->key_idx;
2096 wep_key_len = sme->key_len;
2097
Jes Sorensendeff1152014-05-21 09:37:38 +02002098 if (wep_key_idx > WEP_KEYS || !wep_key_len ||
2099 wep_key_len > WLAN_KEY_LEN_WEP104) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05002100 ret = -EINVAL;
2101 goto exit;
2102 }
2103
Jes Sorensendeff1152014-05-21 09:37:38 +02002104 wep_key_len = wep_key_len <= 5 ? 5 : 13;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002105
Jes Sorensendeff1152014-05-21 09:37:38 +02002106 memset(&wep_key, 0, sizeof(struct rtw_wep_key));
Larry Fingerb1925ad2014-03-28 21:37:40 -05002107
Jes Sorensendeff1152014-05-21 09:37:38 +02002108 wep_key.keylen = wep_key_len;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002109
Jes Sorensendeff1152014-05-21 09:37:38 +02002110 if (wep_key_len == 13) {
2111 padapter->securitypriv.dot11PrivacyAlgrthm =
2112 WLAN_CIPHER_SUITE_WEP104;
2113 padapter->securitypriv.dot118021XGrpPrivacy =
2114 WLAN_CIPHER_SUITE_WEP104;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002115 } else {
Jes Sorensendeff1152014-05-21 09:37:38 +02002116 padapter->securitypriv.dot11PrivacyAlgrthm =
2117 WLAN_CIPHER_SUITE_WEP40;
2118 padapter->securitypriv.dot118021XGrpPrivacy =
2119 WLAN_CIPHER_SUITE_WEP40;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002120 }
2121
Jes Sorensendeff1152014-05-21 09:37:38 +02002122 memcpy(wep_key.key, (void *)sme->key, wep_key.keylen);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002123
Jes Sorensendeff1152014-05-21 09:37:38 +02002124 if (rtw_cfg80211_add_wep(padapter, &wep_key, wep_key_idx) !=
2125 _SUCCESS)
Larry Fingerb1925ad2014-03-28 21:37:40 -05002126 ret = -EOPNOTSUPP;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002127
Larry Fingerb1925ad2014-03-28 21:37:40 -05002128 if (ret < 0)
2129 goto exit;
2130 }
2131
2132 ret = rtw_cfg80211_set_cipher(psecuritypriv,
2133 sme->crypto.cipher_group, false);
2134 if (ret < 0)
Jes Sorensenc5178b02014-06-09 15:16:40 +02002135 goto exit;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002136
2137 if (sme->crypto.n_akm_suites) {
2138 ret = rtw_cfg80211_set_key_mgt(psecuritypriv,
2139 sme->crypto.akm_suites[0]);
2140 if (ret < 0)
2141 goto exit;
2142 }
2143
Jes Sorensen39dbc442014-06-09 15:16:38 +02002144 if (psecuritypriv->ndisauthtype > 3)
2145 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
2146
2147 if (rtw_set_auth23a(padapter, psecuritypriv) != _SUCCESS) {
2148 ret = -EBUSY;
2149 goto exit;
2150 }
Larry Fingerb1925ad2014-03-28 21:37:40 -05002151
2152 /* rtw_set_802_11_encryption_mode(padapter,
2153 padapter->securitypriv.ndisencryptstatus); */
2154
Jes Sorensene73d82e2014-06-09 15:16:43 +02002155 if (rtw_set_ssid(padapter, pnetwork) != _SUCCESS) {
Jes Sorensen97c43612014-06-09 15:16:39 +02002156 ret = -EBUSY;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002157 goto exit;
2158 }
2159
2160 DBG_8723A("set ssid:dot11AuthAlgrthm =%d, dot11PrivacyAlgrthm =%d, "
2161 "dot118021XGrpPrivacy =%d\n", psecuritypriv->dot11AuthAlgrthm,
2162 psecuritypriv->dot11PrivacyAlgrthm,
2163 psecuritypriv->dot118021XGrpPrivacy);
2164
2165exit:
2166
2167 DBG_8723A("<=%s, ret %d\n", __func__, ret);
2168
2169 return ret;
2170}
2171
2172static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev,
2173 u16 reason_code)
2174{
2175 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2176
Jes Sorensena790d582014-05-09 15:04:04 +02002177 DBG_8723A("%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002178
2179 rtw_set_roaming(padapter, 0);
2180
2181 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2182 rtw_scan_abort23a(padapter);
2183 LeaveAllPowerSaveMode23a(padapter);
2184 rtw_disassoc_cmd23a(padapter, 500, false);
2185
2186 DBG_8723A("%s...call rtw_indicate_disconnect23a\n", __func__);
2187
2188 padapter->mlmepriv.not_indic_disco = true;
2189 rtw_indicate_disconnect23a(padapter);
2190 padapter->mlmepriv.not_indic_disco = false;
2191
2192 rtw_free_assoc_resources23a(padapter, 1);
2193 }
2194
2195 return 0;
2196}
2197
2198static int cfg80211_rtw_set_txpower(struct wiphy *wiphy,
2199 struct wireless_dev *wdev,
2200 enum nl80211_tx_power_setting type, int mbm)
2201{
2202 DBG_8723A("%s\n", __func__);
2203 return 0;
2204}
2205
2206static int cfg80211_rtw_get_txpower(struct wiphy *wiphy,
2207 struct wireless_dev *wdev, int *dbm)
2208{
2209 DBG_8723A("%s\n", __func__);
2210 *dbm = (12);
2211 return 0;
2212}
2213
2214inline bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter)
2215{
2216 struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(adapter->rtw_wdev);
2217 return rtw_wdev_priv->power_mgmt;
2218}
2219
2220static int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy,
2221 struct net_device *ndev,
2222 bool enabled, int timeout)
2223{
2224 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2225 struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(padapter->rtw_wdev);
2226
Jes Sorensena790d582014-05-09 15:04:04 +02002227 DBG_8723A("%s(%s): enabled:%u, timeout:%d\n",
2228 __func__, ndev->name, enabled, timeout);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002229
2230 rtw_wdev_priv->power_mgmt = enabled;
2231
2232 if (!enabled)
2233 LPS_Leave23a(padapter);
2234
2235 return 0;
2236}
2237
2238static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,
2239 struct net_device *netdev,
2240 struct cfg80211_pmksa *pmksa)
2241{
2242 u8 index, blInserted = false;
2243 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2244 struct security_priv *psecuritypriv = &padapter->securitypriv;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002245
Jes Sorensena790d582014-05-09 15:04:04 +02002246 DBG_8723A("%s(%s)\n", __func__, netdev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002247
Jes Sorensencc2db7c2014-05-25 22:43:12 +02002248 if (is_zero_ether_addr(pmksa->bssid))
Larry Fingerb1925ad2014-03-28 21:37:40 -05002249 return -EINVAL;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002250
2251 blInserted = false;
2252
2253 /* overwrite PMKID */
2254 for (index = 0; index < NUM_PMKID_CACHE; index++) {
Jes Sorensencc2db7c2014-05-25 22:43:12 +02002255 if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid,
2256 pmksa->bssid)) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05002257 /* BSSID is matched, the same AP => rewrite with
2258 new PMKID. */
Jes Sorensena790d582014-05-09 15:04:04 +02002259 DBG_8723A("%s(%s): BSSID exists in the PMKList.\n",
2260 __func__, netdev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002261
2262 memcpy(psecuritypriv->PMKIDList[index].PMKID,
2263 pmksa->pmkid, WLAN_PMKID_LEN);
2264 psecuritypriv->PMKIDList[index].bUsed = true;
2265 psecuritypriv->PMKIDIndex = index + 1;
2266 blInserted = true;
2267 break;
2268 }
2269 }
2270
2271 if (!blInserted) {
2272 /* Find a new entry */
Jes Sorensena790d582014-05-09 15:04:04 +02002273 DBG_8723A("%s(%s): Use new entry index = %d for this PMKID\n",
2274 __func__, netdev->name, psecuritypriv->PMKIDIndex);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002275
Jes Sorensen888df442014-05-25 22:43:11 +02002276 ether_addr_copy(
2277 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2278 Bssid, pmksa->bssid);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002279 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2280 PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2281
2282 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed =
2283 true;
2284 psecuritypriv->PMKIDIndex++;
2285 if (psecuritypriv->PMKIDIndex == 16) {
2286 psecuritypriv->PMKIDIndex = 0;
2287 }
2288 }
2289
2290 return 0;
2291}
2292
2293static int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,
2294 struct net_device *netdev,
2295 struct cfg80211_pmksa *pmksa)
2296{
2297 u8 index, bMatched = false;
2298 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2299 struct security_priv *psecuritypriv = &padapter->securitypriv;
2300
Jes Sorensena790d582014-05-09 15:04:04 +02002301 DBG_8723A("%s(%s)\n", __func__, netdev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002302
2303 for (index = 0; index < NUM_PMKID_CACHE; index++) {
Jes Sorensencc2db7c2014-05-25 22:43:12 +02002304 if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid,
2305 pmksa->bssid)) {
2306 /* BSSID is matched, the same AP => Remove this PMKID
2307 information and reset it. */
Jes Sorensen43c34be2014-04-15 19:44:20 +02002308 eth_zero_addr(psecuritypriv->PMKIDList[index].Bssid);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002309 memset(psecuritypriv->PMKIDList[index].PMKID, 0x00,
2310 WLAN_PMKID_LEN);
2311 psecuritypriv->PMKIDList[index].bUsed = false;
2312 bMatched = true;
2313 break;
2314 }
2315 }
2316
2317 if (false == bMatched) {
Jes Sorensena790d582014-05-09 15:04:04 +02002318 DBG_8723A("%s(%s): do not have matched BSSID\n", __func__,
2319 netdev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002320 return -EINVAL;
2321 }
2322
2323 return 0;
2324}
2325
2326static int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy,
2327 struct net_device *netdev)
2328{
2329 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2330 struct security_priv *psecuritypriv = &padapter->securitypriv;
2331
Jes Sorensena790d582014-05-09 15:04:04 +02002332 DBG_8723A("%s(%s)\n", __func__, netdev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002333
2334 memset(&psecuritypriv->PMKIDList[0], 0x00,
2335 sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
2336 psecuritypriv->PMKIDIndex = 0;
2337
2338 return 0;
2339}
2340
2341#ifdef CONFIG_8723AU_AP_MODE
2342void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter,
2343 u8 *pmgmt_frame, uint frame_len)
2344{
2345 s32 freq;
2346 int channel;
2347 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2348 struct net_device *ndev = padapter->pnetdev;
2349
2350 DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2351
2352#if defined(RTW_USE_CFG80211_STA_EVENT)
2353 {
2354 struct station_info sinfo;
2355 u8 ie_offset;
Jes Sorensen60e78f3d2014-06-24 15:03:17 +02002356
Larry Fingerb1925ad2014-03-28 21:37:40 -05002357 if (ieee80211_is_assoc_req(hdr->frame_control))
Jes Sorensen60e78f3d2014-06-24 15:03:17 +02002358 ie_offset = offsetof(struct ieee80211_mgmt,
2359 u.assoc_req.variable);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002360 else /* WIFI_REASSOCREQ */
Jes Sorensen60e78f3d2014-06-24 15:03:17 +02002361 ie_offset = offsetof(struct ieee80211_mgmt,
2362 u.reassoc_req.variable);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002363
2364 sinfo.filled = 0;
Jes Sorensen60e78f3d2014-06-24 15:03:17 +02002365 sinfo.assoc_req_ies = pmgmt_frame + ie_offset;
2366 sinfo.assoc_req_ies_len = frame_len - ie_offset;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002367 cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC);
2368 }
2369#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2370 channel = pmlmeext->cur_channel;
2371 if (channel <= RTW_CH_MAX_2G_CHANNEL)
2372 freq = ieee80211_channel_to_frequency(channel,
2373 IEEE80211_BAND_2GHZ);
2374 else
2375 freq = ieee80211_channel_to_frequency(channel,
2376 IEEE80211_BAND_5GHZ);
2377
Jes Sorensen56b0bd92014-05-25 22:43:17 +02002378 cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pmgmt_frame, frame_len,
Vladimir Kondratiev970fdfa2014-08-11 03:29:57 -07002379 0);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002380#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2381}
2382
2383void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter,
2384 unsigned char *da,
2385 unsigned short reason)
2386{
2387 s32 freq;
2388 int channel;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002389 uint frame_len;
Jes Sorensencc531f62014-06-09 15:16:18 +02002390 struct ieee80211_mgmt mgmt;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002391 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2392 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2393 struct net_device *ndev = padapter->pnetdev;
2394
2395 DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2396
Jes Sorensencc531f62014-06-09 15:16:18 +02002397 memset(&mgmt, 0, sizeof(struct ieee80211_mgmt));
Jes Sorensen1daffae2014-05-21 09:37:55 +02002398
Larry Fingerb1925ad2014-03-28 21:37:40 -05002399#if defined(RTW_USE_CFG80211_STA_EVENT)
2400 cfg80211_del_sta(ndev, da, GFP_ATOMIC);
2401#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2402 channel = pmlmeext->cur_channel;
2403 if (channel <= RTW_CH_MAX_2G_CHANNEL)
2404 freq = ieee80211_channel_to_frequency(channel,
2405 IEEE80211_BAND_2GHZ);
2406 else
2407 freq = ieee80211_channel_to_frequency(channel,
2408 IEEE80211_BAND_5GHZ);
2409
Jes Sorensencc531f62014-06-09 15:16:18 +02002410 mgmt.frame_control =
Jes Sorensen036cdd92014-05-21 09:38:11 +02002411 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002412
Jes Sorensencc531f62014-06-09 15:16:18 +02002413 ether_addr_copy(mgmt.da, myid(&padapter->eeprompriv));
2414 ether_addr_copy(mgmt.sa, da);
2415 ether_addr_copy(mgmt.bssid, get_my_bssid23a(&pmlmeinfo->network));
Larry Fingerb1925ad2014-03-28 21:37:40 -05002416
Jes Sorensencc531f62014-06-09 15:16:18 +02002417 mgmt.seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
Larry Fingerb1925ad2014-03-28 21:37:40 -05002418 pmlmeext->mgnt_seq++;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002419
Jes Sorensencc531f62014-06-09 15:16:18 +02002420 mgmt.u.disassoc.reason_code = cpu_to_le16(reason);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002421
Jes Sorensencc531f62014-06-09 15:16:18 +02002422 frame_len = sizeof(struct ieee80211_hdr_3addr) + 2;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002423
Jes Sorensencc531f62014-06-09 15:16:18 +02002424 cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, (u8 *)&mgmt, frame_len,
Vladimir Kondratiev970fdfa2014-08-11 03:29:57 -07002425 0);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002426#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2427}
2428
2429static int rtw_cfg80211_monitor_if_open(struct net_device *ndev)
2430{
Larry Fingerb1925ad2014-03-28 21:37:40 -05002431 DBG_8723A("%s\n", __func__);
2432
Heena Sirwani911f2922014-10-07 14:45:56 +05302433 return 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002434}
2435
2436static int rtw_cfg80211_monitor_if_close(struct net_device *ndev)
2437{
Larry Fingerb1925ad2014-03-28 21:37:40 -05002438 DBG_8723A("%s\n", __func__);
2439
Heena Sirwani911f2922014-10-07 14:45:56 +05302440 return 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002441}
2442
2443static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb,
2444 struct net_device *ndev)
2445{
2446 int ret = 0;
2447 int rtap_len;
2448 int qos_len = 0;
2449 int dot11_hdr_len = 24;
2450 int snap_len = 6;
2451 unsigned char *pdata;
2452 unsigned char src_mac_addr[6];
2453 unsigned char dst_mac_addr[6];
2454 struct ieee80211_hdr *dot11_hdr;
2455 struct ieee80211_radiotap_header *rtap_hdr;
2456 struct rtw_adapter *padapter = netdev_priv(ndev);
2457
Jes Sorensena790d582014-05-09 15:04:04 +02002458 DBG_8723A("%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002459
2460 if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
2461 goto fail;
2462
2463 rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
2464 if (unlikely(rtap_hdr->it_version))
2465 goto fail;
2466
2467 rtap_len = ieee80211_get_radiotap_len(skb->data);
2468 if (unlikely(skb->len < rtap_len))
2469 goto fail;
2470
2471 if (rtap_len != 14) {
2472 DBG_8723A("radiotap len (should be 14): %d\n", rtap_len);
2473 goto fail;
2474 }
2475
2476 /* Skip the ratio tap header */
2477 skb_pull(skb, rtap_len);
2478
2479 dot11_hdr = (struct ieee80211_hdr *)skb->data;
2480 /* Check if the QoS bit is set */
2481 if (ieee80211_is_data(dot11_hdr->frame_control)) {
2482 /* Check if this ia a Wireless Distribution System (WDS) frame
2483 * which has 4 MAC addresses
2484 */
2485 if (ieee80211_is_data_qos(dot11_hdr->frame_control))
2486 qos_len = IEEE80211_QOS_CTL_LEN;
2487 if (ieee80211_has_a4(dot11_hdr->frame_control))
2488 dot11_hdr_len += 6;
2489
2490 memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
2491 memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
2492
2493 /*
2494 * Skip the 802.11 header, QoS (if any) and SNAP,
2495 * but leave spaces for two MAC addresses
2496 */
2497 skb_pull(skb, dot11_hdr_len + qos_len + snap_len -
2498 ETH_ALEN * 2);
2499 pdata = (unsigned char *)skb->data;
Jes Sorensen888df442014-05-25 22:43:11 +02002500 ether_addr_copy(pdata, dst_mac_addr);
2501 ether_addr_copy(pdata + ETH_ALEN, src_mac_addr);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002502
2503 DBG_8723A("should be eapol packet\n");
2504
2505 /* Use the real net device to transmit the packet */
2506 ret = rtw_xmit23a_entry23a(skb, padapter->pnetdev);
2507
2508 return ret;
2509
2510 } else if (ieee80211_is_action(dot11_hdr->frame_control)) {
Jes Sorensen38eb09b2014-05-21 09:38:31 +02002511 struct ieee80211_mgmt *mgmt;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002512 /* only for action frames */
2513 struct xmit_frame *pmgntframe;
2514 struct pkt_attrib *pattrib;
2515 unsigned char *pframe;
2516 /* u8 category, action, OUI_Subtype, dialogToken = 0; */
2517 /* unsigned char *frame_body; */
2518 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2519 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2520 u32 len = skb->len;
2521 u8 category, action;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002522
Jes Sorensen38eb09b2014-05-21 09:38:31 +02002523 mgmt = (struct ieee80211_mgmt *)dot11_hdr;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002524
Joe Perchesea072782015-03-24 11:10:09 -07002525 DBG_8723A("RTW_Tx:da=%pM via %s(%s)\n",
2526 mgmt->da, __func__, ndev->name);
Jes Sorensen38eb09b2014-05-21 09:38:31 +02002527 category = mgmt->u.action.category;
2528 action = mgmt->u.action.u.wme_action.action_code;
Jes Sorensen2e74d332014-06-09 15:16:17 +02002529 DBG_8723A("RTW_Tx:category(%u), action(%u)\n",
2530 category, action);
Jes Sorensen98fb8122014-04-15 19:43:35 +02002531
Larry Fingerb1925ad2014-03-28 21:37:40 -05002532 /* starting alloc mgmt frame to dump it */
2533 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2534 if (pmgntframe == NULL)
2535 goto fail;
2536
2537 /* update attribute */
2538 pattrib = &pmgntframe->attrib;
2539 update_mgntframe_attrib23a(padapter, pattrib);
2540 pattrib->retry_ctrl = false;
2541
2542 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2543
2544 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2545
2546 memcpy(pframe, skb->data, len);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002547 pattrib->pktlen = len;
2548
2549 /* update seq number */
2550 pmlmeext->mgnt_seq = le16_to_cpu(dot11_hdr->seq_ctrl) >> 4;
2551 pattrib->seqnum = pmlmeext->mgnt_seq;
2552 pmlmeext->mgnt_seq++;
2553
2554 pattrib->last_txcmdsz = pattrib->pktlen;
2555
2556 dump_mgntframe23a(padapter, pmgntframe);
2557 }
2558
2559fail:
2560
2561 dev_kfree_skb(skb);
2562
2563 return 0;
2564}
2565
2566static int
2567rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)
2568{
Larry Fingerb1925ad2014-03-28 21:37:40 -05002569 DBG_8723A("%s\n", __func__);
2570
Heena Sirwani911f2922014-10-07 14:45:56 +05302571 return 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002572}
2573
2574static const struct net_device_ops rtw_cfg80211_monitor_if_ops = {
2575 .ndo_open = rtw_cfg80211_monitor_if_open,
2576 .ndo_stop = rtw_cfg80211_monitor_if_close,
2577 .ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
2578 .ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,
2579};
2580
2581static int rtw_cfg80211_add_monitor_if(struct rtw_adapter *padapter, char *name,
2582 struct net_device **ndev)
2583{
2584 int ret = 0;
2585 struct net_device *mon_ndev = NULL;
2586 struct wireless_dev *mon_wdev = NULL;
2587 struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
2588
2589 if (!name) {
Jes Sorensen9cd613c2014-05-09 15:04:03 +02002590 DBG_8723A("%s(%s): without specific name\n",
2591 __func__, padapter->pnetdev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002592 ret = -EINVAL;
2593 goto out;
2594 }
2595
2596 if (pwdev_priv->pmon_ndev) {
Jes Sorensen9cd613c2014-05-09 15:04:03 +02002597 DBG_8723A("%s(%s): monitor interface exist: %s\n", __func__,
2598 padapter->pnetdev->name, pwdev_priv->pmon_ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002599 ret = -EBUSY;
2600 goto out;
2601 }
2602
2603 mon_ndev = alloc_etherdev(sizeof(struct rtw_adapter));
2604 if (!mon_ndev) {
Jes Sorensen9cd613c2014-05-09 15:04:03 +02002605 DBG_8723A("%s(%s): allocate ndev fail\n", __func__,
2606 padapter->pnetdev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002607 ret = -ENOMEM;
2608 goto out;
2609 }
2610
2611 mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;
2612 strncpy(mon_ndev->name, name, IFNAMSIZ);
2613 mon_ndev->name[IFNAMSIZ - 1] = 0;
2614 mon_ndev->destructor = rtw_ndev_destructor;
2615
2616 mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;
2617
2618 /* wdev */
2619 mon_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
2620 if (!mon_wdev) {
Jes Sorensen9cd613c2014-05-09 15:04:03 +02002621 DBG_8723A("%s(%s): allocate mon_wdev fail\n", __func__,
2622 padapter->pnetdev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002623 ret = -ENOMEM;
2624 goto out;
2625 }
2626
2627 mon_wdev->wiphy = padapter->rtw_wdev->wiphy;
2628 mon_wdev->netdev = mon_ndev;
2629 mon_wdev->iftype = NL80211_IFTYPE_MONITOR;
2630 mon_ndev->ieee80211_ptr = mon_wdev;
2631
2632 ret = register_netdevice(mon_ndev);
2633 if (ret) {
2634 goto out;
2635 }
2636
2637 *ndev = pwdev_priv->pmon_ndev = mon_ndev;
2638 memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1);
2639
2640out:
2641 if (ret) {
2642 kfree(mon_wdev);
2643 mon_wdev = NULL;
2644 }
2645
2646 if (ret && mon_ndev) {
2647 free_netdev(mon_ndev);
2648 *ndev = mon_ndev = NULL;
2649 }
2650
2651 return ret;
2652}
2653
2654static struct wireless_dev *
2655cfg80211_rtw_add_virtual_intf(struct wiphy *wiphy, const char *name,
2656 enum nl80211_iftype type, u32 *flags,
2657 struct vif_params *params)
2658{
2659 int ret = 0;
2660 struct net_device *ndev = NULL;
2661 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2662
Jes Sorensen9cd613c2014-05-09 15:04:03 +02002663 DBG_8723A("%s(%s): wiphy:%s, name:%s, type:%d\n", __func__,
2664 padapter->pnetdev->name, wiphy_name(wiphy), name, type);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002665
2666 switch (type) {
2667 case NL80211_IFTYPE_ADHOC:
2668 case NL80211_IFTYPE_AP_VLAN:
2669 case NL80211_IFTYPE_WDS:
2670 case NL80211_IFTYPE_MESH_POINT:
2671 ret = -ENODEV;
2672 break;
2673 case NL80211_IFTYPE_MONITOR:
2674 ret =
2675 rtw_cfg80211_add_monitor_if(padapter, (char *)name, &ndev);
2676 break;
2677
2678 case NL80211_IFTYPE_P2P_CLIENT:
2679 case NL80211_IFTYPE_STATION:
2680 ret = -ENODEV;
2681 break;
2682
2683 case NL80211_IFTYPE_P2P_GO:
2684 case NL80211_IFTYPE_AP:
2685 ret = -ENODEV;
2686 break;
2687 default:
2688 ret = -ENODEV;
2689 DBG_8723A("Unsupported interface type\n");
2690 break;
2691 }
2692
Jes Sorensen9cd613c2014-05-09 15:04:03 +02002693 DBG_8723A("%s(%s): ndev:%p, ret:%d\n", __func__,
2694 padapter->pnetdev->name,
Larry Fingerb1925ad2014-03-28 21:37:40 -05002695 ndev, ret);
2696
2697 return ndev ? ndev->ieee80211_ptr : ERR_PTR(ret);
2698}
2699
2700static int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy,
2701 struct wireless_dev *wdev)
2702{
2703 struct rtw_wdev_priv *pwdev_priv =
2704 (struct rtw_wdev_priv *)wiphy_priv(wiphy);
2705 struct net_device *ndev;
2706 ndev = wdev ? wdev->netdev : NULL;
2707
2708 if (!ndev)
2709 goto exit;
2710
2711 unregister_netdevice(ndev);
2712
2713 if (ndev == pwdev_priv->pmon_ndev) {
2714 pwdev_priv->pmon_ndev = NULL;
2715 pwdev_priv->ifname_mon[0] = '\0';
Jes Sorensena790d582014-05-09 15:04:04 +02002716 DBG_8723A("%s(%s): remove monitor interface\n",
2717 __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002718 }
2719
2720exit:
2721 return 0;
2722}
2723
2724static int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head,
2725 size_t head_len, const u8 *tail, size_t tail_len)
2726{
2727 int ret = 0;
Jes Sorensendb978122014-06-19 11:37:23 +02002728 u8 *pbuf;
Jes Sorensenfb5fd462014-06-24 15:03:20 +02002729 uint len, ielen, wps_ielen = 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002730 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
Jes Sorensenddf5c2b2014-06-19 11:37:24 +02002731 struct wlan_bssid_ex *bss = &pmlmepriv->cur_network.network;
2732 const struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)head;
Jes Sorensenfb5fd462014-06-24 15:03:20 +02002733 struct ieee80211_mgmt *tmpmgmt;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002734 /* struct sta_priv *pstapriv = &padapter->stapriv; */
2735
2736 DBG_8723A("%s beacon_head_len =%zu, beacon_tail_len =%zu\n",
2737 __func__, head_len, tail_len);
2738
2739 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2740 return -EINVAL;
2741
Jes Sorensenddf5c2b2014-06-19 11:37:24 +02002742 if (head_len < offsetof(struct ieee80211_mgmt, u.beacon.variable))
Larry Fingerb1925ad2014-03-28 21:37:40 -05002743 return -EINVAL;
2744
2745 pbuf = kzalloc(head_len + tail_len, GFP_KERNEL);
2746 if (!pbuf)
2747 return -ENOMEM;
Jes Sorensenfb5fd462014-06-24 15:03:20 +02002748 tmpmgmt = (struct ieee80211_mgmt *)pbuf;
Jes Sorensenddf5c2b2014-06-19 11:37:24 +02002749
2750 bss->beacon_interval = get_unaligned_le16(&mgmt->u.beacon.beacon_int);
2751 bss->capability = get_unaligned_le16(&mgmt->u.beacon.capab_info);
2752 bss->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp);
2753
Larry Fingerb1925ad2014-03-28 21:37:40 -05002754 /* 24 = beacon header len. */
Jes Sorensenfb5fd462014-06-24 15:03:20 +02002755 memcpy(pbuf, (void *)head, head_len);
2756 memcpy(pbuf + head_len, (void *)tail, tail_len);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002757
Jes Sorensenfb5fd462014-06-24 15:03:20 +02002758 len = head_len + tail_len;
2759 ielen = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002760 /* check wps ie if inclued */
Jes Sorensend3797af2014-06-09 15:15:56 +02002761 if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2762 WLAN_OUI_TYPE_MICROSOFT_WPS,
Jes Sorensenfb5fd462014-06-24 15:03:20 +02002763 tmpmgmt->u.beacon.variable, ielen))
Larry Fingerb1925ad2014-03-28 21:37:40 -05002764 DBG_8723A("add bcn, wps_ielen =%d\n", wps_ielen);
2765
Larry Fingerb1925ad2014-03-28 21:37:40 -05002766 /* pbss_network->IEs will not include p2p_ie, wfd ie */
Jes Sorensenfb5fd462014-06-24 15:03:20 +02002767 rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0,
Jes Sorensen9300c942014-04-15 19:43:21 +02002768 WLAN_EID_VENDOR_SPECIFIC, P2P_OUI23A, 4);
Jes Sorensenfb5fd462014-06-24 15:03:20 +02002769 rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0,
Jes Sorensen9300c942014-04-15 19:43:21 +02002770 WLAN_EID_VENDOR_SPECIFIC, WFD_OUI23A, 4);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002771
Jes Sorensenfb5fd462014-06-24 15:03:20 +02002772 len = ielen + offsetof(struct ieee80211_mgmt, u.beacon.variable);
2773 if (rtw_check_beacon_data23a(adapter, tmpmgmt, len) == _SUCCESS) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05002774 ret = 0;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002775 } else {
2776 ret = -EINVAL;
2777 }
2778
2779 kfree(pbuf);
2780
2781 return ret;
2782}
2783
2784static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,
2785 struct cfg80211_ap_settings *settings)
2786{
2787 int ret = 0;
2788 struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
2789
Jes Sorensena790d582014-05-09 15:04:04 +02002790 DBG_8723A("%s(%s): hidden_ssid:%d, auth_type:%d\n",
2791 __func__, ndev->name, settings->hidden_ssid,
Larry Fingerb1925ad2014-03-28 21:37:40 -05002792 settings->auth_type);
2793
2794 ret = rtw_add_beacon(adapter, settings->beacon.head,
2795 settings->beacon.head_len, settings->beacon.tail,
2796 settings->beacon.tail_len);
2797
2798 adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode =
2799 settings->hidden_ssid;
2800
2801 if (settings->ssid && settings->ssid_len) {
2802 struct wlan_bssid_ex *pbss_network =
2803 &adapter->mlmepriv.cur_network.network;
2804 struct wlan_bssid_ex *pbss_network_ext =
2805 &adapter->mlmeextpriv.mlmext_info.network;
2806
Larry Fingerb1925ad2014-03-28 21:37:40 -05002807 memcpy(pbss_network->Ssid.ssid, (void *)settings->ssid,
2808 settings->ssid_len);
2809 pbss_network->Ssid.ssid_len = settings->ssid_len;
2810 memcpy(pbss_network_ext->Ssid.ssid, (void *)settings->ssid,
2811 settings->ssid_len);
2812 pbss_network_ext->Ssid.ssid_len = settings->ssid_len;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002813 }
2814
2815 return ret;
2816}
2817
2818static int cfg80211_rtw_change_beacon(struct wiphy *wiphy,
2819 struct net_device *ndev,
2820 struct cfg80211_beacon_data *info)
2821{
2822 int ret = 0;
2823 struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
2824
Jes Sorensena790d582014-05-09 15:04:04 +02002825 DBG_8723A("%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002826
2827 ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail,
2828 info->tail_len);
2829
2830 return ret;
2831}
2832
2833static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
2834{
Jes Sorensena790d582014-05-09 15:04:04 +02002835 DBG_8723A("%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002836 return 0;
2837}
2838
2839static int cfg80211_rtw_add_station(struct wiphy *wiphy,
Linus Torvaldsf9da4552014-06-12 14:27:40 -07002840 struct net_device *ndev, const u8 *mac,
Larry Fingerb1925ad2014-03-28 21:37:40 -05002841 struct station_parameters *params)
2842{
Jes Sorensena790d582014-05-09 15:04:04 +02002843 DBG_8723A("%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002844
2845 return 0;
2846}
2847
2848static int cfg80211_rtw_del_station(struct wiphy *wiphy,
Jouni Malinen89c771e2014-10-10 20:52:40 +03002849 struct net_device *ndev,
2850 struct station_del_parameters *params)
Larry Fingerb1925ad2014-03-28 21:37:40 -05002851{
Jouni Malinen89c771e2014-10-10 20:52:40 +03002852 const u8 *mac = params->mac;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002853 int ret = 0;
2854 struct list_head *phead, *plist, *ptmp;
2855 u8 updated = 0;
2856 struct sta_info *psta;
2857 struct rtw_adapter *padapter = netdev_priv(ndev);
2858 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2859 struct sta_priv *pstapriv = &padapter->stapriv;
2860
Jes Sorensena790d582014-05-09 15:04:04 +02002861 DBG_8723A("+%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002862
2863 if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true) {
2864 DBG_8723A("%s, fw_state != FW_LINKED|WIFI_AP_STATE\n",
2865 __func__);
2866 return -EINVAL;
2867 }
2868
2869 if (!mac) {
2870 DBG_8723A("flush all sta, and cam_entry\n");
2871
2872 flush_all_cam_entry23a(padapter); /* clear CAM */
2873
2874 ret = rtw_sta_flush23a(padapter);
2875
2876 return ret;
2877 }
2878
Joe Perchesea072782015-03-24 11:10:09 -07002879 DBG_8723A("free sta macaddr=%pM\n", mac);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002880
2881 if (is_broadcast_ether_addr(mac))
2882 return -EINVAL;
2883
2884 spin_lock_bh(&pstapriv->asoc_list_lock);
2885
2886 phead = &pstapriv->asoc_list;
2887
2888 /* check asoc_queue */
2889 list_for_each_safe(plist, ptmp, phead) {
2890 psta = container_of(plist, struct sta_info, asoc_list);
2891
Jes Sorensencc2db7c2014-05-25 22:43:12 +02002892 if (ether_addr_equal(mac, psta->hwaddr)) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05002893 if (psta->dot8021xalg == 1 &&
2894 psta->bpairwise_key_installed == false) {
2895 DBG_8723A("%s, sta's dot8021xalg = 1 and "
2896 "key_installed = false\n", __func__);
2897 } else {
2898 DBG_8723A("free psta =%p, aid =%d\n", psta,
2899 psta->aid);
2900
2901 list_del_init(&psta->asoc_list);
2902 pstapriv->asoc_list_cnt--;
2903
2904 /* spin_unlock_bh(&pstapriv->asoc_list_lock); */
2905 updated =
2906 ap_free_sta23a(padapter, psta, true,
2907 WLAN_REASON_DEAUTH_LEAVING);
2908 /* spin_lock_bh(&pstapriv->asoc_list_lock); */
2909
2910 psta = NULL;
2911
2912 break;
2913 }
2914 }
2915 }
2916
2917 spin_unlock_bh(&pstapriv->asoc_list_lock);
2918
2919 associated_clients_update23a(padapter, updated);
2920
Jes Sorensena790d582014-05-09 15:04:04 +02002921 DBG_8723A("-%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002922
2923 return ret;
2924}
2925
2926static int cfg80211_rtw_change_station(struct wiphy *wiphy,
Linus Torvaldsf9da4552014-06-12 14:27:40 -07002927 struct net_device *ndev, const u8 *mac,
Larry Fingerb1925ad2014-03-28 21:37:40 -05002928 struct station_parameters *params)
2929{
Jes Sorensena790d582014-05-09 15:04:04 +02002930 DBG_8723A("%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002931 return 0;
2932}
2933
2934static int cfg80211_rtw_dump_station(struct wiphy *wiphy,
2935 struct net_device *ndev, int idx, u8 *mac,
2936 struct station_info *sinfo)
2937{
Jes Sorensena790d582014-05-09 15:04:04 +02002938 DBG_8723A("%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002939
2940 /* TODO: dump scanned queue */
2941
2942 return -ENOENT;
2943}
2944
2945static int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,
2946 struct bss_parameters *params)
2947{
Jes Sorensena790d582014-05-09 15:04:04 +02002948 DBG_8723A("%s(%s)\n", __func__, ndev->name);
Larry Fingerb1925ad2014-03-28 21:37:40 -05002949 return 0;
2950}
2951#endif /* CONFIG_8723AU_AP_MODE */
2952
Larry Fingerb1925ad2014-03-28 21:37:40 -05002953static int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch,
2954 const u8 *buf, size_t len)
2955{
2956 struct xmit_frame *pmgntframe;
2957 struct pkt_attrib *pattrib;
2958 unsigned char *pframe;
2959 int ret = _FAIL;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002960 struct ieee80211_hdr *pwlanhdr;
2961 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2962 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Fingerb1925ad2014-03-28 21:37:40 -05002963
2964 if (_FAIL == rtw_pwr_wakeup(padapter)) {
2965 ret = -EFAULT;
2966 goto exit;
2967 }
2968
2969 rtw_set_scan_deny(padapter, 1000);
2970
2971 rtw_scan_abort23a(padapter);
2972
2973 if (tx_ch != rtw_get_oper_ch23a(padapter)) {
2974 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
2975 pmlmeext->cur_channel = tx_ch;
2976 set_channel_bwmode23a(padapter, tx_ch,
2977 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
2978 HT_CHANNEL_WIDTH_20);
2979 }
2980
2981 /* starting alloc mgmt frame to dump it */
2982 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
Jes Sorensende62f672014-05-25 22:43:14 +02002983 if (!pmgntframe) {
Larry Fingerb1925ad2014-03-28 21:37:40 -05002984 /* ret = -ENOMEM; */
2985 ret = _FAIL;
2986 goto exit;
2987 }
2988
2989 /* update attribute */
2990 pattrib = &pmgntframe->attrib;
2991 update_mgntframe_attrib23a(padapter, pattrib);
2992 pattrib->retry_ctrl = false;
2993
2994 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2995
2996 pframe = (u8 *) (pmgntframe->buf_addr) + TXDESC_OFFSET;
2997
2998 memcpy(pframe, (void *)buf, len);
2999 pattrib->pktlen = len;
3000
3001 pwlanhdr = (struct ieee80211_hdr *)pframe;
3002 /* update seq number */
3003 pmlmeext->mgnt_seq = le16_to_cpu(pwlanhdr->seq_ctrl) >> 4;
3004 pattrib->seqnum = pmlmeext->mgnt_seq;
3005 pmlmeext->mgnt_seq++;
3006
Larry Fingerb1925ad2014-03-28 21:37:40 -05003007 pattrib->last_txcmdsz = pattrib->pktlen;
3008
Jes Sorensende62f672014-05-25 22:43:14 +02003009 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
Larry Fingerb1925ad2014-03-28 21:37:40 -05003010
Jes Sorensende62f672014-05-25 22:43:14 +02003011 if (ret != _SUCCESS)
3012 DBG_8723A("%s, ack == false\n", __func__);
3013 else
3014 DBG_8723A("%s, ack == true\n", __func__);
Larry Fingerb1925ad2014-03-28 21:37:40 -05003015
3016exit:
3017
Larry Fingerb1925ad2014-03-28 21:37:40 -05003018 DBG_8723A("%s, ret =%d\n", __func__, ret);
Larry Fingerb1925ad2014-03-28 21:37:40 -05003019
3020 return ret;
3021}
3022
3023static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
Larry Fingerb1925ad2014-03-28 21:37:40 -05003024 struct cfg80211_mgmt_tx_params *params,
Larry Fingerb1925ad2014-03-28 21:37:40 -05003025 u64 *cookie)
3026{
3027 struct rtw_adapter *padapter =
3028 (struct rtw_adapter *)wiphy_to_adapter(wiphy);
Larry Fingerb1925ad2014-03-28 21:37:40 -05003029 int ret = 0;
3030 int tx_ret;
3031 u32 dump_limit = RTW_MAX_MGMT_TX_CNT;
3032 u32 dump_cnt = 0;
3033 bool ack = true;
3034 u8 category, action;
Larry Fingerb1925ad2014-03-28 21:37:40 -05003035 unsigned long start = jiffies;
Larry Fingerb1925ad2014-03-28 21:37:40 -05003036 size_t len = params->len;
3037 struct ieee80211_channel *chan = params->chan;
3038 const u8 *buf = params->buf;
Jes Sorensenea2ea442014-05-21 09:38:32 +02003039 struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *)buf;
Larry Fingerb1925ad2014-03-28 21:37:40 -05003040 u8 tx_ch = (u8) ieee80211_frequency_to_channel(chan->center_freq);
3041
Jes Sorensenea2ea442014-05-21 09:38:32 +02003042 if (!ieee80211_is_action(hdr->frame_control))
3043 return -EINVAL;
3044
Larry Fingerb1925ad2014-03-28 21:37:40 -05003045 /* cookie generation */
3046 *cookie = (unsigned long)buf;
3047
Jes Sorensen9cd613c2014-05-09 15:04:03 +02003048 DBG_8723A("%s(%s): len =%zu, ch =%d\n", __func__,
3049 padapter->pnetdev->name, len, tx_ch);
Larry Fingerb1925ad2014-03-28 21:37:40 -05003050
3051 /* indicate ack before issue frame to avoid racing with rsp frame */
Jes Sorensen56b0bd92014-05-25 22:43:17 +02003052 cfg80211_mgmt_tx_status(padapter->rtw_wdev, *cookie, buf, len, ack,
3053 GFP_KERNEL);
Larry Fingerb1925ad2014-03-28 21:37:40 -05003054
Joe Perchesea072782015-03-24 11:10:09 -07003055 DBG_8723A("RTW_Tx:tx_ch =%d, da =%pM\n", tx_ch, hdr->da);
Jes Sorensenea2ea442014-05-21 09:38:32 +02003056 category = hdr->u.action.category;
3057 action = hdr->u.action.u.wme_action.action_code;
Jes Sorensen2e74d332014-06-09 15:16:17 +02003058 DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category, action);
Larry Fingerb1925ad2014-03-28 21:37:40 -05003059
Larry Fingerb1925ad2014-03-28 21:37:40 -05003060 do {
3061 dump_cnt++;
3062 tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, buf, len);
3063 } while (dump_cnt < dump_limit && tx_ret != _SUCCESS);
3064
3065 if (tx_ret != _SUCCESS || dump_cnt > 1) {
Jes Sorensen9cd613c2014-05-09 15:04:03 +02003066 DBG_8723A("%s(%s): %s (%d/%d) in %d ms\n",
3067 __func__, padapter->pnetdev->name,
Larry Fingerb1925ad2014-03-28 21:37:40 -05003068 tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt,
3069 dump_limit, jiffies_to_msecs(jiffies - start));
3070 }
3071
Larry Fingerb1925ad2014-03-28 21:37:40 -05003072 return ret;
3073}
3074
3075static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,
3076 struct wireless_dev *wdev,
3077 u16 frame_type, bool reg)
3078{
Larry Fingerb1925ad2014-03-28 21:37:40 -05003079 if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
3080 return;
3081
3082 return;
3083}
3084
Larry Fingerb1925ad2014-03-28 21:37:40 -05003085static struct cfg80211_ops rtw_cfg80211_ops = {
3086 .change_virtual_intf = cfg80211_rtw_change_iface,
3087 .add_key = cfg80211_rtw_add_key,
3088 .get_key = cfg80211_rtw_get_key,
3089 .del_key = cfg80211_rtw_del_key,
3090 .set_default_key = cfg80211_rtw_set_default_key,
3091 .get_station = cfg80211_rtw_get_station,
3092 .scan = cfg80211_rtw_scan,
3093 .set_wiphy_params = cfg80211_rtw_set_wiphy_params,
3094 .connect = cfg80211_rtw_connect,
3095 .disconnect = cfg80211_rtw_disconnect,
3096 .join_ibss = cfg80211_rtw_join_ibss,
3097 .leave_ibss = cfg80211_rtw_leave_ibss,
3098 .set_tx_power = cfg80211_rtw_set_txpower,
3099 .get_tx_power = cfg80211_rtw_get_txpower,
3100 .set_power_mgmt = cfg80211_rtw_set_power_mgmt,
3101 .set_pmksa = cfg80211_rtw_set_pmksa,
3102 .del_pmksa = cfg80211_rtw_del_pmksa,
3103 .flush_pmksa = cfg80211_rtw_flush_pmksa,
3104
3105#ifdef CONFIG_8723AU_AP_MODE
3106 .add_virtual_intf = cfg80211_rtw_add_virtual_intf,
3107 .del_virtual_intf = cfg80211_rtw_del_virtual_intf,
3108
3109 .start_ap = cfg80211_rtw_start_ap,
3110 .change_beacon = cfg80211_rtw_change_beacon,
3111 .stop_ap = cfg80211_rtw_stop_ap,
3112
3113 .add_station = cfg80211_rtw_add_station,
3114 .del_station = cfg80211_rtw_del_station,
3115 .change_station = cfg80211_rtw_change_station,
3116 .dump_station = cfg80211_rtw_dump_station,
3117 .change_bss = cfg80211_rtw_change_bss,
3118#endif /* CONFIG_8723AU_AP_MODE */
3119
Larry Fingerb1925ad2014-03-28 21:37:40 -05003120 .mgmt_tx = cfg80211_rtw_mgmt_tx,
3121 .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,
3122};
3123
3124static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap,
3125 enum ieee80211_band band, u8 rf_type)
3126{
3127
3128#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */
3129#define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */
3130
3131 ht_cap->ht_supported = true;
3132
3133 ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
3134 IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 |
3135 IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;
3136
3137 /*
3138 *Maximum length of AMPDU that the STA can receive.
3139 *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
3140 */
3141 ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
3142
3143 /*Minimum MPDU start spacing , */
3144 ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
3145
3146 ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
3147
3148 /*
3149 *hw->wiphy->bands[IEEE80211_BAND_2GHZ]
3150 *base on ant_num
3151 *rx_mask: RX mask
3152 *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7
3153 *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15
3154 *if rx_ant >= 3 rx_mask[2]= 0xff;
3155 *if BW_40 rx_mask[4]= 0x01;
3156 *highest supported RX rate
3157 */
3158 if (rf_type == RF_1T1R) {
3159 ht_cap->mcs.rx_mask[0] = 0xFF;
3160 ht_cap->mcs.rx_mask[1] = 0x00;
3161 ht_cap->mcs.rx_mask[4] = 0x01;
3162
Kieron Brownef78c0712014-09-16 23:28:09 +01003163 ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7);
Larry Fingerb1925ad2014-03-28 21:37:40 -05003164 } else if ((rf_type == RF_1T2R) || (rf_type == RF_2T2R)) {
3165 ht_cap->mcs.rx_mask[0] = 0xFF;
3166 ht_cap->mcs.rx_mask[1] = 0xFF;
3167 ht_cap->mcs.rx_mask[4] = 0x01;
3168
Kieron Brownef78c0712014-09-16 23:28:09 +01003169 ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15);
Larry Fingerb1925ad2014-03-28 21:37:40 -05003170 } else {
3171 DBG_8723A("%s, error rf_type =%d\n", __func__, rf_type);
3172 }
3173
3174}
3175
3176void rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter)
3177{
3178 u8 rf_type;
3179 struct ieee80211_supported_band *bands;
3180 struct wireless_dev *pwdev = padapter->rtw_wdev;
3181 struct wiphy *wiphy = pwdev->wiphy;
3182
Jes Sorensenc2370e82014-04-09 23:20:53 +02003183 rf_type = rtl8723a_get_rf_type(padapter);
Larry Fingerb1925ad2014-03-28 21:37:40 -05003184
3185 DBG_8723A("%s:rf_type =%d\n", __func__, rf_type);
3186
3187 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
3188 {
3189 bands = wiphy->bands[IEEE80211_BAND_2GHZ];
3190 if (bands)
3191 rtw_cfg80211_init_ht_capab(&bands->ht_cap,
3192 IEEE80211_BAND_2GHZ,
3193 rf_type);
3194 }
3195
3196 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
3197 {
3198 bands = wiphy->bands[IEEE80211_BAND_5GHZ];
3199 if (bands)
3200 rtw_cfg80211_init_ht_capab(&bands->ht_cap,
3201 IEEE80211_BAND_5GHZ,
3202 rf_type);
3203 }
3204}
3205
3206static void rtw_cfg80211_preinit_wiphy(struct rtw_adapter *padapter,
3207 struct wiphy *wiphy)
3208{
3209 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3210
3211 wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;
3212 wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
3213 wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS;
3214
3215 wiphy->max_remain_on_channel_duration =
3216 RTW_MAX_REMAIN_ON_CHANNEL_DURATION;
3217
3218 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
3219 BIT(NL80211_IFTYPE_ADHOC) |
3220#ifdef CONFIG_8723AU_AP_MODE
3221 BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) |
3222#endif
Larry Fingerb1925ad2014-03-28 21:37:40 -05003223 0;
3224
3225#ifdef CONFIG_8723AU_AP_MODE
3226 wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes;
3227#endif /* CONFIG_8723AU_AP_MODE */
3228
3229 wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
3230
3231 /*
3232 wiphy->iface_combinations = &rtw_combinations;
3233 wiphy->n_iface_combinations = 1;
3234 */
3235
3236 wiphy->cipher_suites = rtw_cipher_suites;
3237 wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);
3238
3239 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
3240 wiphy->bands[IEEE80211_BAND_2GHZ] =
3241 rtw_spt_band_alloc(IEEE80211_BAND_2GHZ);
3242 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
3243 wiphy->bands[IEEE80211_BAND_5GHZ] =
3244 rtw_spt_band_alloc(IEEE80211_BAND_5GHZ);
3245
3246 wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
3247 wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME;
3248
3249 if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
3250 wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
3251 else
3252 wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
3253}
3254
3255int rtw_wdev_alloc(struct rtw_adapter *padapter, struct device *dev)
3256{
3257 int ret = 0;
3258 struct wiphy *wiphy;
3259 struct wireless_dev *wdev;
3260 struct rtw_wdev_priv *pwdev_priv;
3261 struct net_device *pnetdev = padapter->pnetdev;
3262
3263 DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
3264
3265 /* wiphy */
3266 wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wdev_priv));
3267 if (!wiphy) {
3268 DBG_8723A("Couldn't allocate wiphy device\n");
3269 ret = -ENOMEM;
3270 goto exit;
3271 }
Larry Fingerb1925ad2014-03-28 21:37:40 -05003272
3273 /* wdev */
3274 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
3275 if (!wdev) {
3276 DBG_8723A("Couldn't allocate wireless device\n");
3277 ret = -ENOMEM;
Jes Sorensend165e4e2014-05-25 22:43:18 +02003278 goto free_wiphy;
Larry Fingerb1925ad2014-03-28 21:37:40 -05003279 }
Jes Sorensend165e4e2014-05-25 22:43:18 +02003280
3281 set_wiphy_dev(wiphy, dev);
3282 rtw_cfg80211_preinit_wiphy(padapter, wiphy);
3283
3284 ret = wiphy_register(wiphy);
3285 if (ret < 0) {
3286 DBG_8723A("Couldn't register wiphy device\n");
3287 goto free_wdev;
3288 }
3289
Larry Fingerb1925ad2014-03-28 21:37:40 -05003290 wdev->wiphy = wiphy;
3291 wdev->netdev = pnetdev;
3292 /* wdev->iftype = NL80211_IFTYPE_STATION; */
3293 /* for rtw_setopmode_cmd23a() in cfg80211_rtw_change_iface() */
3294 wdev->iftype = NL80211_IFTYPE_MONITOR;
3295 padapter->rtw_wdev = wdev;
3296 pnetdev->ieee80211_ptr = wdev;
3297
3298 /* init pwdev_priv */
3299 pwdev_priv = wdev_to_priv(wdev);
3300 pwdev_priv->rtw_wdev = wdev;
3301 pwdev_priv->pmon_ndev = NULL;
3302 pwdev_priv->ifname_mon[0] = '\0';
3303 pwdev_priv->padapter = padapter;
3304 pwdev_priv->scan_request = NULL;
3305 spin_lock_init(&pwdev_priv->scan_req_lock);
3306
3307 pwdev_priv->p2p_enabled = false;
Larry Fingerb1925ad2014-03-28 21:37:40 -05003308
3309 if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
3310 pwdev_priv->power_mgmt = true;
3311 else
3312 pwdev_priv->power_mgmt = false;
3313
3314 return ret;
Jes Sorensend165e4e2014-05-25 22:43:18 +02003315free_wdev:
3316 kfree(wdev);
Larry Fingerb1925ad2014-03-28 21:37:40 -05003317free_wiphy:
3318 wiphy_free(wiphy);
3319exit:
3320 return ret;
3321}
3322
3323void rtw_wdev_free(struct wireless_dev *wdev)
3324{
Larry Fingerb1925ad2014-03-28 21:37:40 -05003325 DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
3326
3327 if (!wdev)
3328 return;
3329
Larry Fingerb1925ad2014-03-28 21:37:40 -05003330 kfree(wdev->wiphy->bands[IEEE80211_BAND_2GHZ]);
3331 kfree(wdev->wiphy->bands[IEEE80211_BAND_5GHZ]);
3332
3333 wiphy_free(wdev->wiphy);
3334
3335 kfree(wdev);
3336}
3337
3338void rtw_wdev_unregister(struct wireless_dev *wdev)
3339{
3340 struct rtw_wdev_priv *pwdev_priv;
3341
3342 DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
3343
3344 if (!wdev)
3345 return;
3346
3347 pwdev_priv = wdev_to_priv(wdev);
3348
3349 rtw_cfg80211_indicate_scan_done(pwdev_priv, true);
3350
3351 if (pwdev_priv->pmon_ndev) {
3352 DBG_8723A("%s, unregister monitor interface\n", __func__);
3353 unregister_netdev(pwdev_priv->pmon_ndev);
3354 }
3355
3356 wiphy_unregister(wdev->wiphy);
3357}