Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1 | /****************************************************************************** |
| 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 19 | #include <xmit_osdep.h> |
| 20 | |
| 21 | #include "ioctl_cfg80211.h" |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 22 | |
| 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 28 | static 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 | |
| 59 | static 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 | |
| 82 | static 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 | |
| 99 | static 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 | |
| 121 | static 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 | |
| 127 | static 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 | |
| 133 | static 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 | |
| 139 | static 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 | |
| 145 | static struct ieee80211_supported_band * |
| 146 | rtw_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 | |
| 189 | exit: |
| 190 | return spt_band; |
| 191 | } |
| 192 | |
| 193 | static const struct ieee80211_txrx_stypes |
| 194 | rtw_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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 242 | static 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 248 | u16 channel; |
| 249 | u32 freq; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 250 | u8 *notify_ie; |
| 251 | size_t notify_ielen; |
| 252 | s32 notify_signal; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 253 | struct wireless_dev *wdev = padapter->rtw_wdev; |
| 254 | struct wiphy *wiphy = wdev->wiphy; |
| 255 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; |
| 256 | |
Jes Sorensen | 37cb982 | 2014-05-21 09:37:40 +0200 | [diff] [blame] | 257 | channel = pnetwork->network.DSConfig; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 258 | 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 Sorensen | 1de65cc | 2014-06-24 15:03:30 +0200 | [diff] [blame] | 267 | notify_ie = pnetwork->network.IEs; |
| 268 | notify_ielen = pnetwork->network.IELength; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 269 | |
| 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 Sorensen | 60b152c | 2014-10-10 21:41:36 +0200 | [diff] [blame] | 278 | notify_signal = 100 * translate_percentage_to_dbm( |
| 279 | pnetwork->network.SignalStrength); /* dbm */ |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 280 | } |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 281 | |
Jes Sorensen | 4062f7a | 2014-06-19 11:37:17 +0200 | [diff] [blame] | 282 | bss = cfg80211_inform_bss(wiphy, notify_channel, |
Johannes Berg | 5bc8c1f | 2014-08-12 21:01:28 +0200 | [diff] [blame] | 283 | CFG80211_BSS_FTYPE_UNKNOWN, |
Jes Sorensen | 993c52b | 2014-06-19 11:37:18 +0200 | [diff] [blame] | 284 | pnetwork->network.MacAddress, |
| 285 | pnetwork->network.tsf, |
Jes Sorensen | 11a80e8 | 2014-06-19 11:37:21 +0200 | [diff] [blame] | 286 | pnetwork->network.capability, |
Jes Sorensen | 143ced2 | 2014-06-19 11:37:22 +0200 | [diff] [blame] | 287 | pnetwork->network.beacon_interval, |
Jes Sorensen | 4062f7a | 2014-06-19 11:37:17 +0200 | [diff] [blame] | 288 | notify_ie, notify_ielen, |
| 289 | notify_signal, GFP_ATOMIC); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 290 | |
| 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 298 | return ret; |
| 299 | } |
| 300 | |
| 301 | void 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 306 | |
| 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 Sorensen | 5682879 | 2014-04-15 19:44:46 +0200 | [diff] [blame] | 316 | if (padapter->mlmepriv.to_roaming > 0) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 317 | struct wiphy *wiphy = pwdev->wiphy; |
| 318 | struct ieee80211_channel *notify_channel; |
| 319 | u32 freq; |
Jes Sorensen | 37cb982 | 2014-05-21 09:37:40 +0200 | [diff] [blame] | 320 | u16 channel = cur_network->network.DSConfig; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 321 | |
| 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 | |
| 360 | void 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 364 | |
| 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 374 | 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 Sorensen | 16b9632 | 2014-05-16 10:04:41 +0200 | [diff] [blame] | 388 | static int set_pairwise_key(struct rtw_adapter *padapter, struct sta_info *psta) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 389 | { |
| 390 | struct cmd_obj *ph2c; |
| 391 | struct set_stakey_parm *psetstakey_para; |
| 392 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; |
Jes Sorensen | 16b9632 | 2014-05-16 10:04:41 +0200 | [diff] [blame] | 393 | int res = _SUCCESS; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 394 | |
| 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 Sorensen | 7989bcf | 2014-05-21 09:37:31 +0200 | [diff] [blame] | 410 | psetstakey_para->algorithm = psta->dot118021XPrivacy; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 411 | |
Jes Sorensen | 888df44 | 2014-05-25 22:43:11 +0200 | [diff] [blame] | 412 | ether_addr_copy(psetstakey_para->addr, psta->hwaddr); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 413 | |
| 414 | memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16); |
| 415 | |
| 416 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); |
| 417 | |
| 418 | exit: |
| 419 | return res; |
| 420 | } |
| 421 | |
Jes Sorensen | 2dcf6b4 | 2014-06-24 15:03:54 +0200 | [diff] [blame] | 422 | static int set_group_key(struct rtw_adapter *padapter, struct key_params *parms, |
| 423 | u32 alg, u8 keyid) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 424 | { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 425 | 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 Sorensen | 4e489d9 | 2014-05-09 15:04:16 +0200 | [diff] [blame] | 432 | if (keyid >= 4) { |
| 433 | res = _FAIL; |
| 434 | goto exit; |
| 435 | } |
| 436 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 437 | 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 Sorensen | 4e489d9 | 2014-05-09 15:04:16 +0200 | [diff] [blame] | 449 | psetkeyparm->keyid = keyid; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 450 | if (is_wep_enc(alg)) |
Jes Sorensen | 4e489d9 | 2014-05-09 15:04:16 +0200 | [diff] [blame] | 451 | padapter->mlmepriv.key_mask |= BIT(psetkeyparm->keyid); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 452 | |
| 453 | psetkeyparm->algorithm = alg; |
| 454 | |
| 455 | psetkeyparm->set_tx = 1; |
| 456 | |
Jes Sorensen | 2dcf6b4 | 2014-06-24 15:03:54 +0200 | [diff] [blame] | 457 | memcpy(&psetkeyparm->key, parms->key, parms->key_len); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 458 | |
| 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 465 | res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); |
| 466 | |
| 467 | exit: |
| 468 | return res; |
| 469 | } |
| 470 | |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 471 | static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, u8 key_index, |
Jes Sorensen | f88ab54 | 2014-06-24 15:03:50 +0200 | [diff] [blame] | 472 | int set_tx, const u8 *sta_addr, |
Jes Sorensen | 5dab9e7 | 2014-06-24 15:03:35 +0200 | [diff] [blame] | 473 | struct key_params *keyparms) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 474 | { |
Jes Sorensen | c36e122 | 2014-06-24 15:03:37 +0200 | [diff] [blame] | 475 | int key_len; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 476 | struct sta_info *psta = NULL, *pbcmc_sta = NULL; |
| 477 | struct rtw_adapter *padapter = netdev_priv(dev); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 478 | struct security_priv *psecuritypriv = &padapter->securitypriv; |
| 479 | struct sta_priv *pstapriv = &padapter->stapriv; |
| 480 | |
| 481 | DBG_8723A("%s\n", __func__); |
| 482 | |
Jes Sorensen | 7ef2743 | 2014-06-24 15:03:53 +0200 | [diff] [blame] | 483 | if (!is_broadcast_ether_addr(sta_addr)) { |
Jes Sorensen | f88ab54 | 2014-06-24 15:03:50 +0200 | [diff] [blame] | 484 | psta = rtw_get_stainfo23a(pstapriv, sta_addr); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 485 | 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 Sorensen | c36e122 | 2014-06-24 15:03:37 +0200 | [diff] [blame] | 493 | key_len = keyparms->key_len; |
| 494 | |
Jes Sorensen | 5dab9e7 | 2014-06-24 15:03:35 +0200 | [diff] [blame] | 495 | if (!psta && (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || |
| 496 | keyparms->cipher == WLAN_CIPHER_SUITE_WEP104)) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 497 | DBG_8723A("r871x_set_encryption, crypt.alg = WEP\n"); |
| 498 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 499 | DBG_8723A("r871x_set_encryption, wep_key_idx =%d, len =%d\n", |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 500 | key_index, key_len); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 501 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 502 | 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 Sorensen | 55db5d0 | 2014-06-24 15:03:39 +0200 | [diff] [blame] | 508 | psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher; |
| 509 | psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 510 | |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 511 | psecuritypriv->dot11PrivacyKeyIndex = key_index; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 512 | } |
| 513 | |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 514 | memcpy(&psecuritypriv->wep_key[key_index].key, |
Jes Sorensen | c36e122 | 2014-06-24 15:03:37 +0200 | [diff] [blame] | 515 | keyparms->key, key_len); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 516 | |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 517 | psecuritypriv->wep_key[key_index].keylen = key_len; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 518 | |
Jes Sorensen | 2dcf6b4 | 2014-06-24 15:03:54 +0200 | [diff] [blame] | 519 | set_group_key(padapter, keyparms, keyparms->cipher, key_index); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 520 | |
| 521 | goto exit; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 522 | } |
| 523 | |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 524 | if (!psta) { /* group key */ |
Jes Sorensen | 0996cf9 | 2014-06-24 15:03:47 +0200 | [diff] [blame] | 525 | if (set_tx == 0) { /* group key */ |
Jes Sorensen | 5dab9e7 | 2014-06-24 15:03:35 +0200 | [diff] [blame] | 526 | if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || |
| 527 | keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { |
Jes Sorensen | 9cd613c | 2014-05-09 15:04:03 +0200 | [diff] [blame] | 528 | DBG_8723A("%s, set group_key, WEP\n", __func__); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 529 | |
| 530 | memcpy(psecuritypriv-> |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 531 | dot118021XGrpKey[key_index].skey, |
Jes Sorensen | 7ef2743 | 2014-06-24 15:03:53 +0200 | [diff] [blame] | 532 | keyparms->key, key_len); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 533 | |
Jes Sorensen | 55db5d0 | 2014-06-24 15:03:39 +0200 | [diff] [blame] | 534 | psecuritypriv->dot118021XGrpPrivacy = |
| 535 | keyparms->cipher; |
Jes Sorensen | 5dab9e7 | 2014-06-24 15:03:35 +0200 | [diff] [blame] | 536 | } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 537 | DBG_8723A("%s, set group_key, TKIP\n", |
| 538 | __func__); |
| 539 | |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 540 | psecuritypriv->dot118021XGrpPrivacy = |
| 541 | WLAN_CIPHER_SUITE_TKIP; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 542 | |
| 543 | memcpy(psecuritypriv-> |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 544 | dot118021XGrpKey[key_index].skey, |
Jes Sorensen | fd38187 | 2014-06-24 15:03:46 +0200 | [diff] [blame] | 545 | keyparms->key, |
Jes Sorensen | c36e122 | 2014-06-24 15:03:37 +0200 | [diff] [blame] | 546 | (key_len > 16 ? 16 : key_len)); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 547 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 548 | /* set mic key */ |
| 549 | memcpy(psecuritypriv-> |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 550 | dot118021XGrptxmickey[key_index].skey, |
Jes Sorensen | fd38187 | 2014-06-24 15:03:46 +0200 | [diff] [blame] | 551 | &keyparms->key[16], 8); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 552 | memcpy(psecuritypriv-> |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 553 | dot118021XGrprxmickey[key_index].skey, |
Jes Sorensen | fd38187 | 2014-06-24 15:03:46 +0200 | [diff] [blame] | 554 | &keyparms->key[24], 8); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 555 | |
Jes Sorensen | 9216c51 | 2014-05-21 09:37:29 +0200 | [diff] [blame] | 556 | psecuritypriv->busetkipkey = 1; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 557 | |
Jes Sorensen | 5dab9e7 | 2014-06-24 15:03:35 +0200 | [diff] [blame] | 558 | } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) { |
| 559 | DBG_8723A("%s, set group_key, CCMP\n", |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 560 | __func__); |
| 561 | |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 562 | psecuritypriv->dot118021XGrpPrivacy = |
| 563 | WLAN_CIPHER_SUITE_CCMP; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 564 | |
| 565 | memcpy(psecuritypriv-> |
Jes Sorensen | fd38187 | 2014-06-24 15:03:46 +0200 | [diff] [blame] | 566 | dot118021XGrpKey[key_index].skey, |
| 567 | keyparms->key, |
Jes Sorensen | c36e122 | 2014-06-24 15:03:37 +0200 | [diff] [blame] | 568 | (key_len > 16 ? 16 : key_len)); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 569 | } else { |
| 570 | DBG_8723A("%s, set group_key, none\n", |
| 571 | __func__); |
| 572 | |
Jes Sorensen | 7ef2743 | 2014-06-24 15:03:53 +0200 | [diff] [blame] | 573 | psecuritypriv->dot118021XGrpPrivacy = 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 574 | } |
| 575 | |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 576 | psecuritypriv->dot118021XGrpKeyid = key_index; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 577 | |
Jes Sorensen | 9216c51 | 2014-05-21 09:37:29 +0200 | [diff] [blame] | 578 | psecuritypriv->binstallGrpkey = 1; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 579 | |
| 580 | psecuritypriv->dot11PrivacyAlgrthm = |
| 581 | psecuritypriv->dot118021XGrpPrivacy; |
| 582 | |
Jes Sorensen | 2dcf6b4 | 2014-06-24 15:03:54 +0200 | [diff] [blame] | 583 | set_group_key(padapter, keyparms, |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 584 | psecuritypriv->dot118021XGrpPrivacy, |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 585 | key_index); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 586 | |
| 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 Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 601 | if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { |
| 602 | /* psk/802_1x */ |
Jes Sorensen | 0996cf9 | 2014-06-24 15:03:47 +0200 | [diff] [blame] | 603 | if (set_tx == 1) { |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 604 | /* pairwise key */ |
| 605 | memcpy(psta->dot118021x_UncstKey.skey, |
Jes Sorensen | fd38187 | 2014-06-24 15:03:46 +0200 | [diff] [blame] | 606 | keyparms->key, (key_len > 16 ? 16 : key_len)); |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 607 | |
| 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 Sorensen | 55db5d0 | 2014-06-24 15:03:39 +0200 | [diff] [blame] | 613 | psecuritypriv->dot118021XGrpPrivacy = |
| 614 | keyparms->cipher; |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 615 | } 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 Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 622 | /* set mic key */ |
| 623 | memcpy(psta->dot11tkiptxmickey.skey, |
Jes Sorensen | fd38187 | 2014-06-24 15:03:46 +0200 | [diff] [blame] | 624 | &keyparms->key[16], 8); |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 625 | memcpy(psta->dot11tkiprxmickey.skey, |
Jes Sorensen | fd38187 | 2014-06-24 15:03:46 +0200 | [diff] [blame] | 626 | &keyparms->key[24], 8); |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 627 | |
| 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 Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 652 | dot118021XGrpKey[key_index].skey, |
Jes Sorensen | 7ef2743 | 2014-06-24 15:03:53 +0200 | [diff] [blame] | 653 | keyparms->key, key_len); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 654 | |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 655 | psecuritypriv->dot118021XGrpPrivacy = |
Jes Sorensen | 55db5d0 | 2014-06-24 15:03:39 +0200 | [diff] [blame] | 656 | keyparms->cipher; |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 657 | } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) { |
| 658 | psecuritypriv->dot118021XGrpPrivacy = |
| 659 | WLAN_CIPHER_SUITE_TKIP; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 660 | |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 661 | memcpy(psecuritypriv-> |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 662 | dot118021XGrpKey[key_index].skey, |
Jes Sorensen | fd38187 | 2014-06-24 15:03:46 +0200 | [diff] [blame] | 663 | keyparms->key, |
Jes Sorensen | c36e122 | 2014-06-24 15:03:37 +0200 | [diff] [blame] | 664 | (key_len > 16 ? 16 : key_len)); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 665 | |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 666 | /* set mic key */ |
| 667 | memcpy(psecuritypriv-> |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 668 | dot118021XGrptxmickey[key_index].skey, |
Jes Sorensen | fd38187 | 2014-06-24 15:03:46 +0200 | [diff] [blame] | 669 | &keyparms->key[16], 8); |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 670 | memcpy(psecuritypriv-> |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 671 | dot118021XGrprxmickey[key_index].skey, |
Jes Sorensen | fd38187 | 2014-06-24 15:03:46 +0200 | [diff] [blame] | 672 | &keyparms->key[24], 8); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 673 | |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 674 | psecuritypriv->busetkipkey = 1; |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 675 | } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) { |
| 676 | psecuritypriv->dot118021XGrpPrivacy = |
| 677 | WLAN_CIPHER_SUITE_CCMP; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 678 | |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 679 | memcpy(psecuritypriv-> |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 680 | dot118021XGrpKey[key_index].skey, |
Jes Sorensen | fd38187 | 2014-06-24 15:03:46 +0200 | [diff] [blame] | 681 | keyparms->key, |
Jes Sorensen | c36e122 | 2014-06-24 15:03:37 +0200 | [diff] [blame] | 682 | (key_len > 16 ? 16 : key_len)); |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 683 | } else { |
| 684 | psecuritypriv->dot118021XGrpPrivacy = 0; |
| 685 | } |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 686 | |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 687 | psecuritypriv->dot118021XGrpKeyid = key_index; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 688 | |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 689 | psecuritypriv->binstallGrpkey = 1; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 690 | |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 691 | psecuritypriv->dot11PrivacyAlgrthm = |
| 692 | psecuritypriv->dot118021XGrpPrivacy; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 693 | |
Jes Sorensen | 2dcf6b4 | 2014-06-24 15:03:54 +0200 | [diff] [blame] | 694 | set_group_key(padapter, keyparms, |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 695 | psecuritypriv->dot118021XGrpPrivacy, |
Jes Sorensen | f7ce87c | 2014-06-24 15:03:45 +0200 | [diff] [blame] | 696 | key_index); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 697 | |
Jes Sorensen | 4e297c2 | 2014-06-24 15:03:36 +0200 | [diff] [blame] | 698 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 704 | psecuritypriv->dot118021XGrpPrivacy; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 705 | } |
| 706 | } |
| 707 | } |
| 708 | |
| 709 | exit: |
| 710 | |
Heena Sirwani | 911f292 | 2014-10-07 14:45:56 +0530 | [diff] [blame] | 711 | return 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 712 | } |
| 713 | #endif |
| 714 | |
Jes Sorensen | 5292a89 | 2014-06-24 15:03:44 +0200 | [diff] [blame] | 715 | static int rtw_cfg80211_set_encryption(struct net_device *dev, u8 key_index, |
Jes Sorensen | f88ab54 | 2014-06-24 15:03:50 +0200 | [diff] [blame] | 716 | int set_tx, const u8 *sta_addr, |
Jes Sorensen | a9e346f | 2014-06-24 15:03:40 +0200 | [diff] [blame] | 717 | struct key_params *keyparms) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 718 | { |
| 719 | int ret = 0; |
Jes Sorensen | d0dc266 | 2014-06-24 15:03:41 +0200 | [diff] [blame] | 720 | int key_len; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 721 | struct rtw_adapter *padapter = netdev_priv(dev); |
| 722 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; |
| 723 | struct security_priv *psecuritypriv = &padapter->securitypriv; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 724 | |
| 725 | DBG_8723A("%s\n", __func__); |
| 726 | |
Jes Sorensen | d0dc266 | 2014-06-24 15:03:41 +0200 | [diff] [blame] | 727 | key_len = keyparms->key_len; |
| 728 | |
Jes Sorensen | 8188b1c | 2014-06-24 15:03:42 +0200 | [diff] [blame] | 729 | if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || |
| 730 | keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 731 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 735 | if (psecuritypriv->bWepDefaultKeyIdxSet == 0) { |
| 736 | /* wep default key has not been set, so use this |
| 737 | key index as default key. */ |
| 738 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 739 | psecuritypriv->ndisencryptstatus = |
| 740 | Ndis802_11Encryption1Enabled; |
Jes Sorensen | 7ef2743 | 2014-06-24 15:03:53 +0200 | [diff] [blame] | 741 | psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher; |
| 742 | psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 743 | |
Jes Sorensen | 5292a89 | 2014-06-24 15:03:44 +0200 | [diff] [blame] | 744 | psecuritypriv->dot11PrivacyKeyIndex = key_index; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 745 | } |
| 746 | |
Jes Sorensen | 5292a89 | 2014-06-24 15:03:44 +0200 | [diff] [blame] | 747 | memcpy(&psecuritypriv->wep_key[key_index].key, |
Jes Sorensen | e1343f9 | 2014-06-24 15:03:43 +0200 | [diff] [blame] | 748 | keyparms->key, key_len); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 749 | |
Jes Sorensen | 5292a89 | 2014-06-24 15:03:44 +0200 | [diff] [blame] | 750 | psecuritypriv->wep_key[key_index].keylen = key_len; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 751 | |
Jes Sorensen | 5292a89 | 2014-06-24 15:03:44 +0200 | [diff] [blame] | 752 | rtw_set_key23a(padapter, psecuritypriv, key_index, 0); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 753 | |
| 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 Sorensen | efd4216 | 2014-06-24 15:03:49 +0200 | [diff] [blame] | 772 | if (keyparms->cipher != IW_AUTH_CIPHER_NONE && |
| 773 | keyparms->cipher != 0) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 774 | 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 Sorensen | 0996cf9 | 2014-06-24 15:03:47 +0200 | [diff] [blame] | 785 | if (set_tx == 1) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 786 | /* pairwise key */ |
Jes Sorensen | 0996cf9 | 2014-06-24 15:03:47 +0200 | [diff] [blame] | 787 | DBG_8723A("%s, : set_tx == 1\n", |
| 788 | __func__); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 789 | |
| 790 | memcpy(psta->dot118021x_UncstKey.skey, |
Jes Sorensen | e1343f9 | 2014-06-24 15:03:43 +0200 | [diff] [blame] | 791 | keyparms->key, |
Jes Sorensen | d0dc266 | 2014-06-24 15:03:41 +0200 | [diff] [blame] | 792 | (key_len > 16 ? 16 : key_len)); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 793 | |
Jes Sorensen | 8188b1c | 2014-06-24 15:03:42 +0200 | [diff] [blame] | 794 | if (keyparms->cipher == |
| 795 | WLAN_CIPHER_SUITE_TKIP) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 796 | memcpy(psta->dot11tkiptxmickey. |
| 797 | skey, |
Jes Sorensen | e1343f9 | 2014-06-24 15:03:43 +0200 | [diff] [blame] | 798 | &keyparms->key[16], 8); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 799 | memcpy(psta->dot11tkiprxmickey. |
| 800 | skey, |
Jes Sorensen | e1343f9 | 2014-06-24 15:03:43 +0200 | [diff] [blame] | 801 | &keyparms->key[24], 8); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 802 | |
| 803 | padapter->securitypriv. |
Jes Sorensen | 9216c51 | 2014-05-21 09:37:29 +0200 | [diff] [blame] | 804 | busetkipkey = 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 805 | } |
| 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 Sorensen | 5292a89 | 2014-06-24 15:03:44 +0200 | [diff] [blame] | 813 | dot118021XGrpKey[key_index].skey, |
Jes Sorensen | e1343f9 | 2014-06-24 15:03:43 +0200 | [diff] [blame] | 814 | keyparms->key, |
Jes Sorensen | d0dc266 | 2014-06-24 15:03:41 +0200 | [diff] [blame] | 815 | (key_len > 16 ? 16 : key_len)); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 816 | memcpy(padapter->securitypriv. |
Jes Sorensen | 5292a89 | 2014-06-24 15:03:44 +0200 | [diff] [blame] | 817 | dot118021XGrptxmickey[key_index]. |
Jes Sorensen | e1343f9 | 2014-06-24 15:03:43 +0200 | [diff] [blame] | 818 | skey, &keyparms->key[16], 8); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 819 | memcpy(padapter->securitypriv. |
Jes Sorensen | 5292a89 | 2014-06-24 15:03:44 +0200 | [diff] [blame] | 820 | dot118021XGrprxmickey[key_index]. |
Jes Sorensen | e1343f9 | 2014-06-24 15:03:43 +0200 | [diff] [blame] | 821 | skey, &keyparms->key[24], 8); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 822 | padapter->securitypriv.binstallGrpkey = |
Jes Sorensen | 9216c51 | 2014-05-21 09:37:29 +0200 | [diff] [blame] | 823 | 1; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 824 | DBG_8723A |
| 825 | (" ~~~~set sta key:groupkey\n"); |
| 826 | |
| 827 | padapter->securitypriv. |
Jes Sorensen | 5292a89 | 2014-06-24 15:03:44 +0200 | [diff] [blame] | 828 | dot118021XGrpKeyid = key_index; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 829 | |
| 830 | rtw_set_key23a(padapter, |
| 831 | &padapter->securitypriv, |
Jes Sorensen | 5292a89 | 2014-06-24 15:03:44 +0200 | [diff] [blame] | 832 | key_index, 1); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 833 | } |
| 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 Sorensen | efd4216 | 2014-06-24 15:03:49 +0200 | [diff] [blame] | 840 | if (keyparms->cipher != IW_AUTH_CIPHER_NONE && |
| 841 | keyparms->cipher != 0) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 842 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 853 | } |
| 854 | } |
| 855 | |
| 856 | exit: |
| 857 | |
| 858 | DBG_8723A("%s, ret =%d\n", __func__, ret); |
| 859 | |
| 860 | |
| 861 | |
| 862 | return ret; |
| 863 | } |
| 864 | |
| 865 | static 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 Sorensen | 0996cf9 | 2014-06-24 15:03:47 +0200 | [diff] [blame] | 869 | int set_tx, ret = 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 870 | 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 Sorensen | f88ab54 | 2014-06-24 15:03:50 +0200 | [diff] [blame] | 873 | u8 sta_addr[ETH_ALEN]; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 874 | |
Jes Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 875 | DBG_8723A("%s(%s): adding key for %pM\n", __func__, ndev->name, |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 876 | 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 Sorensen | efd4216 | 2014-06-24 15:03:49 +0200 | [diff] [blame] | 883 | switch (params->cipher) { |
| 884 | case IW_AUTH_CIPHER_NONE: |
| 885 | case WLAN_CIPHER_SUITE_WEP40: |
Jes Sorensen | 7ef2743 | 2014-06-24 15:03:53 +0200 | [diff] [blame] | 886 | if (params->key_len != WLAN_KEY_LEN_WEP40) { |
| 887 | ret = -EINVAL; |
| 888 | goto exit; |
| 889 | } |
Jes Sorensen | efd4216 | 2014-06-24 15:03:49 +0200 | [diff] [blame] | 890 | case WLAN_CIPHER_SUITE_WEP104: |
Jes Sorensen | 7ef2743 | 2014-06-24 15:03:53 +0200 | [diff] [blame] | 891 | if (params->key_len != WLAN_KEY_LEN_WEP104) { |
| 892 | ret = -EINVAL; |
| 893 | goto exit; |
| 894 | } |
Jes Sorensen | efd4216 | 2014-06-24 15:03:49 +0200 | [diff] [blame] | 895 | case WLAN_CIPHER_SUITE_TKIP: |
| 896 | case WLAN_CIPHER_SUITE_CCMP: |
| 897 | break; |
| 898 | default: |
| 899 | ret = -ENOTSUPP; |
| 900 | goto exit; |
| 901 | } |
| 902 | |
Jes Sorensen | 7ef2743 | 2014-06-24 15:03:53 +0200 | [diff] [blame] | 903 | if (key_index >= WEP_KEYS || params->key_len < 0) { |
| 904 | ret = -EINVAL; |
| 905 | goto exit; |
| 906 | } |
| 907 | |
Jes Sorensen | f88ab54 | 2014-06-24 15:03:50 +0200 | [diff] [blame] | 908 | eth_broadcast_addr(sta_addr); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 909 | |
Jes Sorensen | 0996cf9 | 2014-06-24 15:03:47 +0200 | [diff] [blame] | 910 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 914 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 915 | if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { |
Jes Sorensen | 0996cf9 | 2014-06-24 15:03:47 +0200 | [diff] [blame] | 916 | ret = rtw_cfg80211_set_encryption(ndev, key_index, set_tx, |
Jes Sorensen | f0bf8dd | 2014-06-24 15:03:51 +0200 | [diff] [blame] | 917 | sta_addr, params); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 918 | } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { |
| 919 | #ifdef CONFIG_8723AU_AP_MODE |
| 920 | if (mac_addr) |
Jes Sorensen | f88ab54 | 2014-06-24 15:03:50 +0200 | [diff] [blame] | 921 | ether_addr_copy(sta_addr, mac_addr); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 922 | |
Jes Sorensen | 0996cf9 | 2014-06-24 15:03:47 +0200 | [diff] [blame] | 923 | ret = rtw_cfg80211_ap_set_encryption(ndev, key_index, set_tx, |
Jes Sorensen | f0bf8dd | 2014-06-24 15:03:51 +0200 | [diff] [blame] | 924 | sta_addr, params); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 925 | #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 Sorensen | efd4216 | 2014-06-24 15:03:49 +0200 | [diff] [blame] | 932 | exit: |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 933 | return ret; |
| 934 | } |
| 935 | |
| 936 | static int |
| 937 | cfg80211_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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 942 | DBG_8723A("%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 943 | return 0; |
| 944 | } |
| 945 | |
| 946 | static 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 953 | DBG_8723A("%s(%s): key_index =%d\n", __func__, ndev->name, key_index); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 954 | |
| 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 | |
| 963 | static 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 970 | DBG_8723A("%s(%s): key_index =%d, unicast =%d, multicast =%d.\n", |
| 971 | __func__, ndev->name, key_index, unicast, multicast); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 972 | |
Jes Sorensen | e082790 | 2014-05-21 09:37:35 +0200 | [diff] [blame] | 973 | if (key_index < NUM_WEP_KEYS && |
| 974 | (psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP40 || |
| 975 | psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP104)) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 976 | /* set wep default key */ |
| 977 | psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled; |
| 978 | |
| 979 | psecuritypriv->dot11PrivacyKeyIndex = key_index; |
| 980 | |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 981 | psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40; |
| 982 | psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40; |
Jes Sorensen | e082790 | 2014-05-21 09:37:35 +0200 | [diff] [blame] | 983 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 988 | } |
| 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 Sorensen | 27fd731 | 2014-06-09 15:17:03 +0200 | [diff] [blame] | 998 | static 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 Sorensen | 1d33b07 | 2014-06-24 15:03:19 +0200 | [diff] [blame] | 1013 | p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, |
Jes Sorensen | 1de65cc | 2014-06-24 15:03:30 +0200 | [diff] [blame] | 1014 | pcur_bss->IEs, pcur_bss->IELength); |
Jes Sorensen | 27fd731 | 2014-06-09 15:17:03 +0200 | [diff] [blame] | 1015 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1055 | static int cfg80211_rtw_get_station(struct wiphy *wiphy, |
| 1056 | struct net_device *ndev, |
Linus Torvalds | f9da455 | 2014-06-12 14:27:40 -0700 | [diff] [blame] | 1057 | const u8 *mac, struct station_info *sinfo) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1058 | { |
| 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 1068 | DBG_8723A("%s(%s): mac ==%p\n", __func__, ndev->name, mac); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1069 | 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 Perches | ea07278 | 2015-03-24 11:10:09 -0700 | [diff] [blame^] | 1079 | DBG_8723A("%s(%s): mac=%pM\n", __func__, ndev->name, mac); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1080 | |
| 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 Sorensen | cc2db7c | 2014-05-25 22:43:12 +0200 | [diff] [blame] | 1086 | if (!ether_addr_equal(mac, cur_network->network.MacAddress)) { |
Joe Perches | ea07278 | 2015-03-24 11:10:09 -0700 | [diff] [blame^] | 1087 | DBG_8723A("%s, mismatch bssid=%pM\n", |
| 1088 | __func__, cur_network->network.MacAddress); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1089 | ret = -ENOENT; |
| 1090 | goto exit; |
| 1091 | } |
| 1092 | |
Johannes Berg | 319090b | 2014-11-17 14:08:11 +0100 | [diff] [blame] | 1093 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1094 | sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv. |
| 1095 | signal_strength); |
| 1096 | |
Johannes Berg | 319090b | 2014-11-17 14:08:11 +0100 | [diff] [blame] | 1097 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); |
Jes Sorensen | 27fd731 | 2014-06-09 15:17:03 +0200 | [diff] [blame] | 1098 | sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1099 | |
Johannes Berg | 319090b | 2014-11-17 14:08:11 +0100 | [diff] [blame] | 1100 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1101 | sinfo->rx_packets = sta_rx_data_pkts(psta); |
| 1102 | |
Johannes Berg | 319090b | 2014-11-17 14:08:11 +0100 | [diff] [blame] | 1103 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1104 | 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 | |
| 1116 | exit: |
| 1117 | return ret; |
| 1118 | } |
| 1119 | |
Rahul Garg | 1da2a44 | 2014-09-25 07:16:59 +0530 | [diff] [blame] | 1120 | static int cfg80211_infrastructure_mode(struct rtw_adapter *padapter, |
Jes Sorensen | efc7144 | 2014-05-21 09:37:26 +0200 | [diff] [blame] | 1121 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1207 | static 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1213 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1216 | int ret = 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1217 | |
Jes Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 1218 | DBG_8723A("%s(%s): call netdev_open23a\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1219 | |
| 1220 | old_type = rtw_wdev->iftype; |
Jes Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 1221 | DBG_8723A("%s(%s): old_iftype =%d, new_iftype =%d\n", |
| 1222 | __func__, ndev->name, old_type, type); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1223 | |
| 1224 | if (old_type != type) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1225 | pmlmeext->action_public_rxseq = 0xffff; |
| 1226 | pmlmeext->action_public_dialog_token = 0xff; |
| 1227 | } |
| 1228 | |
| 1229 | switch (type) { |
| 1230 | case NL80211_IFTYPE_ADHOC: |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1231 | case NL80211_IFTYPE_P2P_CLIENT: |
| 1232 | case NL80211_IFTYPE_STATION: |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1233 | case NL80211_IFTYPE_P2P_GO: |
| 1234 | case NL80211_IFTYPE_AP: |
Jes Sorensen | efc7144 | 2014-05-21 09:37:26 +0200 | [diff] [blame] | 1235 | case NL80211_IFTYPE_UNSPECIFIED: |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1236 | break; |
| 1237 | default: |
| 1238 | return -EOPNOTSUPP; |
| 1239 | } |
| 1240 | |
| 1241 | rtw_wdev->iftype = type; |
| 1242 | |
Jes Sorensen | efc7144 | 2014-05-21 09:37:26 +0200 | [diff] [blame] | 1243 | if (cfg80211_infrastructure_mode(padapter, type) != _SUCCESS) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1244 | rtw_wdev->iftype = old_type; |
| 1245 | ret = -EPERM; |
| 1246 | goto exit; |
| 1247 | } |
| 1248 | |
Jes Sorensen | efc7144 | 2014-05-21 09:37:26 +0200 | [diff] [blame] | 1249 | rtw_setopmode_cmd23a(padapter, type); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1250 | |
| 1251 | exit: |
| 1252 | return ret; |
| 1253 | } |
| 1254 | |
| 1255 | void 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1260 | DBG_8723A("%s with scan req\n", __func__); |
Jes Sorensen | 141bd35 | 2014-04-09 23:20:59 +0200 | [diff] [blame] | 1261 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1262 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1270 | DBG_8723A("%s without scan req\n", __func__); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1271 | } |
| 1272 | spin_unlock_bh(&pwdev_priv->scan_req_lock); |
| 1273 | } |
| 1274 | |
| 1275 | void 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1282 | 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 Sorensen | 37cb982 | 2014-05-21 09:37:40 +0200 | [diff] [blame] | 1293 | pnetwork->network.DSConfig) >= 0) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1294 | 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 | |
| 1304 | static int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter, |
| 1305 | char *buf, int len) |
| 1306 | { |
| 1307 | int ret = 0; |
Jes Sorensen | d3797af | 2014-06-09 15:15:56 +0200 | [diff] [blame] | 1308 | const u8 *wps_ie; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1309 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; |
| 1310 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1311 | DBG_8723A("%s, ielen =%d\n", __func__, len); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1312 | |
| 1313 | if (len > 0) { |
Jes Sorensen | d3797af | 2014-06-09 15:15:56 +0200 | [diff] [blame] | 1314 | wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, |
| 1315 | WLAN_OUI_TYPE_MICROSOFT_WPS, |
| 1316 | buf, len); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1317 | if (wps_ie) { |
Jes Sorensen | d3797af | 2014-06-09 15:15:56 +0200 | [diff] [blame] | 1318 | DBG_8723A("probe_req_wps_ielen =%d\n", wps_ie[1]); |
Jes Sorensen | 141bd35 | 2014-04-09 23:20:59 +0200 | [diff] [blame] | 1319 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1320 | 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 Sorensen | d3797af | 2014-06-09 15:15:56 +0200 | [diff] [blame] | 1326 | pmlmepriv->wps_probe_req_ie = kmemdup(wps_ie, wps_ie[1], |
Benoit Taine | 4a6eea4 | 2014-05-22 15:08:33 +0200 | [diff] [blame] | 1327 | GFP_KERNEL); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1328 | if (pmlmepriv->wps_probe_req_ie == NULL) { |
| 1329 | DBG_8723A("%s()-%d: kmalloc() ERROR!\n", |
| 1330 | __func__, __LINE__); |
| 1331 | return -EINVAL; |
| 1332 | } |
Jes Sorensen | d3797af | 2014-06-09 15:15:56 +0200 | [diff] [blame] | 1333 | pmlmepriv->wps_probe_req_ie_len = wps_ie[1]; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1334 | } |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1335 | } |
| 1336 | |
| 1337 | return ret; |
| 1338 | } |
| 1339 | |
| 1340 | static 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1350 | struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev); |
| 1351 | struct cfg80211_ssid *ssids = request->ssids; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1352 | bool need_indicate_scan_done = false; |
| 1353 | |
Jes Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 1354 | DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1355 | |
| 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1361 | DBG_8723A("%s under WIFI_AP_STATE\n", __func__); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1362 | /* 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1370 | |
| 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 Sorensen | 9cd613c | 2014-05-09 15:04:03 +0200 | [diff] [blame] | 1383 | DBG_8723A("%s(%s): scan deny\n", __func__, |
| 1384 | padapter->pnetdev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1385 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1395 | |
| 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1399 | DBG_8723A("ssid =%s, len =%d\n", ssids[i].ssid, |
| 1400 | ssids[i].ssid_len); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1401 | 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 Sorensen | 9cd613c | 2014-05-09 15:04:03 +0200 | [diff] [blame] | 1412 | DBG_8723A("%s:(%s):" CHAN_FMT "\n", |
| 1413 | __func__, padapter->pnetdev->name, |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1414 | CHAN_ARG(request->channels[i])); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1415 | 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 | |
| 1435 | check_need_indicate_scan_done: |
| 1436 | if (need_indicate_scan_done) |
| 1437 | rtw_cfg80211_surveydone_event_callback(padapter); |
| 1438 | return ret; |
| 1439 | } |
| 1440 | |
| 1441 | static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed) |
| 1442 | { |
| 1443 | DBG_8723A("%s\n", __func__); |
| 1444 | return 0; |
| 1445 | } |
| 1446 | |
| 1447 | static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev, |
| 1448 | struct cfg80211_ibss_params *params) |
| 1449 | { |
Jes Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 1450 | DBG_8723A("%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1451 | return 0; |
| 1452 | } |
| 1453 | |
| 1454 | static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) |
| 1455 | { |
Jes Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 1456 | DBG_8723A("%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1457 | return 0; |
| 1458 | } |
| 1459 | |
| 1460 | static 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 Ancajas | 3895ed0 | 2014-12-08 13:55:21 -0700 | [diff] [blame] | 1470 | if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1471 | psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1472 | |
| 1473 | /* |
| 1474 | if (wpa_version & NL80211_WPA_VERSION_2) |
| 1475 | { |
| 1476 | psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK; |
| 1477 | } |
| 1478 | */ |
| 1479 | |
| 1480 | return 0; |
| 1481 | } |
| 1482 | |
| 1483 | static 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 | |
| 1513 | static 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 Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1524 | *profile_cipher = 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1525 | psecuritypriv->ndisencryptstatus = ndisencryptstatus; |
| 1526 | return 0; |
| 1527 | } |
| 1528 | |
| 1529 | switch (cipher) { |
| 1530 | case IW_AUTH_CIPHER_NONE: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1531 | *profile_cipher = 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1532 | ndisencryptstatus = Ndis802_11EncryptionDisabled; |
| 1533 | break; |
| 1534 | case WLAN_CIPHER_SUITE_WEP40: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1535 | *profile_cipher = WLAN_CIPHER_SUITE_WEP40; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1536 | ndisencryptstatus = Ndis802_11Encryption1Enabled; |
| 1537 | break; |
| 1538 | case WLAN_CIPHER_SUITE_WEP104: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1539 | *profile_cipher = WLAN_CIPHER_SUITE_WEP104; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1540 | ndisencryptstatus = Ndis802_11Encryption1Enabled; |
| 1541 | break; |
| 1542 | case WLAN_CIPHER_SUITE_TKIP: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1543 | *profile_cipher = WLAN_CIPHER_SUITE_TKIP; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1544 | ndisencryptstatus = Ndis802_11Encryption2Enabled; |
| 1545 | break; |
| 1546 | case WLAN_CIPHER_SUITE_CCMP: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1547 | *profile_cipher = WLAN_CIPHER_SUITE_CCMP; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1548 | 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 | |
| 1561 | static 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 | |
| 1576 | static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie, |
| 1577 | size_t ielen) |
| 1578 | { |
Jes Sorensen | d3797af | 2014-06-09 15:15:56 +0200 | [diff] [blame] | 1579 | const u8 *wps_ie; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1580 | int group_cipher = 0, pairwise_cipher = 0; |
| 1581 | int ret = 0; |
Jes Sorensen | 58aedb4 | 2014-04-15 19:44:07 +0200 | [diff] [blame] | 1582 | const u8 *pwpa, *pwpa2; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1583 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1595 | |
| 1596 | /* dump */ |
| 1597 | DBG_8723A("set wpa_ie(length:%zu):\n", ielen); |
| 1598 | for (i = 0; i < ielen; i = i + 8) |
Jes Sorensen | 7579a7e | 2014-06-09 15:17:08 +0200 | [diff] [blame] | 1599 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1603 | 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 Sorensen | 58aedb4 | 2014-04-15 19:44:07 +0200 | [diff] [blame] | 1610 | pwpa = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, |
| 1611 | WLAN_OUI_TYPE_MICROSOFT_WPA, |
Jes Sorensen | 7579a7e | 2014-06-09 15:17:08 +0200 | [diff] [blame] | 1612 | pie, ielen); |
Jes Sorensen | 58aedb4 | 2014-04-15 19:44:07 +0200 | [diff] [blame] | 1613 | if (pwpa && pwpa[1] > 0) { |
| 1614 | if (rtw_parse_wpa_ie23a(pwpa, pwpa[1] + 2, &group_cipher, |
| 1615 | &pairwise_cipher, NULL) == _SUCCESS) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1616 | padapter->securitypriv.dot11AuthAlgrthm = |
| 1617 | dot11AuthAlgrthm_8021X; |
| 1618 | padapter->securitypriv.ndisauthtype = |
| 1619 | Ndis802_11AuthModeWPAPSK; |
Jes Sorensen | 58aedb4 | 2014-04-15 19:44:07 +0200 | [diff] [blame] | 1620 | memcpy(padapter->securitypriv.supplicant_ie, pwpa, |
| 1621 | pwpa[1] + 2); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1622 | |
Jes Sorensen | 58aedb4 | 2014-04-15 19:44:07 +0200 | [diff] [blame] | 1623 | DBG_8723A("got wpa_ie, wpa_ielen:%u\n", pwpa[1]); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1624 | } |
| 1625 | } |
| 1626 | |
Jes Sorensen | 7579a7e | 2014-06-09 15:17:08 +0200 | [diff] [blame] | 1627 | pwpa2 = cfg80211_find_ie(WLAN_EID_RSN, pie, ielen); |
Jes Sorensen | 58aedb4 | 2014-04-15 19:44:07 +0200 | [diff] [blame] | 1628 | if (pwpa2 && pwpa2[1] > 0) { |
| 1629 | if (rtw_parse_wpa2_ie23a (pwpa2, pwpa2[1] + 2, &group_cipher, |
| 1630 | &pairwise_cipher, NULL) == _SUCCESS) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1631 | padapter->securitypriv.dot11AuthAlgrthm = |
| 1632 | dot11AuthAlgrthm_8021X; |
| 1633 | padapter->securitypriv.ndisauthtype = |
| 1634 | Ndis802_11AuthModeWPA2PSK; |
Jes Sorensen | 58aedb4 | 2014-04-15 19:44:07 +0200 | [diff] [blame] | 1635 | memcpy(padapter->securitypriv.supplicant_ie, pwpa2, |
| 1636 | pwpa2[1] + 2); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1637 | |
Jes Sorensen | 58aedb4 | 2014-04-15 19:44:07 +0200 | [diff] [blame] | 1638 | DBG_8723A("got wpa2_ie, wpa2_ielen:%u\n", pwpa2[1]); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1639 | } |
| 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 Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1651 | padapter->securitypriv.dot118021XGrpPrivacy = 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1652 | padapter->securitypriv.ndisencryptstatus = |
| 1653 | Ndis802_11EncryptionDisabled; |
| 1654 | break; |
| 1655 | case WPA_CIPHER_WEP40: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1656 | padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1657 | padapter->securitypriv.ndisencryptstatus = |
| 1658 | Ndis802_11Encryption1Enabled; |
| 1659 | break; |
| 1660 | case WPA_CIPHER_TKIP: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1661 | padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_TKIP; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1662 | padapter->securitypriv.ndisencryptstatus = |
| 1663 | Ndis802_11Encryption2Enabled; |
| 1664 | break; |
| 1665 | case WPA_CIPHER_CCMP: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1666 | padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_CCMP; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1667 | padapter->securitypriv.ndisencryptstatus = |
| 1668 | Ndis802_11Encryption3Enabled; |
| 1669 | break; |
| 1670 | case WPA_CIPHER_WEP104: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1671 | padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1672 | padapter->securitypriv.ndisencryptstatus = |
| 1673 | Ndis802_11Encryption1Enabled; |
| 1674 | break; |
| 1675 | } |
| 1676 | |
| 1677 | switch (pairwise_cipher) { |
| 1678 | case WPA_CIPHER_NONE: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1679 | padapter->securitypriv.dot11PrivacyAlgrthm = 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1680 | padapter->securitypriv.ndisencryptstatus = |
| 1681 | Ndis802_11EncryptionDisabled; |
| 1682 | break; |
| 1683 | case WPA_CIPHER_WEP40: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1684 | padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1685 | padapter->securitypriv.ndisencryptstatus = |
| 1686 | Ndis802_11Encryption1Enabled; |
| 1687 | break; |
| 1688 | case WPA_CIPHER_TKIP: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1689 | padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_TKIP; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1690 | padapter->securitypriv.ndisencryptstatus = |
| 1691 | Ndis802_11Encryption2Enabled; |
| 1692 | break; |
| 1693 | case WPA_CIPHER_CCMP: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1694 | padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_CCMP; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1695 | padapter->securitypriv.ndisencryptstatus = |
| 1696 | Ndis802_11Encryption3Enabled; |
| 1697 | break; |
| 1698 | case WPA_CIPHER_WEP104: |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1699 | padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1700 | padapter->securitypriv.ndisencryptstatus = |
| 1701 | Ndis802_11Encryption1Enabled; |
| 1702 | break; |
| 1703 | } |
| 1704 | |
Jes Sorensen | d3797af | 2014-06-09 15:15:56 +0200 | [diff] [blame] | 1705 | wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, |
| 1706 | WLAN_OUI_TYPE_MICROSOFT_WPS, |
Jes Sorensen | 7579a7e | 2014-06-09 15:17:08 +0200 | [diff] [blame] | 1707 | pie, ielen); |
Jes Sorensen | d3797af | 2014-06-09 15:15:56 +0200 | [diff] [blame] | 1708 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1716 | } |
| 1717 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1718 | /* TKIP and AES disallow multicast packets until installing group key */ |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 1719 | if (padapter->securitypriv.dot11PrivacyAlgrthm == |
| 1720 | WLAN_CIPHER_SUITE_TKIP || |
| 1721 | padapter->securitypriv.dot11PrivacyAlgrthm == |
| 1722 | WLAN_CIPHER_SUITE_CCMP) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1723 | /* WPS open need to enable multicast */ |
| 1724 | /* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true)*/ |
Jes Sorensen | 763b424 | 2014-04-09 23:20:14 +0200 | [diff] [blame] | 1725 | rtl8723a_off_rcr_am(padapter); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1726 | |
| 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 | |
| 1734 | exit: |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1735 | if (ret) |
| 1736 | _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); |
| 1737 | return ret; |
| 1738 | } |
| 1739 | |
Jes Sorensen | 6893c8e | 2014-05-21 09:37:37 +0200 | [diff] [blame] | 1740 | static int rtw_cfg80211_add_wep(struct rtw_adapter *padapter, |
Jes Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 1741 | struct rtw_wep_key *wep, u8 keyid) |
Jes Sorensen | 1e6e7f6 | 2014-05-21 09:37:36 +0200 | [diff] [blame] | 1742 | { |
Jes Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 1743 | int res; |
Jes Sorensen | 1e6e7f6 | 2014-05-21 09:37:36 +0200 | [diff] [blame] | 1744 | struct security_priv *psecuritypriv = &padapter->securitypriv; |
| 1745 | |
Jes Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 1746 | if (keyid >= NUM_WEP_KEYS) { |
Jes Sorensen | 1e6e7f6 | 2014-05-21 09:37:36 +0200 | [diff] [blame] | 1747 | 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 Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 1753 | switch (wep->keylen) { |
Jes Sorensen | 4d9c63b | 2014-06-09 15:16:45 +0200 | [diff] [blame] | 1754 | case WLAN_KEY_LEN_WEP40: |
Jes Sorensen | 1e6e7f6 | 2014-05-21 09:37:36 +0200 | [diff] [blame] | 1755 | 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 Sorensen | 4d9c63b | 2014-06-09 15:16:45 +0200 | [diff] [blame] | 1759 | case WLAN_KEY_LEN_WEP104: |
Jes Sorensen | 1e6e7f6 | 2014-05-21 09:37:36 +0200 | [diff] [blame] | 1760 | 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 Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 1773 | ("%s:before memcpy, wep->KeyLength = 0x%x keyid =%x\n", |
| 1774 | __func__, wep->keylen, keyid)); |
Jes Sorensen | 1e6e7f6 | 2014-05-21 09:37:36 +0200 | [diff] [blame] | 1775 | |
Jes Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 1776 | memcpy(&psecuritypriv->wep_key[keyid], wep, sizeof(struct rtw_wep_key)); |
Jes Sorensen | 1e6e7f6 | 2014-05-21 09:37:36 +0200 | [diff] [blame] | 1777 | |
| 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 | |
| 1799 | exit: |
| 1800 | |
| 1801 | return res; |
| 1802 | } |
| 1803 | |
Jes Sorensen | e73d82e | 2014-06-09 15:16:43 +0200 | [diff] [blame] | 1804 | static int rtw_set_ssid(struct rtw_adapter *padapter, |
| 1805 | struct wlan_network *newnetwork) |
Jes Sorensen | 97c4361 | 2014-06-09 15:16:39 +0200 | [diff] [blame] | 1806 | { |
| 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 Sorensen | e73d82e | 2014-06-09 15:16:43 +0200 | [diff] [blame] | 1813 | newnetwork->network.Ssid.ssid, get_fwstate(pmlmepriv)); |
Jes Sorensen | 97c4361 | 2014-06-09 15:16:39 +0200 | [diff] [blame] | 1814 | |
| 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 Sorensen | 97c4361 | 2014-06-09 15:16:39 +0200 | [diff] [blame] | 1827 | |
| 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 Sorensen | e73d82e | 2014-06-09 15:16:43 +0200 | [diff] [blame] | 1832 | 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 Sorensen | 97c4361 | 2014-06-09 15:16:39 +0200 | [diff] [blame] | 1837 | 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 Sorensen | e73d82e | 2014-06-09 15:16:43 +0200 | [diff] [blame] | 1879 | ("set_ssid =[%s] len = 0x%x\n", |
| 1880 | newnetwork->network.Ssid.ssid, |
| 1881 | newnetwork->network.Ssid.ssid_len)); |
Jes Sorensen | 97c4361 | 2014-06-09 15:16:39 +0200 | [diff] [blame] | 1882 | 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 | |
| 1901 | handle_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 Sorensen | e73d82e | 2014-06-09 15:16:43 +0200 | [diff] [blame] | 1917 | memcpy(&pmlmepriv->assoc_ssid, &newnetwork->network.Ssid, |
| 1918 | sizeof(struct cfg80211_ssid)); |
| 1919 | |
Jes Sorensen | 97c4361 | 2014-06-09 15:16:39 +0200 | [diff] [blame] | 1920 | pmlmepriv->assoc_by_bssid = false; |
| 1921 | |
Jes Sorensen | 72795e9 | 2014-06-09 15:16:58 +0200 | [diff] [blame] | 1922 | pmlmepriv->to_join = true; |
Jes Sorensen | 97c4361 | 2014-06-09 15:16:39 +0200 | [diff] [blame] | 1923 | |
Jes Sorensen | 72795e9 | 2014-06-09 15:16:58 +0200 | [diff] [blame] | 1924 | 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 Sorensen | 97c4361 | 2014-06-09 15:16:39 +0200 | [diff] [blame] | 1944 | release_mlme_lock: |
| 1945 | spin_unlock_bh(&pmlmepriv->lock); |
| 1946 | |
| 1947 | exit: |
| 1948 | RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, |
| 1949 | ("-%s: status =%d\n", __func__, status)); |
| 1950 | |
| 1951 | return status; |
| 1952 | } |
| 1953 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1954 | static 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1960 | /* 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 1968 | DBG_8723A("=>" "%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1969 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1972 | 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 Sorensen | c5178b0 | 2014-06-09 15:16:40 +0200 | [diff] [blame] | 1982 | if (!sme->ssid || !sme->ssid_len || |
| 1983 | sme->ssid_len > IEEE80211_MAX_SSID_LEN) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1984 | ret = -EINVAL; |
| 1985 | goto exit; |
| 1986 | } |
| 1987 | |
Jes Sorensen | c5178b0 | 2014-06-09 15:16:40 +0200 | [diff] [blame] | 1988 | DBG_8723A("ssid =%s, len =%zu\n", sme->ssid, sme->ssid_len); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1989 | |
| 1990 | if (sme->bssid) |
Joe Perches | ea07278 | 2015-03-24 11:10:09 -0700 | [diff] [blame^] | 1991 | DBG_8723A("bssid=%pM\n", sme->bssid); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 1992 | |
| 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2010 | if (sme->bssid) { |
Jes Sorensen | cc2db7c | 2014-05-25 22:43:12 +0200 | [diff] [blame] | 2011 | if (!ether_addr_equal(pnetwork->network.MacAddress, |
| 2012 | sme->bssid)) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2013 | 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 Sorensen | 9ab98d4 | 2014-06-09 15:16:41 +0200 | [diff] [blame] | 2024 | if (ether_addr_equal(pnetwork->network.MacAddress, |
| 2025 | sme->bssid)) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2026 | DBG_8723A("matched by bssid\n"); |
| 2027 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2028 | matched = true; |
| 2029 | break; |
| 2030 | } |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2031 | } else if (sme->ssid && sme->ssid_len) { |
Jes Sorensen | 9ab98d4 | 2014-06-09 15:16:41 +0200 | [diff] [blame] | 2032 | if (!memcmp(pnetwork->network.Ssid.ssid, |
| 2033 | sme->ssid, sme->ssid_len) && |
Jes Sorensen | c5178b0 | 2014-06-09 15:16:40 +0200 | [diff] [blame] | 2034 | pnetwork->network.Ssid.ssid_len == sme->ssid_len) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2035 | DBG_8723A("matched by ssid\n"); |
Jes Sorensen | c5178b0 | 2014-06-09 15:16:40 +0200 | [diff] [blame] | 2036 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2037 | matched = true; |
| 2038 | break; |
| 2039 | } |
| 2040 | } |
| 2041 | } |
| 2042 | |
| 2043 | spin_unlock_bh(&queue->lock); |
| 2044 | |
Jes Sorensen | c5178b0 | 2014-06-09 15:16:40 +0200 | [diff] [blame] | 2045 | if (!matched || !pnetwork) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2046 | ret = -ENOENT; |
| 2047 | DBG_8723A("connect, matched == false, goto exit\n"); |
| 2048 | goto exit; |
| 2049 | } |
| 2050 | |
Jes Sorensen | efc7144 | 2014-05-21 09:37:26 +0200 | [diff] [blame] | 2051 | if (cfg80211_infrastructure_mode( |
| 2052 | padapter, pnetwork->network.ifmode) != _SUCCESS) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2053 | ret = -EPERM; |
| 2054 | goto exit; |
| 2055 | } |
| 2056 | |
| 2057 | psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled; |
Jes Sorensen | 9e3d6df | 2014-05-21 09:37:34 +0200 | [diff] [blame] | 2058 | psecuritypriv->dot11PrivacyAlgrthm = 0; |
| 2059 | psecuritypriv->dot118021XGrpPrivacy = 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2060 | psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; |
| 2061 | psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen; |
| 2062 | |
Jes Sorensen | c5178b0 | 2014-06-09 15:16:40 +0200 | [diff] [blame] | 2063 | ret = rtw_cfg80211_set_wpa_version(psecuritypriv, |
| 2064 | sme->crypto.wpa_versions); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2065 | 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 Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 2091 | struct rtw_wep_key wep_key; |
| 2092 | u8 wep_key_idx, wep_key_len; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2093 | 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 Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 2098 | if (wep_key_idx > WEP_KEYS || !wep_key_len || |
| 2099 | wep_key_len > WLAN_KEY_LEN_WEP104) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2100 | ret = -EINVAL; |
| 2101 | goto exit; |
| 2102 | } |
| 2103 | |
Jes Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 2104 | wep_key_len = wep_key_len <= 5 ? 5 : 13; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2105 | |
Jes Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 2106 | memset(&wep_key, 0, sizeof(struct rtw_wep_key)); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2107 | |
Jes Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 2108 | wep_key.keylen = wep_key_len; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2109 | |
Jes Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 2110 | if (wep_key_len == 13) { |
| 2111 | padapter->securitypriv.dot11PrivacyAlgrthm = |
| 2112 | WLAN_CIPHER_SUITE_WEP104; |
| 2113 | padapter->securitypriv.dot118021XGrpPrivacy = |
| 2114 | WLAN_CIPHER_SUITE_WEP104; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2115 | } else { |
Jes Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 2116 | padapter->securitypriv.dot11PrivacyAlgrthm = |
| 2117 | WLAN_CIPHER_SUITE_WEP40; |
| 2118 | padapter->securitypriv.dot118021XGrpPrivacy = |
| 2119 | WLAN_CIPHER_SUITE_WEP40; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2120 | } |
| 2121 | |
Jes Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 2122 | memcpy(wep_key.key, (void *)sme->key, wep_key.keylen); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2123 | |
Jes Sorensen | deff115 | 2014-05-21 09:37:38 +0200 | [diff] [blame] | 2124 | if (rtw_cfg80211_add_wep(padapter, &wep_key, wep_key_idx) != |
| 2125 | _SUCCESS) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2126 | ret = -EOPNOTSUPP; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2127 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2128 | 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 Sorensen | c5178b0 | 2014-06-09 15:16:40 +0200 | [diff] [blame] | 2135 | goto exit; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2136 | |
| 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 Sorensen | 39dbc44 | 2014-06-09 15:16:38 +0200 | [diff] [blame] | 2144 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2151 | |
| 2152 | /* rtw_set_802_11_encryption_mode(padapter, |
| 2153 | padapter->securitypriv.ndisencryptstatus); */ |
| 2154 | |
Jes Sorensen | e73d82e | 2014-06-09 15:16:43 +0200 | [diff] [blame] | 2155 | if (rtw_set_ssid(padapter, pnetwork) != _SUCCESS) { |
Jes Sorensen | 97c4361 | 2014-06-09 15:16:39 +0200 | [diff] [blame] | 2156 | ret = -EBUSY; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2157 | 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 | |
| 2165 | exit: |
| 2166 | |
| 2167 | DBG_8723A("<=%s, ret %d\n", __func__, ret); |
| 2168 | |
| 2169 | return ret; |
| 2170 | } |
| 2171 | |
| 2172 | static 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2177 | DBG_8723A("%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2178 | |
| 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 | |
| 2198 | static 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 | |
| 2206 | static 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 | |
| 2214 | inline 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 | |
| 2220 | static 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2227 | DBG_8723A("%s(%s): enabled:%u, timeout:%d\n", |
| 2228 | __func__, ndev->name, enabled, timeout); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2229 | |
| 2230 | rtw_wdev_priv->power_mgmt = enabled; |
| 2231 | |
| 2232 | if (!enabled) |
| 2233 | LPS_Leave23a(padapter); |
| 2234 | |
| 2235 | return 0; |
| 2236 | } |
| 2237 | |
| 2238 | static 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2245 | |
Jes Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2246 | DBG_8723A("%s(%s)\n", __func__, netdev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2247 | |
Jes Sorensen | cc2db7c | 2014-05-25 22:43:12 +0200 | [diff] [blame] | 2248 | if (is_zero_ether_addr(pmksa->bssid)) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2249 | return -EINVAL; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2250 | |
| 2251 | blInserted = false; |
| 2252 | |
| 2253 | /* overwrite PMKID */ |
| 2254 | for (index = 0; index < NUM_PMKID_CACHE; index++) { |
Jes Sorensen | cc2db7c | 2014-05-25 22:43:12 +0200 | [diff] [blame] | 2255 | if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid, |
| 2256 | pmksa->bssid)) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2257 | /* BSSID is matched, the same AP => rewrite with |
| 2258 | new PMKID. */ |
Jes Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2259 | DBG_8723A("%s(%s): BSSID exists in the PMKList.\n", |
| 2260 | __func__, netdev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2261 | |
| 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2273 | DBG_8723A("%s(%s): Use new entry index = %d for this PMKID\n", |
| 2274 | __func__, netdev->name, psecuritypriv->PMKIDIndex); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2275 | |
Jes Sorensen | 888df44 | 2014-05-25 22:43:11 +0200 | [diff] [blame] | 2276 | ether_addr_copy( |
| 2277 | psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex]. |
| 2278 | Bssid, pmksa->bssid); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2279 | 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 | |
| 2293 | static 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2301 | DBG_8723A("%s(%s)\n", __func__, netdev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2302 | |
| 2303 | for (index = 0; index < NUM_PMKID_CACHE; index++) { |
Jes Sorensen | cc2db7c | 2014-05-25 22:43:12 +0200 | [diff] [blame] | 2304 | 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 Sorensen | 43c34be | 2014-04-15 19:44:20 +0200 | [diff] [blame] | 2308 | eth_zero_addr(psecuritypriv->PMKIDList[index].Bssid); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2309 | 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2318 | DBG_8723A("%s(%s): do not have matched BSSID\n", __func__, |
| 2319 | netdev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2320 | return -EINVAL; |
| 2321 | } |
| 2322 | |
| 2323 | return 0; |
| 2324 | } |
| 2325 | |
| 2326 | static 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2332 | DBG_8723A("%s(%s)\n", __func__, netdev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2333 | |
| 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 |
| 2342 | void 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 Sorensen | 60e78f3d | 2014-06-24 15:03:17 +0200 | [diff] [blame] | 2356 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2357 | if (ieee80211_is_assoc_req(hdr->frame_control)) |
Jes Sorensen | 60e78f3d | 2014-06-24 15:03:17 +0200 | [diff] [blame] | 2358 | ie_offset = offsetof(struct ieee80211_mgmt, |
| 2359 | u.assoc_req.variable); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2360 | else /* WIFI_REASSOCREQ */ |
Jes Sorensen | 60e78f3d | 2014-06-24 15:03:17 +0200 | [diff] [blame] | 2361 | ie_offset = offsetof(struct ieee80211_mgmt, |
| 2362 | u.reassoc_req.variable); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2363 | |
| 2364 | sinfo.filled = 0; |
Jes Sorensen | 60e78f3d | 2014-06-24 15:03:17 +0200 | [diff] [blame] | 2365 | sinfo.assoc_req_ies = pmgmt_frame + ie_offset; |
| 2366 | sinfo.assoc_req_ies_len = frame_len - ie_offset; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2367 | 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 Sorensen | 56b0bd9 | 2014-05-25 22:43:17 +0200 | [diff] [blame] | 2378 | cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pmgmt_frame, frame_len, |
Vladimir Kondratiev | 970fdfa | 2014-08-11 03:29:57 -0700 | [diff] [blame] | 2379 | 0); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2380 | #endif /* defined(RTW_USE_CFG80211_STA_EVENT) */ |
| 2381 | } |
| 2382 | |
| 2383 | void 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2389 | uint frame_len; |
Jes Sorensen | cc531f6 | 2014-06-09 15:16:18 +0200 | [diff] [blame] | 2390 | struct ieee80211_mgmt mgmt; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2391 | 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 Sorensen | cc531f6 | 2014-06-09 15:16:18 +0200 | [diff] [blame] | 2397 | memset(&mgmt, 0, sizeof(struct ieee80211_mgmt)); |
Jes Sorensen | 1daffae | 2014-05-21 09:37:55 +0200 | [diff] [blame] | 2398 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2399 | #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 Sorensen | cc531f6 | 2014-06-09 15:16:18 +0200 | [diff] [blame] | 2410 | mgmt.frame_control = |
Jes Sorensen | 036cdd9 | 2014-05-21 09:38:11 +0200 | [diff] [blame] | 2411 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2412 | |
Jes Sorensen | cc531f6 | 2014-06-09 15:16:18 +0200 | [diff] [blame] | 2413 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2416 | |
Jes Sorensen | cc531f6 | 2014-06-09 15:16:18 +0200 | [diff] [blame] | 2417 | mgmt.seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2418 | pmlmeext->mgnt_seq++; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2419 | |
Jes Sorensen | cc531f6 | 2014-06-09 15:16:18 +0200 | [diff] [blame] | 2420 | mgmt.u.disassoc.reason_code = cpu_to_le16(reason); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2421 | |
Jes Sorensen | cc531f6 | 2014-06-09 15:16:18 +0200 | [diff] [blame] | 2422 | frame_len = sizeof(struct ieee80211_hdr_3addr) + 2; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2423 | |
Jes Sorensen | cc531f6 | 2014-06-09 15:16:18 +0200 | [diff] [blame] | 2424 | cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, (u8 *)&mgmt, frame_len, |
Vladimir Kondratiev | 970fdfa | 2014-08-11 03:29:57 -0700 | [diff] [blame] | 2425 | 0); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2426 | #endif /* defined(RTW_USE_CFG80211_STA_EVENT) */ |
| 2427 | } |
| 2428 | |
| 2429 | static int rtw_cfg80211_monitor_if_open(struct net_device *ndev) |
| 2430 | { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2431 | DBG_8723A("%s\n", __func__); |
| 2432 | |
Heena Sirwani | 911f292 | 2014-10-07 14:45:56 +0530 | [diff] [blame] | 2433 | return 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2434 | } |
| 2435 | |
| 2436 | static int rtw_cfg80211_monitor_if_close(struct net_device *ndev) |
| 2437 | { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2438 | DBG_8723A("%s\n", __func__); |
| 2439 | |
Heena Sirwani | 911f292 | 2014-10-07 14:45:56 +0530 | [diff] [blame] | 2440 | return 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2441 | } |
| 2442 | |
| 2443 | static 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2458 | DBG_8723A("%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2459 | |
| 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 Sorensen | 888df44 | 2014-05-25 22:43:11 +0200 | [diff] [blame] | 2500 | ether_addr_copy(pdata, dst_mac_addr); |
| 2501 | ether_addr_copy(pdata + ETH_ALEN, src_mac_addr); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2502 | |
| 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 Sorensen | 38eb09b | 2014-05-21 09:38:31 +0200 | [diff] [blame] | 2511 | struct ieee80211_mgmt *mgmt; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2512 | /* 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2522 | |
Jes Sorensen | 38eb09b | 2014-05-21 09:38:31 +0200 | [diff] [blame] | 2523 | mgmt = (struct ieee80211_mgmt *)dot11_hdr; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2524 | |
Joe Perches | ea07278 | 2015-03-24 11:10:09 -0700 | [diff] [blame^] | 2525 | DBG_8723A("RTW_Tx:da=%pM via %s(%s)\n", |
| 2526 | mgmt->da, __func__, ndev->name); |
Jes Sorensen | 38eb09b | 2014-05-21 09:38:31 +0200 | [diff] [blame] | 2527 | category = mgmt->u.action.category; |
| 2528 | action = mgmt->u.action.u.wme_action.action_code; |
Jes Sorensen | 2e74d33 | 2014-06-09 15:16:17 +0200 | [diff] [blame] | 2529 | DBG_8723A("RTW_Tx:category(%u), action(%u)\n", |
| 2530 | category, action); |
Jes Sorensen | 98fb812 | 2014-04-15 19:43:35 +0200 | [diff] [blame] | 2531 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2532 | /* 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2547 | 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 | |
| 2559 | fail: |
| 2560 | |
| 2561 | dev_kfree_skb(skb); |
| 2562 | |
| 2563 | return 0; |
| 2564 | } |
| 2565 | |
| 2566 | static int |
| 2567 | rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr) |
| 2568 | { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2569 | DBG_8723A("%s\n", __func__); |
| 2570 | |
Heena Sirwani | 911f292 | 2014-10-07 14:45:56 +0530 | [diff] [blame] | 2571 | return 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2572 | } |
| 2573 | |
| 2574 | static 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 | |
| 2581 | static 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 Sorensen | 9cd613c | 2014-05-09 15:04:03 +0200 | [diff] [blame] | 2590 | DBG_8723A("%s(%s): without specific name\n", |
| 2591 | __func__, padapter->pnetdev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2592 | ret = -EINVAL; |
| 2593 | goto out; |
| 2594 | } |
| 2595 | |
| 2596 | if (pwdev_priv->pmon_ndev) { |
Jes Sorensen | 9cd613c | 2014-05-09 15:04:03 +0200 | [diff] [blame] | 2597 | DBG_8723A("%s(%s): monitor interface exist: %s\n", __func__, |
| 2598 | padapter->pnetdev->name, pwdev_priv->pmon_ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2599 | ret = -EBUSY; |
| 2600 | goto out; |
| 2601 | } |
| 2602 | |
| 2603 | mon_ndev = alloc_etherdev(sizeof(struct rtw_adapter)); |
| 2604 | if (!mon_ndev) { |
Jes Sorensen | 9cd613c | 2014-05-09 15:04:03 +0200 | [diff] [blame] | 2605 | DBG_8723A("%s(%s): allocate ndev fail\n", __func__, |
| 2606 | padapter->pnetdev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2607 | 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 Sorensen | 9cd613c | 2014-05-09 15:04:03 +0200 | [diff] [blame] | 2621 | DBG_8723A("%s(%s): allocate mon_wdev fail\n", __func__, |
| 2622 | padapter->pnetdev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2623 | 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 | |
| 2640 | out: |
| 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 | |
| 2654 | static struct wireless_dev * |
| 2655 | cfg80211_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 Sorensen | 9cd613c | 2014-05-09 15:04:03 +0200 | [diff] [blame] | 2663 | DBG_8723A("%s(%s): wiphy:%s, name:%s, type:%d\n", __func__, |
| 2664 | padapter->pnetdev->name, wiphy_name(wiphy), name, type); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2665 | |
| 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 Sorensen | 9cd613c | 2014-05-09 15:04:03 +0200 | [diff] [blame] | 2693 | DBG_8723A("%s(%s): ndev:%p, ret:%d\n", __func__, |
| 2694 | padapter->pnetdev->name, |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2695 | ndev, ret); |
| 2696 | |
| 2697 | return ndev ? ndev->ieee80211_ptr : ERR_PTR(ret); |
| 2698 | } |
| 2699 | |
| 2700 | static 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2716 | DBG_8723A("%s(%s): remove monitor interface\n", |
| 2717 | __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2718 | } |
| 2719 | |
| 2720 | exit: |
| 2721 | return 0; |
| 2722 | } |
| 2723 | |
| 2724 | static 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 Sorensen | db97812 | 2014-06-19 11:37:23 +0200 | [diff] [blame] | 2728 | u8 *pbuf; |
Jes Sorensen | fb5fd46 | 2014-06-24 15:03:20 +0200 | [diff] [blame] | 2729 | uint len, ielen, wps_ielen = 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2730 | struct mlme_priv *pmlmepriv = &adapter->mlmepriv; |
Jes Sorensen | ddf5c2b | 2014-06-19 11:37:24 +0200 | [diff] [blame] | 2731 | struct wlan_bssid_ex *bss = &pmlmepriv->cur_network.network; |
| 2732 | const struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)head; |
Jes Sorensen | fb5fd46 | 2014-06-24 15:03:20 +0200 | [diff] [blame] | 2733 | struct ieee80211_mgmt *tmpmgmt; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2734 | /* 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 Sorensen | ddf5c2b | 2014-06-19 11:37:24 +0200 | [diff] [blame] | 2742 | if (head_len < offsetof(struct ieee80211_mgmt, u.beacon.variable)) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2743 | return -EINVAL; |
| 2744 | |
| 2745 | pbuf = kzalloc(head_len + tail_len, GFP_KERNEL); |
| 2746 | if (!pbuf) |
| 2747 | return -ENOMEM; |
Jes Sorensen | fb5fd46 | 2014-06-24 15:03:20 +0200 | [diff] [blame] | 2748 | tmpmgmt = (struct ieee80211_mgmt *)pbuf; |
Jes Sorensen | ddf5c2b | 2014-06-19 11:37:24 +0200 | [diff] [blame] | 2749 | |
| 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2754 | /* 24 = beacon header len. */ |
Jes Sorensen | fb5fd46 | 2014-06-24 15:03:20 +0200 | [diff] [blame] | 2755 | memcpy(pbuf, (void *)head, head_len); |
| 2756 | memcpy(pbuf + head_len, (void *)tail, tail_len); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2757 | |
Jes Sorensen | fb5fd46 | 2014-06-24 15:03:20 +0200 | [diff] [blame] | 2758 | len = head_len + tail_len; |
| 2759 | ielen = len - offsetof(struct ieee80211_mgmt, u.beacon.variable); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2760 | /* check wps ie if inclued */ |
Jes Sorensen | d3797af | 2014-06-09 15:15:56 +0200 | [diff] [blame] | 2761 | if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, |
| 2762 | WLAN_OUI_TYPE_MICROSOFT_WPS, |
Jes Sorensen | fb5fd46 | 2014-06-24 15:03:20 +0200 | [diff] [blame] | 2763 | tmpmgmt->u.beacon.variable, ielen)) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2764 | DBG_8723A("add bcn, wps_ielen =%d\n", wps_ielen); |
| 2765 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2766 | /* pbss_network->IEs will not include p2p_ie, wfd ie */ |
Jes Sorensen | fb5fd46 | 2014-06-24 15:03:20 +0200 | [diff] [blame] | 2767 | rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0, |
Jes Sorensen | 9300c94 | 2014-04-15 19:43:21 +0200 | [diff] [blame] | 2768 | WLAN_EID_VENDOR_SPECIFIC, P2P_OUI23A, 4); |
Jes Sorensen | fb5fd46 | 2014-06-24 15:03:20 +0200 | [diff] [blame] | 2769 | rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0, |
Jes Sorensen | 9300c94 | 2014-04-15 19:43:21 +0200 | [diff] [blame] | 2770 | WLAN_EID_VENDOR_SPECIFIC, WFD_OUI23A, 4); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2771 | |
Jes Sorensen | fb5fd46 | 2014-06-24 15:03:20 +0200 | [diff] [blame] | 2772 | len = ielen + offsetof(struct ieee80211_mgmt, u.beacon.variable); |
| 2773 | if (rtw_check_beacon_data23a(adapter, tmpmgmt, len) == _SUCCESS) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2774 | ret = 0; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2775 | } else { |
| 2776 | ret = -EINVAL; |
| 2777 | } |
| 2778 | |
| 2779 | kfree(pbuf); |
| 2780 | |
| 2781 | return ret; |
| 2782 | } |
| 2783 | |
| 2784 | static 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2790 | DBG_8723A("%s(%s): hidden_ssid:%d, auth_type:%d\n", |
| 2791 | __func__, ndev->name, settings->hidden_ssid, |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2792 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2807 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2813 | } |
| 2814 | |
| 2815 | return ret; |
| 2816 | } |
| 2817 | |
| 2818 | static 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2825 | DBG_8723A("%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2826 | |
| 2827 | ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, |
| 2828 | info->tail_len); |
| 2829 | |
| 2830 | return ret; |
| 2831 | } |
| 2832 | |
| 2833 | static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev) |
| 2834 | { |
Jes Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2835 | DBG_8723A("%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2836 | return 0; |
| 2837 | } |
| 2838 | |
| 2839 | static int cfg80211_rtw_add_station(struct wiphy *wiphy, |
Linus Torvalds | f9da455 | 2014-06-12 14:27:40 -0700 | [diff] [blame] | 2840 | struct net_device *ndev, const u8 *mac, |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2841 | struct station_parameters *params) |
| 2842 | { |
Jes Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2843 | DBG_8723A("%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2844 | |
| 2845 | return 0; |
| 2846 | } |
| 2847 | |
| 2848 | static int cfg80211_rtw_del_station(struct wiphy *wiphy, |
Jouni Malinen | 89c771e | 2014-10-10 20:52:40 +0300 | [diff] [blame] | 2849 | struct net_device *ndev, |
| 2850 | struct station_del_parameters *params) |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2851 | { |
Jouni Malinen | 89c771e | 2014-10-10 20:52:40 +0300 | [diff] [blame] | 2852 | const u8 *mac = params->mac; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2853 | 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2861 | DBG_8723A("+%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2862 | |
| 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 Perches | ea07278 | 2015-03-24 11:10:09 -0700 | [diff] [blame^] | 2879 | DBG_8723A("free sta macaddr=%pM\n", mac); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2880 | |
| 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 Sorensen | cc2db7c | 2014-05-25 22:43:12 +0200 | [diff] [blame] | 2892 | if (ether_addr_equal(mac, psta->hwaddr)) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2893 | 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 Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2921 | DBG_8723A("-%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2922 | |
| 2923 | return ret; |
| 2924 | } |
| 2925 | |
| 2926 | static int cfg80211_rtw_change_station(struct wiphy *wiphy, |
Linus Torvalds | f9da455 | 2014-06-12 14:27:40 -0700 | [diff] [blame] | 2927 | struct net_device *ndev, const u8 *mac, |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2928 | struct station_parameters *params) |
| 2929 | { |
Jes Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2930 | DBG_8723A("%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2931 | return 0; |
| 2932 | } |
| 2933 | |
| 2934 | static int cfg80211_rtw_dump_station(struct wiphy *wiphy, |
| 2935 | struct net_device *ndev, int idx, u8 *mac, |
| 2936 | struct station_info *sinfo) |
| 2937 | { |
Jes Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2938 | DBG_8723A("%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2939 | |
| 2940 | /* TODO: dump scanned queue */ |
| 2941 | |
| 2942 | return -ENOENT; |
| 2943 | } |
| 2944 | |
| 2945 | static int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev, |
| 2946 | struct bss_parameters *params) |
| 2947 | { |
Jes Sorensen | a790d58 | 2014-05-09 15:04:04 +0200 | [diff] [blame] | 2948 | DBG_8723A("%s(%s)\n", __func__, ndev->name); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2949 | return 0; |
| 2950 | } |
| 2951 | #endif /* CONFIG_8723AU_AP_MODE */ |
| 2952 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2953 | static 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2960 | struct ieee80211_hdr *pwlanhdr; |
| 2961 | struct xmit_priv *pxmitpriv = &padapter->xmitpriv; |
| 2962 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2963 | |
| 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 Sorensen | de62f67 | 2014-05-25 22:43:14 +0200 | [diff] [blame] | 2983 | if (!pmgntframe) { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 2984 | /* 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3007 | pattrib->last_txcmdsz = pattrib->pktlen; |
| 3008 | |
Jes Sorensen | de62f67 | 2014-05-25 22:43:14 +0200 | [diff] [blame] | 3009 | ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3010 | |
Jes Sorensen | de62f67 | 2014-05-25 22:43:14 +0200 | [diff] [blame] | 3011 | if (ret != _SUCCESS) |
| 3012 | DBG_8723A("%s, ack == false\n", __func__); |
| 3013 | else |
| 3014 | DBG_8723A("%s, ack == true\n", __func__); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3015 | |
| 3016 | exit: |
| 3017 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3018 | DBG_8723A("%s, ret =%d\n", __func__, ret); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3019 | |
| 3020 | return ret; |
| 3021 | } |
| 3022 | |
| 3023 | static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3024 | struct cfg80211_mgmt_tx_params *params, |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3025 | u64 *cookie) |
| 3026 | { |
| 3027 | struct rtw_adapter *padapter = |
| 3028 | (struct rtw_adapter *)wiphy_to_adapter(wiphy); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3029 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3035 | unsigned long start = jiffies; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3036 | size_t len = params->len; |
| 3037 | struct ieee80211_channel *chan = params->chan; |
| 3038 | const u8 *buf = params->buf; |
Jes Sorensen | ea2ea44 | 2014-05-21 09:38:32 +0200 | [diff] [blame] | 3039 | struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *)buf; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3040 | u8 tx_ch = (u8) ieee80211_frequency_to_channel(chan->center_freq); |
| 3041 | |
Jes Sorensen | ea2ea44 | 2014-05-21 09:38:32 +0200 | [diff] [blame] | 3042 | if (!ieee80211_is_action(hdr->frame_control)) |
| 3043 | return -EINVAL; |
| 3044 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3045 | /* cookie generation */ |
| 3046 | *cookie = (unsigned long)buf; |
| 3047 | |
Jes Sorensen | 9cd613c | 2014-05-09 15:04:03 +0200 | [diff] [blame] | 3048 | DBG_8723A("%s(%s): len =%zu, ch =%d\n", __func__, |
| 3049 | padapter->pnetdev->name, len, tx_ch); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3050 | |
| 3051 | /* indicate ack before issue frame to avoid racing with rsp frame */ |
Jes Sorensen | 56b0bd9 | 2014-05-25 22:43:17 +0200 | [diff] [blame] | 3052 | cfg80211_mgmt_tx_status(padapter->rtw_wdev, *cookie, buf, len, ack, |
| 3053 | GFP_KERNEL); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3054 | |
Joe Perches | ea07278 | 2015-03-24 11:10:09 -0700 | [diff] [blame^] | 3055 | DBG_8723A("RTW_Tx:tx_ch =%d, da =%pM\n", tx_ch, hdr->da); |
Jes Sorensen | ea2ea44 | 2014-05-21 09:38:32 +0200 | [diff] [blame] | 3056 | category = hdr->u.action.category; |
| 3057 | action = hdr->u.action.u.wme_action.action_code; |
Jes Sorensen | 2e74d33 | 2014-06-09 15:16:17 +0200 | [diff] [blame] | 3058 | DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category, action); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3059 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3060 | 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 Sorensen | 9cd613c | 2014-05-09 15:04:03 +0200 | [diff] [blame] | 3066 | DBG_8723A("%s(%s): %s (%d/%d) in %d ms\n", |
| 3067 | __func__, padapter->pnetdev->name, |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3068 | tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt, |
| 3069 | dump_limit, jiffies_to_msecs(jiffies - start)); |
| 3070 | } |
| 3071 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3072 | return ret; |
| 3073 | } |
| 3074 | |
| 3075 | static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy, |
| 3076 | struct wireless_dev *wdev, |
| 3077 | u16 frame_type, bool reg) |
| 3078 | { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3079 | if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ)) |
| 3080 | return; |
| 3081 | |
| 3082 | return; |
| 3083 | } |
| 3084 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3085 | static 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3120 | .mgmt_tx = cfg80211_rtw_mgmt_tx, |
| 3121 | .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register, |
| 3122 | }; |
| 3123 | |
| 3124 | static 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 Browne | f78c071 | 2014-09-16 23:28:09 +0100 | [diff] [blame] | 3163 | ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3164 | } 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 Browne | f78c071 | 2014-09-16 23:28:09 +0100 | [diff] [blame] | 3169 | ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3170 | } else { |
| 3171 | DBG_8723A("%s, error rf_type =%d\n", __func__, rf_type); |
| 3172 | } |
| 3173 | |
| 3174 | } |
| 3175 | |
| 3176 | void 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 Sorensen | c2370e8 | 2014-04-09 23:20:53 +0200 | [diff] [blame] | 3183 | rf_type = rtl8723a_get_rf_type(padapter); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3184 | |
| 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 | |
| 3206 | static 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3223 | 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 | |
| 3255 | int 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3272 | |
| 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 Sorensen | d165e4e | 2014-05-25 22:43:18 +0200 | [diff] [blame] | 3278 | goto free_wiphy; |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3279 | } |
Jes Sorensen | d165e4e | 2014-05-25 22:43:18 +0200 | [diff] [blame] | 3280 | |
| 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3290 | 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 Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3308 | |
| 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 Sorensen | d165e4e | 2014-05-25 22:43:18 +0200 | [diff] [blame] | 3315 | free_wdev: |
| 3316 | kfree(wdev); |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3317 | free_wiphy: |
| 3318 | wiphy_free(wiphy); |
| 3319 | exit: |
| 3320 | return ret; |
| 3321 | } |
| 3322 | |
| 3323 | void rtw_wdev_free(struct wireless_dev *wdev) |
| 3324 | { |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3325 | DBG_8723A("%s(wdev =%p)\n", __func__, wdev); |
| 3326 | |
| 3327 | if (!wdev) |
| 3328 | return; |
| 3329 | |
Larry Finger | b1925ad | 2014-03-28 21:37:40 -0500 | [diff] [blame] | 3330 | 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 | |
| 3338 | void 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 | } |