]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - net/wireless/nl80211.c
mac80211: Assign next hop address to pending mesh frames
[mirror_ubuntu-bionic-kernel.git] / net / wireless / nl80211.c
CommitLineData
55682965
JB
1/*
2 * This is the new netlink-based wireless configuration interface.
3 *
08645126 4 * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net>
55682965
JB
5 */
6
7#include <linux/if.h>
8#include <linux/module.h>
9#include <linux/err.h>
55682965
JB
10#include <linux/list.h>
11#include <linux/if_ether.h>
12#include <linux/ieee80211.h>
13#include <linux/nl80211.h>
14#include <linux/rtnetlink.h>
15#include <linux/netlink.h>
2a519311 16#include <linux/etherdevice.h>
55682965
JB
17#include <net/genetlink.h>
18#include <net/cfg80211.h>
19#include "core.h"
20#include "nl80211.h"
b2e1b302 21#include "reg.h"
55682965
JB
22
23/* the netlink family */
24static struct genl_family nl80211_fam = {
25 .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
26 .name = "nl80211", /* have users key off the name instead */
27 .hdrsize = 0, /* no private header */
28 .version = 1, /* no particular meaning now */
29 .maxattr = NL80211_ATTR_MAX,
30};
31
79c97e97
JB
32/* internal helper: get rdev and dev */
33static int get_rdev_dev_by_info_ifindex(struct nlattr **attrs,
34 struct cfg80211_registered_device **rdev,
55682965
JB
35 struct net_device **dev)
36{
37 int ifindex;
38
bba95fef 39 if (!attrs[NL80211_ATTR_IFINDEX])
55682965
JB
40 return -EINVAL;
41
bba95fef 42 ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
55682965
JB
43 *dev = dev_get_by_index(&init_net, ifindex);
44 if (!*dev)
45 return -ENODEV;
46
79c97e97
JB
47 *rdev = cfg80211_get_dev_from_ifindex(ifindex);
48 if (IS_ERR(*rdev)) {
55682965 49 dev_put(*dev);
79c97e97 50 return PTR_ERR(*rdev);
55682965
JB
51 }
52
53 return 0;
54}
55
56/* policy for the attributes */
57static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
58 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
59 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
079e24ed 60 .len = 20-1 },
31888487 61 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
72bdcf34 62 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
094d05dc 63 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
b9a5f8ca
JM
64 [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 },
65 [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },
66 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
67 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
55682965
JB
68
69 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
70 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
71 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
41ade00f
JB
72
73 [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
3e5d7649 74 [NL80211_ATTR_PREV_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN },
41ade00f
JB
75
76 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
77 .len = WLAN_MAX_KEY_LEN },
78 [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
79 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
80 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
9f26a952 81 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
ed1b6cc7
JB
82
83 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
84 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
85 [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY,
86 .len = IEEE80211_MAX_DATA_LEN },
87 [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY,
88 .len = IEEE80211_MAX_DATA_LEN },
5727ef1b
JB
89 [NL80211_ATTR_STA_AID] = { .type = NLA_U16 },
90 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
91 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
92 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
93 .len = NL80211_MAX_SUPP_RATES },
2ec600d6 94 [NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 },
5727ef1b 95 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
0a9542ee 96 [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
2ec600d6
LCC
97 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
98 .len = IEEE80211_MAX_MESH_ID_LEN },
99 [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
9f1ba906 100
b2e1b302
LR
101 [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },
102 [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
103
9f1ba906
JM
104 [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
105 [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
106 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
90c97a04
JM
107 [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY,
108 .len = NL80211_MAX_SUPP_RATES },
36aedc90 109
93da9cc1 110 [NL80211_ATTR_MESH_PARAMS] = { .type = NLA_NESTED },
111
36aedc90
JM
112 [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY,
113 .len = NL80211_HT_CAPABILITY_LEN },
9aed3cc1
JM
114
115 [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
116 [NL80211_ATTR_IE] = { .type = NLA_BINARY,
117 .len = IEEE80211_MAX_DATA_LEN },
2a519311
JB
118 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
119 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
636a5d36
JM
120
121 [NL80211_ATTR_SSID] = { .type = NLA_BINARY,
122 .len = IEEE80211_MAX_SSID_LEN },
123 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
124 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
04a773ad 125 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
1965c853 126 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
dc6382ce 127 [NL80211_ATTR_USE_MFP] = { .type = NLA_U32 },
eccb8e8f
JB
128 [NL80211_ATTR_STA_FLAGS2] = {
129 .len = sizeof(struct nl80211_sta_flag_update),
130 },
3f77316c 131 [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
b23aa676
SO
132 [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
133 [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
134 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
55682965
JB
135};
136
f4a11bb0
JB
137/* IE validation */
138static bool is_valid_ie_attr(const struct nlattr *attr)
139{
140 const u8 *pos;
141 int len;
142
143 if (!attr)
144 return true;
145
146 pos = nla_data(attr);
147 len = nla_len(attr);
148
149 while (len) {
150 u8 elemlen;
151
152 if (len < 2)
153 return false;
154 len -= 2;
155
156 elemlen = pos[1];
157 if (elemlen > len)
158 return false;
159
160 len -= elemlen;
161 pos += 2 + elemlen;
162 }
163
164 return true;
165}
166
55682965
JB
167/* message building helper */
168static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
169 int flags, u8 cmd)
170{
171 /* since there is no private header just add the generic one */
172 return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
173}
174
5dab3b8a
LR
175static int nl80211_msg_put_channel(struct sk_buff *msg,
176 struct ieee80211_channel *chan)
177{
178 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
179 chan->center_freq);
180
181 if (chan->flags & IEEE80211_CHAN_DISABLED)
182 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
183 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
184 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
185 if (chan->flags & IEEE80211_CHAN_NO_IBSS)
186 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
187 if (chan->flags & IEEE80211_CHAN_RADAR)
188 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
189
190 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
191 DBM_TO_MBM(chan->max_power));
192
193 return 0;
194
195 nla_put_failure:
196 return -ENOBUFS;
197}
198
55682965
JB
199/* netlink command implementations */
200
201static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
202 struct cfg80211_registered_device *dev)
203{
204 void *hdr;
ee688b00
JB
205 struct nlattr *nl_bands, *nl_band;
206 struct nlattr *nl_freqs, *nl_freq;
207 struct nlattr *nl_rates, *nl_rate;
f59ac048 208 struct nlattr *nl_modes;
8fdc621d 209 struct nlattr *nl_cmds;
ee688b00
JB
210 enum ieee80211_band band;
211 struct ieee80211_channel *chan;
212 struct ieee80211_rate *rate;
213 int i;
f59ac048 214 u16 ifmodes = dev->wiphy.interface_modes;
55682965
JB
215
216 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
217 if (!hdr)
218 return -1;
219
b5850a7a 220 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx);
55682965 221 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
b9a5f8ca
JM
222
223 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
224 dev->wiphy.retry_short);
225 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
226 dev->wiphy.retry_long);
227 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
228 dev->wiphy.frag_threshold);
229 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
230 dev->wiphy.rts_threshold);
231
2a519311
JB
232 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
233 dev->wiphy.max_scan_ssids);
18a83659
JB
234 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
235 dev->wiphy.max_scan_ie_len);
ee688b00 236
25e47c18
JB
237 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES,
238 sizeof(u32) * dev->wiphy.n_cipher_suites,
239 dev->wiphy.cipher_suites);
240
f59ac048
LR
241 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
242 if (!nl_modes)
243 goto nla_put_failure;
244
245 i = 0;
246 while (ifmodes) {
247 if (ifmodes & 1)
248 NLA_PUT_FLAG(msg, i);
249 ifmodes >>= 1;
250 i++;
251 }
252
253 nla_nest_end(msg, nl_modes);
254
ee688b00
JB
255 nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
256 if (!nl_bands)
257 goto nla_put_failure;
258
259 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
260 if (!dev->wiphy.bands[band])
261 continue;
262
263 nl_band = nla_nest_start(msg, band);
264 if (!nl_band)
265 goto nla_put_failure;
266
d51626df
JB
267 /* add HT info */
268 if (dev->wiphy.bands[band]->ht_cap.ht_supported) {
269 NLA_PUT(msg, NL80211_BAND_ATTR_HT_MCS_SET,
270 sizeof(dev->wiphy.bands[band]->ht_cap.mcs),
271 &dev->wiphy.bands[band]->ht_cap.mcs);
272 NLA_PUT_U16(msg, NL80211_BAND_ATTR_HT_CAPA,
273 dev->wiphy.bands[band]->ht_cap.cap);
274 NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
275 dev->wiphy.bands[band]->ht_cap.ampdu_factor);
276 NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
277 dev->wiphy.bands[band]->ht_cap.ampdu_density);
278 }
279
ee688b00
JB
280 /* add frequencies */
281 nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
282 if (!nl_freqs)
283 goto nla_put_failure;
284
285 for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) {
286 nl_freq = nla_nest_start(msg, i);
287 if (!nl_freq)
288 goto nla_put_failure;
289
290 chan = &dev->wiphy.bands[band]->channels[i];
5dab3b8a
LR
291
292 if (nl80211_msg_put_channel(msg, chan))
293 goto nla_put_failure;
e2f367f2 294
ee688b00
JB
295 nla_nest_end(msg, nl_freq);
296 }
297
298 nla_nest_end(msg, nl_freqs);
299
300 /* add bitrates */
301 nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
302 if (!nl_rates)
303 goto nla_put_failure;
304
305 for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) {
306 nl_rate = nla_nest_start(msg, i);
307 if (!nl_rate)
308 goto nla_put_failure;
309
310 rate = &dev->wiphy.bands[band]->bitrates[i];
311 NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE,
312 rate->bitrate);
313 if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
314 NLA_PUT_FLAG(msg,
315 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE);
316
317 nla_nest_end(msg, nl_rate);
318 }
319
320 nla_nest_end(msg, nl_rates);
321
322 nla_nest_end(msg, nl_band);
323 }
324 nla_nest_end(msg, nl_bands);
325
8fdc621d
JB
326 nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS);
327 if (!nl_cmds)
328 goto nla_put_failure;
329
330 i = 0;
331#define CMD(op, n) \
332 do { \
333 if (dev->ops->op) { \
334 i++; \
335 NLA_PUT_U32(msg, i, NL80211_CMD_ ## n); \
336 } \
337 } while (0)
338
339 CMD(add_virtual_intf, NEW_INTERFACE);
340 CMD(change_virtual_intf, SET_INTERFACE);
341 CMD(add_key, NEW_KEY);
342 CMD(add_beacon, NEW_BEACON);
343 CMD(add_station, NEW_STATION);
344 CMD(add_mpath, NEW_MPATH);
345 CMD(set_mesh_params, SET_MESH_PARAMS);
346 CMD(change_bss, SET_BSS);
636a5d36
JM
347 CMD(auth, AUTHENTICATE);
348 CMD(assoc, ASSOCIATE);
349 CMD(deauth, DEAUTHENTICATE);
350 CMD(disassoc, DISASSOCIATE);
04a773ad 351 CMD(join_ibss, JOIN_IBSS);
8fdc621d
JB
352
353#undef CMD
b23aa676 354
6829c878 355 if (dev->ops->connect || dev->ops->auth) {
b23aa676
SO
356 i++;
357 NLA_PUT_U32(msg, i, NL80211_CMD_CONNECT);
358 }
359
6829c878 360 if (dev->ops->disconnect || dev->ops->deauth) {
b23aa676
SO
361 i++;
362 NLA_PUT_U32(msg, i, NL80211_CMD_DISCONNECT);
363 }
364
8fdc621d
JB
365 nla_nest_end(msg, nl_cmds);
366
55682965
JB
367 return genlmsg_end(msg, hdr);
368
369 nla_put_failure:
bc3ed28c
TG
370 genlmsg_cancel(msg, hdr);
371 return -EMSGSIZE;
55682965
JB
372}
373
374static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
375{
376 int idx = 0;
377 int start = cb->args[0];
378 struct cfg80211_registered_device *dev;
379
a1794390 380 mutex_lock(&cfg80211_mutex);
79c97e97 381 list_for_each_entry(dev, &cfg80211_rdev_list, list) {
b4637271 382 if (++idx <= start)
55682965
JB
383 continue;
384 if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid,
385 cb->nlh->nlmsg_seq, NLM_F_MULTI,
b4637271
JV
386 dev) < 0) {
387 idx--;
55682965 388 break;
b4637271 389 }
55682965 390 }
a1794390 391 mutex_unlock(&cfg80211_mutex);
55682965
JB
392
393 cb->args[0] = idx;
394
395 return skb->len;
396}
397
398static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
399{
400 struct sk_buff *msg;
401 struct cfg80211_registered_device *dev;
402
403 dev = cfg80211_get_dev_from_info(info);
404 if (IS_ERR(dev))
405 return PTR_ERR(dev);
406
fd2120ca 407 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965
JB
408 if (!msg)
409 goto out_err;
410
411 if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
412 goto out_free;
413
4d0c8aea 414 cfg80211_unlock_rdev(dev);
55682965 415
134e6375 416 return genlmsg_reply(msg, info);
55682965
JB
417
418 out_free:
419 nlmsg_free(msg);
420 out_err:
4d0c8aea 421 cfg80211_unlock_rdev(dev);
55682965
JB
422 return -ENOBUFS;
423}
424
31888487
JM
425static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
426 [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 },
427 [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 },
428 [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 },
429 [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 },
430 [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 },
431};
432
433static int parse_txq_params(struct nlattr *tb[],
434 struct ieee80211_txq_params *txq_params)
435{
436 if (!tb[NL80211_TXQ_ATTR_QUEUE] || !tb[NL80211_TXQ_ATTR_TXOP] ||
437 !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
438 !tb[NL80211_TXQ_ATTR_AIFS])
439 return -EINVAL;
440
441 txq_params->queue = nla_get_u8(tb[NL80211_TXQ_ATTR_QUEUE]);
442 txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
443 txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
444 txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
445 txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);
446
447 return 0;
448}
449
55682965
JB
450static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
451{
452 struct cfg80211_registered_device *rdev;
31888487
JM
453 int result = 0, rem_txq_params = 0;
454 struct nlattr *nl_txq_params;
b9a5f8ca
JM
455 u32 changed;
456 u8 retry_short = 0, retry_long = 0;
457 u32 frag_threshold = 0, rts_threshold = 0;
55682965 458
4bbf4d56 459 rtnl_lock();
55682965 460
4bbf4d56
JB
461 mutex_lock(&cfg80211_mutex);
462
79c97e97 463 rdev = __cfg80211_rdev_from_info(info);
4bbf4d56 464 if (IS_ERR(rdev)) {
1f5fc70a 465 mutex_unlock(&cfg80211_mutex);
4bbf4d56
JB
466 result = PTR_ERR(rdev);
467 goto unlock;
468 }
469
470 mutex_lock(&rdev->mtx);
471
472 if (info->attrs[NL80211_ATTR_WIPHY_NAME])
31888487
JM
473 result = cfg80211_dev_rename(
474 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
4bbf4d56
JB
475
476 mutex_unlock(&cfg80211_mutex);
477
478 if (result)
479 goto bad_res;
31888487
JM
480
481 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
482 struct ieee80211_txq_params txq_params;
483 struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
484
485 if (!rdev->ops->set_txq_params) {
486 result = -EOPNOTSUPP;
487 goto bad_res;
488 }
489
490 nla_for_each_nested(nl_txq_params,
491 info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
492 rem_txq_params) {
493 nla_parse(tb, NL80211_TXQ_ATTR_MAX,
494 nla_data(nl_txq_params),
495 nla_len(nl_txq_params),
496 txq_params_policy);
497 result = parse_txq_params(tb, &txq_params);
498 if (result)
499 goto bad_res;
500
501 result = rdev->ops->set_txq_params(&rdev->wiphy,
502 &txq_params);
503 if (result)
504 goto bad_res;
505 }
506 }
55682965 507
72bdcf34 508 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
094d05dc 509 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
72bdcf34 510 struct ieee80211_channel *chan;
306d6112 511 struct ieee80211_sta_ht_cap *ht_cap;
294196ab 512 u32 freq;
72bdcf34
JM
513
514 if (!rdev->ops->set_channel) {
515 result = -EOPNOTSUPP;
516 goto bad_res;
517 }
518
306d6112
JB
519 result = -EINVAL;
520
094d05dc
S
521 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
522 channel_type = nla_get_u32(info->attrs[
523 NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
524 if (channel_type != NL80211_CHAN_NO_HT &&
525 channel_type != NL80211_CHAN_HT20 &&
526 channel_type != NL80211_CHAN_HT40PLUS &&
527 channel_type != NL80211_CHAN_HT40MINUS)
72bdcf34 528 goto bad_res;
72bdcf34
JM
529 }
530
531 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
532 chan = ieee80211_get_channel(&rdev->wiphy, freq);
306d6112
JB
533
534 /* Primary channel not allowed */
535 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
72bdcf34 536 goto bad_res;
306d6112 537
294196ab
LR
538 if (channel_type == NL80211_CHAN_HT40MINUS &&
539 (chan->flags & IEEE80211_CHAN_NO_HT40MINUS))
306d6112 540 goto bad_res;
294196ab
LR
541 else if (channel_type == NL80211_CHAN_HT40PLUS &&
542 (chan->flags & IEEE80211_CHAN_NO_HT40PLUS))
306d6112
JB
543 goto bad_res;
544
294196ab
LR
545 /*
546 * At this point we know if that if HT40 was requested
547 * we are allowed to use it and the extension channel
548 * exists.
549 */
306d6112 550
294196ab 551 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
306d6112 552
294196ab
LR
553 /* no HT capabilities or intolerant */
554 if (channel_type != NL80211_CHAN_NO_HT) {
555 if (!ht_cap->ht_supported)
556 goto bad_res;
306d6112
JB
557 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
558 (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
559 goto bad_res;
72bdcf34
JM
560 }
561
562 result = rdev->ops->set_channel(&rdev->wiphy, chan,
094d05dc 563 channel_type);
72bdcf34
JM
564 if (result)
565 goto bad_res;
566 }
567
b9a5f8ca
JM
568 changed = 0;
569
570 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
571 retry_short = nla_get_u8(
572 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
573 if (retry_short == 0) {
574 result = -EINVAL;
575 goto bad_res;
576 }
577 changed |= WIPHY_PARAM_RETRY_SHORT;
578 }
579
580 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
581 retry_long = nla_get_u8(
582 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
583 if (retry_long == 0) {
584 result = -EINVAL;
585 goto bad_res;
586 }
587 changed |= WIPHY_PARAM_RETRY_LONG;
588 }
589
590 if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
591 frag_threshold = nla_get_u32(
592 info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
593 if (frag_threshold < 256) {
594 result = -EINVAL;
595 goto bad_res;
596 }
597 if (frag_threshold != (u32) -1) {
598 /*
599 * Fragments (apart from the last one) are required to
600 * have even length. Make the fragmentation code
601 * simpler by stripping LSB should someone try to use
602 * odd threshold value.
603 */
604 frag_threshold &= ~0x1;
605 }
606 changed |= WIPHY_PARAM_FRAG_THRESHOLD;
607 }
608
609 if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
610 rts_threshold = nla_get_u32(
611 info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
612 changed |= WIPHY_PARAM_RTS_THRESHOLD;
613 }
614
615 if (changed) {
616 u8 old_retry_short, old_retry_long;
617 u32 old_frag_threshold, old_rts_threshold;
618
619 if (!rdev->ops->set_wiphy_params) {
620 result = -EOPNOTSUPP;
621 goto bad_res;
622 }
623
624 old_retry_short = rdev->wiphy.retry_short;
625 old_retry_long = rdev->wiphy.retry_long;
626 old_frag_threshold = rdev->wiphy.frag_threshold;
627 old_rts_threshold = rdev->wiphy.rts_threshold;
628
629 if (changed & WIPHY_PARAM_RETRY_SHORT)
630 rdev->wiphy.retry_short = retry_short;
631 if (changed & WIPHY_PARAM_RETRY_LONG)
632 rdev->wiphy.retry_long = retry_long;
633 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
634 rdev->wiphy.frag_threshold = frag_threshold;
635 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
636 rdev->wiphy.rts_threshold = rts_threshold;
637
638 result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed);
639 if (result) {
640 rdev->wiphy.retry_short = old_retry_short;
641 rdev->wiphy.retry_long = old_retry_long;
642 rdev->wiphy.frag_threshold = old_frag_threshold;
643 rdev->wiphy.rts_threshold = old_rts_threshold;
644 }
645 }
72bdcf34 646
306d6112 647 bad_res:
4bbf4d56
JB
648 mutex_unlock(&rdev->mtx);
649 unlock:
650 rtnl_unlock();
55682965
JB
651 return result;
652}
653
654
655static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
d726405a 656 struct cfg80211_registered_device *rdev,
55682965
JB
657 struct net_device *dev)
658{
659 void *hdr;
660
661 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
662 if (!hdr)
663 return -1;
664
665 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
d726405a 666 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
55682965 667 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
60719ffd 668 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype);
55682965
JB
669 return genlmsg_end(msg, hdr);
670
671 nla_put_failure:
bc3ed28c
TG
672 genlmsg_cancel(msg, hdr);
673 return -EMSGSIZE;
55682965
JB
674}
675
676static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
677{
678 int wp_idx = 0;
679 int if_idx = 0;
680 int wp_start = cb->args[0];
681 int if_start = cb->args[1];
682 struct cfg80211_registered_device *dev;
683 struct wireless_dev *wdev;
684
a1794390 685 mutex_lock(&cfg80211_mutex);
79c97e97 686 list_for_each_entry(dev, &cfg80211_rdev_list, list) {
bba95fef
JB
687 if (wp_idx < wp_start) {
688 wp_idx++;
55682965 689 continue;
bba95fef 690 }
55682965
JB
691 if_idx = 0;
692
693 mutex_lock(&dev->devlist_mtx);
694 list_for_each_entry(wdev, &dev->netdev_list, list) {
bba95fef
JB
695 if (if_idx < if_start) {
696 if_idx++;
55682965 697 continue;
bba95fef 698 }
55682965
JB
699 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
700 cb->nlh->nlmsg_seq, NLM_F_MULTI,
d726405a 701 dev, wdev->netdev) < 0) {
bba95fef
JB
702 mutex_unlock(&dev->devlist_mtx);
703 goto out;
704 }
705 if_idx++;
55682965
JB
706 }
707 mutex_unlock(&dev->devlist_mtx);
bba95fef
JB
708
709 wp_idx++;
55682965 710 }
bba95fef 711 out:
a1794390 712 mutex_unlock(&cfg80211_mutex);
55682965
JB
713
714 cb->args[0] = wp_idx;
715 cb->args[1] = if_idx;
716
717 return skb->len;
718}
719
720static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
721{
722 struct sk_buff *msg;
723 struct cfg80211_registered_device *dev;
724 struct net_device *netdev;
725 int err;
726
79c97e97 727 err = get_rdev_dev_by_info_ifindex(info->attrs, &dev, &netdev);
55682965
JB
728 if (err)
729 return err;
730
fd2120ca 731 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965
JB
732 if (!msg)
733 goto out_err;
734
d726405a
JB
735 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0,
736 dev, netdev) < 0)
55682965
JB
737 goto out_free;
738
739 dev_put(netdev);
4d0c8aea 740 cfg80211_unlock_rdev(dev);
55682965 741
134e6375 742 return genlmsg_reply(msg, info);
55682965
JB
743
744 out_free:
745 nlmsg_free(msg);
746 out_err:
747 dev_put(netdev);
4d0c8aea 748 cfg80211_unlock_rdev(dev);
55682965
JB
749 return -ENOBUFS;
750}
751
66f7ac50
MW
752static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
753 [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
754 [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
755 [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
756 [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
757 [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
758};
759
760static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
761{
762 struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
763 int flag;
764
765 *mntrflags = 0;
766
767 if (!nla)
768 return -EINVAL;
769
770 if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX,
771 nla, mntr_flags_policy))
772 return -EINVAL;
773
774 for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
775 if (flags[flag])
776 *mntrflags |= (1<<flag);
777
778 return 0;
779}
780
55682965
JB
781static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
782{
79c97e97 783 struct cfg80211_registered_device *rdev;
2ec600d6 784 struct vif_params params;
e36d56b6 785 int err;
04a773ad 786 enum nl80211_iftype otype, ntype;
55682965 787 struct net_device *dev;
92ffe055 788 u32 _flags, *flags = NULL;
ac7f9cfa 789 bool change = false;
55682965 790
2ec600d6
LCC
791 memset(&params, 0, sizeof(params));
792
3b85875a
JB
793 rtnl_lock();
794
79c97e97 795 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
55682965 796 if (err)
3b85875a
JB
797 goto unlock_rtnl;
798
04a773ad 799 otype = ntype = dev->ieee80211_ptr->iftype;
55682965 800
723b038d 801 if (info->attrs[NL80211_ATTR_IFTYPE]) {
ac7f9cfa 802 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
04a773ad 803 if (otype != ntype)
ac7f9cfa 804 change = true;
04a773ad 805 if (ntype > NL80211_IFTYPE_MAX) {
ac7f9cfa 806 err = -EINVAL;
723b038d 807 goto unlock;
ac7f9cfa 808 }
723b038d
JB
809 }
810
79c97e97
JB
811 if (!rdev->ops->change_virtual_intf ||
812 !(rdev->wiphy.interface_modes & (1 << ntype))) {
55682965
JB
813 err = -EOPNOTSUPP;
814 goto unlock;
815 }
816
92ffe055 817 if (info->attrs[NL80211_ATTR_MESH_ID]) {
04a773ad 818 if (ntype != NL80211_IFTYPE_MESH_POINT) {
92ffe055
JB
819 err = -EINVAL;
820 goto unlock;
821 }
2ec600d6
LCC
822 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
823 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
ac7f9cfa 824 change = true;
2ec600d6
LCC
825 }
826
92ffe055 827 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
04a773ad 828 if (ntype != NL80211_IFTYPE_MONITOR) {
92ffe055
JB
829 err = -EINVAL;
830 goto unlock;
831 }
832 err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
833 &_flags);
ac7f9cfa
JB
834 if (err)
835 goto unlock;
836
837 flags = &_flags;
838 change = true;
92ffe055 839 }
3b85875a 840
ac7f9cfa 841 if (change)
79c97e97 842 err = rdev->ops->change_virtual_intf(&rdev->wiphy, dev,
04a773ad 843 ntype, flags, &params);
ac7f9cfa
JB
844 else
845 err = 0;
60719ffd 846
e36d56b6 847 WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype);
04a773ad 848
e36d56b6 849 if (!err && (ntype != otype)) {
04a773ad 850 if (otype == NL80211_IFTYPE_ADHOC)
9d308429 851 cfg80211_clear_ibss(dev, false);
04a773ad 852 }
60719ffd 853
55682965 854 unlock:
e36d56b6 855 dev_put(dev);
79c97e97 856 cfg80211_unlock_rdev(rdev);
3b85875a
JB
857 unlock_rtnl:
858 rtnl_unlock();
55682965
JB
859 return err;
860}
861
862static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
863{
79c97e97 864 struct cfg80211_registered_device *rdev;
2ec600d6 865 struct vif_params params;
55682965
JB
866 int err;
867 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
66f7ac50 868 u32 flags;
55682965 869
2ec600d6
LCC
870 memset(&params, 0, sizeof(params));
871
55682965
JB
872 if (!info->attrs[NL80211_ATTR_IFNAME])
873 return -EINVAL;
874
875 if (info->attrs[NL80211_ATTR_IFTYPE]) {
876 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
877 if (type > NL80211_IFTYPE_MAX)
878 return -EINVAL;
879 }
880
3b85875a
JB
881 rtnl_lock();
882
79c97e97
JB
883 rdev = cfg80211_get_dev_from_info(info);
884 if (IS_ERR(rdev)) {
885 err = PTR_ERR(rdev);
3b85875a
JB
886 goto unlock_rtnl;
887 }
55682965 888
79c97e97
JB
889 if (!rdev->ops->add_virtual_intf ||
890 !(rdev->wiphy.interface_modes & (1 << type))) {
55682965
JB
891 err = -EOPNOTSUPP;
892 goto unlock;
893 }
894
2ec600d6
LCC
895 if (type == NL80211_IFTYPE_MESH_POINT &&
896 info->attrs[NL80211_ATTR_MESH_ID]) {
897 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
898 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
899 }
900
66f7ac50
MW
901 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
902 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
903 &flags);
79c97e97 904 err = rdev->ops->add_virtual_intf(&rdev->wiphy,
66f7ac50 905 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
2ec600d6 906 type, err ? NULL : &flags, &params);
2ec600d6 907
55682965 908 unlock:
79c97e97 909 cfg80211_unlock_rdev(rdev);
3b85875a
JB
910 unlock_rtnl:
911 rtnl_unlock();
55682965
JB
912 return err;
913}
914
915static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
916{
79c97e97 917 struct cfg80211_registered_device *rdev;
55682965
JB
918 int ifindex, err;
919 struct net_device *dev;
920
3b85875a
JB
921 rtnl_lock();
922
79c97e97 923 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
55682965 924 if (err)
3b85875a 925 goto unlock_rtnl;
55682965
JB
926 ifindex = dev->ifindex;
927 dev_put(dev);
928
79c97e97 929 if (!rdev->ops->del_virtual_intf) {
55682965
JB
930 err = -EOPNOTSUPP;
931 goto out;
932 }
933
79c97e97 934 err = rdev->ops->del_virtual_intf(&rdev->wiphy, ifindex);
55682965
JB
935
936 out:
79c97e97 937 cfg80211_unlock_rdev(rdev);
3b85875a
JB
938 unlock_rtnl:
939 rtnl_unlock();
55682965
JB
940 return err;
941}
942
41ade00f
JB
943struct get_key_cookie {
944 struct sk_buff *msg;
945 int error;
946};
947
948static void get_key_callback(void *c, struct key_params *params)
949{
950 struct get_key_cookie *cookie = c;
951
952 if (params->key)
953 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA,
954 params->key_len, params->key);
955
956 if (params->seq)
957 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ,
958 params->seq_len, params->seq);
959
960 if (params->cipher)
961 NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
962 params->cipher);
963
964 return;
965 nla_put_failure:
966 cookie->error = 1;
967}
968
969static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
970{
79c97e97 971 struct cfg80211_registered_device *rdev;
41ade00f
JB
972 int err;
973 struct net_device *dev;
974 u8 key_idx = 0;
975 u8 *mac_addr = NULL;
976 struct get_key_cookie cookie = {
977 .error = 0,
978 };
979 void *hdr;
980 struct sk_buff *msg;
981
982 if (info->attrs[NL80211_ATTR_KEY_IDX])
983 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
984
3cfcf6ac 985 if (key_idx > 5)
41ade00f
JB
986 return -EINVAL;
987
988 if (info->attrs[NL80211_ATTR_MAC])
989 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
990
3b85875a
JB
991 rtnl_lock();
992
79c97e97 993 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
41ade00f 994 if (err)
3b85875a 995 goto unlock_rtnl;
41ade00f 996
79c97e97 997 if (!rdev->ops->get_key) {
41ade00f
JB
998 err = -EOPNOTSUPP;
999 goto out;
1000 }
1001
fd2120ca 1002 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
41ade00f
JB
1003 if (!msg) {
1004 err = -ENOMEM;
1005 goto out;
1006 }
1007
1008 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
1009 NL80211_CMD_NEW_KEY);
1010
1011 if (IS_ERR(hdr)) {
1012 err = PTR_ERR(hdr);
6c95e2a2 1013 goto free_msg;
41ade00f
JB
1014 }
1015
1016 cookie.msg = msg;
1017
1018 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
1019 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
1020 if (mac_addr)
1021 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
1022
79c97e97 1023 err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, mac_addr,
41ade00f 1024 &cookie, get_key_callback);
41ade00f
JB
1025
1026 if (err)
6c95e2a2 1027 goto free_msg;
41ade00f
JB
1028
1029 if (cookie.error)
1030 goto nla_put_failure;
1031
1032 genlmsg_end(msg, hdr);
134e6375 1033 err = genlmsg_reply(msg, info);
41ade00f
JB
1034 goto out;
1035
1036 nla_put_failure:
1037 err = -ENOBUFS;
6c95e2a2 1038 free_msg:
41ade00f
JB
1039 nlmsg_free(msg);
1040 out:
79c97e97 1041 cfg80211_unlock_rdev(rdev);
41ade00f 1042 dev_put(dev);
3b85875a
JB
1043 unlock_rtnl:
1044 rtnl_unlock();
1045
41ade00f
JB
1046 return err;
1047}
1048
1049static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1050{
79c97e97 1051 struct cfg80211_registered_device *rdev;
41ade00f
JB
1052 int err;
1053 struct net_device *dev;
1054 u8 key_idx;
3cfcf6ac
JM
1055 int (*func)(struct wiphy *wiphy, struct net_device *netdev,
1056 u8 key_index);
41ade00f
JB
1057
1058 if (!info->attrs[NL80211_ATTR_KEY_IDX])
1059 return -EINVAL;
1060
1061 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
1062
3cfcf6ac
JM
1063 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) {
1064 if (key_idx < 4 || key_idx > 5)
1065 return -EINVAL;
1066 } else if (key_idx > 3)
41ade00f
JB
1067 return -EINVAL;
1068
1069 /* currently only support setting default key */
3cfcf6ac
JM
1070 if (!info->attrs[NL80211_ATTR_KEY_DEFAULT] &&
1071 !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT])
41ade00f
JB
1072 return -EINVAL;
1073
3b85875a
JB
1074 rtnl_lock();
1075
79c97e97 1076 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
41ade00f 1077 if (err)
3b85875a 1078 goto unlock_rtnl;
41ade00f 1079
3cfcf6ac 1080 if (info->attrs[NL80211_ATTR_KEY_DEFAULT])
79c97e97 1081 func = rdev->ops->set_default_key;
3cfcf6ac 1082 else
79c97e97 1083 func = rdev->ops->set_default_mgmt_key;
3cfcf6ac
JM
1084
1085 if (!func) {
41ade00f
JB
1086 err = -EOPNOTSUPP;
1087 goto out;
1088 }
1089
79c97e97 1090 err = func(&rdev->wiphy, dev, key_idx);
08645126
JB
1091#ifdef CONFIG_WIRELESS_EXT
1092 if (!err) {
79c97e97 1093 if (func == rdev->ops->set_default_key)
08645126
JB
1094 dev->ieee80211_ptr->wext.default_key = key_idx;
1095 else
1096 dev->ieee80211_ptr->wext.default_mgmt_key = key_idx;
1097 }
1098#endif
41ade00f
JB
1099
1100 out:
79c97e97 1101 cfg80211_unlock_rdev(rdev);
41ade00f 1102 dev_put(dev);
3b85875a
JB
1103
1104 unlock_rtnl:
1105 rtnl_unlock();
1106
41ade00f
JB
1107 return err;
1108}
1109
1110static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1111{
79c97e97 1112 struct cfg80211_registered_device *rdev;
25e47c18 1113 int err, i;
41ade00f
JB
1114 struct net_device *dev;
1115 struct key_params params;
1116 u8 key_idx = 0;
1117 u8 *mac_addr = NULL;
1118
1119 memset(&params, 0, sizeof(params));
1120
1121 if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
1122 return -EINVAL;
1123
1124 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
1125 params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
1126 params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
1127 }
1128
faa8fdc8
JM
1129 if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
1130 params.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
1131 params.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
1132 }
1133
41ade00f
JB
1134 if (info->attrs[NL80211_ATTR_KEY_IDX])
1135 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
1136
1137 params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
1138
1139 if (info->attrs[NL80211_ATTR_MAC])
1140 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1141
08645126 1142 if (cfg80211_validate_key_settings(&params, key_idx, mac_addr))
41ade00f
JB
1143 return -EINVAL;
1144
3b85875a
JB
1145 rtnl_lock();
1146
79c97e97 1147 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
41ade00f 1148 if (err)
3b85875a 1149 goto unlock_rtnl;
41ade00f 1150
79c97e97
JB
1151 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++)
1152 if (params.cipher == rdev->wiphy.cipher_suites[i])
25e47c18 1153 break;
79c97e97 1154 if (i == rdev->wiphy.n_cipher_suites) {
25e47c18
JB
1155 err = -EINVAL;
1156 goto out;
1157 }
1158
79c97e97 1159 if (!rdev->ops->add_key) {
41ade00f
JB
1160 err = -EOPNOTSUPP;
1161 goto out;
1162 }
1163
79c97e97 1164 err = rdev->ops->add_key(&rdev->wiphy, dev, key_idx, mac_addr, &params);
41ade00f
JB
1165
1166 out:
79c97e97 1167 cfg80211_unlock_rdev(rdev);
41ade00f 1168 dev_put(dev);
3b85875a
JB
1169 unlock_rtnl:
1170 rtnl_unlock();
1171
41ade00f
JB
1172 return err;
1173}
1174
1175static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1176{
79c97e97 1177 struct cfg80211_registered_device *rdev;
41ade00f
JB
1178 int err;
1179 struct net_device *dev;
1180 u8 key_idx = 0;
1181 u8 *mac_addr = NULL;
1182
1183 if (info->attrs[NL80211_ATTR_KEY_IDX])
1184 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
1185
3cfcf6ac 1186 if (key_idx > 5)
41ade00f
JB
1187 return -EINVAL;
1188
1189 if (info->attrs[NL80211_ATTR_MAC])
1190 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1191
3b85875a
JB
1192 rtnl_lock();
1193
79c97e97 1194 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
41ade00f 1195 if (err)
3b85875a 1196 goto unlock_rtnl;
41ade00f 1197
79c97e97 1198 if (!rdev->ops->del_key) {
41ade00f
JB
1199 err = -EOPNOTSUPP;
1200 goto out;
1201 }
1202
79c97e97 1203 err = rdev->ops->del_key(&rdev->wiphy, dev, key_idx, mac_addr);
41ade00f 1204
08645126
JB
1205#ifdef CONFIG_WIRELESS_EXT
1206 if (!err) {
1207 if (key_idx == dev->ieee80211_ptr->wext.default_key)
1208 dev->ieee80211_ptr->wext.default_key = -1;
1209 else if (key_idx == dev->ieee80211_ptr->wext.default_mgmt_key)
1210 dev->ieee80211_ptr->wext.default_mgmt_key = -1;
1211 }
1212#endif
1213
41ade00f 1214 out:
79c97e97 1215 cfg80211_unlock_rdev(rdev);
41ade00f 1216 dev_put(dev);
3b85875a
JB
1217
1218 unlock_rtnl:
1219 rtnl_unlock();
1220
41ade00f
JB
1221 return err;
1222}
1223
ed1b6cc7
JB
1224static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1225{
1226 int (*call)(struct wiphy *wiphy, struct net_device *dev,
1227 struct beacon_parameters *info);
79c97e97 1228 struct cfg80211_registered_device *rdev;
ed1b6cc7
JB
1229 int err;
1230 struct net_device *dev;
1231 struct beacon_parameters params;
1232 int haveinfo = 0;
1233
f4a11bb0
JB
1234 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]))
1235 return -EINVAL;
1236
3b85875a
JB
1237 rtnl_lock();
1238
79c97e97 1239 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
ed1b6cc7 1240 if (err)
3b85875a 1241 goto unlock_rtnl;
ed1b6cc7 1242
eec60b03
JM
1243 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
1244 err = -EOPNOTSUPP;
1245 goto out;
1246 }
1247
ed1b6cc7
JB
1248 switch (info->genlhdr->cmd) {
1249 case NL80211_CMD_NEW_BEACON:
1250 /* these are required for NEW_BEACON */
1251 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
1252 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
1253 !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
1254 err = -EINVAL;
1255 goto out;
1256 }
1257
79c97e97 1258 call = rdev->ops->add_beacon;
ed1b6cc7
JB
1259 break;
1260 case NL80211_CMD_SET_BEACON:
79c97e97 1261 call = rdev->ops->set_beacon;
ed1b6cc7
JB
1262 break;
1263 default:
1264 WARN_ON(1);
1265 err = -EOPNOTSUPP;
1266 goto out;
1267 }
1268
1269 if (!call) {
1270 err = -EOPNOTSUPP;
1271 goto out;
1272 }
1273
1274 memset(&params, 0, sizeof(params));
1275
1276 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
1277 params.interval =
1278 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
1279 haveinfo = 1;
1280 }
1281
1282 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
1283 params.dtim_period =
1284 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
1285 haveinfo = 1;
1286 }
1287
1288 if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
1289 params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
1290 params.head_len =
1291 nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]);
1292 haveinfo = 1;
1293 }
1294
1295 if (info->attrs[NL80211_ATTR_BEACON_TAIL]) {
1296 params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]);
1297 params.tail_len =
1298 nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
1299 haveinfo = 1;
1300 }
1301
1302 if (!haveinfo) {
1303 err = -EINVAL;
1304 goto out;
1305 }
1306
79c97e97 1307 err = call(&rdev->wiphy, dev, &params);
ed1b6cc7
JB
1308
1309 out:
79c97e97 1310 cfg80211_unlock_rdev(rdev);
ed1b6cc7 1311 dev_put(dev);
3b85875a
JB
1312 unlock_rtnl:
1313 rtnl_unlock();
1314
ed1b6cc7
JB
1315 return err;
1316}
1317
1318static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
1319{
79c97e97 1320 struct cfg80211_registered_device *rdev;
ed1b6cc7
JB
1321 int err;
1322 struct net_device *dev;
1323
3b85875a
JB
1324 rtnl_lock();
1325
79c97e97 1326 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
ed1b6cc7 1327 if (err)
3b85875a 1328 goto unlock_rtnl;
ed1b6cc7 1329
79c97e97 1330 if (!rdev->ops->del_beacon) {
ed1b6cc7
JB
1331 err = -EOPNOTSUPP;
1332 goto out;
1333 }
1334
eec60b03
JM
1335 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
1336 err = -EOPNOTSUPP;
1337 goto out;
1338 }
79c97e97 1339 err = rdev->ops->del_beacon(&rdev->wiphy, dev);
ed1b6cc7
JB
1340
1341 out:
79c97e97 1342 cfg80211_unlock_rdev(rdev);
ed1b6cc7 1343 dev_put(dev);
3b85875a
JB
1344 unlock_rtnl:
1345 rtnl_unlock();
1346
ed1b6cc7
JB
1347 return err;
1348}
1349
5727ef1b
JB
1350static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
1351 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
1352 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
1353 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
0e46724a 1354 [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
5727ef1b
JB
1355};
1356
eccb8e8f
JB
1357static int parse_station_flags(struct genl_info *info,
1358 struct station_parameters *params)
5727ef1b
JB
1359{
1360 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
eccb8e8f 1361 struct nlattr *nla;
5727ef1b
JB
1362 int flag;
1363
eccb8e8f
JB
1364 /*
1365 * Try parsing the new attribute first so userspace
1366 * can specify both for older kernels.
1367 */
1368 nla = info->attrs[NL80211_ATTR_STA_FLAGS2];
1369 if (nla) {
1370 struct nl80211_sta_flag_update *sta_flags;
1371
1372 sta_flags = nla_data(nla);
1373 params->sta_flags_mask = sta_flags->mask;
1374 params->sta_flags_set = sta_flags->set;
1375 if ((params->sta_flags_mask |
1376 params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
1377 return -EINVAL;
1378 return 0;
1379 }
1380
1381 /* if present, parse the old attribute */
5727ef1b 1382
eccb8e8f 1383 nla = info->attrs[NL80211_ATTR_STA_FLAGS];
5727ef1b
JB
1384 if (!nla)
1385 return 0;
1386
1387 if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX,
1388 nla, sta_flags_policy))
1389 return -EINVAL;
1390
eccb8e8f
JB
1391 params->sta_flags_mask = (1 << __NL80211_STA_FLAG_AFTER_LAST) - 1;
1392 params->sta_flags_mask &= ~1;
5727ef1b
JB
1393
1394 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
1395 if (flags[flag])
eccb8e8f 1396 params->sta_flags_set |= (1<<flag);
5727ef1b
JB
1397
1398 return 0;
1399}
1400
420e7fab
HR
1401static u16 nl80211_calculate_bitrate(struct rate_info *rate)
1402{
1403 int modulation, streams, bitrate;
1404
1405 if (!(rate->flags & RATE_INFO_FLAGS_MCS))
1406 return rate->legacy;
1407
1408 /* the formula below does only work for MCS values smaller than 32 */
1409 if (rate->mcs >= 32)
1410 return 0;
1411
1412 modulation = rate->mcs & 7;
1413 streams = (rate->mcs >> 3) + 1;
1414
1415 bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
1416 13500000 : 6500000;
1417
1418 if (modulation < 4)
1419 bitrate *= (modulation + 1);
1420 else if (modulation == 4)
1421 bitrate *= (modulation + 2);
1422 else
1423 bitrate *= (modulation + 3);
1424
1425 bitrate *= streams;
1426
1427 if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
1428 bitrate = (bitrate / 9) * 10;
1429
1430 /* do NOT round down here */
1431 return (bitrate + 50000) / 100000;
1432}
1433
fd5b74dc
JB
1434static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
1435 int flags, struct net_device *dev,
2ec600d6 1436 u8 *mac_addr, struct station_info *sinfo)
fd5b74dc
JB
1437{
1438 void *hdr;
420e7fab
HR
1439 struct nlattr *sinfoattr, *txrate;
1440 u16 bitrate;
fd5b74dc
JB
1441
1442 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
1443 if (!hdr)
1444 return -1;
1445
1446 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
1447 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
1448
2ec600d6
LCC
1449 sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
1450 if (!sinfoattr)
fd5b74dc 1451 goto nla_put_failure;
2ec600d6
LCC
1452 if (sinfo->filled & STATION_INFO_INACTIVE_TIME)
1453 NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME,
1454 sinfo->inactive_time);
1455 if (sinfo->filled & STATION_INFO_RX_BYTES)
1456 NLA_PUT_U32(msg, NL80211_STA_INFO_RX_BYTES,
1457 sinfo->rx_bytes);
1458 if (sinfo->filled & STATION_INFO_TX_BYTES)
1459 NLA_PUT_U32(msg, NL80211_STA_INFO_TX_BYTES,
1460 sinfo->tx_bytes);
1461 if (sinfo->filled & STATION_INFO_LLID)
1462 NLA_PUT_U16(msg, NL80211_STA_INFO_LLID,
1463 sinfo->llid);
1464 if (sinfo->filled & STATION_INFO_PLID)
1465 NLA_PUT_U16(msg, NL80211_STA_INFO_PLID,
1466 sinfo->plid);
1467 if (sinfo->filled & STATION_INFO_PLINK_STATE)
1468 NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
1469 sinfo->plink_state);
420e7fab
HR
1470 if (sinfo->filled & STATION_INFO_SIGNAL)
1471 NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
1472 sinfo->signal);
1473 if (sinfo->filled & STATION_INFO_TX_BITRATE) {
1474 txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
1475 if (!txrate)
1476 goto nla_put_failure;
1477
1478 /* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
1479 bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
1480 if (bitrate > 0)
1481 NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
2ec600d6 1482
420e7fab
HR
1483 if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
1484 NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
1485 sinfo->txrate.mcs);
1486 if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
1487 NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
1488 if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
1489 NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
1490
1491 nla_nest_end(msg, txrate);
1492 }
98c8a60a
JM
1493 if (sinfo->filled & STATION_INFO_RX_PACKETS)
1494 NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS,
1495 sinfo->rx_packets);
1496 if (sinfo->filled & STATION_INFO_TX_PACKETS)
1497 NLA_PUT_U32(msg, NL80211_STA_INFO_TX_PACKETS,
1498 sinfo->tx_packets);
2ec600d6 1499 nla_nest_end(msg, sinfoattr);
fd5b74dc
JB
1500
1501 return genlmsg_end(msg, hdr);
1502
1503 nla_put_failure:
bc3ed28c
TG
1504 genlmsg_cancel(msg, hdr);
1505 return -EMSGSIZE;
fd5b74dc
JB
1506}
1507
2ec600d6 1508static int nl80211_dump_station(struct sk_buff *skb,
bba95fef 1509 struct netlink_callback *cb)
2ec600d6 1510{
2ec600d6
LCC
1511 struct station_info sinfo;
1512 struct cfg80211_registered_device *dev;
bba95fef 1513 struct net_device *netdev;
2ec600d6 1514 u8 mac_addr[ETH_ALEN];
bba95fef
JB
1515 int ifidx = cb->args[0];
1516 int sta_idx = cb->args[1];
2ec600d6 1517 int err;
2ec600d6 1518
bba95fef
JB
1519 if (!ifidx) {
1520 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
1521 nl80211_fam.attrbuf, nl80211_fam.maxattr,
1522 nl80211_policy);
1523 if (err)
1524 return err;
2ec600d6 1525
bba95fef
JB
1526 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
1527 return -EINVAL;
2ec600d6 1528
bba95fef
JB
1529 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
1530 if (!ifidx)
1531 return -EINVAL;
2ec600d6 1532 }
2ec600d6 1533
3b85875a
JB
1534 rtnl_lock();
1535
1536 netdev = __dev_get_by_index(&init_net, ifidx);
1537 if (!netdev) {
1538 err = -ENODEV;
1539 goto out_rtnl;
1540 }
2ec600d6 1541
bba95fef
JB
1542 dev = cfg80211_get_dev_from_ifindex(ifidx);
1543 if (IS_ERR(dev)) {
1544 err = PTR_ERR(dev);
3b85875a 1545 goto out_rtnl;
bba95fef
JB
1546 }
1547
1548 if (!dev->ops->dump_station) {
eec60b03 1549 err = -EOPNOTSUPP;
bba95fef
JB
1550 goto out_err;
1551 }
1552
bba95fef
JB
1553 while (1) {
1554 err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx,
1555 mac_addr, &sinfo);
1556 if (err == -ENOENT)
1557 break;
1558 if (err)
3b85875a 1559 goto out_err;
bba95fef
JB
1560
1561 if (nl80211_send_station(skb,
1562 NETLINK_CB(cb->skb).pid,
1563 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1564 netdev, mac_addr,
1565 &sinfo) < 0)
1566 goto out;
1567
1568 sta_idx++;
1569 }
1570
1571
1572 out:
1573 cb->args[1] = sta_idx;
1574 err = skb->len;
bba95fef 1575 out_err:
4d0c8aea 1576 cfg80211_unlock_rdev(dev);
3b85875a
JB
1577 out_rtnl:
1578 rtnl_unlock();
bba95fef
JB
1579
1580 return err;
2ec600d6 1581}
fd5b74dc 1582
5727ef1b
JB
1583static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
1584{
79c97e97 1585 struct cfg80211_registered_device *rdev;
fd5b74dc
JB
1586 int err;
1587 struct net_device *dev;
2ec600d6 1588 struct station_info sinfo;
fd5b74dc
JB
1589 struct sk_buff *msg;
1590 u8 *mac_addr = NULL;
1591
2ec600d6 1592 memset(&sinfo, 0, sizeof(sinfo));
fd5b74dc
JB
1593
1594 if (!info->attrs[NL80211_ATTR_MAC])
1595 return -EINVAL;
1596
1597 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1598
3b85875a
JB
1599 rtnl_lock();
1600
79c97e97 1601 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
fd5b74dc 1602 if (err)
3b85875a 1603 goto out_rtnl;
fd5b74dc 1604
79c97e97 1605 if (!rdev->ops->get_station) {
fd5b74dc
JB
1606 err = -EOPNOTSUPP;
1607 goto out;
1608 }
1609
79c97e97 1610 err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo);
2ec600d6
LCC
1611 if (err)
1612 goto out;
1613
fd2120ca 1614 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
fd5b74dc
JB
1615 if (!msg)
1616 goto out;
1617
1618 if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
2ec600d6 1619 dev, mac_addr, &sinfo) < 0)
fd5b74dc
JB
1620 goto out_free;
1621
134e6375 1622 err = genlmsg_reply(msg, info);
fd5b74dc
JB
1623 goto out;
1624
1625 out_free:
1626 nlmsg_free(msg);
fd5b74dc 1627 out:
79c97e97 1628 cfg80211_unlock_rdev(rdev);
fd5b74dc 1629 dev_put(dev);
3b85875a
JB
1630 out_rtnl:
1631 rtnl_unlock();
1632
fd5b74dc 1633 return err;
5727ef1b
JB
1634}
1635
1636/*
1637 * Get vlan interface making sure it is on the right wiphy.
1638 */
1639static int get_vlan(struct nlattr *vlanattr,
1640 struct cfg80211_registered_device *rdev,
1641 struct net_device **vlan)
1642{
1643 *vlan = NULL;
1644
1645 if (vlanattr) {
1646 *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr));
1647 if (!*vlan)
1648 return -ENODEV;
1649 if (!(*vlan)->ieee80211_ptr)
1650 return -EINVAL;
1651 if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
1652 return -EINVAL;
1653 }
1654 return 0;
1655}
1656
1657static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
1658{
79c97e97 1659 struct cfg80211_registered_device *rdev;
5727ef1b
JB
1660 int err;
1661 struct net_device *dev;
1662 struct station_parameters params;
1663 u8 *mac_addr = NULL;
1664
1665 memset(&params, 0, sizeof(params));
1666
1667 params.listen_interval = -1;
1668
1669 if (info->attrs[NL80211_ATTR_STA_AID])
1670 return -EINVAL;
1671
1672 if (!info->attrs[NL80211_ATTR_MAC])
1673 return -EINVAL;
1674
1675 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1676
1677 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
1678 params.supported_rates =
1679 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1680 params.supported_rates_len =
1681 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1682 }
1683
1684 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
1685 params.listen_interval =
1686 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
1687
36aedc90
JM
1688 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
1689 params.ht_capa =
1690 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
1691
eccb8e8f 1692 if (parse_station_flags(info, &params))
5727ef1b
JB
1693 return -EINVAL;
1694
2ec600d6
LCC
1695 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
1696 params.plink_action =
1697 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
1698
3b85875a
JB
1699 rtnl_lock();
1700
79c97e97 1701 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
5727ef1b 1702 if (err)
3b85875a 1703 goto out_rtnl;
5727ef1b 1704
79c97e97 1705 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], rdev, &params.vlan);
a97f4424 1706 if (err)
034d655e 1707 goto out;
a97f4424
JB
1708
1709 /* validate settings */
1710 err = 0;
1711
1712 switch (dev->ieee80211_ptr->iftype) {
1713 case NL80211_IFTYPE_AP:
1714 case NL80211_IFTYPE_AP_VLAN:
1715 /* disallow mesh-specific things */
1716 if (params.plink_action)
1717 err = -EINVAL;
1718 break;
1719 case NL80211_IFTYPE_STATION:
1720 /* disallow everything but AUTHORIZED flag */
1721 if (params.plink_action)
1722 err = -EINVAL;
1723 if (params.vlan)
1724 err = -EINVAL;
1725 if (params.supported_rates)
1726 err = -EINVAL;
1727 if (params.ht_capa)
1728 err = -EINVAL;
1729 if (params.listen_interval >= 0)
1730 err = -EINVAL;
1731 if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
1732 err = -EINVAL;
1733 break;
1734 case NL80211_IFTYPE_MESH_POINT:
1735 /* disallow things mesh doesn't support */
1736 if (params.vlan)
1737 err = -EINVAL;
1738 if (params.ht_capa)
1739 err = -EINVAL;
1740 if (params.listen_interval >= 0)
1741 err = -EINVAL;
1742 if (params.supported_rates)
1743 err = -EINVAL;
1744 if (params.sta_flags_mask)
1745 err = -EINVAL;
1746 break;
1747 default:
1748 err = -EINVAL;
034d655e
JB
1749 }
1750
5727ef1b
JB
1751 if (err)
1752 goto out;
1753
79c97e97 1754 if (!rdev->ops->change_station) {
5727ef1b
JB
1755 err = -EOPNOTSUPP;
1756 goto out;
1757 }
1758
79c97e97 1759 err = rdev->ops->change_station(&rdev->wiphy, dev, mac_addr, &params);
5727ef1b
JB
1760
1761 out:
1762 if (params.vlan)
1763 dev_put(params.vlan);
79c97e97 1764 cfg80211_unlock_rdev(rdev);
5727ef1b 1765 dev_put(dev);
3b85875a
JB
1766 out_rtnl:
1767 rtnl_unlock();
1768
5727ef1b
JB
1769 return err;
1770}
1771
1772static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1773{
79c97e97 1774 struct cfg80211_registered_device *rdev;
5727ef1b
JB
1775 int err;
1776 struct net_device *dev;
1777 struct station_parameters params;
1778 u8 *mac_addr = NULL;
1779
1780 memset(&params, 0, sizeof(params));
1781
1782 if (!info->attrs[NL80211_ATTR_MAC])
1783 return -EINVAL;
1784
5727ef1b
JB
1785 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
1786 return -EINVAL;
1787
1788 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
1789 return -EINVAL;
1790
1791 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1792 params.supported_rates =
1793 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1794 params.supported_rates_len =
1795 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1796 params.listen_interval =
1797 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
51b50fbe 1798
a97f4424
JB
1799 if (info->attrs[NL80211_ATTR_STA_AID]) {
1800 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
1801 if (!params.aid || params.aid > IEEE80211_MAX_AID)
1802 return -EINVAL;
1803 }
51b50fbe 1804
36aedc90
JM
1805 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
1806 params.ht_capa =
1807 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
5727ef1b 1808
eccb8e8f 1809 if (parse_station_flags(info, &params))
5727ef1b
JB
1810 return -EINVAL;
1811
3b85875a
JB
1812 rtnl_lock();
1813
79c97e97 1814 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
5727ef1b 1815 if (err)
3b85875a 1816 goto out_rtnl;
5727ef1b 1817
79c97e97 1818 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], rdev, &params.vlan);
a97f4424 1819 if (err)
e80cf853 1820 goto out;
a97f4424
JB
1821
1822 /* validate settings */
1823 err = 0;
1824
1825 switch (dev->ieee80211_ptr->iftype) {
1826 case NL80211_IFTYPE_AP:
1827 case NL80211_IFTYPE_AP_VLAN:
1828 /* all ok but must have AID */
1829 if (!params.aid)
1830 err = -EINVAL;
1831 break;
1832 case NL80211_IFTYPE_MESH_POINT:
1833 /* disallow things mesh doesn't support */
1834 if (params.vlan)
1835 err = -EINVAL;
1836 if (params.aid)
1837 err = -EINVAL;
1838 if (params.ht_capa)
1839 err = -EINVAL;
1840 if (params.listen_interval >= 0)
1841 err = -EINVAL;
1842 if (params.supported_rates)
1843 err = -EINVAL;
1844 if (params.sta_flags_mask)
1845 err = -EINVAL;
1846 break;
1847 default:
1848 err = -EINVAL;
e80cf853
JB
1849 }
1850
5727ef1b
JB
1851 if (err)
1852 goto out;
1853
79c97e97 1854 if (!rdev->ops->add_station) {
5727ef1b
JB
1855 err = -EOPNOTSUPP;
1856 goto out;
1857 }
1858
35a8efe1
JM
1859 if (!netif_running(dev)) {
1860 err = -ENETDOWN;
1861 goto out;
1862 }
1863
79c97e97 1864 err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, &params);
5727ef1b
JB
1865
1866 out:
1867 if (params.vlan)
1868 dev_put(params.vlan);
79c97e97 1869 cfg80211_unlock_rdev(rdev);
5727ef1b 1870 dev_put(dev);
3b85875a
JB
1871 out_rtnl:
1872 rtnl_unlock();
1873
5727ef1b
JB
1874 return err;
1875}
1876
1877static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
1878{
79c97e97 1879 struct cfg80211_registered_device *rdev;
5727ef1b
JB
1880 int err;
1881 struct net_device *dev;
1882 u8 *mac_addr = NULL;
1883
1884 if (info->attrs[NL80211_ATTR_MAC])
1885 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1886
3b85875a
JB
1887 rtnl_lock();
1888
79c97e97 1889 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
5727ef1b 1890 if (err)
3b85875a 1891 goto out_rtnl;
5727ef1b 1892
e80cf853 1893 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
155cc9e4
AY
1894 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
1895 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
e80cf853
JB
1896 err = -EINVAL;
1897 goto out;
1898 }
1899
79c97e97 1900 if (!rdev->ops->del_station) {
5727ef1b
JB
1901 err = -EOPNOTSUPP;
1902 goto out;
1903 }
1904
79c97e97 1905 err = rdev->ops->del_station(&rdev->wiphy, dev, mac_addr);
5727ef1b
JB
1906
1907 out:
79c97e97 1908 cfg80211_unlock_rdev(rdev);
5727ef1b 1909 dev_put(dev);
3b85875a
JB
1910 out_rtnl:
1911 rtnl_unlock();
1912
5727ef1b
JB
1913 return err;
1914}
1915
2ec600d6
LCC
1916static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
1917 int flags, struct net_device *dev,
1918 u8 *dst, u8 *next_hop,
1919 struct mpath_info *pinfo)
1920{
1921 void *hdr;
1922 struct nlattr *pinfoattr;
1923
1924 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
1925 if (!hdr)
1926 return -1;
1927
1928 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
1929 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
1930 NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop);
1931
1932 pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
1933 if (!pinfoattr)
1934 goto nla_put_failure;
1935 if (pinfo->filled & MPATH_INFO_FRAME_QLEN)
1936 NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
1937 pinfo->frame_qlen);
1938 if (pinfo->filled & MPATH_INFO_DSN)
1939 NLA_PUT_U32(msg, NL80211_MPATH_INFO_DSN,
1940 pinfo->dsn);
1941 if (pinfo->filled & MPATH_INFO_METRIC)
1942 NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC,
1943 pinfo->metric);
1944 if (pinfo->filled & MPATH_INFO_EXPTIME)
1945 NLA_PUT_U32(msg, NL80211_MPATH_INFO_EXPTIME,
1946 pinfo->exptime);
1947 if (pinfo->filled & MPATH_INFO_FLAGS)
1948 NLA_PUT_U8(msg, NL80211_MPATH_INFO_FLAGS,
1949 pinfo->flags);
1950 if (pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT)
1951 NLA_PUT_U32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
1952 pinfo->discovery_timeout);
1953 if (pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES)
1954 NLA_PUT_U8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
1955 pinfo->discovery_retries);
1956
1957 nla_nest_end(msg, pinfoattr);
1958
1959 return genlmsg_end(msg, hdr);
1960
1961 nla_put_failure:
bc3ed28c
TG
1962 genlmsg_cancel(msg, hdr);
1963 return -EMSGSIZE;
2ec600d6
LCC
1964}
1965
1966static int nl80211_dump_mpath(struct sk_buff *skb,
bba95fef 1967 struct netlink_callback *cb)
2ec600d6 1968{
2ec600d6
LCC
1969 struct mpath_info pinfo;
1970 struct cfg80211_registered_device *dev;
bba95fef 1971 struct net_device *netdev;
2ec600d6
LCC
1972 u8 dst[ETH_ALEN];
1973 u8 next_hop[ETH_ALEN];
bba95fef
JB
1974 int ifidx = cb->args[0];
1975 int path_idx = cb->args[1];
2ec600d6 1976 int err;
2ec600d6 1977
bba95fef
JB
1978 if (!ifidx) {
1979 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
1980 nl80211_fam.attrbuf, nl80211_fam.maxattr,
1981 nl80211_policy);
1982 if (err)
1983 return err;
1984
1985 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
1986 return -EINVAL;
1987
1988 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
1989 if (!ifidx)
1990 return -EINVAL;
1991 }
1992
3b85875a
JB
1993 rtnl_lock();
1994
1995 netdev = __dev_get_by_index(&init_net, ifidx);
1996 if (!netdev) {
1997 err = -ENODEV;
1998 goto out_rtnl;
1999 }
bba95fef
JB
2000
2001 dev = cfg80211_get_dev_from_ifindex(ifidx);
2002 if (IS_ERR(dev)) {
2003 err = PTR_ERR(dev);
3b85875a 2004 goto out_rtnl;
bba95fef
JB
2005 }
2006
2007 if (!dev->ops->dump_mpath) {
eec60b03 2008 err = -EOPNOTSUPP;
bba95fef
JB
2009 goto out_err;
2010 }
2011
eec60b03
JM
2012 if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
2013 err = -EOPNOTSUPP;
2014 goto out;
2015 }
2016
bba95fef
JB
2017 while (1) {
2018 err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx,
2019 dst, next_hop, &pinfo);
2020 if (err == -ENOENT)
2ec600d6 2021 break;
bba95fef 2022 if (err)
3b85875a 2023 goto out_err;
2ec600d6 2024
bba95fef
JB
2025 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid,
2026 cb->nlh->nlmsg_seq, NLM_F_MULTI,
2027 netdev, dst, next_hop,
2028 &pinfo) < 0)
2029 goto out;
2ec600d6 2030
bba95fef 2031 path_idx++;
2ec600d6 2032 }
2ec600d6 2033
2ec600d6 2034
bba95fef
JB
2035 out:
2036 cb->args[1] = path_idx;
2037 err = skb->len;
bba95fef 2038 out_err:
4d0c8aea 2039 cfg80211_unlock_rdev(dev);
3b85875a
JB
2040 out_rtnl:
2041 rtnl_unlock();
bba95fef
JB
2042
2043 return err;
2ec600d6
LCC
2044}
2045
2046static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
2047{
79c97e97 2048 struct cfg80211_registered_device *rdev;
2ec600d6
LCC
2049 int err;
2050 struct net_device *dev;
2051 struct mpath_info pinfo;
2052 struct sk_buff *msg;
2053 u8 *dst = NULL;
2054 u8 next_hop[ETH_ALEN];
2055
2056 memset(&pinfo, 0, sizeof(pinfo));
2057
2058 if (!info->attrs[NL80211_ATTR_MAC])
2059 return -EINVAL;
2060
2061 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
2062
3b85875a
JB
2063 rtnl_lock();
2064
79c97e97 2065 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
2ec600d6 2066 if (err)
3b85875a 2067 goto out_rtnl;
2ec600d6 2068
79c97e97 2069 if (!rdev->ops->get_mpath) {
2ec600d6
LCC
2070 err = -EOPNOTSUPP;
2071 goto out;
2072 }
2073
eec60b03
JM
2074 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
2075 err = -EOPNOTSUPP;
2076 goto out;
2077 }
2078
79c97e97 2079 err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo);
2ec600d6
LCC
2080 if (err)
2081 goto out;
2082
fd2120ca 2083 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2ec600d6
LCC
2084 if (!msg)
2085 goto out;
2086
2087 if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0,
2088 dev, dst, next_hop, &pinfo) < 0)
2089 goto out_free;
2090
134e6375 2091 err = genlmsg_reply(msg, info);
2ec600d6
LCC
2092 goto out;
2093
2094 out_free:
2095 nlmsg_free(msg);
2ec600d6 2096 out:
79c97e97 2097 cfg80211_unlock_rdev(rdev);
2ec600d6 2098 dev_put(dev);
3b85875a
JB
2099 out_rtnl:
2100 rtnl_unlock();
2101
2ec600d6
LCC
2102 return err;
2103}
2104
2105static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
2106{
79c97e97 2107 struct cfg80211_registered_device *rdev;
2ec600d6
LCC
2108 int err;
2109 struct net_device *dev;
2110 u8 *dst = NULL;
2111 u8 *next_hop = NULL;
2112
2113 if (!info->attrs[NL80211_ATTR_MAC])
2114 return -EINVAL;
2115
2116 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
2117 return -EINVAL;
2118
2119 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
2120 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
2121
3b85875a
JB
2122 rtnl_lock();
2123
79c97e97 2124 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
2ec600d6 2125 if (err)
3b85875a 2126 goto out_rtnl;
2ec600d6 2127
79c97e97 2128 if (!rdev->ops->change_mpath) {
2ec600d6
LCC
2129 err = -EOPNOTSUPP;
2130 goto out;
2131 }
2132
eec60b03
JM
2133 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
2134 err = -EOPNOTSUPP;
2135 goto out;
2136 }
2137
35a8efe1
JM
2138 if (!netif_running(dev)) {
2139 err = -ENETDOWN;
2140 goto out;
2141 }
2142
79c97e97 2143 err = rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
2ec600d6
LCC
2144
2145 out:
79c97e97 2146 cfg80211_unlock_rdev(rdev);
2ec600d6 2147 dev_put(dev);
3b85875a
JB
2148 out_rtnl:
2149 rtnl_unlock();
2150
2ec600d6
LCC
2151 return err;
2152}
2153static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
2154{
79c97e97 2155 struct cfg80211_registered_device *rdev;
2ec600d6
LCC
2156 int err;
2157 struct net_device *dev;
2158 u8 *dst = NULL;
2159 u8 *next_hop = NULL;
2160
2161 if (!info->attrs[NL80211_ATTR_MAC])
2162 return -EINVAL;
2163
2164 if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
2165 return -EINVAL;
2166
2167 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
2168 next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
2169
3b85875a
JB
2170 rtnl_lock();
2171
79c97e97 2172 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
2ec600d6 2173 if (err)
3b85875a 2174 goto out_rtnl;
2ec600d6 2175
79c97e97 2176 if (!rdev->ops->add_mpath) {
2ec600d6
LCC
2177 err = -EOPNOTSUPP;
2178 goto out;
2179 }
2180
eec60b03
JM
2181 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
2182 err = -EOPNOTSUPP;
2183 goto out;
2184 }
2185
35a8efe1
JM
2186 if (!netif_running(dev)) {
2187 err = -ENETDOWN;
2188 goto out;
2189 }
2190
79c97e97 2191 err = rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
2ec600d6
LCC
2192
2193 out:
79c97e97 2194 cfg80211_unlock_rdev(rdev);
2ec600d6 2195 dev_put(dev);
3b85875a
JB
2196 out_rtnl:
2197 rtnl_unlock();
2198
2ec600d6
LCC
2199 return err;
2200}
2201
2202static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
2203{
79c97e97 2204 struct cfg80211_registered_device *rdev;
2ec600d6
LCC
2205 int err;
2206 struct net_device *dev;
2207 u8 *dst = NULL;
2208
2209 if (info->attrs[NL80211_ATTR_MAC])
2210 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
2211
3b85875a
JB
2212 rtnl_lock();
2213
79c97e97 2214 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
2ec600d6 2215 if (err)
3b85875a 2216 goto out_rtnl;
2ec600d6 2217
79c97e97 2218 if (!rdev->ops->del_mpath) {
2ec600d6
LCC
2219 err = -EOPNOTSUPP;
2220 goto out;
2221 }
2222
79c97e97 2223 err = rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
2ec600d6
LCC
2224
2225 out:
79c97e97 2226 cfg80211_unlock_rdev(rdev);
2ec600d6 2227 dev_put(dev);
3b85875a
JB
2228 out_rtnl:
2229 rtnl_unlock();
2230
2ec600d6
LCC
2231 return err;
2232}
2233
9f1ba906
JM
2234static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
2235{
79c97e97 2236 struct cfg80211_registered_device *rdev;
9f1ba906
JM
2237 int err;
2238 struct net_device *dev;
2239 struct bss_parameters params;
2240
2241 memset(&params, 0, sizeof(params));
2242 /* default to not changing parameters */
2243 params.use_cts_prot = -1;
2244 params.use_short_preamble = -1;
2245 params.use_short_slot_time = -1;
2246
2247 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
2248 params.use_cts_prot =
2249 nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
2250 if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
2251 params.use_short_preamble =
2252 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
2253 if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
2254 params.use_short_slot_time =
2255 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
90c97a04
JM
2256 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
2257 params.basic_rates =
2258 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
2259 params.basic_rates_len =
2260 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
2261 }
9f1ba906 2262
3b85875a
JB
2263 rtnl_lock();
2264
79c97e97 2265 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
9f1ba906 2266 if (err)
3b85875a 2267 goto out_rtnl;
9f1ba906 2268
79c97e97 2269 if (!rdev->ops->change_bss) {
9f1ba906
JM
2270 err = -EOPNOTSUPP;
2271 goto out;
2272 }
2273
eec60b03
JM
2274 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
2275 err = -EOPNOTSUPP;
2276 goto out;
2277 }
2278
79c97e97 2279 err = rdev->ops->change_bss(&rdev->wiphy, dev, &params);
9f1ba906
JM
2280
2281 out:
79c97e97 2282 cfg80211_unlock_rdev(rdev);
9f1ba906 2283 dev_put(dev);
3b85875a
JB
2284 out_rtnl:
2285 rtnl_unlock();
2286
9f1ba906
JM
2287 return err;
2288}
2289
b2e1b302
LR
2290static const struct nla_policy
2291 reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
2292 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
2293 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
2294 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
2295 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
2296 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
2297 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
2298};
2299
2300static int parse_reg_rule(struct nlattr *tb[],
2301 struct ieee80211_reg_rule *reg_rule)
2302{
2303 struct ieee80211_freq_range *freq_range = &reg_rule->freq_range;
2304 struct ieee80211_power_rule *power_rule = &reg_rule->power_rule;
2305
2306 if (!tb[NL80211_ATTR_REG_RULE_FLAGS])
2307 return -EINVAL;
2308 if (!tb[NL80211_ATTR_FREQ_RANGE_START])
2309 return -EINVAL;
2310 if (!tb[NL80211_ATTR_FREQ_RANGE_END])
2311 return -EINVAL;
2312 if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
2313 return -EINVAL;
2314 if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
2315 return -EINVAL;
2316
2317 reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]);
2318
2319 freq_range->start_freq_khz =
2320 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
2321 freq_range->end_freq_khz =
2322 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
2323 freq_range->max_bandwidth_khz =
2324 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
2325
2326 power_rule->max_eirp =
2327 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
2328
2329 if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN])
2330 power_rule->max_antenna_gain =
2331 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
2332
2333 return 0;
2334}
2335
2336static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
2337{
2338 int r;
2339 char *data = NULL;
2340
80778f18
LR
2341 /*
2342 * You should only get this when cfg80211 hasn't yet initialized
2343 * completely when built-in to the kernel right between the time
2344 * window between nl80211_init() and regulatory_init(), if that is
2345 * even possible.
2346 */
2347 mutex_lock(&cfg80211_mutex);
2348 if (unlikely(!cfg80211_regdomain)) {
fe33eb39
LR
2349 mutex_unlock(&cfg80211_mutex);
2350 return -EINPROGRESS;
80778f18 2351 }
fe33eb39 2352 mutex_unlock(&cfg80211_mutex);
80778f18 2353
fe33eb39
LR
2354 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
2355 return -EINVAL;
b2e1b302
LR
2356
2357 data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
2358
2359#ifdef CONFIG_WIRELESS_OLD_REGULATORY
2360 /* We ignore world regdom requests with the old regdom setup */
fe33eb39
LR
2361 if (is_world_regdom(data))
2362 return -EINVAL;
b2e1b302 2363#endif
fe33eb39
LR
2364
2365 r = regulatory_hint_user(data);
2366
b2e1b302
LR
2367 return r;
2368}
2369
93da9cc1 2370static int nl80211_get_mesh_params(struct sk_buff *skb,
2371 struct genl_info *info)
2372{
79c97e97 2373 struct cfg80211_registered_device *rdev;
93da9cc1 2374 struct mesh_config cur_params;
2375 int err;
2376 struct net_device *dev;
2377 void *hdr;
2378 struct nlattr *pinfoattr;
2379 struct sk_buff *msg;
2380
3b85875a
JB
2381 rtnl_lock();
2382
93da9cc1 2383 /* Look up our device */
79c97e97 2384 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
93da9cc1 2385 if (err)
3b85875a 2386 goto out_rtnl;
93da9cc1 2387
79c97e97 2388 if (!rdev->ops->get_mesh_params) {
f3f92586
JM
2389 err = -EOPNOTSUPP;
2390 goto out;
2391 }
2392
93da9cc1 2393 /* Get the mesh params */
79c97e97 2394 err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, &cur_params);
93da9cc1 2395 if (err)
2396 goto out;
2397
2398 /* Draw up a netlink message to send back */
fd2120ca 2399 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
93da9cc1 2400 if (!msg) {
2401 err = -ENOBUFS;
2402 goto out;
2403 }
2404 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
2405 NL80211_CMD_GET_MESH_PARAMS);
2406 if (!hdr)
2407 goto nla_put_failure;
2408 pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_PARAMS);
2409 if (!pinfoattr)
2410 goto nla_put_failure;
2411 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
2412 NLA_PUT_U16(msg, NL80211_MESHCONF_RETRY_TIMEOUT,
2413 cur_params.dot11MeshRetryTimeout);
2414 NLA_PUT_U16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT,
2415 cur_params.dot11MeshConfirmTimeout);
2416 NLA_PUT_U16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT,
2417 cur_params.dot11MeshHoldingTimeout);
2418 NLA_PUT_U16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
2419 cur_params.dot11MeshMaxPeerLinks);
2420 NLA_PUT_U8(msg, NL80211_MESHCONF_MAX_RETRIES,
2421 cur_params.dot11MeshMaxRetries);
2422 NLA_PUT_U8(msg, NL80211_MESHCONF_TTL,
2423 cur_params.dot11MeshTTL);
2424 NLA_PUT_U8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
2425 cur_params.auto_open_plinks);
2426 NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
2427 cur_params.dot11MeshHWMPmaxPREQretries);
2428 NLA_PUT_U32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME,
2429 cur_params.path_refresh_time);
2430 NLA_PUT_U16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
2431 cur_params.min_discovery_timeout);
2432 NLA_PUT_U32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
2433 cur_params.dot11MeshHWMPactivePathTimeout);
2434 NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
2435 cur_params.dot11MeshHWMPpreqMinInterval);
2436 NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
2437 cur_params.dot11MeshHWMPnetDiameterTraversalTime);
2438 nla_nest_end(msg, pinfoattr);
2439 genlmsg_end(msg, hdr);
134e6375 2440 err = genlmsg_reply(msg, info);
93da9cc1 2441 goto out;
2442
3b85875a 2443 nla_put_failure:
93da9cc1 2444 genlmsg_cancel(msg, hdr);
2445 err = -EMSGSIZE;
3b85875a 2446 out:
93da9cc1 2447 /* Cleanup */
79c97e97 2448 cfg80211_unlock_rdev(rdev);
93da9cc1 2449 dev_put(dev);
3b85875a
JB
2450 out_rtnl:
2451 rtnl_unlock();
2452
93da9cc1 2453 return err;
2454}
2455
2456#define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \
2457do {\
2458 if (table[attr_num]) {\
2459 cfg.param = nla_fn(table[attr_num]); \
2460 mask |= (1 << (attr_num - 1)); \
2461 } \
2462} while (0);\
2463
2464static struct nla_policy
2465nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] __read_mostly = {
2466 [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 },
2467 [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 },
2468 [NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 },
2469 [NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 },
2470 [NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 },
2471 [NL80211_MESHCONF_TTL] = { .type = NLA_U8 },
2472 [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 },
2473
2474 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
2475 [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
2476 [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 },
2477 [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
2478 [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 },
2479 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
2480};
2481
2482static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2483{
2484 int err;
2485 u32 mask;
79c97e97 2486 struct cfg80211_registered_device *rdev;
93da9cc1 2487 struct net_device *dev;
2488 struct mesh_config cfg;
2489 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
2490 struct nlattr *parent_attr;
2491
2492 parent_attr = info->attrs[NL80211_ATTR_MESH_PARAMS];
2493 if (!parent_attr)
2494 return -EINVAL;
2495 if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX,
2496 parent_attr, nl80211_meshconf_params_policy))
2497 return -EINVAL;
2498
3b85875a
JB
2499 rtnl_lock();
2500
79c97e97 2501 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
93da9cc1 2502 if (err)
3b85875a 2503 goto out_rtnl;
93da9cc1 2504
79c97e97 2505 if (!rdev->ops->set_mesh_params) {
f3f92586
JM
2506 err = -EOPNOTSUPP;
2507 goto out;
2508 }
2509
93da9cc1 2510 /* This makes sure that there aren't more than 32 mesh config
2511 * parameters (otherwise our bitfield scheme would not work.) */
2512 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
2513
2514 /* Fill in the params struct */
2515 mask = 0;
2516 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout,
2517 mask, NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
2518 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout,
2519 mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, nla_get_u16);
2520 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout,
2521 mask, NL80211_MESHCONF_HOLDING_TIMEOUT, nla_get_u16);
2522 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks,
2523 mask, NL80211_MESHCONF_MAX_PEER_LINKS, nla_get_u16);
2524 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries,
2525 mask, NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
2526 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL,
2527 mask, NL80211_MESHCONF_TTL, nla_get_u8);
2528 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks,
2529 mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, nla_get_u8);
2530 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries,
2531 mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
2532 nla_get_u8);
2533 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time,
2534 mask, NL80211_MESHCONF_PATH_REFRESH_TIME, nla_get_u32);
2535 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout,
2536 mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
2537 nla_get_u16);
2538 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
2539 mask, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
2540 nla_get_u32);
2541 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval,
2542 mask, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
2543 nla_get_u16);
2544 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
2545 dot11MeshHWMPnetDiameterTraversalTime,
2546 mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
2547 nla_get_u16);
2548
2549 /* Apply changes */
79c97e97 2550 err = rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask);
93da9cc1 2551
f3f92586 2552 out:
93da9cc1 2553 /* cleanup */
79c97e97 2554 cfg80211_unlock_rdev(rdev);
93da9cc1 2555 dev_put(dev);
3b85875a
JB
2556 out_rtnl:
2557 rtnl_unlock();
2558
93da9cc1 2559 return err;
2560}
2561
2562#undef FILL_IN_MESH_PARAM_IF_SET
2563
f130347c
LR
2564static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
2565{
2566 struct sk_buff *msg;
2567 void *hdr = NULL;
2568 struct nlattr *nl_reg_rules;
2569 unsigned int i;
2570 int err = -EINVAL;
2571
a1794390 2572 mutex_lock(&cfg80211_mutex);
f130347c
LR
2573
2574 if (!cfg80211_regdomain)
2575 goto out;
2576
fd2120ca 2577 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
f130347c
LR
2578 if (!msg) {
2579 err = -ENOBUFS;
2580 goto out;
2581 }
2582
2583 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
2584 NL80211_CMD_GET_REG);
2585 if (!hdr)
2586 goto nla_put_failure;
2587
2588 NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2,
2589 cfg80211_regdomain->alpha2);
2590
2591 nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
2592 if (!nl_reg_rules)
2593 goto nla_put_failure;
2594
2595 for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) {
2596 struct nlattr *nl_reg_rule;
2597 const struct ieee80211_reg_rule *reg_rule;
2598 const struct ieee80211_freq_range *freq_range;
2599 const struct ieee80211_power_rule *power_rule;
2600
2601 reg_rule = &cfg80211_regdomain->reg_rules[i];
2602 freq_range = &reg_rule->freq_range;
2603 power_rule = &reg_rule->power_rule;
2604
2605 nl_reg_rule = nla_nest_start(msg, i);
2606 if (!nl_reg_rule)
2607 goto nla_put_failure;
2608
2609 NLA_PUT_U32(msg, NL80211_ATTR_REG_RULE_FLAGS,
2610 reg_rule->flags);
2611 NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_START,
2612 freq_range->start_freq_khz);
2613 NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_END,
2614 freq_range->end_freq_khz);
2615 NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
2616 freq_range->max_bandwidth_khz);
2617 NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
2618 power_rule->max_antenna_gain);
2619 NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
2620 power_rule->max_eirp);
2621
2622 nla_nest_end(msg, nl_reg_rule);
2623 }
2624
2625 nla_nest_end(msg, nl_reg_rules);
2626
2627 genlmsg_end(msg, hdr);
134e6375 2628 err = genlmsg_reply(msg, info);
f130347c
LR
2629 goto out;
2630
2631nla_put_failure:
2632 genlmsg_cancel(msg, hdr);
2633 err = -EMSGSIZE;
2634out:
a1794390 2635 mutex_unlock(&cfg80211_mutex);
f130347c
LR
2636 return err;
2637}
2638
b2e1b302
LR
2639static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
2640{
2641 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
2642 struct nlattr *nl_reg_rule;
2643 char *alpha2 = NULL;
2644 int rem_reg_rules = 0, r = 0;
2645 u32 num_rules = 0, rule_idx = 0, size_of_regd;
2646 struct ieee80211_regdomain *rd = NULL;
2647
2648 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
2649 return -EINVAL;
2650
2651 if (!info->attrs[NL80211_ATTR_REG_RULES])
2652 return -EINVAL;
2653
2654 alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
2655
2656 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
2657 rem_reg_rules) {
2658 num_rules++;
2659 if (num_rules > NL80211_MAX_SUPP_REG_RULES)
4776c6e7 2660 return -EINVAL;
b2e1b302
LR
2661 }
2662
61405e97
LR
2663 mutex_lock(&cfg80211_mutex);
2664
d0e18f83
LR
2665 if (!reg_is_valid_request(alpha2)) {
2666 r = -EINVAL;
2667 goto bad_reg;
2668 }
b2e1b302
LR
2669
2670 size_of_regd = sizeof(struct ieee80211_regdomain) +
2671 (num_rules * sizeof(struct ieee80211_reg_rule));
2672
2673 rd = kzalloc(size_of_regd, GFP_KERNEL);
d0e18f83
LR
2674 if (!rd) {
2675 r = -ENOMEM;
2676 goto bad_reg;
2677 }
b2e1b302
LR
2678
2679 rd->n_reg_rules = num_rules;
2680 rd->alpha2[0] = alpha2[0];
2681 rd->alpha2[1] = alpha2[1];
2682
2683 nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
2684 rem_reg_rules) {
2685 nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
2686 nla_data(nl_reg_rule), nla_len(nl_reg_rule),
2687 reg_rule_policy);
2688 r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
2689 if (r)
2690 goto bad_reg;
2691
2692 rule_idx++;
2693
d0e18f83
LR
2694 if (rule_idx > NL80211_MAX_SUPP_REG_RULES) {
2695 r = -EINVAL;
b2e1b302 2696 goto bad_reg;
d0e18f83 2697 }
b2e1b302
LR
2698 }
2699
2700 BUG_ON(rule_idx != num_rules);
2701
b2e1b302 2702 r = set_regdom(rd);
61405e97 2703
a1794390 2704 mutex_unlock(&cfg80211_mutex);
d0e18f83 2705
b2e1b302
LR
2706 return r;
2707
d2372b31 2708 bad_reg:
61405e97 2709 mutex_unlock(&cfg80211_mutex);
b2e1b302 2710 kfree(rd);
d0e18f83 2711 return r;
b2e1b302
LR
2712}
2713
83f5e2cf
JB
2714static int validate_scan_freqs(struct nlattr *freqs)
2715{
2716 struct nlattr *attr1, *attr2;
2717 int n_channels = 0, tmp1, tmp2;
2718
2719 nla_for_each_nested(attr1, freqs, tmp1) {
2720 n_channels++;
2721 /*
2722 * Some hardware has a limited channel list for
2723 * scanning, and it is pretty much nonsensical
2724 * to scan for a channel twice, so disallow that
2725 * and don't require drivers to check that the
2726 * channel list they get isn't longer than what
2727 * they can scan, as long as they can scan all
2728 * the channels they registered at once.
2729 */
2730 nla_for_each_nested(attr2, freqs, tmp2)
2731 if (attr1 != attr2 &&
2732 nla_get_u32(attr1) == nla_get_u32(attr2))
2733 return 0;
2734 }
2735
2736 return n_channels;
2737}
2738
2a519311
JB
2739static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2740{
79c97e97 2741 struct cfg80211_registered_device *rdev;
2a519311
JB
2742 struct net_device *dev;
2743 struct cfg80211_scan_request *request;
2744 struct cfg80211_ssid *ssid;
2745 struct ieee80211_channel *channel;
2746 struct nlattr *attr;
2747 struct wiphy *wiphy;
83f5e2cf 2748 int err, tmp, n_ssids = 0, n_channels, i;
2a519311 2749 enum ieee80211_band band;
70692ad2 2750 size_t ie_len;
2a519311 2751
f4a11bb0
JB
2752 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
2753 return -EINVAL;
2754
3b85875a
JB
2755 rtnl_lock();
2756
79c97e97 2757 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
2a519311 2758 if (err)
3b85875a 2759 goto out_rtnl;
2a519311 2760
79c97e97 2761 wiphy = &rdev->wiphy;
2a519311 2762
79c97e97 2763 if (!rdev->ops->scan) {
2a519311
JB
2764 err = -EOPNOTSUPP;
2765 goto out;
2766 }
2767
35a8efe1
JM
2768 if (!netif_running(dev)) {
2769 err = -ENETDOWN;
2770 goto out;
2771 }
2772
79c97e97 2773 if (rdev->scan_req) {
2a519311 2774 err = -EBUSY;
3b85875a 2775 goto out;
2a519311
JB
2776 }
2777
2778 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
83f5e2cf
JB
2779 n_channels = validate_scan_freqs(
2780 info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
2a519311
JB
2781 if (!n_channels) {
2782 err = -EINVAL;
3b85875a 2783 goto out;
2a519311
JB
2784 }
2785 } else {
83f5e2cf
JB
2786 n_channels = 0;
2787
2a519311
JB
2788 for (band = 0; band < IEEE80211_NUM_BANDS; band++)
2789 if (wiphy->bands[band])
2790 n_channels += wiphy->bands[band]->n_channels;
2791 }
2792
2793 if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
2794 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
2795 n_ssids++;
2796
2797 if (n_ssids > wiphy->max_scan_ssids) {
2798 err = -EINVAL;
3b85875a 2799 goto out;
2a519311
JB
2800 }
2801
70692ad2
JM
2802 if (info->attrs[NL80211_ATTR_IE])
2803 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2804 else
2805 ie_len = 0;
2806
18a83659
JB
2807 if (ie_len > wiphy->max_scan_ie_len) {
2808 err = -EINVAL;
2809 goto out;
2810 }
2811
2a519311
JB
2812 request = kzalloc(sizeof(*request)
2813 + sizeof(*ssid) * n_ssids
70692ad2
JM
2814 + sizeof(channel) * n_channels
2815 + ie_len, GFP_KERNEL);
2a519311
JB
2816 if (!request) {
2817 err = -ENOMEM;
3b85875a 2818 goto out;
2a519311
JB
2819 }
2820
2821 request->channels = (void *)((char *)request + sizeof(*request));
2822 request->n_channels = n_channels;
2823 if (n_ssids)
2824 request->ssids = (void *)(request->channels + n_channels);
2825 request->n_ssids = n_ssids;
70692ad2
JM
2826 if (ie_len) {
2827 if (request->ssids)
2828 request->ie = (void *)(request->ssids + n_ssids);
2829 else
2830 request->ie = (void *)(request->channels + n_channels);
2831 }
2a519311
JB
2832
2833 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
2834 /* user specified, bail out if channel not found */
2835 request->n_channels = n_channels;
2836 i = 0;
2837 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) {
2838 request->channels[i] = ieee80211_get_channel(wiphy, nla_get_u32(attr));
2839 if (!request->channels[i]) {
2840 err = -EINVAL;
2841 goto out_free;
2842 }
2843 i++;
2844 }
2845 } else {
2846 /* all channels */
2847 i = 0;
2848 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
2849 int j;
2850 if (!wiphy->bands[band])
2851 continue;
2852 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
2853 request->channels[i] = &wiphy->bands[band]->channels[j];
2854 i++;
2855 }
2856 }
2857 }
2858
2859 i = 0;
2860 if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
2861 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
2862 if (request->ssids[i].ssid_len > IEEE80211_MAX_SSID_LEN) {
2863 err = -EINVAL;
2864 goto out_free;
2865 }
2866 memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
2867 request->ssids[i].ssid_len = nla_len(attr);
2868 i++;
2869 }
2870 }
2871
70692ad2
JM
2872 if (info->attrs[NL80211_ATTR_IE]) {
2873 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
de95a54b
JB
2874 memcpy((void *)request->ie,
2875 nla_data(info->attrs[NL80211_ATTR_IE]),
70692ad2
JM
2876 request->ie_len);
2877 }
2878
2a519311 2879 request->ifidx = dev->ifindex;
79c97e97 2880 request->wiphy = &rdev->wiphy;
2a519311 2881
79c97e97
JB
2882 rdev->scan_req = request;
2883 err = rdev->ops->scan(&rdev->wiphy, dev, request);
2a519311 2884
a538e2d5 2885 if (!err)
79c97e97 2886 nl80211_send_scan_start(rdev, dev);
a538e2d5 2887
2a519311
JB
2888 out_free:
2889 if (err) {
79c97e97 2890 rdev->scan_req = NULL;
2a519311
JB
2891 kfree(request);
2892 }
2a519311 2893 out:
79c97e97 2894 cfg80211_unlock_rdev(rdev);
2a519311 2895 dev_put(dev);
3b85875a
JB
2896 out_rtnl:
2897 rtnl_unlock();
2898
2a519311
JB
2899 return err;
2900}
2901
2902static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
2903 struct cfg80211_registered_device *rdev,
2904 struct net_device *dev,
2905 struct cfg80211_bss *res)
2906{
2907 void *hdr;
2908 struct nlattr *bss;
2909
2910 hdr = nl80211hdr_put(msg, pid, seq, flags,
2911 NL80211_CMD_NEW_SCAN_RESULTS);
2912 if (!hdr)
2913 return -1;
2914
2915 NLA_PUT_U32(msg, NL80211_ATTR_SCAN_GENERATION,
2916 rdev->bss_generation);
2917 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
2918
2919 bss = nla_nest_start(msg, NL80211_ATTR_BSS);
2920 if (!bss)
2921 goto nla_put_failure;
2922 if (!is_zero_ether_addr(res->bssid))
2923 NLA_PUT(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid);
2924 if (res->information_elements && res->len_information_elements)
2925 NLA_PUT(msg, NL80211_BSS_INFORMATION_ELEMENTS,
2926 res->len_information_elements,
2927 res->information_elements);
2928 if (res->tsf)
2929 NLA_PUT_U64(msg, NL80211_BSS_TSF, res->tsf);
2930 if (res->beacon_interval)
2931 NLA_PUT_U16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval);
2932 NLA_PUT_U16(msg, NL80211_BSS_CAPABILITY, res->capability);
2933 NLA_PUT_U32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq);
2934
77965c97 2935 switch (rdev->wiphy.signal_type) {
2a519311
JB
2936 case CFG80211_SIGNAL_TYPE_MBM:
2937 NLA_PUT_U32(msg, NL80211_BSS_SIGNAL_MBM, res->signal);
2938 break;
2939 case CFG80211_SIGNAL_TYPE_UNSPEC:
2940 NLA_PUT_U8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal);
2941 break;
2942 default:
2943 break;
2944 }
2945
2946 nla_nest_end(msg, bss);
2947
2948 return genlmsg_end(msg, hdr);
2949
2950 nla_put_failure:
2951 genlmsg_cancel(msg, hdr);
2952 return -EMSGSIZE;
2953}
2954
2955static int nl80211_dump_scan(struct sk_buff *skb,
2956 struct netlink_callback *cb)
2957{
2958 struct cfg80211_registered_device *dev;
2959 struct net_device *netdev;
2960 struct cfg80211_internal_bss *scan;
2961 int ifidx = cb->args[0];
2962 int start = cb->args[1], idx = 0;
2963 int err;
2964
2965 if (!ifidx) {
2966 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
2967 nl80211_fam.attrbuf, nl80211_fam.maxattr,
2968 nl80211_policy);
2969 if (err)
2970 return err;
2971
2972 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
2973 return -EINVAL;
2974
2975 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
2976 if (!ifidx)
2977 return -EINVAL;
2978 cb->args[0] = ifidx;
2979 }
2980
2981 netdev = dev_get_by_index(&init_net, ifidx);
2982 if (!netdev)
2983 return -ENODEV;
2984
2985 dev = cfg80211_get_dev_from_ifindex(ifidx);
2986 if (IS_ERR(dev)) {
2987 err = PTR_ERR(dev);
2988 goto out_put_netdev;
2989 }
2990
2991 spin_lock_bh(&dev->bss_lock);
2992 cfg80211_bss_expire(dev);
2993
2994 list_for_each_entry(scan, &dev->bss_list, list) {
2995 if (++idx <= start)
2996 continue;
2997 if (nl80211_send_bss(skb,
2998 NETLINK_CB(cb->skb).pid,
2999 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3000 dev, netdev, &scan->pub) < 0) {
3001 idx--;
3002 goto out;
3003 }
3004 }
3005
3006 out:
3007 spin_unlock_bh(&dev->bss_lock);
3008
3009 cb->args[1] = idx;
3010 err = skb->len;
4d0c8aea 3011 cfg80211_unlock_rdev(dev);
2a519311
JB
3012 out_put_netdev:
3013 dev_put(netdev);
3014
3015 return err;
3016}
3017
255e737e
JM
3018static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type)
3019{
b23aa676
SO
3020 return auth_type <= NL80211_AUTHTYPE_MAX;
3021}
3022
3023static bool nl80211_valid_wpa_versions(u32 wpa_versions)
3024{
3025 return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
3026 NL80211_WPA_VERSION_2));
3027}
3028
3029static bool nl80211_valid_akm_suite(u32 akm)
3030{
3031 return akm == WLAN_AKM_SUITE_8021X ||
3032 akm == WLAN_AKM_SUITE_PSK;
3033}
3034
3035static bool nl80211_valid_cipher_suite(u32 cipher)
3036{
3037 return cipher == WLAN_CIPHER_SUITE_WEP40 ||
3038 cipher == WLAN_CIPHER_SUITE_WEP104 ||
3039 cipher == WLAN_CIPHER_SUITE_TKIP ||
3040 cipher == WLAN_CIPHER_SUITE_CCMP ||
3041 cipher == WLAN_CIPHER_SUITE_AES_CMAC;
255e737e
JM
3042}
3043
b23aa676 3044
636a5d36
JM
3045static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3046{
79c97e97 3047 struct cfg80211_registered_device *rdev;
636a5d36 3048 struct net_device *dev;
19957bb3
JB
3049 struct ieee80211_channel *chan;
3050 const u8 *bssid, *ssid, *ie = NULL;
3051 int err, ssid_len, ie_len = 0;
3052 enum nl80211_auth_type auth_type;
636a5d36 3053
f4a11bb0
JB
3054 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3055 return -EINVAL;
3056
3057 if (!info->attrs[NL80211_ATTR_MAC])
3058 return -EINVAL;
3059
1778092e
JM
3060 if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
3061 return -EINVAL;
3062
19957bb3
JB
3063 if (!info->attrs[NL80211_ATTR_SSID])
3064 return -EINVAL;
3065
3066 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
3067 return -EINVAL;
3068
636a5d36
JM
3069 rtnl_lock();
3070
79c97e97 3071 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
636a5d36
JM
3072 if (err)
3073 goto unlock_rtnl;
3074
79c97e97 3075 if (!rdev->ops->auth) {
636a5d36
JM
3076 err = -EOPNOTSUPP;
3077 goto out;
3078 }
3079
eec60b03
JM
3080 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
3081 err = -EOPNOTSUPP;
3082 goto out;
3083 }
3084
35a8efe1
JM
3085 if (!netif_running(dev)) {
3086 err = -ENETDOWN;
3087 goto out;
3088 }
3089
19957bb3 3090 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
79c97e97 3091 chan = ieee80211_get_channel(&rdev->wiphy,
19957bb3
JB
3092 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3093 if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) {
3094 err = -EINVAL;
3095 goto out;
636a5d36
JM
3096 }
3097
19957bb3
JB
3098 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
3099 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
3100
3101 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
3102 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
3103 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
3104 }
3105
19957bb3
JB
3106 auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
3107 if (!nl80211_valid_auth_type(auth_type)) {
1778092e
JM
3108 err = -EINVAL;
3109 goto out;
636a5d36
JM
3110 }
3111
79c97e97 3112 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
19957bb3 3113 ssid, ssid_len, ie, ie_len);
636a5d36
JM
3114
3115out:
79c97e97 3116 cfg80211_unlock_rdev(rdev);
636a5d36
JM
3117 dev_put(dev);
3118unlock_rtnl:
3119 rtnl_unlock();
3120 return err;
3121}
3122
b23aa676 3123static int nl80211_crypto_settings(struct genl_info *info,
3dc27d25
JB
3124 struct cfg80211_crypto_settings *settings,
3125 int cipher_limit)
b23aa676
SO
3126{
3127 settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
3128
3129 if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
3130 void *data;
3131 int len, i;
3132
3133 data = nla_data(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
3134 len = nla_len(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
3135 settings->n_ciphers_pairwise = len / sizeof(u32);
3136
3137 if (len % sizeof(u32))
3138 return -EINVAL;
3139
3dc27d25 3140 if (settings->n_ciphers_pairwise > cipher_limit)
b23aa676
SO
3141 return -EINVAL;
3142
3143 memcpy(settings->ciphers_pairwise, data, len);
3144
3145 for (i = 0; i < settings->n_ciphers_pairwise; i++)
3146 if (!nl80211_valid_cipher_suite(
3147 settings->ciphers_pairwise[i]))
3148 return -EINVAL;
3149 }
3150
3151 if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) {
3152 settings->cipher_group =
3153 nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]);
3154 if (!nl80211_valid_cipher_suite(settings->cipher_group))
3155 return -EINVAL;
3156 }
3157
3158 if (info->attrs[NL80211_ATTR_WPA_VERSIONS]) {
3159 settings->wpa_versions =
3160 nla_get_u32(info->attrs[NL80211_ATTR_WPA_VERSIONS]);
3161 if (!nl80211_valid_wpa_versions(settings->wpa_versions))
3162 return -EINVAL;
3163 }
3164
3165 if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
3166 void *data;
3167 int len, i;
3168
3169 data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
3170 len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
3171 settings->n_akm_suites = len / sizeof(u32);
3172
3173 if (len % sizeof(u32))
3174 return -EINVAL;
3175
3176 memcpy(settings->akm_suites, data, len);
3177
3178 for (i = 0; i < settings->n_ciphers_pairwise; i++)
3179 if (!nl80211_valid_akm_suite(settings->akm_suites[i]))
3180 return -EINVAL;
3181 }
3182
3183 return 0;
3184}
3185
636a5d36
JM
3186static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3187{
19957bb3 3188 struct cfg80211_registered_device *rdev;
636a5d36 3189 struct net_device *dev;
19957bb3
JB
3190 struct cfg80211_crypto_settings crypto;
3191 struct ieee80211_channel *chan;
3e5d7649 3192 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
19957bb3
JB
3193 int err, ssid_len, ie_len = 0;
3194 bool use_mfp = false;
636a5d36 3195
f4a11bb0
JB
3196 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3197 return -EINVAL;
3198
3199 if (!info->attrs[NL80211_ATTR_MAC] ||
19957bb3
JB
3200 !info->attrs[NL80211_ATTR_SSID] ||
3201 !info->attrs[NL80211_ATTR_WIPHY_FREQ])
f4a11bb0
JB
3202 return -EINVAL;
3203
636a5d36
JM
3204 rtnl_lock();
3205
79c97e97 3206 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
636a5d36
JM
3207 if (err)
3208 goto unlock_rtnl;
3209
19957bb3 3210 if (!rdev->ops->assoc) {
636a5d36
JM
3211 err = -EOPNOTSUPP;
3212 goto out;
3213 }
3214
eec60b03
JM
3215 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
3216 err = -EOPNOTSUPP;
3217 goto out;
3218 }
3219
35a8efe1
JM
3220 if (!netif_running(dev)) {
3221 err = -ENETDOWN;
3222 goto out;
3223 }
3224
19957bb3 3225 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 3226
19957bb3
JB
3227 chan = ieee80211_get_channel(&rdev->wiphy,
3228 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3229 if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) {
3230 err = -EINVAL;
3231 goto out;
636a5d36
JM
3232 }
3233
19957bb3
JB
3234 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
3235 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
636a5d36
JM
3236
3237 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
3238 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
3239 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
3240 }
3241
dc6382ce 3242 if (info->attrs[NL80211_ATTR_USE_MFP]) {
4f5dadce 3243 enum nl80211_mfp mfp =
dc6382ce 3244 nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
4f5dadce 3245 if (mfp == NL80211_MFP_REQUIRED)
19957bb3 3246 use_mfp = true;
4f5dadce 3247 else if (mfp != NL80211_MFP_NO) {
dc6382ce
JM
3248 err = -EINVAL;
3249 goto out;
3250 }
3251 }
3252
3e5d7649
JB
3253 if (info->attrs[NL80211_ATTR_PREV_BSSID])
3254 prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
3255
3dc27d25 3256 err = nl80211_crypto_settings(info, &crypto, 1);
b23aa676 3257 if (!err)
3e5d7649
JB
3258 err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
3259 ssid, ssid_len, ie, ie_len, use_mfp,
19957bb3 3260 &crypto);
636a5d36
JM
3261
3262out:
4d0c8aea 3263 cfg80211_unlock_rdev(rdev);
636a5d36
JM
3264 dev_put(dev);
3265unlock_rtnl:
3266 rtnl_unlock();
3267 return err;
3268}
3269
3270static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
3271{
79c97e97 3272 struct cfg80211_registered_device *rdev;
636a5d36 3273 struct net_device *dev;
19957bb3
JB
3274 const u8 *ie = NULL, *bssid;
3275 int err, ie_len = 0;
3276 u16 reason_code;
636a5d36 3277
f4a11bb0
JB
3278 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3279 return -EINVAL;
3280
3281 if (!info->attrs[NL80211_ATTR_MAC])
3282 return -EINVAL;
3283
3284 if (!info->attrs[NL80211_ATTR_REASON_CODE])
3285 return -EINVAL;
3286
636a5d36
JM
3287 rtnl_lock();
3288
79c97e97 3289 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
636a5d36
JM
3290 if (err)
3291 goto unlock_rtnl;
3292
79c97e97 3293 if (!rdev->ops->deauth) {
636a5d36
JM
3294 err = -EOPNOTSUPP;
3295 goto out;
3296 }
3297
eec60b03
JM
3298 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
3299 err = -EOPNOTSUPP;
3300 goto out;
3301 }
3302
35a8efe1
JM
3303 if (!netif_running(dev)) {
3304 err = -ENETDOWN;
3305 goto out;
3306 }
3307
19957bb3 3308 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 3309
19957bb3
JB
3310 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
3311 if (reason_code == 0) {
f4a11bb0
JB
3312 /* Reason Code 0 is reserved */
3313 err = -EINVAL;
3314 goto out;
255e737e 3315 }
636a5d36
JM
3316
3317 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
3318 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
3319 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
3320 }
3321
79c97e97 3322 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code);
636a5d36
JM
3323
3324out:
79c97e97 3325 cfg80211_unlock_rdev(rdev);
636a5d36
JM
3326 dev_put(dev);
3327unlock_rtnl:
3328 rtnl_unlock();
3329 return err;
3330}
3331
3332static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
3333{
79c97e97 3334 struct cfg80211_registered_device *rdev;
636a5d36 3335 struct net_device *dev;
19957bb3
JB
3336 const u8 *ie = NULL, *bssid;
3337 int err, ie_len = 0;
3338 u16 reason_code;
636a5d36 3339
f4a11bb0
JB
3340 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3341 return -EINVAL;
3342
3343 if (!info->attrs[NL80211_ATTR_MAC])
3344 return -EINVAL;
3345
3346 if (!info->attrs[NL80211_ATTR_REASON_CODE])
3347 return -EINVAL;
3348
636a5d36
JM
3349 rtnl_lock();
3350
79c97e97 3351 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
636a5d36
JM
3352 if (err)
3353 goto unlock_rtnl;
3354
79c97e97 3355 if (!rdev->ops->disassoc) {
636a5d36
JM
3356 err = -EOPNOTSUPP;
3357 goto out;
3358 }
3359
eec60b03
JM
3360 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
3361 err = -EOPNOTSUPP;
3362 goto out;
3363 }
3364
35a8efe1
JM
3365 if (!netif_running(dev)) {
3366 err = -ENETDOWN;
3367 goto out;
3368 }
3369
19957bb3 3370 bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
636a5d36 3371
19957bb3
JB
3372 reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
3373 if (reason_code == 0) {
f4a11bb0
JB
3374 /* Reason Code 0 is reserved */
3375 err = -EINVAL;
3376 goto out;
255e737e 3377 }
636a5d36
JM
3378
3379 if (info->attrs[NL80211_ATTR_IE]) {
19957bb3
JB
3380 ie = nla_data(info->attrs[NL80211_ATTR_IE]);
3381 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
636a5d36
JM
3382 }
3383
79c97e97 3384 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code);
636a5d36
JM
3385
3386out:
79c97e97 3387 cfg80211_unlock_rdev(rdev);
636a5d36
JM
3388 dev_put(dev);
3389unlock_rtnl:
3390 rtnl_unlock();
3391 return err;
3392}
3393
04a773ad
JB
3394static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
3395{
79c97e97 3396 struct cfg80211_registered_device *rdev;
04a773ad
JB
3397 struct net_device *dev;
3398 struct cfg80211_ibss_params ibss;
3399 struct wiphy *wiphy;
3400 int err;
3401
8e30bc55
JB
3402 memset(&ibss, 0, sizeof(ibss));
3403
04a773ad
JB
3404 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3405 return -EINVAL;
3406
3407 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
3408 !info->attrs[NL80211_ATTR_SSID] ||
3409 !nla_len(info->attrs[NL80211_ATTR_SSID]))
3410 return -EINVAL;
3411
8e30bc55
JB
3412 ibss.beacon_interval = 100;
3413
3414 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
3415 ibss.beacon_interval =
3416 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
3417 if (ibss.beacon_interval < 1 || ibss.beacon_interval > 10000)
3418 return -EINVAL;
3419 }
3420
04a773ad
JB
3421 rtnl_lock();
3422
79c97e97 3423 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
04a773ad
JB
3424 if (err)
3425 goto unlock_rtnl;
3426
79c97e97 3427 if (!rdev->ops->join_ibss) {
04a773ad
JB
3428 err = -EOPNOTSUPP;
3429 goto out;
3430 }
3431
3432 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
3433 err = -EOPNOTSUPP;
3434 goto out;
3435 }
3436
3437 if (!netif_running(dev)) {
3438 err = -ENETDOWN;
3439 goto out;
3440 }
3441
79c97e97 3442 wiphy = &rdev->wiphy;
04a773ad
JB
3443
3444 if (info->attrs[NL80211_ATTR_MAC])
3445 ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
3446 ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
3447 ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
3448
3449 if (info->attrs[NL80211_ATTR_IE]) {
3450 ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
3451 ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
3452 }
3453
3454 ibss.channel = ieee80211_get_channel(wiphy,
3455 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3456 if (!ibss.channel ||
3457 ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
3458 ibss.channel->flags & IEEE80211_CHAN_DISABLED) {
3459 err = -EINVAL;
3460 goto out;
3461 }
3462
3463 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
3464
79c97e97 3465 err = cfg80211_join_ibss(rdev, dev, &ibss);
04a773ad
JB
3466
3467out:
79c97e97 3468 cfg80211_unlock_rdev(rdev);
04a773ad
JB
3469 dev_put(dev);
3470unlock_rtnl:
3471 rtnl_unlock();
3472 return err;
3473}
3474
3475static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
3476{
79c97e97 3477 struct cfg80211_registered_device *rdev;
04a773ad
JB
3478 struct net_device *dev;
3479 int err;
3480
3481 rtnl_lock();
3482
79c97e97 3483 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
04a773ad
JB
3484 if (err)
3485 goto unlock_rtnl;
3486
79c97e97 3487 if (!rdev->ops->leave_ibss) {
04a773ad
JB
3488 err = -EOPNOTSUPP;
3489 goto out;
3490 }
3491
3492 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
3493 err = -EOPNOTSUPP;
3494 goto out;
3495 }
3496
3497 if (!netif_running(dev)) {
3498 err = -ENETDOWN;
3499 goto out;
3500 }
3501
79c97e97 3502 err = cfg80211_leave_ibss(rdev, dev, false);
04a773ad
JB
3503
3504out:
79c97e97 3505 cfg80211_unlock_rdev(rdev);
04a773ad
JB
3506 dev_put(dev);
3507unlock_rtnl:
3508 rtnl_unlock();
3509 return err;
3510}
3511
aff89a9b
JB
3512#ifdef CONFIG_NL80211_TESTMODE
3513static struct genl_multicast_group nl80211_testmode_mcgrp = {
3514 .name = "testmode",
3515};
3516
3517static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
3518{
3519 struct cfg80211_registered_device *rdev;
3520 int err;
3521
3522 if (!info->attrs[NL80211_ATTR_TESTDATA])
3523 return -EINVAL;
3524
3525 rtnl_lock();
3526
3527 rdev = cfg80211_get_dev_from_info(info);
3528 if (IS_ERR(rdev)) {
3529 err = PTR_ERR(rdev);
3530 goto unlock_rtnl;
3531 }
3532
3533 err = -EOPNOTSUPP;
3534 if (rdev->ops->testmode_cmd) {
3535 rdev->testmode_info = info;
3536 err = rdev->ops->testmode_cmd(&rdev->wiphy,
3537 nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
3538 nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
3539 rdev->testmode_info = NULL;
3540 }
3541
4d0c8aea 3542 cfg80211_unlock_rdev(rdev);
aff89a9b
JB
3543
3544 unlock_rtnl:
3545 rtnl_unlock();
3546 return err;
3547}
3548
3549static struct sk_buff *
3550__cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev,
3551 int approxlen, u32 pid, u32 seq, gfp_t gfp)
3552{
3553 struct sk_buff *skb;
3554 void *hdr;
3555 struct nlattr *data;
3556
3557 skb = nlmsg_new(approxlen + 100, gfp);
3558 if (!skb)
3559 return NULL;
3560
3561 hdr = nl80211hdr_put(skb, pid, seq, 0, NL80211_CMD_TESTMODE);
3562 if (!hdr) {
3563 kfree_skb(skb);
3564 return NULL;
3565 }
3566
3567 NLA_PUT_U32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
3568 data = nla_nest_start(skb, NL80211_ATTR_TESTDATA);
3569
3570 ((void **)skb->cb)[0] = rdev;
3571 ((void **)skb->cb)[1] = hdr;
3572 ((void **)skb->cb)[2] = data;
3573
3574 return skb;
3575
3576 nla_put_failure:
3577 kfree_skb(skb);
3578 return NULL;
3579}
3580
3581struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
3582 int approxlen)
3583{
3584 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
3585
3586 if (WARN_ON(!rdev->testmode_info))
3587 return NULL;
3588
3589 return __cfg80211_testmode_alloc_skb(rdev, approxlen,
3590 rdev->testmode_info->snd_pid,
3591 rdev->testmode_info->snd_seq,
3592 GFP_KERNEL);
3593}
3594EXPORT_SYMBOL(cfg80211_testmode_alloc_reply_skb);
3595
3596int cfg80211_testmode_reply(struct sk_buff *skb)
3597{
3598 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
3599 void *hdr = ((void **)skb->cb)[1];
3600 struct nlattr *data = ((void **)skb->cb)[2];
3601
3602 if (WARN_ON(!rdev->testmode_info)) {
3603 kfree_skb(skb);
3604 return -EINVAL;
3605 }
3606
3607 nla_nest_end(skb, data);
3608 genlmsg_end(skb, hdr);
3609 return genlmsg_reply(skb, rdev->testmode_info);
3610}
3611EXPORT_SYMBOL(cfg80211_testmode_reply);
3612
3613struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
3614 int approxlen, gfp_t gfp)
3615{
3616 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
3617
3618 return __cfg80211_testmode_alloc_skb(rdev, approxlen, 0, 0, gfp);
3619}
3620EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb);
3621
3622void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
3623{
3624 void *hdr = ((void **)skb->cb)[1];
3625 struct nlattr *data = ((void **)skb->cb)[2];
3626
3627 nla_nest_end(skb, data);
3628 genlmsg_end(skb, hdr);
3629 genlmsg_multicast(skb, 0, nl80211_testmode_mcgrp.id, gfp);
3630}
3631EXPORT_SYMBOL(cfg80211_testmode_event);
3632#endif
3633
b23aa676
SO
3634static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
3635{
79c97e97 3636 struct cfg80211_registered_device *rdev;
b23aa676
SO
3637 struct net_device *dev;
3638 struct cfg80211_connect_params connect;
3639 struct wiphy *wiphy;
3640 int err;
3641
3642 memset(&connect, 0, sizeof(connect));
3643
3644 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3645 return -EINVAL;
3646
3647 if (!info->attrs[NL80211_ATTR_SSID] ||
3648 !nla_len(info->attrs[NL80211_ATTR_SSID]))
3649 return -EINVAL;
3650
3651 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
3652 connect.auth_type =
3653 nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
3654 if (!nl80211_valid_auth_type(connect.auth_type))
3655 return -EINVAL;
3656 } else
3657 connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
3658
3659 connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
3660
3dc27d25
JB
3661 err = nl80211_crypto_settings(info, &connect.crypto,
3662 NL80211_MAX_NR_CIPHER_SUITES);
b23aa676
SO
3663 if (err)
3664 return err;
3665 rtnl_lock();
3666
79c97e97 3667 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
b23aa676
SO
3668 if (err)
3669 goto unlock_rtnl;
3670
3671 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
3672 err = -EOPNOTSUPP;
3673 goto out;
3674 }
3675
3676 if (!netif_running(dev)) {
3677 err = -ENETDOWN;
3678 goto out;
3679 }
3680
79c97e97 3681 wiphy = &rdev->wiphy;
b23aa676 3682
b23aa676
SO
3683 if (info->attrs[NL80211_ATTR_MAC])
3684 connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
3685 connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
3686 connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
3687
3688 if (info->attrs[NL80211_ATTR_IE]) {
3689 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
3690 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
3691 }
3692
3693 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
3694 connect.channel =
3695 ieee80211_get_channel(wiphy,
3696 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3697 if (!connect.channel ||
3698 connect.channel->flags & IEEE80211_CHAN_DISABLED) {
3699 err = -EINVAL;
3700 goto out;
3701 }
3702 }
3703
79c97e97 3704 err = cfg80211_connect(rdev, dev, &connect);
b23aa676
SO
3705
3706out:
79c97e97 3707 cfg80211_unlock_rdev(rdev);
b23aa676
SO
3708 dev_put(dev);
3709unlock_rtnl:
3710 rtnl_unlock();
3711 return err;
3712}
3713
3714static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
3715{
79c97e97 3716 struct cfg80211_registered_device *rdev;
b23aa676
SO
3717 struct net_device *dev;
3718 int err;
3719 u16 reason;
3720
3721 if (!info->attrs[NL80211_ATTR_REASON_CODE])
3722 reason = WLAN_REASON_DEAUTH_LEAVING;
3723 else
3724 reason = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
3725
3726 if (reason == 0)
3727 return -EINVAL;
3728
3729 rtnl_lock();
3730
79c97e97 3731 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
b23aa676
SO
3732 if (err)
3733 goto unlock_rtnl;
3734
3735 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
3736 err = -EOPNOTSUPP;
3737 goto out;
3738 }
3739
3740 if (!netif_running(dev)) {
3741 err = -ENETDOWN;
3742 goto out;
3743 }
3744
79c97e97 3745 err = cfg80211_disconnect(rdev, dev, reason, true);
b23aa676
SO
3746
3747out:
79c97e97 3748 cfg80211_unlock_rdev(rdev);
b23aa676
SO
3749 dev_put(dev);
3750unlock_rtnl:
3751 rtnl_unlock();
3752 return err;
3753}
3754
55682965
JB
3755static struct genl_ops nl80211_ops[] = {
3756 {
3757 .cmd = NL80211_CMD_GET_WIPHY,
3758 .doit = nl80211_get_wiphy,
3759 .dumpit = nl80211_dump_wiphy,
3760 .policy = nl80211_policy,
3761 /* can be retrieved by unprivileged users */
3762 },
3763 {
3764 .cmd = NL80211_CMD_SET_WIPHY,
3765 .doit = nl80211_set_wiphy,
3766 .policy = nl80211_policy,
3767 .flags = GENL_ADMIN_PERM,
3768 },
3769 {
3770 .cmd = NL80211_CMD_GET_INTERFACE,
3771 .doit = nl80211_get_interface,
3772 .dumpit = nl80211_dump_interface,
3773 .policy = nl80211_policy,
3774 /* can be retrieved by unprivileged users */
3775 },
3776 {
3777 .cmd = NL80211_CMD_SET_INTERFACE,
3778 .doit = nl80211_set_interface,
3779 .policy = nl80211_policy,
3780 .flags = GENL_ADMIN_PERM,
3781 },
3782 {
3783 .cmd = NL80211_CMD_NEW_INTERFACE,
3784 .doit = nl80211_new_interface,
3785 .policy = nl80211_policy,
3786 .flags = GENL_ADMIN_PERM,
3787 },
3788 {
3789 .cmd = NL80211_CMD_DEL_INTERFACE,
3790 .doit = nl80211_del_interface,
3791 .policy = nl80211_policy,
41ade00f
JB
3792 .flags = GENL_ADMIN_PERM,
3793 },
3794 {
3795 .cmd = NL80211_CMD_GET_KEY,
3796 .doit = nl80211_get_key,
3797 .policy = nl80211_policy,
3798 .flags = GENL_ADMIN_PERM,
3799 },
3800 {
3801 .cmd = NL80211_CMD_SET_KEY,
3802 .doit = nl80211_set_key,
3803 .policy = nl80211_policy,
3804 .flags = GENL_ADMIN_PERM,
3805 },
3806 {
3807 .cmd = NL80211_CMD_NEW_KEY,
3808 .doit = nl80211_new_key,
3809 .policy = nl80211_policy,
3810 .flags = GENL_ADMIN_PERM,
3811 },
3812 {
3813 .cmd = NL80211_CMD_DEL_KEY,
3814 .doit = nl80211_del_key,
3815 .policy = nl80211_policy,
55682965
JB
3816 .flags = GENL_ADMIN_PERM,
3817 },
ed1b6cc7
JB
3818 {
3819 .cmd = NL80211_CMD_SET_BEACON,
3820 .policy = nl80211_policy,
3821 .flags = GENL_ADMIN_PERM,
3822 .doit = nl80211_addset_beacon,
3823 },
3824 {
3825 .cmd = NL80211_CMD_NEW_BEACON,
3826 .policy = nl80211_policy,
3827 .flags = GENL_ADMIN_PERM,
3828 .doit = nl80211_addset_beacon,
3829 },
3830 {
3831 .cmd = NL80211_CMD_DEL_BEACON,
3832 .policy = nl80211_policy,
3833 .flags = GENL_ADMIN_PERM,
3834 .doit = nl80211_del_beacon,
3835 },
5727ef1b
JB
3836 {
3837 .cmd = NL80211_CMD_GET_STATION,
3838 .doit = nl80211_get_station,
2ec600d6 3839 .dumpit = nl80211_dump_station,
5727ef1b 3840 .policy = nl80211_policy,
5727ef1b
JB
3841 },
3842 {
3843 .cmd = NL80211_CMD_SET_STATION,
3844 .doit = nl80211_set_station,
3845 .policy = nl80211_policy,
3846 .flags = GENL_ADMIN_PERM,
3847 },
3848 {
3849 .cmd = NL80211_CMD_NEW_STATION,
3850 .doit = nl80211_new_station,
3851 .policy = nl80211_policy,
3852 .flags = GENL_ADMIN_PERM,
3853 },
3854 {
3855 .cmd = NL80211_CMD_DEL_STATION,
3856 .doit = nl80211_del_station,
3857 .policy = nl80211_policy,
2ec600d6
LCC
3858 .flags = GENL_ADMIN_PERM,
3859 },
3860 {
3861 .cmd = NL80211_CMD_GET_MPATH,
3862 .doit = nl80211_get_mpath,
3863 .dumpit = nl80211_dump_mpath,
3864 .policy = nl80211_policy,
3865 .flags = GENL_ADMIN_PERM,
3866 },
3867 {
3868 .cmd = NL80211_CMD_SET_MPATH,
3869 .doit = nl80211_set_mpath,
3870 .policy = nl80211_policy,
3871 .flags = GENL_ADMIN_PERM,
3872 },
3873 {
3874 .cmd = NL80211_CMD_NEW_MPATH,
3875 .doit = nl80211_new_mpath,
3876 .policy = nl80211_policy,
3877 .flags = GENL_ADMIN_PERM,
3878 },
3879 {
3880 .cmd = NL80211_CMD_DEL_MPATH,
3881 .doit = nl80211_del_mpath,
3882 .policy = nl80211_policy,
9f1ba906
JM
3883 .flags = GENL_ADMIN_PERM,
3884 },
3885 {
3886 .cmd = NL80211_CMD_SET_BSS,
3887 .doit = nl80211_set_bss,
3888 .policy = nl80211_policy,
b2e1b302
LR
3889 .flags = GENL_ADMIN_PERM,
3890 },
f130347c
LR
3891 {
3892 .cmd = NL80211_CMD_GET_REG,
3893 .doit = nl80211_get_reg,
3894 .policy = nl80211_policy,
3895 /* can be retrieved by unprivileged users */
3896 },
b2e1b302
LR
3897 {
3898 .cmd = NL80211_CMD_SET_REG,
3899 .doit = nl80211_set_reg,
3900 .policy = nl80211_policy,
3901 .flags = GENL_ADMIN_PERM,
3902 },
3903 {
3904 .cmd = NL80211_CMD_REQ_SET_REG,
3905 .doit = nl80211_req_set_reg,
3906 .policy = nl80211_policy,
93da9cc1 3907 .flags = GENL_ADMIN_PERM,
3908 },
3909 {
3910 .cmd = NL80211_CMD_GET_MESH_PARAMS,
3911 .doit = nl80211_get_mesh_params,
3912 .policy = nl80211_policy,
3913 /* can be retrieved by unprivileged users */
3914 },
3915 {
3916 .cmd = NL80211_CMD_SET_MESH_PARAMS,
3917 .doit = nl80211_set_mesh_params,
3918 .policy = nl80211_policy,
9aed3cc1
JM
3919 .flags = GENL_ADMIN_PERM,
3920 },
2a519311
JB
3921 {
3922 .cmd = NL80211_CMD_TRIGGER_SCAN,
3923 .doit = nl80211_trigger_scan,
3924 .policy = nl80211_policy,
3925 .flags = GENL_ADMIN_PERM,
3926 },
3927 {
3928 .cmd = NL80211_CMD_GET_SCAN,
3929 .policy = nl80211_policy,
3930 .dumpit = nl80211_dump_scan,
3931 },
636a5d36
JM
3932 {
3933 .cmd = NL80211_CMD_AUTHENTICATE,
3934 .doit = nl80211_authenticate,
3935 .policy = nl80211_policy,
3936 .flags = GENL_ADMIN_PERM,
3937 },
3938 {
3939 .cmd = NL80211_CMD_ASSOCIATE,
3940 .doit = nl80211_associate,
3941 .policy = nl80211_policy,
3942 .flags = GENL_ADMIN_PERM,
3943 },
3944 {
3945 .cmd = NL80211_CMD_DEAUTHENTICATE,
3946 .doit = nl80211_deauthenticate,
3947 .policy = nl80211_policy,
3948 .flags = GENL_ADMIN_PERM,
3949 },
3950 {
3951 .cmd = NL80211_CMD_DISASSOCIATE,
3952 .doit = nl80211_disassociate,
3953 .policy = nl80211_policy,
3954 .flags = GENL_ADMIN_PERM,
3955 },
04a773ad
JB
3956 {
3957 .cmd = NL80211_CMD_JOIN_IBSS,
3958 .doit = nl80211_join_ibss,
3959 .policy = nl80211_policy,
3960 .flags = GENL_ADMIN_PERM,
3961 },
3962 {
3963 .cmd = NL80211_CMD_LEAVE_IBSS,
3964 .doit = nl80211_leave_ibss,
3965 .policy = nl80211_policy,
3966 .flags = GENL_ADMIN_PERM,
3967 },
aff89a9b
JB
3968#ifdef CONFIG_NL80211_TESTMODE
3969 {
3970 .cmd = NL80211_CMD_TESTMODE,
3971 .doit = nl80211_testmode_do,
3972 .policy = nl80211_policy,
3973 .flags = GENL_ADMIN_PERM,
3974 },
3975#endif
b23aa676
SO
3976 {
3977 .cmd = NL80211_CMD_CONNECT,
3978 .doit = nl80211_connect,
3979 .policy = nl80211_policy,
3980 .flags = GENL_ADMIN_PERM,
3981 },
3982 {
3983 .cmd = NL80211_CMD_DISCONNECT,
3984 .doit = nl80211_disconnect,
3985 .policy = nl80211_policy,
3986 .flags = GENL_ADMIN_PERM,
3987 },
55682965 3988};
6039f6d2
JM
3989static struct genl_multicast_group nl80211_mlme_mcgrp = {
3990 .name = "mlme",
3991};
55682965
JB
3992
3993/* multicast groups */
3994static struct genl_multicast_group nl80211_config_mcgrp = {
3995 .name = "config",
3996};
2a519311
JB
3997static struct genl_multicast_group nl80211_scan_mcgrp = {
3998 .name = "scan",
3999};
73d54c9e
LR
4000static struct genl_multicast_group nl80211_regulatory_mcgrp = {
4001 .name = "regulatory",
4002};
55682965
JB
4003
4004/* notification functions */
4005
4006void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
4007{
4008 struct sk_buff *msg;
4009
fd2120ca 4010 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
55682965
JB
4011 if (!msg)
4012 return;
4013
4014 if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) {
4015 nlmsg_free(msg);
4016 return;
4017 }
4018
4019 genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
4020}
4021
362a415d
JB
4022static int nl80211_add_scan_req(struct sk_buff *msg,
4023 struct cfg80211_registered_device *rdev)
4024{
4025 struct cfg80211_scan_request *req = rdev->scan_req;
4026 struct nlattr *nest;
4027 int i;
4028
667503dd
JB
4029 ASSERT_RDEV_LOCK(rdev);
4030
362a415d
JB
4031 if (WARN_ON(!req))
4032 return 0;
4033
4034 nest = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
4035 if (!nest)
4036 goto nla_put_failure;
4037 for (i = 0; i < req->n_ssids; i++)
4038 NLA_PUT(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid);
4039 nla_nest_end(msg, nest);
4040
4041 nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
4042 if (!nest)
4043 goto nla_put_failure;
4044 for (i = 0; i < req->n_channels; i++)
4045 NLA_PUT_U32(msg, i, req->channels[i]->center_freq);
4046 nla_nest_end(msg, nest);
4047
4048 if (req->ie)
4049 NLA_PUT(msg, NL80211_ATTR_IE, req->ie_len, req->ie);
4050
4051 return 0;
4052 nla_put_failure:
4053 return -ENOBUFS;
4054}
4055
a538e2d5
JB
4056static int nl80211_send_scan_msg(struct sk_buff *msg,
4057 struct cfg80211_registered_device *rdev,
4058 struct net_device *netdev,
4059 u32 pid, u32 seq, int flags,
4060 u32 cmd)
2a519311
JB
4061{
4062 void *hdr;
4063
4064 hdr = nl80211hdr_put(msg, pid, seq, flags, cmd);
4065 if (!hdr)
4066 return -1;
4067
b5850a7a 4068 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
2a519311
JB
4069 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
4070
362a415d
JB
4071 /* ignore errors and send incomplete event anyway */
4072 nl80211_add_scan_req(msg, rdev);
2a519311
JB
4073
4074 return genlmsg_end(msg, hdr);
4075
4076 nla_put_failure:
4077 genlmsg_cancel(msg, hdr);
4078 return -EMSGSIZE;
4079}
4080
a538e2d5
JB
4081void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
4082 struct net_device *netdev)
4083{
4084 struct sk_buff *msg;
4085
4086 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
4087 if (!msg)
4088 return;
4089
4090 if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0,
4091 NL80211_CMD_TRIGGER_SCAN) < 0) {
4092 nlmsg_free(msg);
4093 return;
4094 }
4095
4096 genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL);
4097}
4098
2a519311
JB
4099void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
4100 struct net_device *netdev)
4101{
4102 struct sk_buff *msg;
4103
fd2120ca 4104 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2a519311
JB
4105 if (!msg)
4106 return;
4107
a538e2d5
JB
4108 if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0,
4109 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
2a519311
JB
4110 nlmsg_free(msg);
4111 return;
4112 }
4113
4114 genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL);
4115}
4116
4117void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
4118 struct net_device *netdev)
4119{
4120 struct sk_buff *msg;
4121
fd2120ca 4122 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2a519311
JB
4123 if (!msg)
4124 return;
4125
a538e2d5
JB
4126 if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0,
4127 NL80211_CMD_SCAN_ABORTED) < 0) {
2a519311
JB
4128 nlmsg_free(msg);
4129 return;
4130 }
4131
4132 genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL);
4133}
4134
73d54c9e
LR
4135/*
4136 * This can happen on global regulatory changes or device specific settings
4137 * based on custom world regulatory domains.
4138 */
4139void nl80211_send_reg_change_event(struct regulatory_request *request)
4140{
4141 struct sk_buff *msg;
4142 void *hdr;
4143
fd2120ca 4144 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
73d54c9e
LR
4145 if (!msg)
4146 return;
4147
4148 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_CHANGE);
4149 if (!hdr) {
4150 nlmsg_free(msg);
4151 return;
4152 }
4153
4154 /* Userspace can always count this one always being set */
4155 NLA_PUT_U8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator);
4156
4157 if (request->alpha2[0] == '0' && request->alpha2[1] == '0')
4158 NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
4159 NL80211_REGDOM_TYPE_WORLD);
4160 else if (request->alpha2[0] == '9' && request->alpha2[1] == '9')
4161 NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
4162 NL80211_REGDOM_TYPE_CUSTOM_WORLD);
4163 else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') ||
4164 request->intersect)
4165 NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
4166 NL80211_REGDOM_TYPE_INTERSECTION);
4167 else {
4168 NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
4169 NL80211_REGDOM_TYPE_COUNTRY);
4170 NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, request->alpha2);
4171 }
4172
4173 if (wiphy_idx_valid(request->wiphy_idx))
4174 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx);
4175
4176 if (genlmsg_end(msg, hdr) < 0) {
4177 nlmsg_free(msg);
4178 return;
4179 }
4180
4181 genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_KERNEL);
4182
4183 return;
4184
4185nla_put_failure:
4186 genlmsg_cancel(msg, hdr);
4187 nlmsg_free(msg);
4188}
4189
6039f6d2
JM
4190static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
4191 struct net_device *netdev,
4192 const u8 *buf, size_t len,
e6d6e342 4193 enum nl80211_commands cmd, gfp_t gfp)
6039f6d2
JM
4194{
4195 struct sk_buff *msg;
4196 void *hdr;
4197
e6d6e342 4198 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
6039f6d2
JM
4199 if (!msg)
4200 return;
4201
4202 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
4203 if (!hdr) {
4204 nlmsg_free(msg);
4205 return;
4206 }
4207
4208 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
4209 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
4210 NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf);
4211
4212 if (genlmsg_end(msg, hdr) < 0) {
4213 nlmsg_free(msg);
4214 return;
4215 }
4216
e6d6e342 4217 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
6039f6d2
JM
4218 return;
4219
4220 nla_put_failure:
4221 genlmsg_cancel(msg, hdr);
4222 nlmsg_free(msg);
4223}
4224
4225void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
e6d6e342
JB
4226 struct net_device *netdev, const u8 *buf,
4227 size_t len, gfp_t gfp)
6039f6d2
JM
4228{
4229 nl80211_send_mlme_event(rdev, netdev, buf, len,
e6d6e342 4230 NL80211_CMD_AUTHENTICATE, gfp);
6039f6d2
JM
4231}
4232
4233void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
4234 struct net_device *netdev, const u8 *buf,
e6d6e342 4235 size_t len, gfp_t gfp)
6039f6d2 4236{
e6d6e342
JB
4237 nl80211_send_mlme_event(rdev, netdev, buf, len,
4238 NL80211_CMD_ASSOCIATE, gfp);
6039f6d2
JM
4239}
4240
53b46b84 4241void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
e6d6e342
JB
4242 struct net_device *netdev, const u8 *buf,
4243 size_t len, gfp_t gfp)
6039f6d2
JM
4244{
4245 nl80211_send_mlme_event(rdev, netdev, buf, len,
e6d6e342 4246 NL80211_CMD_DEAUTHENTICATE, gfp);
6039f6d2
JM
4247}
4248
53b46b84
JM
4249void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
4250 struct net_device *netdev, const u8 *buf,
e6d6e342 4251 size_t len, gfp_t gfp)
6039f6d2
JM
4252{
4253 nl80211_send_mlme_event(rdev, netdev, buf, len,
e6d6e342 4254 NL80211_CMD_DISASSOCIATE, gfp);
6039f6d2
JM
4255}
4256
1b06bb40
LR
4257static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
4258 struct net_device *netdev, int cmd,
e6d6e342 4259 const u8 *addr, gfp_t gfp)
1965c853
JM
4260{
4261 struct sk_buff *msg;
4262 void *hdr;
4263
e6d6e342 4264 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
1965c853
JM
4265 if (!msg)
4266 return;
4267
4268 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
4269 if (!hdr) {
4270 nlmsg_free(msg);
4271 return;
4272 }
4273
4274 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
4275 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
4276 NLA_PUT_FLAG(msg, NL80211_ATTR_TIMED_OUT);
4277 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
4278
4279 if (genlmsg_end(msg, hdr) < 0) {
4280 nlmsg_free(msg);
4281 return;
4282 }
4283
e6d6e342 4284 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
1965c853
JM
4285 return;
4286
4287 nla_put_failure:
4288 genlmsg_cancel(msg, hdr);
4289 nlmsg_free(msg);
4290}
4291
4292void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
4293 struct net_device *netdev, const u8 *addr,
4294 gfp_t gfp)
1965c853
JM
4295{
4296 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
e6d6e342 4297 addr, gfp);
1965c853
JM
4298}
4299
4300void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
e6d6e342
JB
4301 struct net_device *netdev, const u8 *addr,
4302 gfp_t gfp)
1965c853 4303{
e6d6e342
JB
4304 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE,
4305 addr, gfp);
1965c853
JM
4306}
4307
b23aa676
SO
4308void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
4309 struct net_device *netdev, const u8 *bssid,
4310 const u8 *req_ie, size_t req_ie_len,
4311 const u8 *resp_ie, size_t resp_ie_len,
4312 u16 status, gfp_t gfp)
4313{
4314 struct sk_buff *msg;
4315 void *hdr;
4316
4317 msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
4318 if (!msg)
4319 return;
4320
4321 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONNECT);
4322 if (!hdr) {
4323 nlmsg_free(msg);
4324 return;
4325 }
4326
4327 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
4328 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
4329 if (bssid)
4330 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
4331 NLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status);
4332 if (req_ie)
4333 NLA_PUT(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie);
4334 if (resp_ie)
4335 NLA_PUT(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie);
4336
4337 if (genlmsg_end(msg, hdr) < 0) {
4338 nlmsg_free(msg);
4339 return;
4340 }
4341
4342 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
4343 return;
4344
4345 nla_put_failure:
4346 genlmsg_cancel(msg, hdr);
4347 nlmsg_free(msg);
4348
4349}
4350
4351void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
4352 struct net_device *netdev, const u8 *bssid,
4353 const u8 *req_ie, size_t req_ie_len,
4354 const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp)
4355{
4356 struct sk_buff *msg;
4357 void *hdr;
4358
4359 msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
4360 if (!msg)
4361 return;
4362
4363 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ROAM);
4364 if (!hdr) {
4365 nlmsg_free(msg);
4366 return;
4367 }
4368
4369 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
4370 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
4371 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
4372 if (req_ie)
4373 NLA_PUT(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie);
4374 if (resp_ie)
4375 NLA_PUT(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie);
4376
4377 if (genlmsg_end(msg, hdr) < 0) {
4378 nlmsg_free(msg);
4379 return;
4380 }
4381
4382 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
4383 return;
4384
4385 nla_put_failure:
4386 genlmsg_cancel(msg, hdr);
4387 nlmsg_free(msg);
4388
4389}
4390
4391void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
4392 struct net_device *netdev, u16 reason,
667503dd 4393 const u8 *ie, size_t ie_len, bool from_ap)
b23aa676
SO
4394{
4395 struct sk_buff *msg;
4396 void *hdr;
4397
667503dd 4398 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
b23aa676
SO
4399 if (!msg)
4400 return;
4401
4402 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DISCONNECT);
4403 if (!hdr) {
4404 nlmsg_free(msg);
4405 return;
4406 }
4407
4408 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
4409 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
4410 if (from_ap && reason)
4411 NLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason);
4412 if (from_ap)
4413 NLA_PUT_FLAG(msg, NL80211_ATTR_DISCONNECTED_BY_AP);
4414 if (ie)
4415 NLA_PUT(msg, NL80211_ATTR_IE, ie_len, ie);
4416
4417 if (genlmsg_end(msg, hdr) < 0) {
4418 nlmsg_free(msg);
4419 return;
4420 }
4421
667503dd 4422 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL);
b23aa676
SO
4423 return;
4424
4425 nla_put_failure:
4426 genlmsg_cancel(msg, hdr);
4427 nlmsg_free(msg);
4428
4429}
4430
04a773ad
JB
4431void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
4432 struct net_device *netdev, const u8 *bssid,
4433 gfp_t gfp)
4434{
4435 struct sk_buff *msg;
4436 void *hdr;
4437
fd2120ca 4438 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
04a773ad
JB
4439 if (!msg)
4440 return;
4441
4442 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS);
4443 if (!hdr) {
4444 nlmsg_free(msg);
4445 return;
4446 }
4447
4448 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
4449 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
4450 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
4451
4452 if (genlmsg_end(msg, hdr) < 0) {
4453 nlmsg_free(msg);
4454 return;
4455 }
4456
4457 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
4458 return;
4459
4460 nla_put_failure:
4461 genlmsg_cancel(msg, hdr);
4462 nlmsg_free(msg);
4463}
4464
a3b8b056
JM
4465void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
4466 struct net_device *netdev, const u8 *addr,
4467 enum nl80211_key_type key_type, int key_id,
e6d6e342 4468 const u8 *tsc, gfp_t gfp)
a3b8b056
JM
4469{
4470 struct sk_buff *msg;
4471 void *hdr;
4472
e6d6e342 4473 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
a3b8b056
JM
4474 if (!msg)
4475 return;
4476
4477 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
4478 if (!hdr) {
4479 nlmsg_free(msg);
4480 return;
4481 }
4482
4483 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
4484 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
4485 if (addr)
4486 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
4487 NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, key_type);
4488 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id);
4489 if (tsc)
4490 NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc);
4491
4492 if (genlmsg_end(msg, hdr) < 0) {
4493 nlmsg_free(msg);
4494 return;
4495 }
4496
e6d6e342 4497 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
a3b8b056
JM
4498 return;
4499
4500 nla_put_failure:
4501 genlmsg_cancel(msg, hdr);
4502 nlmsg_free(msg);
4503}
4504
6bad8766
LR
4505void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
4506 struct ieee80211_channel *channel_before,
4507 struct ieee80211_channel *channel_after)
4508{
4509 struct sk_buff *msg;
4510 void *hdr;
4511 struct nlattr *nl_freq;
4512
fd2120ca 4513 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
6bad8766
LR
4514 if (!msg)
4515 return;
4516
4517 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT);
4518 if (!hdr) {
4519 nlmsg_free(msg);
4520 return;
4521 }
4522
4523 /*
4524 * Since we are applying the beacon hint to a wiphy we know its
4525 * wiphy_idx is valid
4526 */
4527 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy));
4528
4529 /* Before */
4530 nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE);
4531 if (!nl_freq)
4532 goto nla_put_failure;
4533 if (nl80211_msg_put_channel(msg, channel_before))
4534 goto nla_put_failure;
4535 nla_nest_end(msg, nl_freq);
4536
4537 /* After */
4538 nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER);
4539 if (!nl_freq)
4540 goto nla_put_failure;
4541 if (nl80211_msg_put_channel(msg, channel_after))
4542 goto nla_put_failure;
4543 nla_nest_end(msg, nl_freq);
4544
4545 if (genlmsg_end(msg, hdr) < 0) {
4546 nlmsg_free(msg);
4547 return;
4548 }
4549
4550 genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_ATOMIC);
4551
4552 return;
4553
4554nla_put_failure:
4555 genlmsg_cancel(msg, hdr);
4556 nlmsg_free(msg);
4557}
4558
55682965
JB
4559/* initialisation/exit functions */
4560
4561int nl80211_init(void)
4562{
0d63cbb5 4563 int err;
55682965 4564
0d63cbb5
MM
4565 err = genl_register_family_with_ops(&nl80211_fam,
4566 nl80211_ops, ARRAY_SIZE(nl80211_ops));
55682965
JB
4567 if (err)
4568 return err;
4569
55682965
JB
4570 err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
4571 if (err)
4572 goto err_out;
4573
2a519311
JB
4574 err = genl_register_mc_group(&nl80211_fam, &nl80211_scan_mcgrp);
4575 if (err)
4576 goto err_out;
4577
73d54c9e
LR
4578 err = genl_register_mc_group(&nl80211_fam, &nl80211_regulatory_mcgrp);
4579 if (err)
4580 goto err_out;
4581
6039f6d2
JM
4582 err = genl_register_mc_group(&nl80211_fam, &nl80211_mlme_mcgrp);
4583 if (err)
4584 goto err_out;
4585
aff89a9b
JB
4586#ifdef CONFIG_NL80211_TESTMODE
4587 err = genl_register_mc_group(&nl80211_fam, &nl80211_testmode_mcgrp);
4588 if (err)
4589 goto err_out;
4590#endif
4591
55682965
JB
4592 return 0;
4593 err_out:
4594 genl_unregister_family(&nl80211_fam);
4595 return err;
4596}
4597
4598void nl80211_exit(void)
4599{
4600 genl_unregister_family(&nl80211_fam);
4601}