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