Blame view
net/mac80211/cfg.c
55.1 KB
f0706e828 [MAC80211]: Add m... |
1 2 3 |
/* * mac80211 configuration hooks for cfg80211 * |
026331c4d cfg80211/mac80211... |
4 |
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
f0706e828 [MAC80211]: Add m... |
5 6 7 |
* * This file is GPLv2 as found in COPYING. */ |
e8cbb4cbe mac80211: support... |
8 |
#include <linux/ieee80211.h> |
f0706e828 [MAC80211]: Add m... |
9 10 |
#include <linux/nl80211.h> #include <linux/rtnetlink.h> |
5a0e3ad6a include cleanup: ... |
11 |
#include <linux/slab.h> |
881d966b4 [NET]: Make the d... |
12 |
#include <net/net_namespace.h> |
5dfdaf58d mac80211: add bea... |
13 |
#include <linux/rcupdate.h> |
f0706e828 [MAC80211]: Add m... |
14 15 |
#include <net/cfg80211.h> #include "ieee80211_i.h" |
244879813 mac80211: add dri... |
16 |
#include "driver-ops.h" |
e0eb68596 [MAC80211]: renam... |
17 |
#include "cfg.h" |
2c8dccc77 mac80211: rename ... |
18 |
#include "rate.h" |
c5dd9c2bd mac80211: mesh pa... |
19 |
#include "mesh.h" |
c5dd9c2bd mac80211: mesh pa... |
20 |
|
f9e10ce4c cfg80211: require... |
21 22 23 24 |
static struct net_device *ieee80211_add_iface(struct wiphy *wiphy, char *name, enum nl80211_iftype type, u32 *flags, struct vif_params *params) |
f0706e828 [MAC80211]: Add m... |
25 26 |
{ struct ieee80211_local *local = wiphy_priv(wiphy); |
8cc9a7391 mac80211: Use mon... |
27 28 29 |
struct net_device *dev; struct ieee80211_sub_if_data *sdata; int err; |
f0706e828 [MAC80211]: Add m... |
30 |
|
05c914fe3 mac80211: use nl8... |
31 |
err = ieee80211_if_add(local, name, &dev, type, params); |
f9e10ce4c cfg80211: require... |
32 33 |
if (err) return ERR_PTR(err); |
8cc9a7391 mac80211: Use mon... |
34 |
|
f9e10ce4c cfg80211: require... |
35 36 37 38 39 40 |
if (type == NL80211_IFTYPE_MONITOR && flags) { sdata = IEEE80211_DEV_TO_SUB_IF(dev); sdata->u.mntr_flags = *flags; } return dev; |
f0706e828 [MAC80211]: Add m... |
41 |
} |
463d01832 cfg80211: make aw... |
42 |
static int ieee80211_del_iface(struct wiphy *wiphy, struct net_device *dev) |
f0706e828 [MAC80211]: Add m... |
43 |
{ |
463d01832 cfg80211: make aw... |
44 |
ieee80211_if_remove(IEEE80211_DEV_TO_SUB_IF(dev)); |
f0706e828 [MAC80211]: Add m... |
45 |
|
75636525f mac80211: revamp ... |
46 |
return 0; |
f0706e828 [MAC80211]: Add m... |
47 |
} |
e36d56b64 cfg80211: pass ne... |
48 49 |
static int ieee80211_change_iface(struct wiphy *wiphy, struct net_device *dev, |
2ec600d67 nl80211/cfg80211:... |
50 51 |
enum nl80211_iftype type, u32 *flags, struct vif_params *params) |
42613db76 [MAC80211]: imple... |
52 |
{ |
9607e6b66 mac80211: add iee... |
53 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
f3947e2df mac80211: push in... |
54 |
int ret; |
42613db76 [MAC80211]: imple... |
55 |
|
05c914fe3 mac80211: use nl8... |
56 |
ret = ieee80211_if_change_type(sdata, type); |
f3947e2df mac80211: push in... |
57 58 |
if (ret) return ret; |
42613db76 [MAC80211]: imple... |
59 |
|
9bc383de3 cfg80211: introdu... |
60 61 62 63 64 65 |
if (type == NL80211_IFTYPE_AP_VLAN && params && params->use_4addr == 0) rcu_assign_pointer(sdata->u.vlan.sta, NULL); else if (type == NL80211_IFTYPE_STATION && params && params->use_4addr >= 0) sdata->u.mgd.use_4addr = params->use_4addr; |
85416a4fa mac80211: fix rx ... |
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) { struct ieee80211_local *local = sdata->local; if (ieee80211_sdata_running(sdata)) { /* * Prohibit MONITOR_FLAG_COOK_FRAMES to be * changed while the interface is up. * Else we would need to add a lot of cruft * to update everything: * cooked_mntrs, monitor and all fif_* counters * reconfigure hardware */ if ((*flags & MONITOR_FLAG_COOK_FRAMES) != (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) return -EBUSY; ieee80211_adjust_monitor_flags(sdata, -1); sdata->u.mntr_flags = *flags; ieee80211_adjust_monitor_flags(sdata, 1); ieee80211_configure_filter(local); } else { /* * Because the interface is down, ieee80211_do_stop * and ieee80211_do_open take care of "everything" * mentioned in the comment above. */ sdata->u.mntr_flags = *flags; } } |
f7917af92 mac80211: fix han... |
96 |
|
42613db76 [MAC80211]: imple... |
97 98 |
return 0; } |
e8cbb4cbe mac80211: support... |
99 |
static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, |
e31b82136 cfg80211/mac80211... |
100 |
u8 key_idx, bool pairwise, const u8 *mac_addr, |
e8cbb4cbe mac80211: support... |
101 102 |
struct key_params *params) { |
26a58456b mac80211: switch ... |
103 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
e8cbb4cbe mac80211: support... |
104 |
struct sta_info *sta = NULL; |
db4d1169d mac80211: split i... |
105 |
struct ieee80211_key *key; |
3b96766f0 mac80211: fix key... |
106 |
int err; |
e8cbb4cbe mac80211: support... |
107 |
|
26a58456b mac80211: switch ... |
108 |
if (!ieee80211_sdata_running(sdata)) |
ad0e2b5a0 mac80211: simplif... |
109 |
return -ENETDOWN; |
97359d123 mac80211: use cip... |
110 |
/* reject WEP and TKIP keys if WEP failed to initialize */ |
e8cbb4cbe mac80211: support... |
111 112 |
switch (params->cipher) { case WLAN_CIPHER_SUITE_WEP40: |
e8cbb4cbe mac80211: support... |
113 |
case WLAN_CIPHER_SUITE_TKIP: |
97359d123 mac80211: use cip... |
114 115 116 |
case WLAN_CIPHER_SUITE_WEP104: if (IS_ERR(sdata->local->wep_tx_tfm)) return -EINVAL; |
3cfcf6ac6 mac80211: 802.11w... |
117 |
break; |
e8cbb4cbe mac80211: support... |
118 |
default: |
97359d123 mac80211: use cip... |
119 |
break; |
e8cbb4cbe mac80211: support... |
120 |
} |
97359d123 mac80211: use cip... |
121 122 |
key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len, params->key, params->seq_len, params->seq); |
1ac62ba7c mac80211: Don't s... |
123 124 |
if (IS_ERR(key)) return PTR_ERR(key); |
db4d1169d mac80211: split i... |
125 |
|
e31b82136 cfg80211/mac80211... |
126 127 |
if (pairwise) key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; |
ad0e2b5a0 mac80211: simplif... |
128 |
mutex_lock(&sdata->local->sta_mtx); |
3b96766f0 mac80211: fix key... |
129 |
|
e8cbb4cbe mac80211: support... |
130 |
if (mac_addr) { |
ff973af74 nl80211: allow in... |
131 132 133 134 |
if (ieee80211_vif_is_mesh(&sdata->vif)) sta = sta_info_get(sdata, mac_addr); else sta = sta_info_get_bss(sdata, mac_addr); |
db4d1169d mac80211: split i... |
135 |
if (!sta) { |
32162a4da mac80211: Fix key... |
136 |
ieee80211_key_free(sdata->local, key); |
3b96766f0 mac80211: fix key... |
137 138 |
err = -ENOENT; goto out_unlock; |
db4d1169d mac80211: split i... |
139 |
} |
e8cbb4cbe mac80211: support... |
140 |
} |
3ffc2a905 mac80211: allow v... |
141 142 143 |
err = ieee80211_key_link(key, sdata, sta); if (err) ieee80211_key_free(sdata->local, key); |
db4d1169d mac80211: split i... |
144 |
|
3b96766f0 mac80211: fix key... |
145 |
out_unlock: |
ad0e2b5a0 mac80211: simplif... |
146 |
mutex_unlock(&sdata->local->sta_mtx); |
3b96766f0 mac80211: fix key... |
147 148 |
return err; |
e8cbb4cbe mac80211: support... |
149 150 151 |
} static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
e31b82136 cfg80211/mac80211... |
152 |
u8 key_idx, bool pairwise, const u8 *mac_addr) |
e8cbb4cbe mac80211: support... |
153 |
{ |
5c0c36412 mac80211: make ke... |
154 155 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; |
e8cbb4cbe mac80211: support... |
156 |
struct sta_info *sta; |
5c0c36412 mac80211: make ke... |
157 |
struct ieee80211_key *key = NULL; |
e8cbb4cbe mac80211: support... |
158 |
int ret; |
5c0c36412 mac80211: make ke... |
159 160 |
mutex_lock(&local->sta_mtx); mutex_lock(&local->key_mtx); |
3b96766f0 mac80211: fix key... |
161 |
|
e8cbb4cbe mac80211: support... |
162 |
if (mac_addr) { |
3b96766f0 mac80211: fix key... |
163 |
ret = -ENOENT; |
0e5ded5a8 mac80211: allow s... |
164 |
sta = sta_info_get_bss(sdata, mac_addr); |
e8cbb4cbe mac80211: support... |
165 |
if (!sta) |
3b96766f0 mac80211: fix key... |
166 |
goto out_unlock; |
e8cbb4cbe mac80211: support... |
167 |
|
5c0c36412 mac80211: make ke... |
168 |
if (pairwise) |
40b275b69 mac80211: sparse ... |
169 |
key = key_mtx_dereference(local, sta->ptk); |
5c0c36412 mac80211: make ke... |
170 |
else |
40b275b69 mac80211: sparse ... |
171 |
key = key_mtx_dereference(local, sta->gtk[key_idx]); |
5c0c36412 mac80211: make ke... |
172 |
} else |
40b275b69 mac80211: sparse ... |
173 |
key = key_mtx_dereference(local, sdata->keys[key_idx]); |
e8cbb4cbe mac80211: support... |
174 |
|
5c0c36412 mac80211: make ke... |
175 |
if (!key) { |
3b96766f0 mac80211: fix key... |
176 177 178 |
ret = -ENOENT; goto out_unlock; } |
e8cbb4cbe mac80211: support... |
179 |
|
5c0c36412 mac80211: make ke... |
180 |
__ieee80211_key_free(key); |
e8cbb4cbe mac80211: support... |
181 |
|
3b96766f0 mac80211: fix key... |
182 183 |
ret = 0; out_unlock: |
5c0c36412 mac80211: make ke... |
184 185 |
mutex_unlock(&local->key_mtx); mutex_unlock(&local->sta_mtx); |
3b96766f0 mac80211: fix key... |
186 187 |
return ret; |
e8cbb4cbe mac80211: support... |
188 |
} |
62da92fb7 mac80211: support... |
189 |
static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, |
e31b82136 cfg80211/mac80211... |
190 191 |
u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie, |
62da92fb7 mac80211: support... |
192 193 194 |
void (*callback)(void *cookie, struct key_params *params)) { |
14db74bcc mac80211: fix cfg... |
195 |
struct ieee80211_sub_if_data *sdata; |
62da92fb7 mac80211: support... |
196 197 198 |
struct sta_info *sta = NULL; u8 seq[6] = {0}; struct key_params params; |
e31b82136 cfg80211/mac80211... |
199 |
struct ieee80211_key *key = NULL; |
aba83a0b3 mac80211: fix CCM... |
200 |
u64 pn64; |
62da92fb7 mac80211: support... |
201 202 203 |
u32 iv32; u16 iv16; int err = -ENOENT; |
14db74bcc mac80211: fix cfg... |
204 |
sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
3b96766f0 mac80211: fix key... |
205 |
rcu_read_lock(); |
62da92fb7 mac80211: support... |
206 |
if (mac_addr) { |
0e5ded5a8 mac80211: allow s... |
207 |
sta = sta_info_get_bss(sdata, mac_addr); |
62da92fb7 mac80211: support... |
208 209 |
if (!sta) goto out; |
e31b82136 cfg80211/mac80211... |
210 |
if (pairwise) |
a3836e02b mac80211: fix a f... |
211 |
key = rcu_dereference(sta->ptk); |
e31b82136 cfg80211/mac80211... |
212 |
else if (key_idx < NUM_DEFAULT_KEYS) |
a3836e02b mac80211: fix a f... |
213 |
key = rcu_dereference(sta->gtk[key_idx]); |
62da92fb7 mac80211: support... |
214 |
} else |
a3836e02b mac80211: fix a f... |
215 |
key = rcu_dereference(sdata->keys[key_idx]); |
62da92fb7 mac80211: support... |
216 217 218 219 220 |
if (!key) goto out; memset(¶ms, 0, sizeof(params)); |
97359d123 mac80211: use cip... |
221 |
params.cipher = key->conf.cipher; |
62da92fb7 mac80211: support... |
222 |
|
97359d123 mac80211: use cip... |
223 224 |
switch (key->conf.cipher) { case WLAN_CIPHER_SUITE_TKIP: |
b0f76b335 mac80211: add a s... |
225 226 |
iv32 = key->u.tkip.tx.iv32; iv16 = key->u.tkip.tx.iv16; |
62da92fb7 mac80211: support... |
227 |
|
244879813 mac80211: add dri... |
228 229 230 231 |
if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) drv_get_tkip_seq(sdata->local, key->conf.hw_key_idx, &iv32, &iv16); |
62da92fb7 mac80211: support... |
232 233 234 235 236 237 238 239 240 241 |
seq[0] = iv16 & 0xff; seq[1] = (iv16 >> 8) & 0xff; seq[2] = iv32 & 0xff; seq[3] = (iv32 >> 8) & 0xff; seq[4] = (iv32 >> 16) & 0xff; seq[5] = (iv32 >> 24) & 0xff; params.seq = seq; params.seq_len = 6; break; |
97359d123 mac80211: use cip... |
242 |
case WLAN_CIPHER_SUITE_CCMP: |
aba83a0b3 mac80211: fix CCM... |
243 244 245 246 247 248 249 |
pn64 = atomic64_read(&key->u.ccmp.tx_pn); seq[0] = pn64; seq[1] = pn64 >> 8; seq[2] = pn64 >> 16; seq[3] = pn64 >> 24; seq[4] = pn64 >> 32; seq[5] = pn64 >> 40; |
62da92fb7 mac80211: support... |
250 251 252 |
params.seq = seq; params.seq_len = 6; break; |
97359d123 mac80211: use cip... |
253 |
case WLAN_CIPHER_SUITE_AES_CMAC: |
75396ae6d mac80211: fix CMA... |
254 255 256 257 258 259 260 |
pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); seq[0] = pn64; seq[1] = pn64 >> 8; seq[2] = pn64 >> 16; seq[3] = pn64 >> 24; seq[4] = pn64 >> 32; seq[5] = pn64 >> 40; |
3cfcf6ac6 mac80211: 802.11w... |
261 262 263 |
params.seq = seq; params.seq_len = 6; break; |
62da92fb7 mac80211: support... |
264 265 266 267 268 269 270 271 272 |
} params.key = key->conf.key; params.key_len = key->conf.keylen; callback(cookie, ¶ms); err = 0; out: |
3b96766f0 mac80211: fix key... |
273 |
rcu_read_unlock(); |
62da92fb7 mac80211: support... |
274 275 |
return err; } |
e8cbb4cbe mac80211: support... |
276 277 |
static int ieee80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, |
dbd2fd656 cfg80211/nl80211:... |
278 279 |
u8 key_idx, bool uni, bool multi) |
e8cbb4cbe mac80211: support... |
280 |
{ |
ad0e2b5a0 mac80211: simplif... |
281 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
3b96766f0 mac80211: fix key... |
282 |
|
f7e0104c1 mac80211: support... |
283 |
ieee80211_set_default_key(sdata, key_idx, uni, multi); |
e8cbb4cbe mac80211: support... |
284 285 286 |
return 0; } |
3cfcf6ac6 mac80211: 802.11w... |
287 288 289 290 |
static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx) { |
66c524210 mac80211: remove ... |
291 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
3cfcf6ac6 mac80211: 802.11w... |
292 |
|
3cfcf6ac6 mac80211: 802.11w... |
293 |
ieee80211_set_default_mgmt_key(sdata, key_idx); |
3cfcf6ac6 mac80211: 802.11w... |
294 295 |
return 0; } |
3af6334c9 mac80211: add sup... |
296 297 298 299 300 301 302 303 304 305 |
static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx) { if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { struct ieee80211_supported_band *sband; sband = sta->local->hw.wiphy->bands[ sta->local->hw.conf.channel->band]; rate->legacy = sband->bitrates[idx].bitrate; } else rate->mcs = idx; } |
c5dd9c2bd mac80211: mesh pa... |
306 307 |
static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) { |
d0709a651 mac80211: RCU-ify... |
308 |
struct ieee80211_sub_if_data *sdata = sta->sdata; |
ebe27c91a {mac|nl}80211: Ad... |
309 |
struct timespec uptime; |
c5dd9c2bd mac80211: mesh pa... |
310 |
|
f5ea9120b nl80211: add gene... |
311 |
sinfo->generation = sdata->local->sta_generation; |
c5dd9c2bd mac80211: mesh pa... |
312 313 |
sinfo->filled = STATION_INFO_INACTIVE_TIME | STATION_INFO_RX_BYTES | |
420e7fabd nl80211: Add sign... |
314 |
STATION_INFO_TX_BYTES | |
98c8a60a0 nl80211: Provide ... |
315 316 |
STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS | |
b206b4ef0 nl80211/mac80211:... |
317 318 |
STATION_INFO_TX_RETRIES | STATION_INFO_TX_FAILED | |
5a5c731aa wireless: Set som... |
319 |
STATION_INFO_TX_BITRATE | |
3af6334c9 mac80211: add sup... |
320 |
STATION_INFO_RX_BITRATE | |
f4263c985 nl80211: Add BSS ... |
321 |
STATION_INFO_RX_DROP_MISC | |
ebe27c91a {mac|nl}80211: Ad... |
322 323 324 325 326 |
STATION_INFO_BSS_PARAM | STATION_INFO_CONNECTED_TIME; do_posix_clock_monotonic_gettime(&uptime); sinfo->connected_time = uptime.tv_sec - sta->last_connected; |
c5dd9c2bd mac80211: mesh pa... |
327 328 329 330 |
sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); sinfo->rx_bytes = sta->rx_bytes; sinfo->tx_bytes = sta->tx_bytes; |
98c8a60a0 nl80211: Provide ... |
331 332 |
sinfo->rx_packets = sta->rx_packets; sinfo->tx_packets = sta->tx_packets; |
b206b4ef0 nl80211/mac80211:... |
333 334 |
sinfo->tx_retries = sta->tx_retry_count; sinfo->tx_failed = sta->tx_retry_failed; |
5a5c731aa wireless: Set som... |
335 |
sinfo->rx_dropped_misc = sta->rx_dropped; |
c5dd9c2bd mac80211: mesh pa... |
336 |
|
19deffbeb wireless: correct... |
337 338 |
if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { |
541a45a14 nl80211/mac80211:... |
339 |
sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; |
420e7fabd nl80211: Add sign... |
340 |
sinfo->signal = (s8)sta->last_signal; |
541a45a14 nl80211/mac80211:... |
341 |
sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); |
420e7fabd nl80211: Add sign... |
342 343 344 345 346 347 348 349 350 |
} sinfo->txrate.flags = 0; if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS) sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH) sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI) sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
3af6334c9 mac80211: add sup... |
351 352 353 354 355 356 357 358 359 360 |
rate_idx_to_bitrate(&sinfo->txrate, sta, sta->last_tx_rate.idx); sinfo->rxrate.flags = 0; if (sta->last_rx_rate_flag & RX_FLAG_HT) sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; rate_idx_to_bitrate(&sinfo->rxrate, sta, sta->last_rx_rate_idx); |
420e7fabd nl80211: Add sign... |
361 |
|
902acc789 mac80211: clean u... |
362 |
if (ieee80211_vif_is_mesh(&sdata->vif)) { |
c5dd9c2bd mac80211: mesh pa... |
363 |
#ifdef CONFIG_MAC80211_MESH |
c5dd9c2bd mac80211: mesh pa... |
364 365 366 367 368 369 370 |
sinfo->filled |= STATION_INFO_LLID | STATION_INFO_PLID | STATION_INFO_PLINK_STATE; sinfo->llid = le16_to_cpu(sta->llid); sinfo->plid = le16_to_cpu(sta->plid); sinfo->plink_state = sta->plink_state; |
c5dd9c2bd mac80211: mesh pa... |
371 |
#endif |
902acc789 mac80211: clean u... |
372 |
} |
f4263c985 nl80211: Add BSS ... |
373 374 375 376 377 378 379 380 381 382 |
sinfo->bss_param.flags = 0; if (sdata->vif.bss_conf.use_cts_prot) sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT; if (sdata->vif.bss_conf.use_short_preamble) sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; if (sdata->vif.bss_conf.use_short_slot) sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period; sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; |
c5dd9c2bd mac80211: mesh pa... |
383 384 385 386 387 388 |
} static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *mac, struct station_info *sinfo) { |
3b53fde8a mac80211: let sta... |
389 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
c5dd9c2bd mac80211: mesh pa... |
390 |
struct sta_info *sta; |
d0709a651 mac80211: RCU-ify... |
391 392 393 |
int ret = -ENOENT; rcu_read_lock(); |
c5dd9c2bd mac80211: mesh pa... |
394 |
|
3b53fde8a mac80211: let sta... |
395 |
sta = sta_info_get_by_idx(sdata, idx); |
d0709a651 mac80211: RCU-ify... |
396 397 |
if (sta) { ret = 0; |
17741cdc2 mac80211: share S... |
398 |
memcpy(mac, sta->sta.addr, ETH_ALEN); |
d0709a651 mac80211: RCU-ify... |
399 400 |
sta_set_sinfo(sta, sinfo); } |
c5dd9c2bd mac80211: mesh pa... |
401 |
|
d0709a651 mac80211: RCU-ify... |
402 |
rcu_read_unlock(); |
c5dd9c2bd mac80211: mesh pa... |
403 |
|
d0709a651 mac80211: RCU-ify... |
404 |
return ret; |
c5dd9c2bd mac80211: mesh pa... |
405 |
} |
1289723ef mac80211: sample ... |
406 407 408 409 |
static int ieee80211_dump_survey(struct wiphy *wiphy, struct net_device *dev, int idx, struct survey_info *survey) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1289723ef mac80211: sample ... |
410 411 |
return drv_get_survey(local, idx, survey); } |
7bbdd2d98 mac80211: impleme... |
412 |
static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, |
2ec600d67 nl80211/cfg80211:... |
413 |
u8 *mac, struct station_info *sinfo) |
7bbdd2d98 mac80211: impleme... |
414 |
{ |
abe60632f mac80211: make st... |
415 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
7bbdd2d98 mac80211: impleme... |
416 |
struct sta_info *sta; |
d0709a651 mac80211: RCU-ify... |
417 |
int ret = -ENOENT; |
7bbdd2d98 mac80211: impleme... |
418 |
|
d0709a651 mac80211: RCU-ify... |
419 |
rcu_read_lock(); |
7bbdd2d98 mac80211: impleme... |
420 |
|
0e5ded5a8 mac80211: allow s... |
421 |
sta = sta_info_get_bss(sdata, mac); |
d0709a651 mac80211: RCU-ify... |
422 423 424 425 426 427 428 429 |
if (sta) { ret = 0; sta_set_sinfo(sta, sinfo); } rcu_read_unlock(); return ret; |
7bbdd2d98 mac80211: impleme... |
430 |
} |
5dfdaf58d mac80211: add bea... |
431 432 433 434 435 436 437 438 439 440 |
/* * This handles both adding a beacon and setting new beacon info */ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, struct beacon_parameters *params) { struct beacon_data *new, *old; int new_head_len, new_tail_len; int size; int err = -EINVAL; |
40b275b69 mac80211: sparse ... |
441 |
old = rtnl_dereference(sdata->u.ap.beacon); |
5dfdaf58d mac80211: add bea... |
442 443 444 445 446 447 448 449 450 |
/* head must not be zero-length */ if (params->head && !params->head_len) return -EINVAL; /* * This is a kludge. beacon interval should really be part * of the beacon information. */ |
57c4d7b4c mac80211: clean u... |
451 452 453 454 455 |
if (params->interval && (sdata->vif.bss_conf.beacon_int != params->interval)) { sdata->vif.bss_conf.beacon_int = params->interval; ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_INT); |
5dfdaf58d mac80211: add bea... |
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 |
} /* Need to have a beacon head if we don't have one yet */ if (!params->head && !old) return err; /* sorry, no way to start beaconing without dtim period */ if (!params->dtim_period && !old) return err; /* new or old head? */ if (params->head) new_head_len = params->head_len; else new_head_len = old->head_len; /* new or old tail? */ if (params->tail || !old) /* params->tail_len will be zero for !params->tail */ new_tail_len = params->tail_len; else new_tail_len = old->tail_len; size = sizeof(*new) + new_head_len + new_tail_len; new = kzalloc(size, GFP_KERNEL); if (!new) return -ENOMEM; /* start filling the new info now */ /* new or old dtim period? */ if (params->dtim_period) new->dtim_period = params->dtim_period; else new->dtim_period = old->dtim_period; /* * pointers go into the block we allocated, * memory is | beacon_data | head | tail | */ new->head = ((u8 *) new) + sizeof(*new); new->tail = new->head + new_head_len; new->head_len = new_head_len; new->tail_len = new_tail_len; /* copy in head */ if (params->head) memcpy(new->head, params->head, new_head_len); else memcpy(new->head, old->head, new_head_len); /* copy in optional tail */ if (params->tail) memcpy(new->tail, params->tail, new_tail_len); else if (old) memcpy(new->tail, old->tail, new_tail_len); |
19885c4fb mac80211: fix bss... |
514 |
sdata->vif.bss_conf.dtim_period = new->dtim_period; |
5dfdaf58d mac80211: add bea... |
515 516 517 518 519 |
rcu_assign_pointer(sdata->u.ap.beacon, new); synchronize_rcu(); kfree(old); |
2d0ddec5b mac80211: unify c... |
520 521 522 |
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON); return 0; |
5dfdaf58d mac80211: add bea... |
523 524 525 526 527 |
} static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) { |
14db74bcc mac80211: fix cfg... |
528 |
struct ieee80211_sub_if_data *sdata; |
5dfdaf58d mac80211: add bea... |
529 |
struct beacon_data *old; |
14db74bcc mac80211: fix cfg... |
530 |
sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
40b275b69 mac80211: sparse ... |
531 |
old = rtnl_dereference(sdata->u.ap.beacon); |
5dfdaf58d mac80211: add bea... |
532 533 534 535 536 537 538 539 540 |
if (old) return -EALREADY; return ieee80211_config_beacon(sdata, params); } static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) { |
14db74bcc mac80211: fix cfg... |
541 |
struct ieee80211_sub_if_data *sdata; |
5dfdaf58d mac80211: add bea... |
542 |
struct beacon_data *old; |
14db74bcc mac80211: fix cfg... |
543 |
sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
40b275b69 mac80211: sparse ... |
544 |
old = rtnl_dereference(sdata->u.ap.beacon); |
5dfdaf58d mac80211: add bea... |
545 546 547 548 549 550 551 552 |
if (!old) return -ENOENT; return ieee80211_config_beacon(sdata, params); } static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) { |
14db74bcc mac80211: fix cfg... |
553 |
struct ieee80211_sub_if_data *sdata; |
5dfdaf58d mac80211: add bea... |
554 |
struct beacon_data *old; |
14db74bcc mac80211: fix cfg... |
555 |
sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
40b275b69 mac80211: sparse ... |
556 |
old = rtnl_dereference(sdata->u.ap.beacon); |
5dfdaf58d mac80211: add bea... |
557 558 559 560 561 562 |
if (!old) return -ENOENT; rcu_assign_pointer(sdata->u.ap.beacon, NULL); synchronize_rcu(); kfree(old); |
2d0ddec5b mac80211: unify c... |
563 564 |
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); return 0; |
5dfdaf58d mac80211: add bea... |
565 |
} |
4fd6931eb mac80211: impleme... |
566 567 568 569 570 571 572 573 574 |
/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ struct iapp_layer2_update { u8 da[ETH_ALEN]; /* broadcast */ u8 sa[ETH_ALEN]; /* STA addr */ __be16 len; /* 6 */ u8 dsap; /* 0 */ u8 ssap; /* 0 */ u8 control; u8 xid_info[3]; |
bc10502db net: use __packed... |
575 |
} __packed; |
4fd6931eb mac80211: impleme... |
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 |
static void ieee80211_send_layer2_update(struct sta_info *sta) { struct iapp_layer2_update *msg; struct sk_buff *skb; /* Send Level 2 Update Frame to update forwarding tables in layer 2 * bridge devices */ skb = dev_alloc_skb(sizeof(*msg)); if (!skb) return; msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg)); /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ memset(msg->da, 0xff, ETH_ALEN); |
17741cdc2 mac80211: share S... |
594 |
memcpy(msg->sa, sta->sta.addr, ETH_ALEN); |
4fd6931eb mac80211: impleme... |
595 596 597 598 599 600 601 602 |
msg->len = htons(6); msg->dsap = 0; msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */ msg->control = 0xaf; /* XID response lsb.1111F101. * F=0 (no poll command; unsolicited frame) */ msg->xid_info[0] = 0x81; /* XID format identifier */ msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */ msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */ |
d0709a651 mac80211: RCU-ify... |
603 604 |
skb->dev = sta->sdata->dev; skb->protocol = eth_type_trans(skb, sta->sdata->dev); |
4fd6931eb mac80211: impleme... |
605 |
memset(skb->cb, 0, sizeof(skb->cb)); |
06ee1c261 wireless: use net... |
606 |
netif_rx_ni(skb); |
4fd6931eb mac80211: impleme... |
607 608 609 610 611 612 |
} static void sta_apply_parameters(struct ieee80211_local *local, struct sta_info *sta, struct station_parameters *params) { |
f5521b138 mac80211: use cor... |
613 |
unsigned long flags; |
4fd6931eb mac80211: impleme... |
614 615 |
u32 rates; int i, j; |
8318d78a4 cfg80211 API for ... |
616 |
struct ieee80211_supported_band *sband; |
d0709a651 mac80211: RCU-ify... |
617 |
struct ieee80211_sub_if_data *sdata = sta->sdata; |
eccb8e8f0 nl80211: improve ... |
618 |
u32 mask, set; |
4fd6931eb mac80211: impleme... |
619 |
|
ae5eb0264 mac80211: rewrite... |
620 |
sband = local->hw.wiphy->bands[local->oper_channel->band]; |
f5521b138 mac80211: use cor... |
621 |
spin_lock_irqsave(&sta->flaglock, flags); |
eccb8e8f0 nl80211: improve ... |
622 623 |
mask = params->sta_flags_mask; set = params->sta_flags_set; |
73651ee63 mac80211: split s... |
624 |
|
eccb8e8f0 nl80211: improve ... |
625 |
if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { |
4fd6931eb mac80211: impleme... |
626 |
sta->flags &= ~WLAN_STA_AUTHORIZED; |
eccb8e8f0 nl80211: improve ... |
627 |
if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) |
4fd6931eb mac80211: impleme... |
628 |
sta->flags |= WLAN_STA_AUTHORIZED; |
eccb8e8f0 nl80211: improve ... |
629 |
} |
4fd6931eb mac80211: impleme... |
630 |
|
eccb8e8f0 nl80211: improve ... |
631 |
if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { |
4fd6931eb mac80211: impleme... |
632 |
sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; |
eccb8e8f0 nl80211: improve ... |
633 |
if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) |
4fd6931eb mac80211: impleme... |
634 |
sta->flags |= WLAN_STA_SHORT_PREAMBLE; |
eccb8e8f0 nl80211: improve ... |
635 |
} |
4fd6931eb mac80211: impleme... |
636 |
|
eccb8e8f0 nl80211: improve ... |
637 |
if (mask & BIT(NL80211_STA_FLAG_WME)) { |
4fd6931eb mac80211: impleme... |
638 |
sta->flags &= ~WLAN_STA_WME; |
39df600aa mac80211: propaga... |
639 640 |
sta->sta.wme = false; if (set & BIT(NL80211_STA_FLAG_WME)) { |
4fd6931eb mac80211: impleme... |
641 |
sta->flags |= WLAN_STA_WME; |
39df600aa mac80211: propaga... |
642 643 |
sta->sta.wme = true; } |
eccb8e8f0 nl80211: improve ... |
644 |
} |
5394af4d8 mac80211: 802.11w... |
645 |
|
eccb8e8f0 nl80211: improve ... |
646 |
if (mask & BIT(NL80211_STA_FLAG_MFP)) { |
5394af4d8 mac80211: 802.11w... |
647 |
sta->flags &= ~WLAN_STA_MFP; |
eccb8e8f0 nl80211: improve ... |
648 |
if (set & BIT(NL80211_STA_FLAG_MFP)) |
5394af4d8 mac80211: 802.11w... |
649 |
sta->flags |= WLAN_STA_MFP; |
4fd6931eb mac80211: impleme... |
650 |
} |
b39c48fac nl80211/mac80211:... |
651 652 653 654 655 656 |
if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { sta->flags &= ~WLAN_STA_AUTH; if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) sta->flags |= WLAN_STA_AUTH; } |
f5521b138 mac80211: use cor... |
657 |
spin_unlock_irqrestore(&sta->flaglock, flags); |
4fd6931eb mac80211: impleme... |
658 |
|
73651ee63 mac80211: split s... |
659 |
/* |
51b50fbeb cfg80211: validat... |
660 661 662 663 664 665 666 |
* cfg80211 validates this (1-2007) and allows setting the AID * only when creating a new station entry */ if (params->aid) sta->sta.aid = params->aid; /* |
73651ee63 mac80211: split s... |
667 668 669 670 671 |
* FIXME: updating the following information is racy when this * function is called from ieee80211_change_station(). * However, all this information should be static so * maybe we should just reject attemps to change it. */ |
4fd6931eb mac80211: impleme... |
672 673 674 675 676 |
if (params->listen_interval >= 0) sta->listen_interval = params->listen_interval; if (params->supported_rates) { rates = 0; |
8318d78a4 cfg80211 API for ... |
677 |
|
4fd6931eb mac80211: impleme... |
678 679 |
for (i = 0; i < params->supported_rates_len; i++) { int rate = (params->supported_rates[i] & 0x7f) * 5; |
8318d78a4 cfg80211 API for ... |
680 681 |
for (j = 0; j < sband->n_bitrates; j++) { if (sband->bitrates[j].bitrate == rate) |
4fd6931eb mac80211: impleme... |
682 683 684 |
rates |= BIT(j); } } |
323ce79a9 mac80211: share s... |
685 |
sta->sta.supp_rates[local->oper_channel->band] = rates; |
4fd6931eb mac80211: impleme... |
686 |
} |
c5dd9c2bd mac80211: mesh pa... |
687 |
|
d9fe60dea 802.11: clean up/... |
688 |
if (params->ht_capa) |
ae5eb0264 mac80211: rewrite... |
689 690 |
ieee80211_ht_cap_ie_to_sta_ht_cap(sband, params->ht_capa, |
d9fe60dea 802.11: clean up/... |
691 |
&sta->sta.ht_cap); |
36aedc903 mac80211/cfg80211... |
692 |
|
9c3990aae nl80211: Let user... |
693 |
if (ieee80211_vif_is_mesh(&sdata->vif)) { |
4daf50f20 mac80211: Fix mes... |
694 |
#ifdef CONFIG_MAC80211_MESH |
9c3990aae nl80211: Let user... |
695 696 |
if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) switch (params->plink_state) { |
57cf8043a nl80211: Move pee... |
697 698 699 |
case NL80211_PLINK_LISTEN: case NL80211_PLINK_ESTAB: case NL80211_PLINK_BLOCKED: |
9c3990aae nl80211: Let user... |
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 |
sta->plink_state = params->plink_state; break; default: /* nothing */ break; } else switch (params->plink_action) { case PLINK_ACTION_OPEN: mesh_plink_open(sta); break; case PLINK_ACTION_BLOCK: mesh_plink_block(sta); break; } |
4daf50f20 mac80211: Fix mes... |
715 |
#endif |
902acc789 mac80211: clean u... |
716 |
} |
4fd6931eb mac80211: impleme... |
717 718 719 720 721 |
} static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, u8 *mac, struct station_parameters *params) { |
14db74bcc mac80211: fix cfg... |
722 |
struct ieee80211_local *local = wiphy_priv(wiphy); |
4fd6931eb mac80211: impleme... |
723 724 |
struct sta_info *sta; struct ieee80211_sub_if_data *sdata; |
73651ee63 mac80211: split s... |
725 |
int err; |
b8d476c8c mac80211: Send La... |
726 |
int layer2_update; |
4fd6931eb mac80211: impleme... |
727 |
|
4fd6931eb mac80211: impleme... |
728 729 |
if (params->vlan) { sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
05c914fe3 mac80211: use nl8... |
730 731 |
if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && sdata->vif.type != NL80211_IFTYPE_AP) |
4fd6931eb mac80211: impleme... |
732 733 734 |
return -EINVAL; } else sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
47846c9b0 mac80211: reduce ... |
735 |
if (compare_ether_addr(mac, sdata->vif.addr) == 0) |
03e4497eb mac80211: fix sta... |
736 737 738 739 740 741 |
return -EINVAL; if (is_multicast_ether_addr(mac)) return -EINVAL; sta = sta_info_alloc(sdata, mac, GFP_KERNEL); |
73651ee63 mac80211: split s... |
742 743 |
if (!sta) return -ENOMEM; |
4fd6931eb mac80211: impleme... |
744 745 746 747 |
sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; sta_apply_parameters(local, sta, params); |
4b7679a56 mac80211: clean u... |
748 |
rate_control_rate_init(sta); |
4fd6931eb mac80211: impleme... |
749 |
|
b8d476c8c mac80211: Send La... |
750 751 |
layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || sdata->vif.type == NL80211_IFTYPE_AP; |
34e895075 mac80211: allow s... |
752 |
err = sta_info_insert_rcu(sta); |
73651ee63 mac80211: split s... |
753 |
if (err) { |
73651ee63 mac80211: split s... |
754 755 756 |
rcu_read_unlock(); return err; } |
b8d476c8c mac80211: Send La... |
757 |
if (layer2_update) |
73651ee63 mac80211: split s... |
758 759 760 |
ieee80211_send_layer2_update(sta); rcu_read_unlock(); |
4fd6931eb mac80211: impleme... |
761 762 763 764 765 766 |
return 0; } static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, u8 *mac) { |
14db74bcc mac80211: fix cfg... |
767 768 |
struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; |
4fd6931eb mac80211: impleme... |
769 |
|
14db74bcc mac80211: fix cfg... |
770 |
sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
34e895075 mac80211: allow s... |
771 772 |
if (mac) return sta_info_destroy_addr_bss(sdata, mac); |
4fd6931eb mac80211: impleme... |
773 |
|
34e895075 mac80211: allow s... |
774 |
sta_info_flush(local, sdata); |
4fd6931eb mac80211: impleme... |
775 776 777 778 779 780 781 782 |
return 0; } static int ieee80211_change_station(struct wiphy *wiphy, struct net_device *dev, u8 *mac, struct station_parameters *params) { |
abe60632f mac80211: make st... |
783 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
14db74bcc mac80211: fix cfg... |
784 |
struct ieee80211_local *local = wiphy_priv(wiphy); |
4fd6931eb mac80211: impleme... |
785 786 |
struct sta_info *sta; struct ieee80211_sub_if_data *vlansdata; |
98dd6a575 mac80211: further... |
787 |
rcu_read_lock(); |
0e5ded5a8 mac80211: allow s... |
788 |
sta = sta_info_get_bss(sdata, mac); |
98dd6a575 mac80211: further... |
789 790 |
if (!sta) { rcu_read_unlock(); |
4fd6931eb mac80211: impleme... |
791 |
return -ENOENT; |
98dd6a575 mac80211: further... |
792 |
} |
4fd6931eb mac80211: impleme... |
793 |
|
d0709a651 mac80211: RCU-ify... |
794 |
if (params->vlan && params->vlan != sta->sdata->dev) { |
4fd6931eb mac80211: impleme... |
795 |
vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
05c914fe3 mac80211: use nl8... |
796 797 |
if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && vlansdata->vif.type != NL80211_IFTYPE_AP) { |
98dd6a575 mac80211: further... |
798 |
rcu_read_unlock(); |
4fd6931eb mac80211: impleme... |
799 |
return -EINVAL; |
98dd6a575 mac80211: further... |
800 |
} |
4fd6931eb mac80211: impleme... |
801 |
|
9bc383de3 cfg80211: introdu... |
802 |
if (params->vlan->ieee80211_ptr->use_4addr) { |
3305443c9 mac80211: fix rcu... |
803 804 |
if (vlansdata->u.vlan.sta) { rcu_read_unlock(); |
f14543ee4 mac80211: impleme... |
805 |
return -EBUSY; |
3305443c9 mac80211: fix rcu... |
806 |
} |
f14543ee4 mac80211: impleme... |
807 808 809 |
rcu_assign_pointer(vlansdata->u.vlan.sta, sta); } |
14db74bcc mac80211: fix cfg... |
810 |
sta->sdata = vlansdata; |
4fd6931eb mac80211: impleme... |
811 812 813 814 |
ieee80211_send_layer2_update(sta); } sta_apply_parameters(local, sta, params); |
98dd6a575 mac80211: further... |
815 |
rcu_read_unlock(); |
808118cb4 mac80211: do not ... |
816 817 818 |
if (sdata->vif.type == NL80211_IFTYPE_STATION && params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) ieee80211_recalc_ps(local, -1); |
4fd6931eb mac80211: impleme... |
819 820 |
return 0; } |
c5dd9c2bd mac80211: mesh pa... |
821 822 823 824 |
#ifdef CONFIG_MAC80211_MESH static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, u8 *dst, u8 *next_hop) { |
14db74bcc mac80211: fix cfg... |
825 |
struct ieee80211_sub_if_data *sdata; |
c5dd9c2bd mac80211: mesh pa... |
826 827 828 |
struct mesh_path *mpath; struct sta_info *sta; int err; |
14db74bcc mac80211: fix cfg... |
829 |
sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
d0709a651 mac80211: RCU-ify... |
830 |
rcu_read_lock(); |
abe60632f mac80211: make st... |
831 |
sta = sta_info_get(sdata, next_hop); |
d0709a651 mac80211: RCU-ify... |
832 833 |
if (!sta) { rcu_read_unlock(); |
c5dd9c2bd mac80211: mesh pa... |
834 |
return -ENOENT; |
d0709a651 mac80211: RCU-ify... |
835 |
} |
c5dd9c2bd mac80211: mesh pa... |
836 |
|
f698d856f replace net_devic... |
837 |
err = mesh_path_add(dst, sdata); |
d0709a651 mac80211: RCU-ify... |
838 839 |
if (err) { rcu_read_unlock(); |
c5dd9c2bd mac80211: mesh pa... |
840 |
return err; |
d0709a651 mac80211: RCU-ify... |
841 |
} |
c5dd9c2bd mac80211: mesh pa... |
842 |
|
f698d856f replace net_devic... |
843 |
mpath = mesh_path_lookup(dst, sdata); |
c5dd9c2bd mac80211: mesh pa... |
844 845 |
if (!mpath) { rcu_read_unlock(); |
c5dd9c2bd mac80211: mesh pa... |
846 847 848 |
return -ENXIO; } mesh_path_fix_nexthop(mpath, sta); |
d0709a651 mac80211: RCU-ify... |
849 |
|
c5dd9c2bd mac80211: mesh pa... |
850 851 852 853 854 855 856 |
rcu_read_unlock(); return 0; } static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, u8 *dst) { |
f698d856f replace net_devic... |
857 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
c5dd9c2bd mac80211: mesh pa... |
858 |
if (dst) |
f698d856f replace net_devic... |
859 |
return mesh_path_del(dst, sdata); |
c5dd9c2bd mac80211: mesh pa... |
860 |
|
f698d856f replace net_devic... |
861 |
mesh_path_flush(sdata); |
c5dd9c2bd mac80211: mesh pa... |
862 863 864 865 866 867 868 |
return 0; } static int ieee80211_change_mpath(struct wiphy *wiphy, struct net_device *dev, u8 *dst, u8 *next_hop) { |
14db74bcc mac80211: fix cfg... |
869 |
struct ieee80211_sub_if_data *sdata; |
c5dd9c2bd mac80211: mesh pa... |
870 871 |
struct mesh_path *mpath; struct sta_info *sta; |
14db74bcc mac80211: fix cfg... |
872 |
sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
d0709a651 mac80211: RCU-ify... |
873 |
rcu_read_lock(); |
abe60632f mac80211: make st... |
874 |
sta = sta_info_get(sdata, next_hop); |
d0709a651 mac80211: RCU-ify... |
875 876 |
if (!sta) { rcu_read_unlock(); |
c5dd9c2bd mac80211: mesh pa... |
877 |
return -ENOENT; |
d0709a651 mac80211: RCU-ify... |
878 |
} |
c5dd9c2bd mac80211: mesh pa... |
879 |
|
f698d856f replace net_devic... |
880 |
mpath = mesh_path_lookup(dst, sdata); |
c5dd9c2bd mac80211: mesh pa... |
881 882 |
if (!mpath) { rcu_read_unlock(); |
c5dd9c2bd mac80211: mesh pa... |
883 884 885 886 |
return -ENOENT; } mesh_path_fix_nexthop(mpath, sta); |
d0709a651 mac80211: RCU-ify... |
887 |
|
c5dd9c2bd mac80211: mesh pa... |
888 889 890 891 892 893 894 |
rcu_read_unlock(); return 0; } static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, struct mpath_info *pinfo) { |
a3836e02b mac80211: fix a f... |
895 896 897 898 |
struct sta_info *next_hop_sta = rcu_dereference(mpath->next_hop); if (next_hop_sta) memcpy(next_hop, next_hop_sta->sta.addr, ETH_ALEN); |
c5dd9c2bd mac80211: mesh pa... |
899 900 |
else memset(next_hop, 0, ETH_ALEN); |
f5ea9120b nl80211: add gene... |
901 |
pinfo->generation = mesh_paths_generation; |
c5dd9c2bd mac80211: mesh pa... |
902 |
pinfo->filled = MPATH_INFO_FRAME_QLEN | |
d19b3bf63 mac80211: replace... |
903 |
MPATH_INFO_SN | |
c5dd9c2bd mac80211: mesh pa... |
904 905 906 907 908 909 910 |
MPATH_INFO_METRIC | MPATH_INFO_EXPTIME | MPATH_INFO_DISCOVERY_TIMEOUT | MPATH_INFO_DISCOVERY_RETRIES | MPATH_INFO_FLAGS; pinfo->frame_qlen = mpath->frame_queue.qlen; |
d19b3bf63 mac80211: replace... |
911 |
pinfo->sn = mpath->sn; |
c5dd9c2bd mac80211: mesh pa... |
912 913 914 915 916 917 918 919 920 921 922 |
pinfo->metric = mpath->metric; if (time_before(jiffies, mpath->exp_time)) pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies); pinfo->discovery_timeout = jiffies_to_msecs(mpath->discovery_timeout); pinfo->discovery_retries = mpath->discovery_retries; pinfo->flags = 0; if (mpath->flags & MESH_PATH_ACTIVE) pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE; if (mpath->flags & MESH_PATH_RESOLVING) pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING; |
d19b3bf63 mac80211: replace... |
923 924 |
if (mpath->flags & MESH_PATH_SN_VALID) pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID; |
c5dd9c2bd mac80211: mesh pa... |
925 926 927 928 929 930 931 932 933 934 935 936 |
if (mpath->flags & MESH_PATH_FIXED) pinfo->flags |= NL80211_MPATH_FLAG_FIXED; if (mpath->flags & MESH_PATH_RESOLVING) pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING; pinfo->flags = mpath->flags; } static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, u8 *dst, u8 *next_hop, struct mpath_info *pinfo) { |
14db74bcc mac80211: fix cfg... |
937 |
struct ieee80211_sub_if_data *sdata; |
c5dd9c2bd mac80211: mesh pa... |
938 |
struct mesh_path *mpath; |
14db74bcc mac80211: fix cfg... |
939 |
sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
c5dd9c2bd mac80211: mesh pa... |
940 |
rcu_read_lock(); |
f698d856f replace net_devic... |
941 |
mpath = mesh_path_lookup(dst, sdata); |
c5dd9c2bd mac80211: mesh pa... |
942 943 944 945 946 947 948 949 950 951 952 953 954 955 |
if (!mpath) { rcu_read_unlock(); return -ENOENT; } memcpy(dst, mpath->dst, ETH_ALEN); mpath_set_pinfo(mpath, next_hop, pinfo); rcu_read_unlock(); return 0; } static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *dst, u8 *next_hop, struct mpath_info *pinfo) { |
14db74bcc mac80211: fix cfg... |
956 |
struct ieee80211_sub_if_data *sdata; |
c5dd9c2bd mac80211: mesh pa... |
957 |
struct mesh_path *mpath; |
14db74bcc mac80211: fix cfg... |
958 |
sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
c5dd9c2bd mac80211: mesh pa... |
959 |
rcu_read_lock(); |
f698d856f replace net_devic... |
960 |
mpath = mesh_path_lookup_by_idx(idx, sdata); |
c5dd9c2bd mac80211: mesh pa... |
961 962 963 964 965 966 967 968 969 |
if (!mpath) { rcu_read_unlock(); return -ENOENT; } memcpy(dst, mpath->dst, ETH_ALEN); mpath_set_pinfo(mpath, next_hop, pinfo); rcu_read_unlock(); return 0; } |
93da9cc17 Add nl80211 comma... |
970 |
|
24bdd9f4c mac80211: Rename ... |
971 |
static int ieee80211_get_mesh_config(struct wiphy *wiphy, |
93da9cc17 Add nl80211 comma... |
972 973 974 975 976 |
struct net_device *dev, struct mesh_config *conf) { struct ieee80211_sub_if_data *sdata; sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
93da9cc17 Add nl80211 comma... |
977 978 979 980 981 982 983 984 |
memcpy(conf, &(sdata->u.mesh.mshcfg), sizeof(struct mesh_config)); return 0; } static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask) { return (mask >> (parm-1)) & 0x1; } |
c80d545da mac80211: Let use... |
985 986 987 988 989 |
static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, const struct mesh_setup *setup) { u8 *new_ie; const u8 *old_ie; |
581a8b0fe nl80211: rename N... |
990 |
/* allocate information elements */ |
c80d545da mac80211: Let use... |
991 |
new_ie = NULL; |
581a8b0fe nl80211: rename N... |
992 |
old_ie = ifmsh->ie; |
c80d545da mac80211: Let use... |
993 |
|
581a8b0fe nl80211: rename N... |
994 995 |
if (setup->ie_len) { new_ie = kmemdup(setup->ie, setup->ie_len, |
c80d545da mac80211: Let use... |
996 997 998 999 |
GFP_KERNEL); if (!new_ie) return -ENOMEM; } |
581a8b0fe nl80211: rename N... |
1000 1001 1002 |
ifmsh->ie_len = setup->ie_len; ifmsh->ie = new_ie; kfree(old_ie); |
c80d545da mac80211: Let use... |
1003 1004 1005 1006 1007 1008 |
/* now copy the rest of the setup parameters */ ifmsh->mesh_id_len = setup->mesh_id_len; memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); ifmsh->mesh_pp_id = setup->path_sel_proto; ifmsh->mesh_pm_id = setup->path_metric; |
b130e5cec nl80211: Introduc... |
1009 1010 1011 1012 1013 |
ifmsh->security = IEEE80211_MESH_SEC_NONE; if (setup->is_authenticated) ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; if (setup->is_secure) ifmsh->security |= IEEE80211_MESH_SEC_SECURED; |
c80d545da mac80211: Let use... |
1014 1015 1016 |
return 0; } |
24bdd9f4c mac80211: Rename ... |
1017 |
static int ieee80211_update_mesh_config(struct wiphy *wiphy, |
29cbe68c5 cfg80211/mac80211... |
1018 1019 |
struct net_device *dev, u32 mask, const struct mesh_config *nconf) |
93da9cc17 Add nl80211 comma... |
1020 1021 1022 |
{ struct mesh_config *conf; struct ieee80211_sub_if_data *sdata; |
63c5723bc mac80211: add nl8... |
1023 |
struct ieee80211_if_mesh *ifmsh; |
93da9cc17 Add nl80211 comma... |
1024 |
sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
63c5723bc mac80211: add nl8... |
1025 |
ifmsh = &sdata->u.mesh; |
93da9cc17 Add nl80211 comma... |
1026 |
|
93da9cc17 Add nl80211 comma... |
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 |
/* Set the config options which we are interested in setting */ conf = &(sdata->u.mesh.mshcfg); if (_chg_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask)) conf->dot11MeshRetryTimeout = nconf->dot11MeshRetryTimeout; if (_chg_mesh_attr(NL80211_MESHCONF_CONFIRM_TIMEOUT, mask)) conf->dot11MeshConfirmTimeout = nconf->dot11MeshConfirmTimeout; if (_chg_mesh_attr(NL80211_MESHCONF_HOLDING_TIMEOUT, mask)) conf->dot11MeshHoldingTimeout = nconf->dot11MeshHoldingTimeout; if (_chg_mesh_attr(NL80211_MESHCONF_MAX_PEER_LINKS, mask)) conf->dot11MeshMaxPeerLinks = nconf->dot11MeshMaxPeerLinks; if (_chg_mesh_attr(NL80211_MESHCONF_MAX_RETRIES, mask)) conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries; if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask)) conf->dot11MeshTTL = nconf->dot11MeshTTL; |
45904f216 nl80211/mac80211:... |
1041 1042 |
if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) conf->dot11MeshTTL = nconf->element_ttl; |
93da9cc17 Add nl80211 comma... |
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 |
if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) conf->auto_open_plinks = nconf->auto_open_plinks; if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask)) conf->dot11MeshHWMPmaxPREQretries = nconf->dot11MeshHWMPmaxPREQretries; if (_chg_mesh_attr(NL80211_MESHCONF_PATH_REFRESH_TIME, mask)) conf->path_refresh_time = nconf->path_refresh_time; if (_chg_mesh_attr(NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, mask)) conf->min_discovery_timeout = nconf->min_discovery_timeout; if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, mask)) conf->dot11MeshHWMPactivePathTimeout = nconf->dot11MeshHWMPactivePathTimeout; if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask)) conf->dot11MeshHWMPpreqMinInterval = nconf->dot11MeshHWMPpreqMinInterval; if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, mask)) conf->dot11MeshHWMPnetDiameterTraversalTime = nconf->dot11MeshHWMPnetDiameterTraversalTime; |
63c5723bc mac80211: add nl8... |
1062 1063 1064 1065 |
if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ROOTMODE, mask)) { conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode; ieee80211_mesh_root_setup(ifmsh); } |
93da9cc17 Add nl80211 comma... |
1066 1067 |
return 0; } |
29cbe68c5 cfg80211/mac80211... |
1068 1069 1070 1071 1072 1073 |
static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, const struct mesh_config *conf, const struct mesh_setup *setup) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
c80d545da mac80211: Let use... |
1074 |
int err; |
29cbe68c5 cfg80211/mac80211... |
1075 |
|
c80d545da mac80211: Let use... |
1076 1077 1078 1079 |
memcpy(&ifmsh->mshcfg, conf, sizeof(struct mesh_config)); err = copy_mesh_setup(ifmsh, setup); if (err) return err; |
29cbe68c5 cfg80211/mac80211... |
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 |
ieee80211_start_mesh(sdata); return 0; } static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ieee80211_stop_mesh(sdata); return 0; } |
c5dd9c2bd mac80211: mesh pa... |
1093 |
#endif |
9f1ba9062 mac80211/cfg80211... |
1094 1095 1096 1097 |
static int ieee80211_change_bss(struct wiphy *wiphy, struct net_device *dev, struct bss_parameters *params) { |
9f1ba9062 mac80211/cfg80211... |
1098 1099 |
struct ieee80211_sub_if_data *sdata; u32 changed = 0; |
9f1ba9062 mac80211/cfg80211... |
1100 |
sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
9f1ba9062 mac80211/cfg80211... |
1101 |
if (params->use_cts_prot >= 0) { |
bda3933a8 mac80211: move bs... |
1102 |
sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; |
9f1ba9062 mac80211/cfg80211... |
1103 1104 1105 |
changed |= BSS_CHANGED_ERP_CTS_PROT; } if (params->use_short_preamble >= 0) { |
bda3933a8 mac80211: move bs... |
1106 |
sdata->vif.bss_conf.use_short_preamble = |
9f1ba9062 mac80211/cfg80211... |
1107 1108 1109 |
params->use_short_preamble; changed |= BSS_CHANGED_ERP_PREAMBLE; } |
43d353434 mac80211: force u... |
1110 1111 1112 1113 1114 1115 |
if (!sdata->vif.bss_conf.use_short_slot && sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) { sdata->vif.bss_conf.use_short_slot = true; changed |= BSS_CHANGED_ERP_SLOT; } |
9f1ba9062 mac80211/cfg80211... |
1116 |
if (params->use_short_slot_time >= 0) { |
bda3933a8 mac80211: move bs... |
1117 |
sdata->vif.bss_conf.use_short_slot = |
9f1ba9062 mac80211/cfg80211... |
1118 1119 1120 |
params->use_short_slot_time; changed |= BSS_CHANGED_ERP_SLOT; } |
90c97a040 nl80211: Add basi... |
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 |
if (params->basic_rates) { int i, j; u32 rates = 0; struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_supported_band *sband = wiphy->bands[local->oper_channel->band]; for (i = 0; i < params->basic_rates_len; i++) { int rate = (params->basic_rates[i] & 0x7f) * 5; for (j = 0; j < sband->n_bitrates; j++) { if (sband->bitrates[j].bitrate == rate) rates |= BIT(j); } } sdata->vif.bss_conf.basic_rates = rates; changed |= BSS_CHANGED_BASIC_RATES; } |
7b7b5e56d mac80211: impleme... |
1138 1139 1140 1141 1142 1143 |
if (params->ap_isolate >= 0) { if (params->ap_isolate) sdata->flags |= IEEE80211_SDATA_DONT_BRIDGE_PACKETS; else sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS; } |
80d7e403c mac80211: Apply h... |
1144 1145 1146 1147 1148 |
if (params->ht_opmode >= 0) { sdata->vif.bss_conf.ht_operation_mode = (u16) params->ht_opmode; changed |= BSS_CHANGED_HT; } |
9f1ba9062 mac80211/cfg80211... |
1149 1150 1151 1152 |
ieee80211_bss_info_change_notify(sdata, changed); return 0; } |
318884875 nl80211: Add TX q... |
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 |
static int ieee80211_set_txq_params(struct wiphy *wiphy, struct ieee80211_txq_params *params) { struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_tx_queue_params p; if (!local->ops->conf_tx) return -EOPNOTSUPP; memset(&p, 0, sizeof(p)); p.aifs = params->aifs; p.cw_max = params->cwmax; p.cw_min = params->cwmin; p.txop = params->txop; |
ab13315af mac80211: add U-A... |
1167 1168 1169 1170 1171 1172 |
/* * Setting tx queue params disables u-apsd because it's only * called in master mode. */ p.uapsd = false; |
2683d65bb mac80211: reconfi... |
1173 1174 1175 1176 |
if (params->queue >= local->hw.queues) return -EINVAL; local->tx_conf[params->queue] = p; |
244879813 mac80211: add dri... |
1177 |
if (drv_conf_tx(local, params->queue, &p)) { |
0fb9a9ec2 net/mac80211: Use... |
1178 1179 1180 1181 |
wiphy_debug(local->hw.wiphy, "failed to set TX queue parameters for queue %d ", params->queue); |
318884875 nl80211: Add TX q... |
1182 1183 1184 1185 1186 |
return -EINVAL; } return 0; } |
72bdcf343 nl80211: Add freq... |
1187 |
static int ieee80211_set_channel(struct wiphy *wiphy, |
f444de05d cfg80211/mac80211... |
1188 |
struct net_device *netdev, |
72bdcf343 nl80211: Add freq... |
1189 |
struct ieee80211_channel *chan, |
094d05dc3 mac80211: Fix HT ... |
1190 |
enum nl80211_channel_type channel_type) |
72bdcf343 nl80211: Add freq... |
1191 1192 |
{ struct ieee80211_local *local = wiphy_priv(wiphy); |
0aaffa9b9 mac80211: improve... |
1193 |
struct ieee80211_sub_if_data *sdata = NULL; |
eeabee7e5 mac80211: Be more... |
1194 1195 1196 |
struct ieee80211_channel *old_oper; enum nl80211_channel_type old_oper_type; enum nl80211_channel_type old_vif_oper_type= NL80211_CHAN_NO_HT; |
0aaffa9b9 mac80211: improve... |
1197 1198 1199 |
if (netdev) sdata = IEEE80211_DEV_TO_SUB_IF(netdev); |
72bdcf343 nl80211: Add freq... |
1200 |
|
f444de05d cfg80211/mac80211... |
1201 1202 1203 1204 |
switch (ieee80211_get_channel_mode(local, NULL)) { case CHAN_MODE_HOPPING: return -EBUSY; case CHAN_MODE_FIXED: |
0aaffa9b9 mac80211: improve... |
1205 1206 1207 |
if (local->oper_channel != chan) return -EBUSY; if (!sdata && local->_oper_channel_type == channel_type) |
f444de05d cfg80211/mac80211... |
1208 |
return 0; |
0aaffa9b9 mac80211: improve... |
1209 |
break; |
f444de05d cfg80211/mac80211... |
1210 1211 1212 |
case CHAN_MODE_UNDEFINED: break; } |
72bdcf343 nl80211: Add freq... |
1213 |
|
eeabee7e5 mac80211: Be more... |
1214 1215 1216 |
if (sdata) old_vif_oper_type = sdata->vif.bss_conf.channel_type; old_oper_type = local->_oper_channel_type; |
72bdcf343 nl80211: Add freq... |
1217 |
|
0aaffa9b9 mac80211: improve... |
1218 1219 |
if (!ieee80211_set_channel_type(local, sdata, channel_type)) return -EBUSY; |
eeabee7e5 mac80211: Be more... |
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 |
old_oper = local->oper_channel; local->oper_channel = chan; /* Update driver if changes were actually made. */ if ((old_oper != local->oper_channel) || (old_oper_type != local->_oper_channel_type)) ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); if ((sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR) && old_vif_oper_type != sdata->vif.bss_conf.channel_type) |
0aaffa9b9 mac80211: improve... |
1230 1231 1232 |
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); return 0; |
72bdcf343 nl80211: Add freq... |
1233 |
} |
665af4fc8 mac80211: add sus... |
1234 |
#ifdef CONFIG_PM |
ff1b6e69a nl80211/cfg80211:... |
1235 1236 |
static int ieee80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wowlan) |
665af4fc8 mac80211: add sus... |
1237 |
{ |
eecc48000 mac80211: add bas... |
1238 |
return __ieee80211_suspend(wiphy_priv(wiphy), wowlan); |
665af4fc8 mac80211: add sus... |
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 |
} static int ieee80211_resume(struct wiphy *wiphy) { return __ieee80211_resume(wiphy_priv(wiphy)); } #else #define ieee80211_suspend NULL #define ieee80211_resume NULL #endif |
2a5193119 cfg80211/nl80211:... |
1249 1250 1251 1252 |
static int ieee80211_scan(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_scan_request *req) { |
2ca27bcff mac80211: add p2p... |
1253 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2a5193119 cfg80211/nl80211:... |
1254 |
|
2ca27bcff mac80211: add p2p... |
1255 1256 1257 1258 1259 1260 1261 1262 1263 |
switch (ieee80211_vif_type_p2p(&sdata->vif)) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_P2P_CLIENT: break; case NL80211_IFTYPE_P2P_GO: if (sdata->local->ops->hw_scan) break; |
e9d7732ea mac80211: allow G... |
1264 1265 1266 1267 1268 |
/* * FIXME: implement NoA while scanning in software, * for now fall through to allow scanning only when * beaconing hasn't been configured yet */ |
2ca27bcff mac80211: add p2p... |
1269 1270 1271 1272 1273 1274 1275 |
case NL80211_IFTYPE_AP: if (sdata->u.ap.beacon) return -EOPNOTSUPP; break; default: return -EOPNOTSUPP; } |
2a5193119 cfg80211/nl80211:... |
1276 1277 1278 |
return ieee80211_request_scan(sdata, req); } |
79f460ca4 mac80211: add sup... |
1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 |
static int ieee80211_sched_scan_start(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_sched_scan_request *req) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (!sdata->local->ops->sched_scan_start) return -EOPNOTSUPP; return ieee80211_request_sched_scan_start(sdata, req); } static int |
85a9994a0 cfg80211/mac80211... |
1293 |
ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) |
79f460ca4 mac80211: add sup... |
1294 1295 1296 1297 1298 |
{ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (!sdata->local->ops->sched_scan_stop) return -EOPNOTSUPP; |
85a9994a0 cfg80211/mac80211... |
1299 |
return ieee80211_request_sched_scan_stop(sdata); |
79f460ca4 mac80211: add sup... |
1300 |
} |
636a5d362 nl80211: Add MLME... |
1301 1302 1303 |
static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_auth_request *req) { |
77fdaa12c mac80211: rework ... |
1304 |
return ieee80211_mgd_auth(IEEE80211_DEV_TO_SUB_IF(dev), req); |
636a5d362 nl80211: Add MLME... |
1305 1306 1307 1308 1309 |
} static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_assoc_request *req) { |
f444de05d cfg80211/mac80211... |
1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 |
struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); switch (ieee80211_get_channel_mode(local, sdata)) { case CHAN_MODE_HOPPING: return -EBUSY; case CHAN_MODE_FIXED: if (local->oper_channel == req->bss->channel) break; return -EBUSY; case CHAN_MODE_UNDEFINED: break; } |
77fdaa12c mac80211: rework ... |
1323 |
return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req); |
636a5d362 nl80211: Add MLME... |
1324 1325 1326 |
} static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev, |
667503ddc cfg80211: fix loc... |
1327 1328 |
struct cfg80211_deauth_request *req, void *cookie) |
636a5d362 nl80211: Add MLME... |
1329 |
{ |
667503ddc cfg80211: fix loc... |
1330 1331 |
return ieee80211_mgd_deauth(IEEE80211_DEV_TO_SUB_IF(dev), req, cookie); |
636a5d362 nl80211: Add MLME... |
1332 1333 1334 |
} static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, |
667503ddc cfg80211: fix loc... |
1335 1336 |
struct cfg80211_disassoc_request *req, void *cookie) |
636a5d362 nl80211: Add MLME... |
1337 |
{ |
667503ddc cfg80211: fix loc... |
1338 1339 |
return ieee80211_mgd_disassoc(IEEE80211_DEV_TO_SUB_IF(dev), req, cookie); |
636a5d362 nl80211: Add MLME... |
1340 |
} |
af8cdcd82 mac80211: convert... |
1341 1342 1343 |
static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params) { |
f444de05d cfg80211/mac80211... |
1344 |
struct ieee80211_local *local = wiphy_priv(wiphy); |
af8cdcd82 mac80211: convert... |
1345 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
f444de05d cfg80211/mac80211... |
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 |
switch (ieee80211_get_channel_mode(local, sdata)) { case CHAN_MODE_HOPPING: return -EBUSY; case CHAN_MODE_FIXED: if (!params->channel_fixed) return -EBUSY; if (local->oper_channel == params->channel) break; return -EBUSY; case CHAN_MODE_UNDEFINED: break; } |
af8cdcd82 mac80211: convert... |
1358 1359 1360 1361 1362 1363 1364 1365 1366 |
return ieee80211_ibss_join(sdata, params); } static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); return ieee80211_ibss_leave(sdata); } |
b9a5f8cab nl80211: Add set/... |
1367 1368 1369 |
static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) { struct ieee80211_local *local = wiphy_priv(wiphy); |
244879813 mac80211: add dri... |
1370 |
int err; |
b9a5f8cab nl80211: Add set/... |
1371 |
|
f23a47807 mac80211: support... |
1372 1373 1374 1375 1376 1377 |
if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { err = drv_set_frag_threshold(local, wiphy->frag_threshold); if (err) return err; } |
310bc676e mac80211: Add new... |
1378 1379 1380 1381 1382 1383 |
if (changed & WIPHY_PARAM_COVERAGE_CLASS) { err = drv_set_coverage_class(local, wiphy->coverage_class); if (err) return err; } |
b9a5f8cab nl80211: Add set/... |
1384 |
if (changed & WIPHY_PARAM_RTS_THRESHOLD) { |
244879813 mac80211: add dri... |
1385 |
err = drv_set_rts_threshold(local, wiphy->rts_threshold); |
b9a5f8cab nl80211: Add set/... |
1386 |
|
244879813 mac80211: add dri... |
1387 1388 |
if (err) return err; |
b9a5f8cab nl80211: Add set/... |
1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 |
} if (changed & WIPHY_PARAM_RETRY_SHORT) local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; if (changed & WIPHY_PARAM_RETRY_LONG) local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; if (changed & (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG)) ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); return 0; } |
7643a2c3f cfg80211: move tx... |
1401 |
static int ieee80211_set_tx_power(struct wiphy *wiphy, |
fa61cf70a cfg80211/mac80211... |
1402 |
enum nl80211_tx_power_setting type, int mbm) |
7643a2c3f cfg80211: move tx... |
1403 1404 1405 1406 |
{ struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_channel *chan = local->hw.conf.channel; u32 changes = 0; |
7643a2c3f cfg80211: move tx... |
1407 1408 |
switch (type) { |
fa61cf70a cfg80211/mac80211... |
1409 |
case NL80211_TX_POWER_AUTOMATIC: |
7643a2c3f cfg80211: move tx... |
1410 1411 |
local->user_power_level = -1; break; |
fa61cf70a cfg80211/mac80211... |
1412 1413 1414 1415 |
case NL80211_TX_POWER_LIMITED: if (mbm < 0 || (mbm % 100)) return -EOPNOTSUPP; local->user_power_level = MBM_TO_DBM(mbm); |
7643a2c3f cfg80211: move tx... |
1416 |
break; |
fa61cf70a cfg80211/mac80211... |
1417 1418 1419 |
case NL80211_TX_POWER_FIXED: if (mbm < 0 || (mbm % 100)) return -EOPNOTSUPP; |
7643a2c3f cfg80211: move tx... |
1420 |
/* TODO: move to cfg80211 when it knows the channel */ |
fa61cf70a cfg80211/mac80211... |
1421 |
if (MBM_TO_DBM(mbm) > chan->max_power) |
7643a2c3f cfg80211: move tx... |
1422 |
return -EINVAL; |
fa61cf70a cfg80211/mac80211... |
1423 |
local->user_power_level = MBM_TO_DBM(mbm); |
7643a2c3f cfg80211: move tx... |
1424 |
break; |
7643a2c3f cfg80211: move tx... |
1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 |
} ieee80211_hw_config(local, changes); return 0; } static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm) { struct ieee80211_local *local = wiphy_priv(wiphy); *dbm = local->hw.conf.power_level; |
7643a2c3f cfg80211: move tx... |
1437 1438 |
return 0; } |
ab737a4f7 cfg80211: impleme... |
1439 |
static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, |
388ac775b cfg80211: constif... |
1440 |
const u8 *addr) |
ab737a4f7 cfg80211: impleme... |
1441 1442 1443 1444 1445 1446 1447 |
{ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); memcpy(&sdata->u.wds.remote_addr, addr, ETH_ALEN); return 0; } |
1f87f7d3a cfg80211: add rfk... |
1448 1449 1450 1451 1452 1453 |
static void ieee80211_rfkill_poll(struct wiphy *wiphy) { struct ieee80211_local *local = wiphy_priv(wiphy); drv_rfkill_poll(local); } |
aff89a9b9 cfg80211: introdu... |
1454 |
#ifdef CONFIG_NL80211_TESTMODE |
99783e2cd mac80211: fix spa... |
1455 |
static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) |
aff89a9b9 cfg80211: introdu... |
1456 1457 1458 1459 1460 1461 1462 1463 |
{ struct ieee80211_local *local = wiphy_priv(wiphy); if (!local->ops->testmode_cmd) return -EOPNOTSUPP; return local->ops->testmode_cmd(&local->hw, data, len); } |
71063f0e8 nl80211: add test... |
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 |
static int ieee80211_testmode_dump(struct wiphy *wiphy, struct sk_buff *skb, struct netlink_callback *cb, void *data, int len) { struct ieee80211_local *local = wiphy_priv(wiphy); if (!local->ops->testmode_dump) return -EOPNOTSUPP; return local->ops->testmode_dump(&local->hw, skb, cb, data, len); } |
aff89a9b9 cfg80211: introdu... |
1477 |
#endif |
0f78231bf mac80211: enable ... |
1478 1479 1480 1481 1482 1483 |
int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, enum ieee80211_smps_mode smps_mode) { const u8 *ap; enum ieee80211_smps_mode old_req; int err; |
243e6df4e mac80211: fix SMP... |
1484 |
lockdep_assert_held(&sdata->u.mgd.mtx); |
0f78231bf mac80211: enable ... |
1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 |
old_req = sdata->u.mgd.req_smps; sdata->u.mgd.req_smps = smps_mode; if (old_req == smps_mode && smps_mode != IEEE80211_SMPS_AUTOMATIC) return 0; /* * If not associated, or current association is not an HT * association, there's no need to send an action frame. */ if (!sdata->u.mgd.associated || |
0aaffa9b9 mac80211: improve... |
1497 |
sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { |
0f78231bf mac80211: enable ... |
1498 |
mutex_lock(&sdata->local->iflist_mtx); |
025e6be22 mac80211: fix dea... |
1499 |
ieee80211_recalc_smps(sdata->local); |
0f78231bf mac80211: enable ... |
1500 1501 1502 |
mutex_unlock(&sdata->local->iflist_mtx); return 0; } |
0c1ad2cac mac80211: proper ... |
1503 |
ap = sdata->u.mgd.associated->bssid; |
0f78231bf mac80211: enable ... |
1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 |
if (smps_mode == IEEE80211_SMPS_AUTOMATIC) { if (sdata->u.mgd.powersave) smps_mode = IEEE80211_SMPS_DYNAMIC; else smps_mode = IEEE80211_SMPS_OFF; } /* send SM PS frame to AP */ err = ieee80211_send_smps_action(sdata, smps_mode, ap, ap); if (err) sdata->u.mgd.req_smps = old_req; return err; } |
bc92afd92 cfg80211: impleme... |
1520 1521 1522 1523 1524 |
static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
bc92afd92 cfg80211: impleme... |
1525 |
|
e5de30c9b mac80211: check t... |
1526 1527 |
if (sdata->vif.type != NL80211_IFTYPE_STATION) return -EOPNOTSUPP; |
bc92afd92 cfg80211: impleme... |
1528 1529 1530 1531 |
if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) return -EOPNOTSUPP; if (enabled == sdata->u.mgd.powersave && |
ff6163810 mac80211: Fix ps-... |
1532 |
timeout == local->dynamic_ps_forced_timeout) |
bc92afd92 cfg80211: impleme... |
1533 1534 1535 |
return 0; sdata->u.mgd.powersave = enabled; |
ff6163810 mac80211: Fix ps-... |
1536 |
local->dynamic_ps_forced_timeout = timeout; |
bc92afd92 cfg80211: impleme... |
1537 |
|
0f78231bf mac80211: enable ... |
1538 1539 1540 1541 |
/* no change, but if automatic follow powersave */ mutex_lock(&sdata->u.mgd.mtx); __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps); mutex_unlock(&sdata->u.mgd.mtx); |
bc92afd92 cfg80211: impleme... |
1542 1543 1544 1545 1546 1547 1548 |
if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); ieee80211_recalc_ps(local, -1); return 0; } |
a97c13c34 mac80211: Add sup... |
1549 1550 1551 1552 1553 1554 1555 1556 |
static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev, s32 rssi_thold, u32 rssi_hyst) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_vif *vif = &sdata->vif; struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
a97c13c34 mac80211: Add sup... |
1557 1558 1559 1560 1561 1562 |
if (rssi_thold == bss_conf->cqm_rssi_thold && rssi_hyst == bss_conf->cqm_rssi_hyst) return 0; bss_conf->cqm_rssi_thold = rssi_thold; bss_conf->cqm_rssi_hyst = rssi_hyst; |
17e4ec147 mac80211: Track B... |
1563 1564 1565 1566 1567 |
if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { if (sdata->vif.type != NL80211_IFTYPE_STATION) return -EOPNOTSUPP; return 0; } |
a97c13c34 mac80211: Add sup... |
1568 1569 1570 1571 1572 1573 |
/* tell the driver upon association, unless already associated */ if (sdata->u.mgd.associated) ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM); return 0; } |
9930380f0 cfg80211: impleme... |
1574 1575 1576 1577 1578 1579 1580 |
static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev, const u8 *addr, const struct cfg80211_bitrate_mask *mask) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
bdbfd6b58 mac80211: Add new... |
1581 |
int i, ret; |
2c7e6bc9a mac80211: disallo... |
1582 |
|
bdbfd6b58 mac80211: Add new... |
1583 1584 1585 1586 1587 |
if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) { ret = drv_set_bitrate_mask(local, sdata, mask); if (ret) return ret; } |
9930380f0 cfg80211: impleme... |
1588 |
|
37eb0b164 cfg80211/mac80211... |
1589 1590 |
for (i = 0; i < IEEE80211_NUM_BANDS; i++) sdata->rc_rateidx_mask[i] = mask->control[i].legacy; |
9930380f0 cfg80211: impleme... |
1591 |
|
37eb0b164 cfg80211/mac80211... |
1592 |
return 0; |
9930380f0 cfg80211: impleme... |
1593 |
} |
21f835896 mac80211: impleme... |
1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 |
static int ieee80211_remain_on_channel_hw(struct ieee80211_local *local, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_channel_type chantype, unsigned int duration, u64 *cookie) { int ret; u32 random_cookie; lockdep_assert_held(&local->mtx); if (local->hw_roc_cookie) return -EBUSY; /* must be nonzero */ random_cookie = random32() | 1; *cookie = random_cookie; local->hw_roc_dev = dev; local->hw_roc_cookie = random_cookie; local->hw_roc_channel = chan; local->hw_roc_channel_type = chantype; local->hw_roc_duration = duration; ret = drv_remain_on_channel(local, chan, chantype, duration); if (ret) { local->hw_roc_channel = NULL; local->hw_roc_cookie = 0; } return ret; } |
b8bc4b0aa mac80211: support... |
1624 1625 1626 1627 1628 1629 1630 1631 |
static int ieee80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type, unsigned int duration, u64 *cookie) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
21f835896 mac80211: impleme... |
1632 1633 1634 1635 1636 1637 1638 1639 1640 |
struct ieee80211_local *local = sdata->local; if (local->ops->remain_on_channel) { int ret; mutex_lock(&local->mtx); ret = ieee80211_remain_on_channel_hw(local, dev, chan, channel_type, duration, cookie); |
90fc4b3a5 mac80211: impleme... |
1641 |
local->hw_roc_for_tx = false; |
21f835896 mac80211: impleme... |
1642 1643 1644 1645 |
mutex_unlock(&local->mtx); return ret; } |
b8bc4b0aa mac80211: support... |
1646 1647 1648 1649 |
return ieee80211_wk_remain_on_channel(sdata, chan, channel_type, duration, cookie); } |
21f835896 mac80211: impleme... |
1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 |
static int ieee80211_cancel_remain_on_channel_hw(struct ieee80211_local *local, u64 cookie) { int ret; lockdep_assert_held(&local->mtx); if (local->hw_roc_cookie != cookie) return -ENOENT; ret = drv_cancel_remain_on_channel(local); if (ret) return ret; local->hw_roc_cookie = 0; local->hw_roc_channel = NULL; ieee80211_recalc_idle(local); return 0; } |
b8bc4b0aa mac80211: support... |
1671 1672 1673 1674 1675 |
static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, u64 cookie) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
21f835896 mac80211: impleme... |
1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 |
struct ieee80211_local *local = sdata->local; if (local->ops->cancel_remain_on_channel) { int ret; mutex_lock(&local->mtx); ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); mutex_unlock(&local->mtx); return ret; } |
b8bc4b0aa mac80211: support... |
1687 1688 1689 |
return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); } |
f30221e4e mac80211: impleme... |
1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 |
static enum work_done_result ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb) { /* * Use the data embedded in the work struct for reporting * here so if the driver mangled the SKB before dropping * it (which is the only way we really should get here) * then we don't report mangled data. * * If there was no wait time, then by the time we get here * the driver will likely not have reported the status yet, * so in that case userspace will have to deal with it. */ if (wk->offchan_tx.wait && wk->offchan_tx.frame) cfg80211_mgmt_tx_status(wk->sdata->dev, (unsigned long) wk->offchan_tx.frame, wk->ie, wk->ie_len, false, GFP_KERNEL); return WORK_DONE_DESTROY; } |
2e161f78e cfg80211/mac80211... |
1711 |
static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, |
f7ca38dfe nl80211/cfg80211:... |
1712 |
struct ieee80211_channel *chan, bool offchan, |
2e161f78e cfg80211/mac80211... |
1713 |
enum nl80211_channel_type channel_type, |
f7ca38dfe nl80211/cfg80211:... |
1714 |
bool channel_type_valid, unsigned int wait, |
2e161f78e cfg80211/mac80211... |
1715 |
const u8 *buf, size_t len, u64 *cookie) |
026331c4d cfg80211/mac80211... |
1716 |
{ |
9d38d85de cfg80211/mac80211... |
1717 1718 1719 1720 |
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct sta_info *sta; |
f30221e4e mac80211: impleme... |
1721 |
struct ieee80211_work *wk; |
9d38d85de cfg80211/mac80211... |
1722 1723 1724 |
const struct ieee80211_mgmt *mgmt = (void *)buf; u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | IEEE80211_TX_CTL_REQ_TX_STATUS; |
f30221e4e mac80211: impleme... |
1725 |
bool is_offchan = false; |
f7ca38dfe nl80211/cfg80211:... |
1726 |
|
9d38d85de cfg80211/mac80211... |
1727 1728 1729 |
/* Check that we are on the requested channel for transmission */ if (chan != local->tmp_channel && chan != local->oper_channel) |
f30221e4e mac80211: impleme... |
1730 |
is_offchan = true; |
9d38d85de cfg80211/mac80211... |
1731 1732 1733 |
if (channel_type_valid && (channel_type != local->tmp_channel_type && channel_type != local->_oper_channel_type)) |
f30221e4e mac80211: impleme... |
1734 |
is_offchan = true; |
21f835896 mac80211: impleme... |
1735 1736 1737 1738 1739 |
if (chan == local->hw_roc_channel) { /* TODO: check channel type? */ is_offchan = false; flags |= IEEE80211_TX_CTL_TX_OFFCHAN; } |
f30221e4e mac80211: impleme... |
1740 |
if (is_offchan && !offchan) |
9d38d85de cfg80211/mac80211... |
1741 1742 1743 1744 |
return -EBUSY; switch (sdata->vif.type) { case NL80211_IFTYPE_ADHOC: |
663fcafd9 cfg80211/mac80211... |
1745 1746 1747 |
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_P2P_GO: |
c7108a711 mac80211: Send me... |
1748 |
case NL80211_IFTYPE_MESH_POINT: |
663fcafd9 cfg80211/mac80211... |
1749 1750 |
if (!ieee80211_is_action(mgmt->frame_control) || mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) |
9d38d85de cfg80211/mac80211... |
1751 1752 1753 1754 1755 1756 1757 1758 |
break; rcu_read_lock(); sta = sta_info_get(sdata, mgmt->da); rcu_read_unlock(); if (!sta) return -ENOLINK; break; case NL80211_IFTYPE_STATION: |
663fcafd9 cfg80211/mac80211... |
1759 |
case NL80211_IFTYPE_P2P_CLIENT: |
9d38d85de cfg80211/mac80211... |
1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 |
break; default: return -EOPNOTSUPP; } skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); if (!skb) return -ENOMEM; skb_reserve(skb, local->hw.extra_tx_headroom); memcpy(skb_put(skb, len), buf, len); IEEE80211_SKB_CB(skb)->flags = flags; skb->dev = sdata->dev; |
9d38d85de cfg80211/mac80211... |
1775 1776 |
*cookie = (unsigned long) skb; |
f30221e4e mac80211: impleme... |
1777 |
|
5f16a4361 mac80211: support... |
1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 |
if (is_offchan && local->ops->offchannel_tx) { int ret; IEEE80211_SKB_CB(skb)->band = chan->band; mutex_lock(&local->mtx); if (local->hw_offchan_tx_cookie) { mutex_unlock(&local->mtx); return -EBUSY; } /* TODO: bitrate control, TX processing? */ ret = drv_offchannel_tx(local, skb, chan, channel_type, wait); if (ret == 0) local->hw_offchan_tx_cookie = *cookie; mutex_unlock(&local->mtx); /* * Allow driver to return 1 to indicate it wants to have the * frame transmitted with a remain_on_channel + regular TX. */ if (ret != 1) return ret; } |
90fc4b3a5 mac80211: impleme... |
1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 |
if (is_offchan && local->ops->remain_on_channel) { unsigned int duration; int ret; mutex_lock(&local->mtx); /* * If the duration is zero, then the driver * wouldn't actually do anything. Set it to * 100 for now. * * TODO: cancel the off-channel operation * when we get the SKB's TX status and * the wait time was zero before. */ duration = 100; if (wait) duration = wait; ret = ieee80211_remain_on_channel_hw(local, dev, chan, channel_type, duration, cookie); if (ret) { kfree_skb(skb); mutex_unlock(&local->mtx); return ret; } local->hw_roc_for_tx = true; local->hw_roc_duration = wait; /* * queue up frame for transmission after * ieee80211_ready_on_channel call */ /* modify cookie to prevent API mismatches */ *cookie ^= 2; IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; local->hw_roc_skb = skb; |
4334ec851 mac80211: fix TX ... |
1842 |
local->hw_roc_skb_for_status = skb; |
90fc4b3a5 mac80211: impleme... |
1843 1844 1845 1846 |
mutex_unlock(&local->mtx); return 0; } |
f30221e4e mac80211: impleme... |
1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 |
/* * Can transmit right away if the channel was the * right one and there's no wait involved... If a * wait is involved, we might otherwise not be on * the right channel for long enough! */ if (!is_offchan && !wait && !sdata->vif.bss_conf.idle) { ieee80211_tx_skb(sdata, skb); return 0; } wk = kzalloc(sizeof(*wk) + len, GFP_KERNEL); if (!wk) { kfree_skb(skb); return -ENOMEM; } wk->type = IEEE80211_WORK_OFFCHANNEL_TX; wk->chan = chan; |
4d51e149a mac80211: Properl... |
1866 |
wk->chan_type = channel_type; |
f30221e4e mac80211: impleme... |
1867 1868 1869 1870 1871 1872 1873 1874 |
wk->sdata = sdata; wk->done = ieee80211_offchan_tx_done; wk->offchan_tx.frame = skb; wk->offchan_tx.wait = wait; wk->ie_len = len; memcpy(wk->ie, buf, len); ieee80211_add_work(wk); |
9d38d85de cfg80211/mac80211... |
1875 |
return 0; |
026331c4d cfg80211/mac80211... |
1876 |
} |
f30221e4e mac80211: impleme... |
1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 |
static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct net_device *dev, u64 cookie) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; struct ieee80211_work *wk; int ret = -ENOENT; mutex_lock(&local->mtx); |
90fc4b3a5 mac80211: impleme... |
1887 |
|
5f16a4361 mac80211: support... |
1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 |
if (local->ops->offchannel_tx_cancel_wait && local->hw_offchan_tx_cookie == cookie) { ret = drv_offchannel_tx_cancel_wait(local); if (!ret) local->hw_offchan_tx_cookie = 0; mutex_unlock(&local->mtx); return ret; } |
90fc4b3a5 mac80211: impleme... |
1899 1900 1901 1902 1903 1904 1905 |
if (local->ops->cancel_remain_on_channel) { cookie ^= 2; ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); if (ret == 0) { kfree_skb(local->hw_roc_skb); local->hw_roc_skb = NULL; |
4334ec851 mac80211: fix TX ... |
1906 |
local->hw_roc_skb_for_status = NULL; |
90fc4b3a5 mac80211: impleme... |
1907 1908 1909 1910 1911 1912 |
} mutex_unlock(&local->mtx); return ret; } |
f30221e4e mac80211: impleme... |
1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 |
list_for_each_entry(wk, &local->work_list, list) { if (wk->sdata != sdata) continue; if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX) continue; if (cookie != (unsigned long) wk->offchan_tx.frame) continue; wk->timeout = jiffies; ieee80211_queue_work(&local->hw, &local->work_work); ret = 0; break; } mutex_unlock(&local->mtx); return ret; } |
7be5086d4 mac80211: add pro... |
1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 |
static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, struct net_device *dev, u16 frame_type, bool reg) { struct ieee80211_local *local = wiphy_priv(wiphy); if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ)) return; if (reg) local->probe_req_reg++; else local->probe_req_reg--; ieee80211_queue_work(&local->hw, &local->reconfig_filter); } |
15d967532 mac80211: Add ant... |
1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 |
static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) { struct ieee80211_local *local = wiphy_priv(wiphy); if (local->started) return -EOPNOTSUPP; return drv_set_antenna(local, tx_ant, rx_ant); } static int ieee80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant) { struct ieee80211_local *local = wiphy_priv(wiphy); return drv_get_antenna(local, tx_ant, rx_ant); } |
38c091590 mac80211: impleme... |
1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 |
static int ieee80211_set_ringparam(struct wiphy *wiphy, u32 tx, u32 rx) { struct ieee80211_local *local = wiphy_priv(wiphy); return drv_set_ringparam(local, tx, rx); } static void ieee80211_get_ringparam(struct wiphy *wiphy, u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max) { struct ieee80211_local *local = wiphy_priv(wiphy); drv_get_ringparam(local, tx, tx_max, rx, rx_max); } |
c68f4b892 mac80211: support... |
1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 |
static int ieee80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_gtk_rekey_data *data) { struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (!local->ops->set_rekey_data) return -EOPNOTSUPP; drv_set_rekey_data(local, sdata, data); return 0; } |
f0706e828 [MAC80211]: Add m... |
1993 1994 1995 |
struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, |
42613db76 [MAC80211]: imple... |
1996 |
.change_virtual_intf = ieee80211_change_iface, |
e8cbb4cbe mac80211: support... |
1997 1998 |
.add_key = ieee80211_add_key, .del_key = ieee80211_del_key, |
62da92fb7 mac80211: support... |
1999 |
.get_key = ieee80211_get_key, |
e8cbb4cbe mac80211: support... |
2000 |
.set_default_key = ieee80211_config_default_key, |
3cfcf6ac6 mac80211: 802.11w... |
2001 |
.set_default_mgmt_key = ieee80211_config_default_mgmt_key, |
5dfdaf58d mac80211: add bea... |
2002 2003 2004 |
.add_beacon = ieee80211_add_beacon, .set_beacon = ieee80211_set_beacon, .del_beacon = ieee80211_del_beacon, |
4fd6931eb mac80211: impleme... |
2005 2006 2007 |
.add_station = ieee80211_add_station, .del_station = ieee80211_del_station, .change_station = ieee80211_change_station, |
7bbdd2d98 mac80211: impleme... |
2008 |
.get_station = ieee80211_get_station, |
c5dd9c2bd mac80211: mesh pa... |
2009 |
.dump_station = ieee80211_dump_station, |
1289723ef mac80211: sample ... |
2010 |
.dump_survey = ieee80211_dump_survey, |
c5dd9c2bd mac80211: mesh pa... |
2011 2012 2013 2014 2015 2016 |
#ifdef CONFIG_MAC80211_MESH .add_mpath = ieee80211_add_mpath, .del_mpath = ieee80211_del_mpath, .change_mpath = ieee80211_change_mpath, .get_mpath = ieee80211_get_mpath, .dump_mpath = ieee80211_dump_mpath, |
24bdd9f4c mac80211: Rename ... |
2017 2018 |
.update_mesh_config = ieee80211_update_mesh_config, .get_mesh_config = ieee80211_get_mesh_config, |
29cbe68c5 cfg80211/mac80211... |
2019 2020 |
.join_mesh = ieee80211_join_mesh, .leave_mesh = ieee80211_leave_mesh, |
c5dd9c2bd mac80211: mesh pa... |
2021 |
#endif |
9f1ba9062 mac80211/cfg80211... |
2022 |
.change_bss = ieee80211_change_bss, |
318884875 nl80211: Add TX q... |
2023 |
.set_txq_params = ieee80211_set_txq_params, |
72bdcf343 nl80211: Add freq... |
2024 |
.set_channel = ieee80211_set_channel, |
665af4fc8 mac80211: add sus... |
2025 2026 |
.suspend = ieee80211_suspend, .resume = ieee80211_resume, |
2a5193119 cfg80211/nl80211:... |
2027 |
.scan = ieee80211_scan, |
79f460ca4 mac80211: add sup... |
2028 2029 |
.sched_scan_start = ieee80211_sched_scan_start, .sched_scan_stop = ieee80211_sched_scan_stop, |
636a5d362 nl80211: Add MLME... |
2030 2031 2032 2033 |
.auth = ieee80211_auth, .assoc = ieee80211_assoc, .deauth = ieee80211_deauth, .disassoc = ieee80211_disassoc, |
af8cdcd82 mac80211: convert... |
2034 2035 |
.join_ibss = ieee80211_join_ibss, .leave_ibss = ieee80211_leave_ibss, |
b9a5f8cab nl80211: Add set/... |
2036 |
.set_wiphy_params = ieee80211_set_wiphy_params, |
7643a2c3f cfg80211: move tx... |
2037 2038 |
.set_tx_power = ieee80211_set_tx_power, .get_tx_power = ieee80211_get_tx_power, |
ab737a4f7 cfg80211: impleme... |
2039 |
.set_wds_peer = ieee80211_set_wds_peer, |
1f87f7d3a cfg80211: add rfk... |
2040 |
.rfkill_poll = ieee80211_rfkill_poll, |
aff89a9b9 cfg80211: introdu... |
2041 |
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) |
71063f0e8 nl80211: add test... |
2042 |
CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump) |
bc92afd92 cfg80211: impleme... |
2043 |
.set_power_mgmt = ieee80211_set_power_mgmt, |
9930380f0 cfg80211: impleme... |
2044 |
.set_bitrate_mask = ieee80211_set_bitrate_mask, |
b8bc4b0aa mac80211: support... |
2045 2046 |
.remain_on_channel = ieee80211_remain_on_channel, .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, |
2e161f78e cfg80211/mac80211... |
2047 |
.mgmt_tx = ieee80211_mgmt_tx, |
f30221e4e mac80211: impleme... |
2048 |
.mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait, |
a97c13c34 mac80211: Add sup... |
2049 |
.set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, |
7be5086d4 mac80211: add pro... |
2050 |
.mgmt_frame_register = ieee80211_mgmt_frame_register, |
15d967532 mac80211: Add ant... |
2051 2052 |
.set_antenna = ieee80211_set_antenna, .get_antenna = ieee80211_get_antenna, |
38c091590 mac80211: impleme... |
2053 2054 |
.set_ringparam = ieee80211_set_ringparam, .get_ringparam = ieee80211_get_ringparam, |
c68f4b892 mac80211: support... |
2055 |
.set_rekey_data = ieee80211_set_rekey_data, |
f0706e828 [MAC80211]: Add m... |
2056 |
}; |